@@ -670,15 +670,14 @@ void CAliM1543C::reg_61_write(u8 data) {
670670 * Read time-of-year clock ports (70h-73h).
671671 **/
672672u8 CAliM1543C::toy_read (u32 address) {
673-
674673 // printf("%%ALI-I-READTOY: read port %02x: 0x%02x\n", (u32)(0x70 + address),
675674 // state.toy_access_ports[address]);
676675 return (u8 )state.toy_access_ports [address];
677676}
678677
679678/* *
680679 * Write time-of-year clock ports (70h-73h). On a write to port 0, recalculate
681- *clock values.
680+ * clock values.
682681 **/
683682void CAliM1543C::toy_write (u32 address, u8 data) {
684683 time_t ltime;
@@ -693,17 +692,17 @@ void CAliM1543C::toy_write(u32 address, u8 data) {
693692 switch (address) {
694693 case 0 :
695694 if ((data & 0x7f ) < 14 ) {
696- state.toy_stored_data [0x0d ] = 0x80 ; // data is geldig!
695+ // Assign VRT (valid RAM and time) bit
696+ state.toy_stored_data [RTC_REG_D] = RTC_VRT;
697697
698- // update clock.......
698+ // Update time
699699 time (<ime);
700700 gmtime_s (&stime, <ime);
701- if (state.toy_stored_data [0x0b ] & 4 ) {
702-
701+ if (state.toy_stored_data [RTC_REG_B] & RTC_DM) {
703702 // binary
704703 state.toy_stored_data [0 ] = (u8 )(stime.tm_sec );
705704 state.toy_stored_data [2 ] = (u8 )(stime.tm_min );
706- if (state.toy_stored_data [0x0b ] & 2 ) // 24-hour
705+ if (state.toy_stored_data [RTC_REG_B ] & RTC_2412 ) // 24-hour
707706 state.toy_stored_data [4 ] = (u8 )(stime.tm_hour );
708707 else
709708 // 12-hour
@@ -714,7 +713,6 @@ void CAliM1543C::toy_write(u32 address, u8 data) {
714713 state.toy_stored_data [8 ] = (u8 )(stime.tm_mon + 1 );
715714 state.toy_stored_data [9 ] = (u8 )(stime.tm_year % 100 );
716715 } else {
717-
718716 // BCD
719717 state.toy_stored_data [0 ] =
720718 (u8 )(((stime.tm_sec / 10 ) << 4 ) | (stime.tm_sec % 10 ));
@@ -738,38 +736,21 @@ void CAliM1543C::toy_write(u32 address, u8 data) {
738736 ((stime.tm_year % 100 ) % 10 ));
739737 }
740738
741- // Debian Linux wants something out of 0x0a. It gets initialized
742- // with 0x26, by the SRM
743- // Ah, here's something from the linux kernel:
744- // # /********************************************************
745- // # * register details
746- // # ********************************************************/
747- // # #define RTC_FREQ_SELECT RTC_REG_A
748- // #
749- // # /* update-in-progress - set to "1" 244 microsecs before RTC goes off
750- // the bus, # * reset after update (may take 1.984ms @ 32768Hz RefClock)
751- // is complete, # * totalling to a max high interval of 2.228 ms. # */ # #
752- // define RTC_UIP 0x80 # # define RTC_DIV_CTL 0x70 # /* divider control:
753- // refclock values 4.194 / 1.049 MHz / 32.768 kHz */ # # define
754- // RTC_REF_CLCK_4MHZ 0x00 # # define RTC_REF_CLCK_1MHZ 0x10 # # define
755- // RTC_REF_CLCK_32KHZ 0x20 # /* 2 values for divider stage reset, others
756- // for "testing purposes only" */ # # define RTC_DIV_RESET1 0x60 # #
757- // define RTC_DIV_RESET2 0x70 # /* Periodic intr. / Square wave rate
758- // select. 0=none, 1=32.8kHz,... 15=2Hz */ # # define RTC_RATE_SELECT 0x0F
759- // #
760- // The SRM-init value of 0x26 means:
761- // xtal speed 32.768KHz (standard)
739+ // SRM initializes the value of A register to 0x26. This means:
740+ // xtal speed is set to MC_BASE_32_KHz 32.768KHz (standard)
762741 // periodic interrupt rate divisor of 32 = interrupt every 976.562 ms
763742 // (1024Hz clock)
764- if (state.toy_stored_data [0x0a ] & 0x80 ) {
743+ if (state.toy_stored_data [RTC_REG_A ] & RTC_UIP ) {
765744 // Once the UIP line goes high, we have to stay high for 2228us.
766745 hold_count--;
767- if (hold_count == 0 ) {
768- state.toy_stored_data [0x0a ] &= ~0x80 ;
746+ if (hold_count == 0 || (state.toy_stored_data [RTC_REG_B] & RTC_SET)) {
747+ // Set UIP low and trigger the related interrupt.
748+ state.toy_stored_data [RTC_REG_A] &= ~RTC_UIP;
749+ state.toy_stored_data [RTC_REG_C] |= RTC_UF;
750+ toy_update_irqf ();
769751 read_count = 0 ;
770752 }
771753 } else {
772-
773754 // UIP isn't high, so if we're looping and waiting for it to go, it
774755 // will take 1,000,000/(IPus*3) reads for a 3 instruction loop.
775756 // If it happens to be a one time read, it'll only throw our
@@ -778,20 +759,31 @@ void CAliM1543C::toy_write(u32 address, u8 data) {
778759 read_count++;
779760 if (read_count > 1000000 / (IPus * 3 )) // 3541 @ 847IPus
780761 {
781- state.toy_stored_data [0x0a ] |= 0x80 ;
762+ state.toy_stored_data [RTC_REG_A ] |= RTC_UIP ;
782763 hold_count =
783764 (2228 / (IPus * 3 )) + 1 ; // .876 @ 847IPus, so we add one.
784765 }
785766 }
786767 }
787768
788769 toy_handle_periodic_interrupt (data);
770+ toy_update_irqf ();
771+
772+ // Assign specified data to port so it can be read by the program
773+ state.toy_access_ports [1 ] = state.toy_stored_data [data & 0x7f ];
774+
775+ // Register C is cleared after a read, and we don't care if it's a write
776+ if (data == RTC_REG_C)
777+ state.toy_stored_data [data & 0x7f ] = 0 ;
778+
789779 break ;
790780 case 1 :
791- if (state.toy_access_ports [0 ] == 0x0b &&
781+ if (state.toy_access_ports [0 ] == RTC_REG_B &&
792782 data & 0x040 ) // If we're writing to register B, we make register C look
793783 // like it fired.
794- state.toy_stored_data [0x0c ] = 0xf0 ;
784+ // TODO: Do actual interrupt implementation instead of
785+ // a workaround.
786+ state.toy_stored_data [RTC_REG_C] = 0xf0 ;
795787 state.toy_stored_data [state.toy_access_ports [0 ] & 0x7f ] = (u8 )data;
796788 break ;
797789
@@ -818,10 +810,10 @@ void CAliM1543C::toy_handle_periodic_interrupt(u8 data) {
818810
819811 // For the meaning of the period calculation see the table on page 14 of the
820812 // aforementioned datasheet
821- int rate_pow = state.toy_stored_data [0x0a ] & 0x0f ;
813+ int rate_pow = state.toy_stored_data [RTC_REG_A ] & 0x0f ;
822814 double period = (1 << rate_pow) / 65536.0 ;
823815
824- if (state.toy_stored_data [0x0a ] & MC_BASE_32_KHz) {
816+ if (state.toy_stored_data [RTC_REG_A ] & MC_BASE_32_KHz) {
825817 if (rate_pow == 0x1 ) {
826818 period = 1 / 256.0 ;
827819 } else if (rate_pow == 0x2 ) {
@@ -833,15 +825,24 @@ void CAliM1543C::toy_handle_periodic_interrupt(u8 data) {
833825 // Elapsed time since last check is equal or greater than the specified
834826 // period - fire the interrupt by setting the PF flag in register C
835827 // (see page 16 in the datasheet).
836- state.toy_stored_data [0x0c ] |= RTC_PF;
828+ state.toy_stored_data [RTC_REG_C ] |= RTC_PF;
837829 state.toy_pi_last_fire = now;
838830 }
831+ }
839832
840- state.toy_access_ports [1 ] = state.toy_stored_data [data & 0x7f ];
841-
842- // register C is cleared after a read, and we don't care if it's a write
843- if (data == 0x0c )
844- state.toy_stored_data [data & 0x7f ] = 0 ;
833+ /* *
834+ * Update RTC interrupt request flag
835+ **/
836+ void CAliM1543C::toy_update_irqf () {
837+ if ((state.toy_stored_data [RTC_REG_B] & RTC_PIE &&
838+ state.toy_stored_data [RTC_REG_C] & RTC_PF) ||
839+ (state.toy_stored_data [RTC_REG_B] & RTC_UIE &&
840+ state.toy_stored_data [RTC_REG_C] & RTC_UF) ||
841+ (state.toy_stored_data [RTC_REG_B] & RTC_AIE &&
842+ state.toy_stored_data [RTC_REG_C] & RTC_AF))
843+ state.toy_stored_data [RTC_REG_C] |= RTC_IRQF;
844+ else
845+ state.toy_stored_data [RTC_REG_C] &= ~RTC_IRQF;
845846}
846847
847848/* *
0 commit comments