Subversion Repositories pentevo

Rev

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