Subversion Repositories pentevo

Rev

Rev 589 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. #include <util/twi.h>
  4.  
  5. #include "pins.h"
  6. #include "mytypes.h"
  7. #include "main.h"
  8. #include "zx.h"
  9. #include "rtc.h"
  10. #include "ps2.h"
  11. #include "version.h"
  12. #include "rs232.h"
  13.  
  14. //if want Log than comment next string
  15. #undef LOGENABLE
  16.  
  17. volatile UBYTE gluk_regs[14];
  18.  
  19. //stop transmit
  20. static void tw_send_stop(void)
  21. {
  22.         TWCR = _BV(TWINT)|_BV(TWEN)|_BV(TWSTO);
  23.         //wait for flag
  24. //      while ( (TWCR&_BV(TWSTO))!=0 );
  25. //      _delay_us(20); //4mks for PCF8583
  26. }
  27.  
  28. static UBYTE tw_send_start(void)
  29. {
  30.         //start transmit
  31.         TWCR =_BV(TWINT)|_BV(TWSTA)|_BV(TWEN);
  32.  
  33.         //wait for flag
  34.         while ( (TWCR&_BV(TWINT))==0 );
  35. //      while ( TWCR & (1<<TWSTA) );
  36.  
  37. //#ifdef LOGENABLE
  38. //      char log_reset_type[] = "TWS..[..]..\r\n";
  39. //      UBYTE b = TWSR;
  40. //      log_reset_type[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  41. //      log_reset_type[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  42. //      b=TWCR;
  43. //      log_reset_type[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  44. //      log_reset_type[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  45. //      b=TWDR;
  46. //      log_reset_type[9] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  47. //      log_reset_type[10] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  48. //      to_log(log_reset_type);
  49. //#endif
  50.         //return status
  51.    return TW_STATUS;
  52. }
  53.  
  54. static UBYTE tw_send_addr(UBYTE addr)
  55. {
  56.         //set address
  57.         TWDR = addr;
  58.  
  59.         //enable transmit
  60.         TWCR = _BV(TWINT)|_BV(TWEN);
  61.  
  62.         //wait for end transmit
  63.         while ( (TWCR &_BV(TWINT))==0 );
  64.  
  65. //#ifdef LOGENABLE
  66. //      char log_tw[] = "TWA..[..]..\r\n";
  67. //      UBYTE b = TWSR;
  68. //      log_tw[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  69. //      log_tw[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  70. //      b=TWCR;
  71. //      log_tw[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  72. //      log_tw[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  73. //      log_tw[9] = ((addr >> 4) <= 9 )?'0'+(addr >> 4):'A'+(addr >> 4)-10;
  74. //      log_tw[10] = ((addr & 0x0F) <= 9 )?'0'+(addr & 0x0F):'A'+(addr & 0x0F)-10;
  75. //      to_log(log_tw);
  76. //#endif
  77.         //return status
  78.    return TW_STATUS;
  79. }
  80.  
  81. static UBYTE tw_send_data(UBYTE data)
  82. {
  83.         //set data
  84.         TWDR = data;
  85.  
  86.         //enable transmit
  87.         TWCR = _BV(TWINT)|_BV(TWEN);
  88.  
  89.         //wait for end transmit
  90.         while ( (TWCR&_BV(TWINT))==0 );
  91.  
  92. //#ifdef LOGENABLE
  93. //      char log_tw[] = "TWW..[..]..\r\n";
  94. //      UBYTE b = TWSR;
  95. //      log_tw[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  96. //      log_tw[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  97. //      b=TWCR;
  98. //      log_tw[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  99. //      log_tw[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  100. //      log_tw[9] = ((data >> 4) <= 9 )?'0'+(data >> 4):'A'+(data >> 4)-10;
  101. //      log_tw[10] = ((data & 0x0F) <= 9 )?'0'+(data & 0x0F):'A'+(data & 0x0F)-10;
  102. //      to_log(log_tw);
  103. //#endif
  104.         //return status
  105.    return TW_STATUS;
  106. }
  107.  
  108. static UBYTE tw_read_data(UBYTE* data)
  109. {
  110.         //enable
  111.         TWCR = _BV(TWINT)|_BV(TWEN);
  112.  
  113.         //wait for flag set
  114.         while ( (TWCR&_BV(TWINT))==0 );
  115.  
  116. //#ifdef LOGENABLE
  117. //      char log_tw[] = "TWR..[..]..\r\n";
  118. //      UBYTE b = TWSR;
  119. //      log_tw[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  120. //      log_tw[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  121. //      b=TWCR;
  122. //      log_tw[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  123. //      log_tw[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  124. //      log_tw[9] = ((TWDR >> 4) <= 9 )?'0'+(TWDR >> 4):'A'+(TWDR >> 4)-10;
  125. //      log_tw[10] = ((TWDR & 0x0F) <= 9 )?'0'+(TWDR & 0x0F):'A'+(TWDR & 0x0F)-10;
  126. //      to_log(log_tw);
  127. //#endif
  128.         //get data
  129.         *data = TWDR;
  130.  
  131.         //return status
  132.    return TW_STATUS;
  133. }
  134.  
  135. static UBYTE bcd_to_hex(UBYTE data)
  136. {
  137.         //convert BCD to HEX
  138.         return  (UBYTE)(data>>4)*10 + (UBYTE)(data&0x0F);
  139. }
  140.  
  141. static UBYTE hex_to_bcd(UBYTE data)
  142. {
  143.         //convert HEX to BCD
  144.         return  (UBYTE)((data/10)<<4) + (UBYTE)(data%10);
  145. }
  146.  
  147. static UBYTE days_of_months()
  148. {
  149.         //return number of days in month
  150.         static const UBYTE days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  151.         UBYTE tmp = gluk_regs[GLUK_REG_MONTH]-1;
  152.  
  153.         if ( tmp > sizeof(days)-1 ) tmp = 0; //check range
  154.  
  155.         tmp = days[tmp];
  156.  
  157.         //check leap-year
  158.         if ( (tmp == 28) && ( ( gluk_regs[GLUK_REG_YEAR]&0x03 ) == 0 ) ) tmp++;
  159.  
  160.         return tmp;
  161. }
  162.  
  163. void rtc_init(void)
  164. {
  165.         //SCL frequency = CPU clk/ ( 16 + 2* (TWBR) * 4^(TWPS) )
  166.         // 11052000 / (16 + 2*48 ) = 98678,5Hz (100000Hz recommended for PCF8583)
  167.         TWSR = 0;
  168.         TWBR = 48;
  169.         TWAR = 0; //disable address match unit
  170.  
  171.         //reset RTC
  172.         //write 0 to control/status register [0] on PCF8583
  173.         rtc_write(0, 0);
  174.  
  175.         //set Gluk clock registers
  176.         gluk_init();
  177.         if ( gluk_regs[GLUK_REG_SEC] == 0 ) gluk_init();
  178.  
  179.         //restore mode register from NVRAM (CAPS LED off on init)
  180.         modes_register = rtc_read(RTC_COMMON_MODE_REG) & ~(MODE_CAPSLED);
  181.  
  182.         //set modes on fpga
  183.         zx_set_config(0);
  184. }
  185.  
  186. void rtc_write(UBYTE addr, UBYTE data)
  187. {
  188.         //set address
  189.         if ( tw_send_start() & (TW_START|TW_REP_START) )
  190.         {
  191.                 if ( tw_send_addr(RTC_ADDRESS|TW_WRITE) == TW_MT_SLA_ACK )
  192.                 {
  193.                         if ( tw_send_data(addr) == TW_MT_DATA_ACK )
  194.                         {
  195.                                 //write data
  196.                                 tw_send_data(data);
  197.                         }
  198.                 }
  199.         }
  200.         tw_send_stop();
  201. }
  202.  
  203. UBYTE rtc_read(UBYTE addr)
  204. {
  205.         UBYTE ret = 0;
  206.  
  207.         //set address
  208.         if ( tw_send_start() & (TW_START|TW_REP_START) )
  209.         {
  210.                 if ( tw_send_addr(RTC_ADDRESS|TW_WRITE) == TW_MT_SLA_ACK )
  211.                 {
  212.                         if ( tw_send_data(addr) == TW_MT_DATA_ACK )
  213.                         {
  214.                                 //read data
  215.                                 if ( tw_send_start() == TW_REP_START )
  216.                                 {
  217.                                         if ( tw_send_addr(RTC_ADDRESS|TW_READ) == TW_MR_SLA_ACK )
  218.                                         {
  219.                                                 tw_read_data(&ret);
  220.                                         }
  221.                                 }
  222.                         }
  223.                 }
  224.         }
  225.         tw_send_stop();
  226.         return ret;
  227. }
  228.  
  229. void gluk_init(void)
  230. {
  231.         UBYTE tmp;
  232.         //default values
  233.         gluk_regs[GLUK_REG_A] = GLUK_A_INIT_VALUE;
  234.         gluk_regs[GLUK_REG_B] = GLUK_B_INIT_VALUE;
  235.         gluk_regs[GLUK_REG_C] = GLUK_C_INIT_VALUE;
  236.         gluk_regs[GLUK_REG_D] = GLUK_D_INIT_VALUE;
  237.  
  238.         //setup
  239.  
  240.         //read month and day of week
  241.         tmp = rtc_read(6);
  242.         gluk_regs[GLUK_REG_MONTH] = bcd_to_hex(0x1F&tmp);
  243.         tmp = (tmp>>5);
  244.         //PC8583 dayweek 0..6 => DS12788 dayweek 1..7
  245.         gluk_regs[GLUK_REG_DAY_WEEK] = (tmp>6)?1:tmp+1;
  246.  
  247.         //read year and day of month
  248.         tmp = rtc_read(5);
  249.         gluk_regs[GLUK_REG_DAY_MONTH] = bcd_to_hex(0x3F&tmp);
  250.         gluk_regs[GLUK_REG_YEAR] = tmp>>6;
  251.         tmp = rtc_read(RTC_YEAR_ADD_REG);
  252.         if ( (tmp&0x03) > gluk_regs[GLUK_REG_YEAR] )
  253.         {
  254.                 //count of year over - correct year
  255.                 tmp += 4;
  256.                 if ( tmp >= 100 ) tmp = 0;
  257.         }
  258.         gluk_regs[GLUK_REG_YEAR] += tmp&0xFC;
  259.         rtc_write(RTC_YEAR_ADD_REG,gluk_regs[GLUK_REG_YEAR]); //save year
  260.  
  261.         //read time
  262.         gluk_regs[GLUK_REG_HOUR] = bcd_to_hex(0x3F&rtc_read(4)); //TODO 12/24 format
  263.         gluk_regs[GLUK_REG_MIN] = bcd_to_hex(rtc_read(3));
  264.         gluk_regs[GLUK_REG_SEC] = bcd_to_hex(rtc_read(2));
  265. }
  266.  
  267. void gluk_inc(void)
  268. {
  269.         if ( ++gluk_regs[GLUK_REG_SEC] >= 60 )
  270.         {
  271.                 gluk_regs[GLUK_REG_SEC] = 0;
  272.                 if ( ++gluk_regs[GLUK_REG_MIN] >= 60 )
  273.                 {
  274.                         gluk_regs[GLUK_REG_MIN] = 0;
  275.                         if ( ++gluk_regs[GLUK_REG_HOUR] >= 24 )
  276.                         {
  277.                                 gluk_regs[GLUK_REG_HOUR] = 0;
  278.                                 if ( ++gluk_regs[GLUK_REG_DAY_WEEK] > 7  )
  279.                                 {
  280.                                         gluk_regs[GLUK_REG_DAY_WEEK] = 1;
  281.                                 }
  282.                                 if ( ++gluk_regs[GLUK_REG_DAY_MONTH] > days_of_months() )
  283.                                 {
  284.                                         gluk_regs[GLUK_REG_DAY_MONTH] = 1;
  285.                                         if ( ++gluk_regs[GLUK_REG_MONTH] > 12 )
  286.                                         {
  287.                                                 gluk_regs[GLUK_REG_MONTH] = 1;
  288.                                                 if( ++gluk_regs[GLUK_REG_YEAR] >= 100 )
  289.                                                 {
  290.                                                         gluk_regs[GLUK_REG_YEAR] = 0;
  291.                                                 }
  292.                                         }
  293.                                 }
  294.                         }
  295.                 }
  296.         }
  297.  
  298.         //set update flag
  299.         gluk_regs[GLUK_REG_C] |= GLUK_C_UPDATE_FLAG;
  300.  
  301. //#ifdef LOGENABLE
  302. //{
  303. //      char log_int_rtc[] = "00.00.00\r\n";
  304. //      log_int_rtc[0] = '0' + gluk_regs[GLUK_REG_HOUR]/10;
  305. //      log_int_rtc[1] = '0' + gluk_regs[GLUK_REG_HOUR]%10;
  306. //      log_int_rtc[3] = '0' + gluk_regs[GLUK_REG_MIN]/10;
  307. //      log_int_rtc[4] = '0' + gluk_regs[GLUK_REG_MIN]%10;
  308. //      log_int_rtc[6] = '0' + gluk_regs[GLUK_REG_SEC]/10;
  309. //      log_int_rtc[7] = '0' + gluk_regs[GLUK_REG_SEC]%10;
  310. //      to_log(log_int_rtc);
  311. //}
  312. //#endif
  313. }
  314.  
  315. UBYTE gluk_get_reg(UBYTE index)
  316. {
  317.         UBYTE tmp;
  318.  
  319.         if( index < sizeof(gluk_regs)/sizeof(gluk_regs[0]) )
  320.         {
  321.                 //clock registers from array
  322.                 tmp = gluk_regs[index];
  323.                 if ( ( index<10 ) && ( (gluk_regs[GLUK_REG_B]&GLUK_B_DATA_MODE) == 0 ) )
  324.                 {
  325.                         //clock registers mast be in BCD if HEX-bit not set in reg B
  326.                         tmp = hex_to_bcd(tmp);
  327.                 }
  328.  
  329.                 if ( index == GLUK_REG_C )
  330.                 {
  331.                         //clear update flag
  332.                         gluk_regs[GLUK_REG_C] &= ~GLUK_C_UPDATE_FLAG;
  333.  
  334.                         //3 bit - SD card detect
  335.                         //2 bit - SD WRP detect
  336.                         tmp = tmp | (((~SD_PIN)&((1<<SDWRP)|(1<<SDDET)))>>2);
  337.                 }
  338.         }
  339.         else
  340.         {
  341.                 if ( index >= 0xF0 )
  342.                 {
  343.                         //read version
  344.                         tmp = GetVersionByte( index&0x0F );
  345.                 }
  346.                 else
  347.                 {
  348.                         //other from nvram
  349.                         //- on PCF8583 nvram started from #10
  350.                         //- on 512vi1[DS12887] nvram started from #0E
  351.                         tmp = rtc_read( (index/*&0x3F*/)+2 );
  352.                 }
  353.         }
  354.  
  355. #ifdef LOGENABLE
  356.         {
  357.                 char log_gs[] = "GR[..]..\r\n";
  358.                 UBYTE b = index;
  359.                 log_gs[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  360.                 log_gs[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  361.                 b = tmp;
  362.                 log_gs[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  363.                 log_gs[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  364.                 to_log(log_gs);
  365.         }
  366. #endif
  367.         return tmp;
  368. }
  369.  
  370. void gluk_set_reg(UBYTE index, UBYTE data)
  371. {
  372. #ifdef LOGENABLE
  373.         char log_gs[] = "GS[..]..\r\n";
  374.         UBYTE b = index;
  375.         log_gs[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  376.         log_gs[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  377.         b=data;
  378.         log_gs[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  379.         log_gs[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  380.         to_log(log_gs);
  381. #endif
  382.  
  383.         if( index < sizeof(gluk_regs)/sizeof(gluk_regs[0]) )
  384.         {
  385.                 if ( index<10 )
  386.                 {
  387.                         //write to clock registers
  388.                         if ( (gluk_regs[GLUK_REG_B]&GLUK_B_DATA_MODE) == 0 )
  389.                         {
  390.                                 //array of registers must be in Hex, but data in BCD if HEX-bit not set in reg B
  391.                                 data = bcd_to_hex(data);
  392.                         }
  393.                         gluk_regs[index] = data;
  394.  
  395.                         //write to nvram if need
  396.                         switch( index )
  397.                         {
  398.                                 case GLUK_REG_SEC:
  399.                                         if( data <= 59 ) rtc_write(2, hex_to_bcd(data/*gluk_regs[GLUK_REG_SEC]*/));
  400.                                         break;
  401.                                 case GLUK_REG_MIN:
  402.                                         if( data <= 59) rtc_write(3, hex_to_bcd(data/*gluk_regs[GLUK_REG_MIN]*/));
  403.                                         break;
  404.                                 case GLUK_REG_HOUR:
  405.                                         if( data <= 23) rtc_write(4, 0x3F&hex_to_bcd(data/*gluk_regs[GLUK_REG_HOUR]*/));
  406.                                         break;
  407.                                 case GLUK_REG_MONTH:
  408.                                 case GLUK_REG_DAY_WEEK:
  409.                                         if( ( gluk_regs[GLUK_REG_DAY_WEEK]-1 <= 6 ) &&
  410.                                                 ( gluk_regs[GLUK_REG_MONTH] > 0 ) &&
  411.                                                 ( gluk_regs[GLUK_REG_MONTH] <= 12 ) )
  412.                                         {
  413.                                                 //DS12788 dayweek 1..7 => PC8583 dayweek 0..6
  414.                                                 rtc_write(6, ((gluk_regs[GLUK_REG_DAY_WEEK]-1)<<5)+(0x1F&hex_to_bcd(gluk_regs[GLUK_REG_MONTH])));
  415.                                         }
  416.                                         break;
  417.                                 case GLUK_REG_YEAR:
  418.                                         rtc_write(RTC_YEAR_ADD_REG, gluk_regs[GLUK_REG_YEAR]);
  419.                                 case GLUK_REG_DAY_MONTH:
  420.                                         rtc_write(5, (gluk_regs[GLUK_REG_YEAR]<<6)+(0x3F&hex_to_bcd(gluk_regs[GLUK_REG_DAY_MONTH])));
  421.                                         break;
  422.                         }
  423.                 }
  424.                 else
  425.                 {
  426.                         switch( index )
  427.                         {
  428.                                 case GLUK_REG_B:
  429.                                         //BCD or Hex mode set
  430.                                         gluk_regs[GLUK_REG_B]=(data&GLUK_B_DATA_MODE)|GLUK_B_INIT_VALUE;
  431.                                         break;
  432.  
  433.                                 case GLUK_REG_C:
  434.                                         if ( (data&GLUK_C_CLEAR_LOG_FLAG) != 0 )
  435.                                         {
  436.                                                 //clear PS2 keyboard log
  437.                                                 ps2keyboard_reset_log();
  438.                                         }
  439.                                         if ( (data&GLUK_C_CAPS_LED_FLAG) != (gluk_regs[GLUK_REG_C]&GLUK_C_CAPS_LED_FLAG) )
  440.                                         {
  441.                                                 //switch state of CAPS LED on PS2 keyboard
  442.                                                 gluk_regs[GLUK_REG_C] = gluk_regs[GLUK_REG_C]^GLUK_C_CAPS_LED_FLAG;
  443.                                                 modes_register = modes_register^MODE_CAPSLED;
  444.                                                 //set led on keyboard
  445.                                                 ps2keyboard_send_cmd(PS2KEYBOARD_CMD_SETLED);
  446.                                         }
  447.                                         break;
  448.                         }
  449.                 }
  450.         }
  451.         else
  452.         {
  453.                 if ( index >= 0xF0 )
  454.                 {
  455.                         //set version data type
  456.                         SetVersionType( data );
  457.                 }
  458.                 else
  459.                 {
  460.                         //write to nvram
  461.                         //- on PCF8583 nvram started from #10
  462.                         //- on 512vi1[DS12887] nvram started from #0E
  463.                         rtc_write( (index/*&0x3F*/)+2, data);
  464.                 }
  465.         }
  466. }
  467.