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.
This commit is contained in:
finga 2021-09-16 22:02:00 +02:00
parent 52e161f43b
commit 99175efc8c

View file

@ -2,6 +2,7 @@
#include <avr/io.h> #include <avr/io.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <util/delay.h> #include <util/delay.h>
#include <util/twi.h>
#include <assert.h> #include <assert.h>
#include <stdbool.h> #include <stdbool.h>
@ -17,6 +18,12 @@
#define ENC_A (PINB & (1 << PB6)) #define ENC_A (PINB & (1 << PB6))
#define ENC_B (PINB & (1 << PB7)) #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 } #define SYM_ENTRY(SYM) { SYM, sizeof(SYM) / 2 }
static uint8_t EEMEM eeprom_contrast = 8; 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) { static void lcd_home(void) {
lcd_fill(0x00); lcd_fill(0x00);
@ -682,6 +766,12 @@ int main(void) {
// Enable interrupts // Enable interrupts
sei(); sei();
// Set TWI bit rate to 200kHz
TWBR = 12;
(void) &twi_read_register;
(void) &twi_write_register;
// Run... // Run...
for (;;); for (;;);
} }