From 99175efc8c73e89b52bd4de2ce8236fb3c9406bc Mon Sep 17 00:00:00 2001 From: finga Date: Thu, 16 Sep 2021 22:02:00 +0200 Subject: [PATCH] Add basic TWI support To support basic TWI support some defines are created to keep track of port, pins and address. Fundamental procedures such as: - `twi_error()` - `twi_start()` - `twi_transmit()` - `twi_receive()` - `twi_stop()` are created. Those procedures are used in `twi_read_register()` and `twi_write_register()` which read and write data from and to registers respectively. Lastly the TWI bit rate is set to 200kHz. --- firmware/src/main.c | 90 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/firmware/src/main.c b/firmware/src/main.c index 44d33da..3ef0c76 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,12 @@ #define ENC_A (PINB & (1 << PB6)) #define ENC_B (PINB & (1 << PB7)) +#define TWI_PORT PORTC +#define TWI_SDA PC4 +#define TWI_SCL PC5 + +#define SI5351_ADDRESS (0x60 << 1) + #define SYM_ENTRY(SYM) { SYM, sizeof(SYM) / 2 } static uint8_t EEMEM eeprom_contrast = 8; @@ -312,6 +319,83 @@ static void lcd_splash(void) { } } +static void twi_error(void) { + lcd_fill(0xFF); + + for (;;); +} + +static void twi_start(void) { + TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // Start transmission + while (!(TWCR & (1 << TWINT))); // Wait until start is transmitted + + if (TW_STATUS != TW_START) // Check status + twi_error(); +} + +static uint8_t twi_transmit(const uint8_t data) { + TWDR = data; + TWCR = (1 << TWINT) | (1 << TWEN); // Transmit data + while (!(TWCR & (1 << TWINT))); // Wait until data is transmitted + + return TW_STATUS; +} + +static uint8_t twi_receive(void) { + TWCR = (1 << TWINT) | (1 << TWEN); // Receive data + while (!(TWCR & (1 << TWINT))); // Wait until data is received + + return TW_STATUS; +} + +static void twi_stop(void) { + TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); +} + +static uint8_t twi_read_register(const uint8_t address, + const uint8_t reg) { + twi_start(); + + if (twi_transmit(address) != TW_MT_SLA_ACK) + twi_error(); + + if (twi_transmit(reg) != TW_MT_DATA_ACK) + twi_error(); + + twi_stop(); + + _delay_us(2); + + twi_start(); + + if (twi_transmit(address + 1) != TW_MR_SLA_ACK) + twi_error(); + + if (twi_receive() != TW_MR_DATA_NACK) + twi_error(); + + twi_stop(); + + return TWDR; +} + +static void twi_write_register(const uint8_t address, + const uint8_t reg, + const uint8_t data) { + twi_start(); + + if (twi_transmit(address) != TW_MT_SLA_ACK) + twi_error(); + + if (twi_transmit(reg) != TW_MT_DATA_ACK) + twi_error(); + + if (twi_transmit(data) != TW_MT_DATA_ACK) + twi_error(); + + twi_stop(); +} + static void lcd_home(void) { lcd_fill(0x00); @@ -682,6 +766,12 @@ int main(void) { // Enable interrupts sei(); + // Set TWI bit rate to 200kHz + TWBR = 12; + + (void) &twi_read_register; + (void) &twi_write_register; + // Run... for (;;); }