Subversion Repositories pentevo

Rev

Rev 370 | Rev 505 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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
  180.         modes_register = rtc_read(RTC_COMMON_MODE_REG);
  181.  
  182.         //set modes on fpga
  183.         //zx_spi_send(SPI_CONFIG_REG, modes_register&MODE_VGA, 0);
  184.         zx_set_config(0);
  185. }
  186.  
  187. void rtc_write(UBYTE addr, UBYTE data)
  188. {
  189.         //set address
  190.         if ( tw_send_start() & (TW_START|TW_REP_START) )
  191.         {
  192.                 if ( tw_send_addr(RTC_ADDRESS|TW_WRITE) == TW_MT_SLA_ACK )
  193.                 {
  194.                         if ( tw_send_data(addr) == TW_MT_DATA_ACK )
  195.                         {
  196.                                 //write data
  197.                                 tw_send_data(data);
  198.                         }
  199.                 }
  200.         }
  201.         tw_send_stop();
  202. }
  203.  
  204. UBYTE rtc_read(UBYTE addr)
  205. {
  206.         UBYTE ret = 0;
  207.  
  208.         //set address
  209.         if ( tw_send_start() & (TW_START|TW_REP_START) )
  210.         {
  211.                 if ( tw_send_addr(RTC_ADDRESS|TW_WRITE) == TW_MT_SLA_ACK )
  212.                 {
  213.                         if ( tw_send_data(addr) == TW_MT_DATA_ACK )
  214.                         {
  215.                                 //read data
  216.                                 if ( tw_send_start() == TW_REP_START )
  217.                                 {
  218.                                         if ( tw_send_addr(RTC_ADDRESS|TW_READ) == TW_MR_SLA_ACK )
  219.                                         {
  220.                                                 tw_read_data(&ret);
  221.                                         }
  222.                                 }
  223.                         }
  224.                 }
  225.         }
  226.         tw_send_stop();
  227.         return ret;
  228. }
  229.  
  230. void gluk_init(void)
  231. {
  232.         UBYTE tmp;
  233.         //default values
  234.         gluk_regs[GLUK_REG_A] = 0x00;
  235.         gluk_regs[GLUK_REG_B] = 0x02;
  236.         gluk_regs[GLUK_REG_C] = 0x00;
  237.         gluk_regs[GLUK_REG_D] = 0x80;
  238.  
  239.         //setup
  240.  
  241.         //read month and day of week
  242.         tmp = rtc_read(6);
  243.         gluk_regs[GLUK_REG_MONTH] = bcd_to_hex(0x1F&tmp);
  244.         tmp = (tmp>>5);
  245.         //PC8583 dayweek 0..6 => DS12788 dayweek 1..7
  246.         gluk_regs[GLUK_REG_DAY_WEEK] = (tmp>6)?1:tmp+1;
  247.  
  248.         //read year and day of month
  249.         tmp = rtc_read(5);
  250.         gluk_regs[GLUK_REG_DAY_MONTH] = bcd_to_hex(0x3F&tmp);
  251.         gluk_regs[GLUK_REG_YEAR] = tmp>>6;
  252.         tmp = rtc_read(RTC_YEAR_ADD_REG);
  253.         if ( (tmp&0x03) > gluk_regs[GLUK_REG_YEAR] )
  254.         {
  255.                 //count of year over - correct year
  256.                 tmp += 4;
  257.                 if ( tmp >= 100 ) tmp = 0;
  258.         }
  259.         gluk_regs[GLUK_REG_YEAR] += tmp&0xFC;
  260.         rtc_write(RTC_YEAR_ADD_REG,gluk_regs[GLUK_REG_YEAR]); //save year
  261.  
  262.         //read time
  263.         gluk_regs[GLUK_REG_HOUR] = bcd_to_hex(0x3F&rtc_read(4)); //TODO 12/24 format
  264.         gluk_regs[GLUK_REG_MIN] = bcd_to_hex(rtc_read(3));
  265.         gluk_regs[GLUK_REG_SEC] = bcd_to_hex(rtc_read(2));
  266. }
  267.  
  268. void gluk_inc(void)
  269. {
  270.         if ( ++gluk_regs[GLUK_REG_SEC] >= 60 )
  271.         {
  272.                 gluk_regs[GLUK_REG_SEC] = 0;
  273.                 if ( ++gluk_regs[GLUK_REG_MIN] >= 60 )
  274.                 {
  275.                         gluk_regs[GLUK_REG_MIN] = 0;
  276.                         if ( ++gluk_regs[GLUK_REG_HOUR] >= 24 )
  277.                         {
  278.                                 gluk_regs[GLUK_REG_HOUR] = 0;
  279.                                 if ( ++gluk_regs[GLUK_REG_DAY_WEEK] > 7  )
  280.                                 {
  281.                                         gluk_regs[GLUK_REG_DAY_WEEK] = 1;
  282.                                 }
  283.                                 if ( ++gluk_regs[GLUK_REG_DAY_MONTH] > days_of_months() )
  284.                                 {
  285.                                         gluk_regs[GLUK_REG_DAY_MONTH] = 1;
  286.                                         if ( ++gluk_regs[GLUK_REG_MONTH] > 12 )
  287.                                         {
  288.                                                 gluk_regs[GLUK_REG_MONTH] = 1;
  289.                                                 if( ++gluk_regs[GLUK_REG_YEAR] >= 100 )
  290.                                                 {
  291.                                                         gluk_regs[GLUK_REG_YEAR] = 0;
  292.                                                 }
  293.                                         }
  294.                                 }
  295.                         }
  296.                 }
  297.         }
  298.  
  299.         //set update flag
  300.         gluk_regs[GLUK_REG_C] |= GLUK_C_UPDATE_FLAG;
  301.  
  302. //#ifdef LOGENABLE
  303. //{
  304. //      char log_int_rtc[] = "00.00.00\r\n";
  305. //      log_int_rtc[0] = '0' + gluk_regs[GLUK_REG_HOUR]/10;
  306. //      log_int_rtc[1] = '0' + gluk_regs[GLUK_REG_HOUR]%10;
  307. //      log_int_rtc[3] = '0' + gluk_regs[GLUK_REG_MIN]/10;
  308. //      log_int_rtc[4] = '0' + gluk_regs[GLUK_REG_MIN]%10;
  309. //      log_int_rtc[6] = '0' + gluk_regs[GLUK_REG_SEC]/10;
  310. //      log_int_rtc[7] = '0' + gluk_regs[GLUK_REG_SEC]%10;
  311. //      to_log(log_int_rtc);
  312. //}
  313. //#endif
  314. }
  315.  
  316. UBYTE gluk_get_reg(UBYTE index)
  317. {
  318.         if( index < sizeof(gluk_regs)/sizeof(gluk_regs[0]) )
  319.         {
  320.                 //clock registers from array
  321.                 UBYTE tmp = gluk_regs[index];
  322.                 if ( ( index<10 ) && ( (gluk_regs[GLUK_REG_B]&GLUK_B_DATA_MODE) == 0 ) )
  323.                 {
  324.                         //clock registers mast be in BCD if HEX-bit not set in reg B
  325.                         tmp = hex_to_bcd(tmp);
  326.                 }
  327.  
  328.                 if ( index == GLUK_REG_C )
  329.                 {
  330.                         //clear update flag
  331.                         gluk_regs[GLUK_REG_C] &= ~GLUK_C_UPDATE_FLAG;
  332.                 }
  333.  
  334.                 return tmp;
  335.         }
  336.         else
  337.         {
  338.                 if ( index >= 0xF0 )
  339.                 {
  340.                         //read version
  341.                         return GetVersionByte( index&0x0F );
  342.                 }
  343.                 else
  344.                 {
  345.                         //other from nvram
  346.                         //- on PCF8583 nvram started from #10
  347.                         //- on 512vi1[DS12887] nvram started from #0E
  348.                         return rtc_read( (index/*&0x3F*/)+2 );
  349.                 }
  350.         }
  351. }
  352.  
  353. void gluk_set_reg(UBYTE index, UBYTE data)
  354. {
  355. #ifdef LOGENABLE
  356.         char log_gs[] = "GS[..]..\r\n";
  357.         UBYTE b = index;
  358.         log_gs[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  359.         log_gs[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  360.         b=data;
  361.         log_gs[6] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  362.         log_gs[7] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  363.         to_log(log_gs);
  364. #endif
  365.  
  366.         if( index < sizeof(gluk_regs)/sizeof(gluk_regs[0]) )
  367.         {
  368.                 if ( index<10 )
  369.                 {
  370.                         //write to clock registers
  371.                         if ( (gluk_regs[GLUK_REG_B]&GLUK_B_DATA_MODE) == 0 )
  372.                         {
  373.                                 //array of registers must be in Hex, but data in BCD if HEX-bit not set in reg B
  374.                                 data = bcd_to_hex(data);
  375.                         }
  376.                         gluk_regs[index] = data;
  377.  
  378.                         //write to nvram if need
  379.                         switch( index )
  380.                         {
  381.                                 case GLUK_REG_SEC:
  382.                                         if( data <= 59 ) rtc_write(2, hex_to_bcd(data/*gluk_regs[GLUK_REG_SEC]*/));
  383.                                         break;
  384.                                 case GLUK_REG_MIN:
  385.                                         if( data <= 59) rtc_write(3, hex_to_bcd(data/*gluk_regs[GLUK_REG_MIN]*/));
  386.                                         break;
  387.                                 case GLUK_REG_HOUR:
  388.                                         if( data <= 23) rtc_write(4, 0x3F&hex_to_bcd(data/*gluk_regs[GLUK_REG_HOUR]*/));
  389.                                         break;
  390.                                 case GLUK_REG_MONTH:
  391.                                 case GLUK_REG_DAY_WEEK:
  392.                                         if( ( gluk_regs[GLUK_REG_DAY_WEEK]-1 <= 6 ) &&
  393.                                                 ( gluk_regs[GLUK_REG_MONTH] > 0 ) &&
  394.                                                 ( gluk_regs[GLUK_REG_MONTH] <= 12 ) )
  395.                                         {
  396.                                                 //DS12788 dayweek 1..7 => PC8583 dayweek 0..6
  397.                                                 rtc_write(6, ((gluk_regs[GLUK_REG_DAY_WEEK]-1)<<5)+(0x1F&hex_to_bcd(gluk_regs[GLUK_REG_MONTH])));
  398.                                         }
  399.                                         break;
  400.                                 case GLUK_REG_YEAR:
  401.                                         rtc_write(RTC_YEAR_ADD_REG, gluk_regs[GLUK_REG_YEAR]);
  402.                                 case GLUK_REG_DAY_MONTH:
  403.                                         rtc_write(5, (gluk_regs[GLUK_REG_YEAR]<<6)+(0x3F&hex_to_bcd(gluk_regs[GLUK_REG_DAY_MONTH])));
  404.                                         break;
  405.                         }
  406.                 }
  407.         }
  408.         else
  409.         {
  410.                 if ( index >= 0xF0 )
  411.                 {
  412.                         //set version data type
  413.                         SetVersionType( data );
  414.                 }
  415.                 else
  416.                 {
  417.                         //write to nvram
  418.                         //- on PCF8583 nvram started from #10
  419.                         //- on 512vi1[DS12887] nvram started from #0E
  420.                         rtc_write( (index/*&0x3F*/)+2, data);
  421.                 }
  422.         }
  423. }
  424.