Subversion Repositories pentevo

Rev

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