mirror of https://github.com/F5OEO/rpitx
Add Gaionim pyhthon dcf77 generator : works on setting my clock
This commit is contained in:
parent
25e5869d2e
commit
9648bc4beb
|
|
@ -0,0 +1,229 @@
|
|||
|
||||
# encoding: utf-8
|
||||
|
||||
"""
|
||||
From https://github.com/gaionim
|
||||
inspired by https://github.com/CodingGhost/DCF77-Transmitter
|
||||
|
||||
reference
|
||||
https://en.wikipedia.org/wiki/DCF77
|
||||
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
import struct
|
||||
from subprocess import call
|
||||
from ctypes import *
|
||||
class Sample(Structure):
|
||||
_fields_ = [("amplitude", c_double), ("timing", c_uint)]
|
||||
|
||||
#with open("/tmp/upstream.bin", "rb") as file:
|
||||
# result = []
|
||||
# x = Pippo()
|
||||
# while file.readinto(x) == sizeof(x):
|
||||
# result.append((x.a, x.t))
|
||||
|
||||
BASE = [1, 2, 4, 8, 10, 20, 40, 80]
|
||||
NUMS = 5
|
||||
UP = 32767.0
|
||||
#DOWN = 3276.0
|
||||
DOWN = 0.0
|
||||
filename = "/tmp/pippo.rfa"
|
||||
|
||||
|
||||
# from https://git.s7t.de/dcf77/dcf77-python/blob/master/dcf77/dcfvalue.py
|
||||
class DCF77Value:
|
||||
def __init__(self):
|
||||
self.hour = 00
|
||||
self.minute = 00
|
||||
self.second = 00
|
||||
self.day = 00
|
||||
self.month = 00
|
||||
self.year = 0000
|
||||
self.data = []
|
||||
self.parity = True
|
||||
self.data = []
|
||||
self.chunklist = {
|
||||
"startbit" : [0, 1],
|
||||
"weather" : [1, 14],
|
||||
"callbit" : [15, 1],
|
||||
"cest_announce" : [16, 1],
|
||||
"cest" : [17, 1],
|
||||
"cet" : [18, 1],
|
||||
"leap_second_announce" : [19, 1],
|
||||
"start_time" : [20, 1],
|
||||
"minute" : [21, 7],
|
||||
"minute_parity" : [28, 1],
|
||||
"hour" : [29, 6],
|
||||
"hour_parity" : [35, 1],
|
||||
"day_month" : [36, 6],
|
||||
"day_week" : [42, 3],
|
||||
"month" : [45, 5],
|
||||
"year" : [50, 8],
|
||||
"date_parity" : [58, 1],
|
||||
"date" : [36, 22],
|
||||
"minute_mark" : [59, 1],
|
||||
}
|
||||
|
||||
def getByte(self, byte):
|
||||
if len(self.data) >= byte:
|
||||
return self.data[byte]
|
||||
return False
|
||||
|
||||
|
||||
def getChunk(self, chunk):
|
||||
start = self.chunklist[chunk][0];
|
||||
end = start + self.chunklist[chunk][1];
|
||||
if len(self.data) >= end:
|
||||
return self.data[start:end]
|
||||
return False
|
||||
|
||||
|
||||
def getCurrentBitCount(self):
|
||||
return len(self.data)
|
||||
|
||||
def setMinute(self):
|
||||
data = self.getChunk("minute")
|
||||
if data == False or len(data) < 7:
|
||||
return
|
||||
|
||||
self.minute = (data[0] + (2 * data[1]) + (4 * data[2]) + (8 * data[3]) + (10 * data[4]) + (20 * data[5]) + (40 * data[6]))
|
||||
|
||||
def setHour(self):
|
||||
data = self.getChunk("hour");
|
||||
print data
|
||||
if data == False or len(data) < 6:
|
||||
return
|
||||
|
||||
self.hour = (data[0] + (2 * data[1]) + (4 * data[2]) + (8 * data[3]) + (10 * data[4]) + (20 * data[5]))
|
||||
|
||||
def setDay(self):
|
||||
data = self.getChunk("day_month")
|
||||
if data == False or len(data) < 6:
|
||||
return
|
||||
|
||||
self.day = (data[0] + (2 * data[1]) + (4 * data[2]) + (8 * data[3]) + (10 * data[4]) + (20 * data[5]))
|
||||
|
||||
def setMonth(self):
|
||||
data = self.getChunk("month")
|
||||
if data == False or len(data) < 5:
|
||||
return
|
||||
|
||||
self.month = (data[0] + (2 * data[1]) + (4 * data[2]) + (8 * data[3]) + (10 * data[4]))
|
||||
|
||||
def setYear(self):
|
||||
data = self.getChunk("year")
|
||||
if data == False or len(data) < 8:
|
||||
return;
|
||||
|
||||
self.year = (data[0] + (2 * data[1]) + (4 * data[2]) + (8 * data[3]) + (10 * data[4]) + (20 * data[5]) + (40 * data[6]) + (80 * data[7]) + 2000)
|
||||
|
||||
def getMinute(self):
|
||||
return self.minute
|
||||
def getHour(self):
|
||||
return self.hour
|
||||
def getDay(self):
|
||||
return self.day
|
||||
def getMonth(self):
|
||||
return self.month
|
||||
def getYear(self):
|
||||
return self.year
|
||||
def getTime(self):
|
||||
return "%02d:%02d" % (self.getHour(), self.getMinute())
|
||||
def getDate(self):
|
||||
return "%02d.%02d.%04d" % (self.getDay(), self.getMonth(), self.getYear())
|
||||
|
||||
def parse(self):
|
||||
self.setMinute()
|
||||
self.setHour()
|
||||
self.setDay()
|
||||
self.setMonth()
|
||||
self.setYear()
|
||||
# fine
|
||||
|
||||
|
||||
def int_to_bcd(value, num_bits):
|
||||
"""
|
||||
|
||||
"""
|
||||
bits = []
|
||||
for base in reversed(BASE[:num_bits]):
|
||||
if value >= base:
|
||||
bits.append("1")
|
||||
value -= base
|
||||
else:
|
||||
bits.append("0")
|
||||
return "".join(reversed(bits))
|
||||
|
||||
def add_crc(value, odd=True):
|
||||
num = value.count("1")
|
||||
p = num % 2
|
||||
if(( p == 1 ) and odd) or ( p==0 and not odd) :
|
||||
return "%s1" % value
|
||||
else:
|
||||
return "%s0" % value
|
||||
|
||||
def to_dcf77(data):
|
||||
time_code = ["011111111100000",]
|
||||
time_code.append("11")
|
||||
if data.dst():
|
||||
time_code.append("10")
|
||||
else:
|
||||
time_code.append("01")
|
||||
time_code.append("0") #leap second
|
||||
time_code.append("1")
|
||||
time_code.append(add_crc(int_to_bcd(data.minute, 7)))
|
||||
time_code.append(add_crc(int_to_bcd(data.hour, 6)))
|
||||
date = [int_to_bcd(data.day, 6),]
|
||||
date.append(int_to_bcd(data.weekday()+1, 3))
|
||||
date.append(int_to_bcd(data.month, 5))
|
||||
date.append(int_to_bcd(data.year - 2000, 8))
|
||||
time_code.append(add_crc("".join(date)))
|
||||
return "".join(time_code)
|
||||
|
||||
def modulate(value=None):
|
||||
if value is None:
|
||||
# last secons
|
||||
return [(UP,1000000000)]
|
||||
else:
|
||||
if value == 0:
|
||||
return [(DOWN,100000000),
|
||||
(UP,900000000)]
|
||||
else:
|
||||
return [(DOWN,200000000),
|
||||
(UP,800000000)]
|
||||
if __name__ == "__main__":
|
||||
with open(filename, "wb") as f:
|
||||
now = datetime.datetime.now()
|
||||
# tolgo secondi per arrivare a inizio minuto
|
||||
# aggiungo 1 per arrivare a prossimo minuto
|
||||
# aggiungo 1 perchè ad ogni minuto, comunico il minuto dopo
|
||||
start = now + datetime.timedelta(minutes=2) - \
|
||||
datetime.timedelta(microseconds = now.microsecond,
|
||||
seconds = now.second )
|
||||
if now.second >= 58:
|
||||
# not enougth time
|
||||
start = start + datetime.timedelta(minutes=1)
|
||||
sample = Sample()
|
||||
for i in range(NUMS):
|
||||
for val in ( int(v) for v in to_dcf77(start + datetime.timedelta(i))):
|
||||
print val, ":",
|
||||
for amplitude, timing in modulate(val):
|
||||
sample.amplitude = amplitude
|
||||
sample.timing = timing
|
||||
#f.write(struct.pack("!fI", amplitude, timing))
|
||||
f.write(sample)
|
||||
print "%s, %s" % (amplitude, timing)
|
||||
# inizio minuto
|
||||
print "chiusura :",
|
||||
for amplitude, timing in modulate():
|
||||
sample.amplitude = amplitude
|
||||
sample.timing = timing
|
||||
#f.write(struct.pack("!fI", amplitude, timing))
|
||||
f.write(sample)
|
||||
print "%s, %s" % (amplitude, timing)
|
||||
trigger = start - datetime.timedelta(minutes=1)
|
||||
|
||||
|
||||
call(["sudo", "./rpitx", "-m", "RFA", "-i", filename, "-f", "77.500", "-l","-c","1"])
|
||||
Loading…
Reference in New Issue