package apple2 import ( "time" ) /* microPD1990ac Serial I/O Calendar Clock IC See: https://www.semiee.com/file/backup/NEC-D1990.pdf Used by the ThunderClock+ real time clock card. The 40 bit register has 5 bytes (10 nibbles): byte 4: month, binary from 1 to 12 day of week, BCD 0 to 6 byte 3: day of month, BCD 1 to 31 byte 2: hour, BCD 0 to 23 byte 1: minute, BCD 0 to 59 byte 0: seconds, BCD 0 to 59 */ type microPD1990ac struct { clock bool // CLK state strobe bool // STB state command uint8 // C0, C1, C2 command. From 0 to 7 register uint64 // 40 bit shift register } const ( mpd1990commandRegHold = 0 mpd1990commandRegShift = 1 mpd1990commandTimeSet = 2 mpd1990commandTimeRead = 3 ) func (m *microPD1990ac) in(clock bool, strobe bool, command uint8, dataIn bool) { // Detect signal raise clockRaise := clock && !m.clock strobeRaise := strobe && !m.strobe // Update signal status m.clock = clock m.strobe = strobe // On strobe raise, update command and execute if needed if strobeRaise { m.command = command switch m.command { case mpd1990commandRegShift: // Nothing to do case mpd1990commandTimeRead: m.loadTime() default: // Ignore unknown commands (like set time) //panic(fmt.Sprintf("PD1990ac command %v not implemented.", m.command)) } } // On clock raise, with shift enable, shift the register if clockRaise && m.command == mpd1990commandRegShift { // Rotate right the 40 bits of the shift register lsb := m.register & 1 m.register >>= 1 m.register += lsb << 39 } } func (m *microPD1990ac) out() bool { if m.command == mpd1990commandRegHold { //panic("Output on RegHold should be a 1Hz signal. Not implemented.") } if m.command == mpd1990commandTimeRead { //panic("Output on RegHold should be a 512Hz signal with LSB. Not implemented.") } // Return the LSB of the register shift return (m.register & 1) == 1 } func (m *microPD1990ac) loadTime() { now := time.Now() var register uint64 register = uint64(now.Month()) register <<= 4 register += uint64(now.Weekday()) day := uint64(now.Day()) register <<= 4 register += day / 10 register <<= 4 register += day % 10 hour := uint64(now.Hour()) register <<= 4 register += hour / 10 register <<= 4 register += hour % 10 minute := uint64(now.Minute()) register <<= 4 register += minute / 10 register <<= 4 register += minute % 10 second := uint64(now.Second()) register <<= 4 register += second / 10 register <<= 4 register += second % 10 m.register = register }