firmware/saa1064.c

Go to the documentation of this file.
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 }

Generated on Wed Jan 3 22:22:35 2007 for Binary DCF-77 Clock by  doxygen 1.5.1