diff --git a/lorawan_toa.py b/lorawan_toa.py index bfe4967..b9c4066 100644 --- a/lorawan_toa.py +++ b/lorawan_toa.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# 4.1.1.6. LoRaTM Packet Structure, SX1276/77/78/79 Datasheet -# http://www.semtech.com/images/datasheet/sx1276_77_78_79.pdf +# 4.1.1.6. LoRaTM Packet Structure, SX1276/77/78/79 Datasheet Rev.5 Aug 2016 +# http://www.semtech.com/images/datasheet/sx1276.pdf import math @@ -18,45 +18,57 @@ def mpsrange(a, b): def get_toa(n_size, n_sf, n_bw=125, enable_dro=1, disable_h=0, n_cr=1, n_preamble=8): ''' - return the time on air in milisecond. - n_size: - PL in the fomula. PHY Payload size in byte (= MAC Payload + 5) - n_sf: SF (12 to 7) - n_bw: Bandwidth in kHz. default is 125 kHz for AS923. - enable_dro: - DE in the fomula. - 1 when the low data rate optimization is enabled. - 0 for disabled. - LoRaWAN always use the low data optimization. - disable_eh: - H in the fomula. - 0 when the explicit header is enabled. - 1 when no header is present. - LoRaWAN always use the header. - n_cr: - CR in the fomula, should be from 1 to 4. - Coding Rate = (n_cr/(n_cr+1)). - LoRaWAN takes alway 1. - n_preamble: - The preamble length in bit. - default is 8 in AS923. + Parameters: + n_size: + PL in the fomula. PHY Payload size in byte (= MAC Payload + 5) + n_sf: SF (12 to 7) + n_bw: Bandwidth in kHz. default is 125 kHz for AS923. + enable_dro: + DE in the fomula. + 1 when the low data rate optimization is enabled. + 0 for disabled. + LoRaWAN always use the low data optimization. + disable_eh: + IH in the fomula. + 0 when the explicit header is enabled. + 1 when no header is present. + LoRaWAN always use the header. + n_cr: + CR in the fomula, should be from 1 to 4. + Coding Rate = (n_cr/(n_cr+1)). + LoRaWAN takes alway 1. + n_preamble: + The preamble length in bit. + default is 8 in AS923. + Return: + dict type contains below: + r_sym: symbol rate in *second* + t_sym: the time on air in millisecond*. + t_preamble: + v_ceil: + n_payload: + t_payload: + t_packet: the time on air in *milisecond*. ''' - t_sym = math.pow(2, n_sf) / (n_bw*1000.) * 1000. + r_sym = (n_bw*1000.) / math.pow(2,n_sf) + t_sym = 1000. / r_sym t_preamble = (n_preamble + 4.25) * t_sym a = 8.*n_size - 4.*n_sf + 28 + 16 - 20.*disable_h b = 4.*(n_sf-2.*enable_dro) v_ceil = a/b - nb_sym_payload = 8 + max(math.ceil(a/b)*(n_cr+4), 0) - t_payload = nb_sym_payload * t_sym - t_frame = t_preamble+ t_payload + n_payload = 8 + max(math.ceil(a/b)*(n_cr+4), 0) + t_payload = n_payload * t_sym + t_packet = t_preamble+ t_payload ret = {} + ret["r_sym"] = r_sym ret["t_sym"] = t_sym + ret["n_preamble"] = n_preamble ret["t_preamble"] = t_preamble ret["v_ceil"] = v_ceil - ret["nb_sym_payload"] = nb_sym_payload + ret["n_payload"] = n_payload ret["t_payload"] = t_payload - ret["t_frame"] = round(t_frame, 3) + ret["t_packet"] = round(t_packet, 3) return ret @@ -102,8 +114,6 @@ if __name__ == "__main__" : opt = parse_args() ret = get_toa(opt.n_size, opt.n_sf, n_bw=opt.n_bw, enable_dro=opt.v_de, disable_h=opt.v_h, n_cr=opt.n_cr, n_preamble=opt.n_preamble) - ret0 = get_toa(0, opt.n_sf, n_bw=opt.n_bw, enable_dro=opt.v_de, - disable_h=opt.v_h, n_cr=opt.n_cr, n_preamble=opt.n_preamble) if opt.f_verbose: print "PHY payload size : %d Bytes" % opt.n_size print "MAC payload size : %d Bytes" % (opt.n_size-5) @@ -112,15 +122,23 @@ if __name__ == "__main__" : print "Low data rate opt. : %s" % ("enable" if opt.v_de else "disable") print "Explicit header : %s" % ("disable" if opt.v_h else "enable") print "CR (coding rate) : %d (4/%d)" % (opt.n_cr, 4+opt.n_cr) + print "Symbol Rate : %.3f symbol/s" % ret["r_sym"] + print "Symbol Time : %.3f msec/symbol" % ret["t_sym"] print "Preamble size : %d symbols" % opt.n_preamble - print "Other symbol size : %d symbols" % ret["nb_sym_payload"] - print "Symbol Time : %.3f msec" % ret["t_sym"] + print "Packet symbol size : %d symbols" % ret["n_payload"] print "Preamble ToA : %.3f msec" % ret["t_preamble"] print "Payload ToA : %.3f msec" % ret["t_payload"] - print "Time on Air : %.3f msec" % ret["t_frame"] + print "Time on Air : %.3f msec" % ret["t_packet"] if opt.debug_level: - print "MAC frame data rate : %.3f bps" % ((8.*(opt.n_size-5)) / - ((ret["t_frame"]-ret0["t_frame"])/1000.)) + ret0 = get_toa(0, opt.n_sf, n_bw=opt.n_bw, + enable_dro=opt.v_de, disable_h=opt.v_h, + n_cr=opt.n_cr, n_preamble=opt.n_preamble) + print "PHY PL=0 ToA : %.3f msec" % (ret0["t_packet"]) + # preamble=8 cr=1? payload-len=7? crc=16 (payload) payload-crc=16 + # =? 48 ==> 6 bytes ? + t0 = (ret["t_packet"]-ret0["t_packet"])/1000. + print "PHY fr.dr.(48b) 7:15: %.3f bps" % ((8.*opt.n_size+48)/t0) + print "MAC frame DR : %.3f bps" % ((8.*(opt.n_size)) /t0) print "Ceil(x) : %.3f" % ret["v_ceil"] else: - print "%.3f" % ret["t_frame"] + print "%.3f" % ret["t_packet"]