Subversion Repositories pentevo

Rev

Rev 126 | Rev 149 | 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 "rs232.h"
  11.  
  12. volatile UBYTE gluk_regs[16];
  13.  
  14. //stop transmit
  15. #define tw_send_stop() {TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);}
  16.  
  17. static UBYTE tw_send_start(void)
  18. {
  19.         //start transmit
  20.         TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
  21.  
  22.         //wait for flag
  23.         while (!(TWCR & (1<<TWINT)));
  24.  
  25. #ifdef LOGENABLE
  26.         char log_reset_type[] = "TWS..\r\n";
  27.         UBYTE b = TWSR;
  28.         log_reset_type[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  29.         log_reset_type[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  30.         to_log(log_reset_type);
  31. #endif
  32.         //return status
  33.    return TWSR&0xF8;
  34. }
  35.  
  36. static UBYTE tw_send_addr(UBYTE addr)
  37. {
  38.         //set address
  39.         TWDR = addr;
  40.  
  41.         //enable transmit
  42.         TWCR = (1<<TWINT)|(1<<TWEN);
  43.  
  44.         //wait for end transmit
  45.         while (!(TWCR & (1<<TWINT)));
  46.  
  47. #ifdef LOGENABLE
  48.         char log_tw[] = "TWA.. ..\r\n";
  49.         UBYTE b = TWSR;
  50.         log_tw[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  51.         log_tw[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  52.         log_tw[6] = ((addr >> 4) <= 9 )?'0'+(addr >> 4):'A'+(addr >> 4)-10;
  53.         log_tw[7] = ((addr & 0x0F) <= 9 )?'0'+(addr & 0x0F):'A'+(addr & 0x0F)-10;
  54.         to_log(log_tw);
  55. #endif
  56.         //return status
  57.    return TWSR&0xF8;
  58. }
  59.  
  60. static UBYTE tw_send_data(UBYTE data)
  61. {
  62.         //set data
  63.         TWDR = data;
  64.  
  65.         //enable transmit
  66.         TWCR = (1<<TWINT)|(1<<TWEN);
  67.  
  68.         //wait for end transmit
  69.         while (!(TWCR & (1<<TWINT)));
  70.  
  71. #ifdef LOGENABLE
  72.         char log_tw[] = "TWD.. ..\r\n";
  73.         UBYTE b = TWSR;
  74.         log_tw[3] = ((b >> 4) <= 9 )?'0'+(b >> 4):'A'+(b >> 4)-10;
  75.         log_tw[4] = ((b & 0x0F) <= 9 )?'0'+(b & 0x0F):'A'+(b & 0x0F)-10;
  76.         log_tw[6] = ((data >> 4) <= 9 )?'0'+(data >> 4):'A'+(data >> 4)-10;
  77.         log_tw[7] = ((data & 0x0F) <= 9 )?'0'+(data & 0x0F):'A'+(data & 0x0F)-10;
  78.         to_log(log_tw);
  79. #endif
  80.         //return status
  81.    return TWSR&0xF8;
  82. }
  83.  
  84. static UBYTE tw_read_data(UBYTE* data)
  85. {
  86.         //enable
  87.         TWCR = (1<<TWINT)|(1<<TWEN);
  88.  
  89.         //wait for flag set
  90.         while (!(TWCR & (1<<TWINT)));
  91.  
  92. #ifdef LOGENABLE
  93.         char log_tw[] = "TWR.. ..\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.         log_tw[6] = ((TWDR >> 4) <= 9 )?'0'+(TWDR >> 4):'A'+(TWDR >> 4)-10;
  98.         log_tw[7] = ((TWDR & 0x0F) <= 9 )?'0'+(TWDR & 0x0F):'A'+(TWDR & 0x0F)-10;
  99.         to_log(log_tw);
  100. #endif
  101.         //get data
  102.         *data = TWDR;
  103.  
  104.         //return status
  105.    return TWSR & 0xF8;
  106. }
  107.  
  108. static UBYTE bcd_to_hex(UBYTE data)
  109. {
  110.         //convert BCD to HEX
  111.         return  (data>>4)*10 + (data&0x0F);
  112. }
  113.  
  114. static UBYTE hex_to_bcd(UBYTE data)
  115. {
  116.         //convert HEX to BCD
  117.         return  ((data/10)<<4) + (data%10);
  118. }
  119.  
  120. static UBYTE days_of_months()
  121. {
  122.         //return number of days in month
  123.         static const UBYTE days[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
  124.         UBYTE tmp = gluk_regs[GLUK_REG_MONTH]-1;
  125.  
  126.         if ( tmp > sizeof(days)-1 ) tmp = 0; //check range
  127.  
  128.         tmp = days[tmp];
  129.  
  130.         //check leap-year
  131.         if ( (tmp == 28) && ( ( gluk_regs[GLUK_REG_YEAR]&0x03 ) == 0 ) ) tmp++;
  132.  
  133.         return tmp;
  134. }
  135.  
  136. void rtc_init(void)
  137. {
  138.         //SCL frequency = CPU clk/ ( 16 + 2* (TWBR) * 4^(TWPS) )
  139.         // 11052000 / (16 + 2*48 ) = 98678,5Hz (100000Hz recommended for PCF8583)
  140.         TWBR = 48;
  141.         TWSR = 0;
  142.  
  143.         //reset RTC
  144.         //write 0 to control/status register [0] on PCF8583
  145.         rtc_write(0, 0);
  146.  
  147.         //set Gluk clock registers
  148.         gluk_init();
  149.         if ( gluk_regs[GLUK_REG_SEC] == 0 ) gluk_init();
  150.  
  151.         //restore mode register from NVRAM
  152.         modes_register = rtc_read(RTC_COMMON_MODE_REG);
  153.         //set modes on fpga
  154.         zx_spi_send(SPI_VGA_REG, modes_register&MODE_VGA, 0);
  155. }
  156.  
  157. void rtc_write(UBYTE addr, UBYTE data)
  158. {
  159.         //set address
  160.         if ( tw_send_start() & (TW_START|TW_REP_START) )
  161.         {
  162.                 if ( tw_send_addr(RTC_ADDRESS) == TW_MT_SLA_ACK )
  163.                 {
  164.                         if ( tw_send_data(addr) == TW_MT_DATA_ACK )
  165.                         {
  166.                                 //write data
  167.                                 tw_send_data(data);
  168.                         }
  169.                 }
  170.         }
  171.         tw_send_stop();
  172. }
  173.  
  174. UBYTE rtc_read(UBYTE addr)
  175. {
  176.         UBYTE ret = 0;
  177.         //set address
  178.         if ( tw_send_start() & (TW_START|TW_REP_START) )
  179.         {
  180.                 if ( tw_send_addr(RTC_ADDRESS) == TW_MT_SLA_ACK )
  181.                 {
  182.                         if ( tw_send_data(addr) == TW_MT_DATA_ACK )
  183.                         {
  184.                                 //read data
  185.                                 if ( tw_send_start() == TW_REP_START )
  186.                                 {
  187.                                         if ( tw_send_addr(RTC_ADDRESS|0x01) == TW_MR_SLA_ACK )
  188.                                         {
  189.                                                 tw_read_data(&ret);
  190.                                         }
  191.                                 }
  192.                         }
  193.                 }
  194.         }
  195.         tw_send_stop();
  196.         return ret;
  197. }
  198.  
  199. void gluk_init(void)
  200. {
  201.         UBYTE tmp;
  202.         //default values
  203.         gluk_regs[GLUK_REG_A] = 0x00;
  204.         gluk_regs[GLUK_REG_B] = 0x02;
  205.         gluk_regs[GLUK_REG_C] = 0x00;
  206.         gluk_regs[GLUK_REG_D] = 0x80;
  207.  
  208.         //setup
  209.  
  210.         //read month and day of week
  211.         tmp = rtc_read(6);
  212.         gluk_regs[GLUK_REG_MONTH] = bcd_to_hex(0x1F&tmp);
  213.         gluk_regs[GLUK_REG_DAY_WEEK] = tmp>>5;
  214.  
  215.         //read year and day of month
  216.         tmp = rtc_read(5);
  217.         gluk_regs[GLUK_REG_DAY_MONTH] = bcd_to_hex(0x3F&tmp);
  218.         gluk_regs[GLUK_REG_YEAR] = tmp>>6;
  219.         tmp = rtc_read(RTC_YEAR_ADD_REG);
  220.         if ( (tmp&0x03) > gluk_regs[GLUK_REG_YEAR] )
  221.         {
  222.                 //count of year over - correct year
  223.                 tmp += 4;
  224.                 if ( tmp >= 100 ) tmp = 0;
  225.         }
  226.         gluk_regs[GLUK_REG_YEAR] += tmp&0xFC;
  227.         rtc_write(RTC_YEAR_ADD_REG,gluk_regs[GLUK_REG_YEAR]); //save year
  228.  
  229.         //read time
  230.         gluk_regs[GLUK_REG_HOUR] = bcd_to_hex(0x3F&rtc_read(4)); //TODO 12/24 format
  231.         gluk_regs[GLUK_REG_MIN] = bcd_to_hex(rtc_read(3));
  232.         gluk_regs[GLUK_REG_SEC] = bcd_to_hex(rtc_read(2));
  233. }
  234.  
  235. void gluk_inc(void)
  236. {
  237.         if ( ++gluk_regs[GLUK_REG_SEC] >= 60 )
  238.         {
  239.                 gluk_regs[GLUK_REG_SEC] = 0;
  240.                 if ( ++gluk_regs[GLUK_REG_MIN] >= 60 )
  241.                 {
  242.                         gluk_regs[GLUK_REG_MIN] = 0;
  243.                         if ( ++gluk_regs[GLUK_REG_HOUR] >= 24 )
  244.                         {
  245.                                 gluk_regs[GLUK_REG_HOUR] = 0;
  246.                                 if ( ++gluk_regs[GLUK_REG_DAY_WEEK] > 7  )
  247.                                 {
  248.                                         gluk_regs[GLUK_REG_DAY_WEEK] = 1;
  249.                                 }
  250.                                 if ( ++gluk_regs[GLUK_REG_DAY_MONTH] > days_of_months() )
  251.                                 {
  252.                                         gluk_regs[GLUK_REG_DAY_MONTH] = 1;
  253.                                         if ( ++gluk_regs[GLUK_REG_MONTH] > 12 )
  254.                                         {
  255.                                                 gluk_regs[GLUK_REG_MONTH] = 1;
  256.                                                 if( ++gluk_regs[GLUK_REG_YEAR] >= 100 )
  257.                                                 {
  258.                                                         gluk_regs[GLUK_REG_YEAR] = 0;
  259.                                                 }
  260.                                         }
  261.                                 }
  262.                         }
  263.                 }
  264.         }
  265.  
  266.         //set update flag
  267.         gluk_regs[GLUK_REG_C] |= GLUK_C_UPDATE_FLAG;
  268.  
  269. //#ifdef LOGENABLE
  270. //{
  271. //      char log_int_rtc[] = "00.00.00\r\n";
  272. //      log_int_rtc[0] = '0' + gluk_regs[GLUK_REG_HOUR]/10;
  273. //      log_int_rtc[1] = '0' + gluk_regs[GLUK_REG_HOUR]%10;
  274. //      log_int_rtc[3] = '0' + gluk_regs[GLUK_REG_MIN]/10;
  275. //      log_int_rtc[4] = '0' + gluk_regs[GLUK_REG_MIN]%10;
  276. //      log_int_rtc[6] = '0' + gluk_regs[GLUK_REG_SEC]/10;
  277. //      log_int_rtc[7] = '0' + gluk_regs[GLUK_REG_SEC]%10;
  278. //      to_log(log_int_rtc);
  279. //}
  280. //#endif
  281. }
  282.  
  283. UBYTE gluk_get_reg(UBYTE index)
  284. {
  285.         if( index < sizeof(gluk_regs)/sizeof(gluk_regs[0]) )
  286.         {
  287.                 //clock registers from array
  288.                 UBYTE tmp = gluk_regs[index];
  289.                 if ( ( index<10 ) && ( (gluk_regs[GLUK_REG_B]&GLUK_B_DATA_MODE) == 0 ) )
  290.                 {
  291.                         //clock registers mast be in BCD if HEX-bit not set in reg B
  292.                         tmp = hex_to_bcd(tmp);
  293.                 }
  294.  
  295.                 if ( index == GLUK_REG_C )
  296.                 {
  297.                         //clear update flag
  298.                         gluk_regs[GLUK_REG_C] &= ~GLUK_C_UPDATE_FLAG;
  299.                 }
  300.  
  301.                 return tmp;
  302.         }
  303.         else
  304.         {
  305.                 //other from nvram
  306.                 return rtc_read(index&0x3F);
  307.         }
  308. }
  309.  
  310. void gluk_set_reg(UBYTE index, UBYTE data)
  311. {
  312.         if( index < sizeof(gluk_regs)/sizeof(gluk_regs[0]) )
  313.         {
  314.                 if ( index<10 )
  315.                 {
  316.                         //write to clock registers
  317.                         if ( (gluk_regs[GLUK_REG_B]&GLUK_B_DATA_MODE) == 0 )
  318.                         {
  319.                                 //array of registers must be in Hex, but data in BCD if HEX-bit not set in reg B
  320.                                 data = bcd_to_hex(data);
  321.                         }
  322.                         gluk_regs[index] = data;
  323.  
  324.                         //write to nvram if need
  325.                         switch( index )
  326.                         {
  327.                                 case GLUK_REG_SEC:
  328.                                         rtc_write(2, hex_to_bcd(gluk_regs[GLUK_REG_SEC]));
  329.                                         break;
  330.                                 case GLUK_REG_MIN:
  331.                                         rtc_write(3, hex_to_bcd(gluk_regs[GLUK_REG_MIN]));
  332.                                         break;
  333.                                 case GLUK_REG_HOUR:
  334.                                         rtc_write(4, 0x3F&hex_to_bcd(gluk_regs[GLUK_REG_HOUR]));
  335.                                         break;
  336.                                 case GLUK_REG_MONTH:
  337.                                 case GLUK_REG_DAY_WEEK:
  338.                                         rtc_write(6, (hex_to_bcd(gluk_regs[GLUK_REG_DAY_WEEK])<<5)+(0x1F&hex_to_bcd(gluk_regs[GLUK_REG_MONTH])));
  339.                                         break;
  340.                                 case GLUK_REG_YEAR:
  341.                                         rtc_write(RTC_YEAR_ADD_REG, gluk_regs[GLUK_REG_YEAR]);
  342.                                 case GLUK_REG_DAY_MONTH:
  343.                                         rtc_write(5, (gluk_regs[GLUK_REG_YEAR]<<6)+(0x3F&hex_to_bcd(gluk_regs[GLUK_REG_DAY_MONTH])));
  344.                                         break;
  345.                         }
  346.                 }
  347.         }
  348.         else
  349.         {
  350.                 //write to nvram
  351.                 rtc_write(index&0x3F, data);
  352.         }
  353. }
  354.