# A very simple command line dB calculator # # Fabian Kurz, DJ1YFK (2008-Jan-19) # # You may do whatever you want with this code. # # Input formats: # # 1) x POWERUNIT (+/- y RATIOUNIT) (in POWERUNIT) # e.g. db.pl 5W + 10dB in dBm # db.pl 100W + 6dB (in W) # db.pl 100W - 1SU # db.pl 100W in dBm # 2) x POWERUNIT to y POWERUNIT, output: dB and S-Units # e.g. db.pl 100W to 200W # db.pl 200W to 5W # # POWERUNITs: [pnumkMG]W, dBm, dBW, S (defined as S9 = -73dBm, 6dB per unit) # RATIOUNITs: dB, SU (S-Units, 6dB each) use strict; use warnings; my %pfx = (p => 1E-12, n=>1E-9, u=>1E-6, m=>1E-3, k=>1E3, M=>1E6, G=>1E9); my $line = "@ARGV"; $line =~ s/\s+/ /g; if ($line=~ /^([-0-9.a-zA-Z]+)( ([+-]) ([-0-9.a-zA-Z]+))?( in ([a-zA-Z]+))?$/) { my ($power, $unit) = &todbm($1); unless (defined($power)) { print "Unable to convert $power $unit to dBm\n"; exit(1); } if (defined($2)) { # only conversion my $sign = ($3."1")+0; my $db = &todb($4); $power += ($db * $sign); } my $tounit = $unit; if (defined($5) && defined($6)) { $tounit = $6; } my $result = &dbmtounit($power, $tounit); unless (defined($result)) { print "Unable to convert $power dBm to $tounit\n"; exit(1); } printf "%.2f $tounit\n", $result; } elsif ($line =~ /([-0-9.a-zA-Z]+) to ([-0-9.a-zA-Z]+)/) { my ($power1, undef) = &todbm($1); my ($power2, undef) = &todbm($2); unless (defined($power1) && defined($power2)) { print "Unable to convert $1 or $2 to dBm.\n"; exit(1); } my $db = ($power2 - $power1); my $sunits = ($power2 - $power1)/6; printf "%.2f dB, %.2f S-Units\n", $db, $sunits; } exit(0); sub todbm { my $v = shift; $v =~ s/\s+//g; if ($v =~ /^([-0-9.]+)([A-Za-z]+)$/) { my ($value, $unit) = ($1, $2); # Convert to dBm if ($unit =~ /^([pnumkMG])?[Ww]$/) { if ($value < 0) { print STDERR "Error: Value ($value) of unit $unit may ". "not negative.\n"; exit(1); } if (defined($1)) { if (defined($pfx{$1})) { $value *= $pfx{$1}; } else { return undef; } } $value = 10*log($value/0.001)/log(10); return ($value, $unit); } elsif ($unit =~ /dB([mW])/) { if ($1 eq 'W') { $value += 30; } return ($value, $unit); } else { return undef; } } elsif ($v =~ /^S(\d)([+]\d+)?$/) { my $value= -127+(6*$1); if (defined($2)) { $value += $2; } return ($value, "S"); } else { return undef; } } sub todb { my $v = shift; $v =~ s/\s+//g; if ($v =~ /^([-0-9.]+)dB$/) { return $1; } elsif ($v =~ /^([0-9])SU$/) { return $1*6; } else { print STDERR "Invalid unit/value $v.\n"; exit(1); } } sub dbmtounit { my ($power, $tounit) = @_; if ($tounit =~ /^([pnumkMG])?[Ww]$/) { my $mult=1; if (defined($1)) { if (defined($pfx{$1})) { $mult = $pfx{$1}; } else { return undef; } } return (0.001 * 10**($power/10)) / $mult; } elsif ($tounit =~ /^dB([mW])$/) { if ($1 eq 'W') { return $power-30; } else { return $power; } } elsif ($tounit eq 'S') { if ($power < -126) { return 0; } else { return ($power + 127)/6; } } elsif ($tounit eq 'V') { print "Conversion to Volts @ 50 Ohms: "; return sqrt(50*(0.001 * 10**($power/10))); } else { return undef; } }