00001 00010 /* based on http://www.mulder.franken.de/ntpdcfledclock/ */ 00011 00012 #include <avr/io.h> 00013 #include <util/delay.h> 00014 #include "saa1064.h" 00015 00016 #define LEDPORT PORTC 00017 #define LEDPIN PINC 00018 #define LEDDDR DDRC 00020 #define SDAPIN PC4 00021 #define SCLPIN PC5 00023 #define SAA_ADR 0x70 00025 #define I2C_READ 0x01 00026 #define I2C_WRITE 0x00 00028 #define DELAYVAL 3 00030 void led_init(void) { 00031 /* activate pullups */ 00032 LEDPORT |= (1 << SCLPIN) | (1 << SDAPIN); 00033 } 00034 00040 static void I2C_start(void) { 00041 /* Change to output mode. */ 00042 LEDDDR |= (1 << SDAPIN) | (1 << SCLPIN); 00043 /* change SDA to low */ 00044 LEDPORT &= ~(1 << SDAPIN); 00045 _delay_loop_1(DELAYVAL); 00046 /* and SCL too */ 00047 LEDPORT &= ~(1 << SCLPIN); 00048 _delay_loop_1(DELAYVAL); 00049 } 00050 00056 static void I2C_stop(void) { 00057 /* Set SCL */ 00058 LEDPORT |= (1 << SCLPIN); 00059 _delay_loop_1(DELAYVAL); 00060 /* Set SDA */ 00061 LEDPORT |= (1 << SDAPIN); 00062 _delay_loop_1(DELAYVAL); 00063 /* Probably safer to tristate the bus */ 00064 LEDDDR &= ~((1 << SDAPIN) | (1 << SCLPIN)); 00065 } 00066 00074 static uint8_t I2C_transmit_byte(uint8_t what) { 00075 uint8_t i; 00076 for (i = 0; i < 8; i++) { 00077 /* First put data on the bus */ 00078 if (what & 0x80) { 00079 LEDPORT |= (1 << SDAPIN); 00080 } 00081 _delay_loop_1(DELAYVAL); 00082 /* Then set SCL high */ 00083 LEDPORT |= (1 << SCLPIN); 00084 _delay_loop_1(DELAYVAL); 00085 /* Take SCL back */ 00086 LEDPORT &= ~(1 << SCLPIN); 00087 _delay_loop_1(DELAYVAL); 00088 /* And SDA too */ 00089 LEDPORT &= ~(1 << SDAPIN); 00090 _delay_loop_1(DELAYVAL); 00091 what <<= 1; 00092 } 00093 /* OK that was the data, now we read back the ACK */ 00094 /* We need to tristate SDA for that */ 00095 LEDPORT |= (1 << SDAPIN); 00096 LEDDDR &= ~(1 << SDAPIN); 00097 /* Give the device some time */ 00098 _delay_loop_1(DELAYVAL); 00099 _delay_loop_1(DELAYVAL); 00100 _delay_loop_1(DELAYVAL); 00101 /* Then set SCL high */ 00102 LEDPORT |= (1 << SCLPIN); 00103 _delay_loop_1(DELAYVAL); 00104 _delay_loop_1(DELAYVAL); 00105 _delay_loop_1(DELAYVAL); 00106 i = LEDPIN & (1 << SDAPIN); /* Read ACK */ 00107 /* Take SCL back */ 00108 LEDPORT &= ~(1 << SCLPIN); 00109 _delay_loop_1(DELAYVAL); 00110 /* No more tristate, we pull SDA again */ 00111 LEDPORT &= ~(1 << SDAPIN); 00112 LEDDDR |= (1 << SDAPIN); 00113 _delay_loop_1(DELAYVAL); 00114 return (i == 0); 00115 } 00116 00117 void set_led_digit(uint8_t digit, uint8_t val) { 00118 I2C_start(); 00119 /* Address device */ 00120 I2C_transmit_byte(SAA_ADR | I2C_WRITE); 00121 I2C_transmit_byte((digit & 3) + 1); /* Address Digit Register on device */ 00122 I2C_transmit_byte(val); /* Send value for Digit */ 00123 I2C_stop(); 00124 } 00125 00126 void set_led_brightness(uint8_t led_brightness) { 00127 I2C_start(); 00128 I2C_transmit_byte(SAA_ADR | I2C_WRITE); /* Address first driver */ 00129 I2C_transmit_byte(0); /* Address Config Register on device */ 00130 I2C_transmit_byte(((led_brightness & 0x07) << 4) | 0x07); /* Send Settings */ 00131 I2C_stop(); 00132 }