From 9648bc4beb22d25ddfbcc5da71934679c5a49f8a Mon Sep 17 00:00:00 2001 From: F5OEO Date: Fri, 2 Sep 2016 13:20:06 +0000 Subject: [PATCH] Add Gaionim pyhthon dcf77 generator : works on setting my clock --- setTime.py | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100755 setTime.py diff --git a/setTime.py b/setTime.py new file mode 100755 index 0000000..db1bed9 --- /dev/null +++ b/setTime.py @@ -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"])