From 4e0b81034644f7f2332c532ecce5fb31590545d6 Mon Sep 17 00:00:00 2001 From: "Sebastian H. Gabrielli" Date: Wed, 20 Mar 2024 13:00:40 +0100 Subject: [PATCH] Functioning I2C slave data receive The slave now receives and prints data successfully. --- prosjekt.X/i2c.c | 63 ++++++++++++++++++++++--- prosjekt.X/i2c.h | 2 + prosjekt.X/main.c | 8 +++- prosjekt.X/nbproject/configurations.xml | 3 ++ 4 files changed, 67 insertions(+), 9 deletions(-) diff --git a/prosjekt.X/i2c.c b/prosjekt.X/i2c.c index 6474273..7b0eddc 100644 --- a/prosjekt.X/i2c.c +++ b/prosjekt.X/i2c.c @@ -1,6 +1,15 @@ #include "i2c.h" +// Heavily inspired by: https://github.com/microchip-pic-avr-examples/avr128db48-bare-metal-twi-mplab/blob/master/twi-client.X/peripherals/TWI/TWI_client.c + void init_i2c(void) { + // Pin setup + PORTA.DIRSET = PIN2_bm | PIN3_bm; + PORTA.PINCTRLUPD = PIN2_bm | PIN3_bm; + + // Enable operating in debug + TWI0.DBGCTRL = TWI_DBGRUN_bm; + // Initialize the control A register TWI0.CTRLA = TWI_INPUTLVL_I2C_gc // I2C voltage transition level | TWI_SDASETUP_4CYC_gc // Four clock cycles setup time @@ -13,20 +22,60 @@ void init_i2c(void) { // Enable acting as a slave TWI0.SCTRLA = TWI_DIEN_bm // Enable data interrupt + | TWI_APIEN_bm // Enable more interrupts | TWI_PIEN_bm // Enable stop flag interrupt - | TWI_SMEN_bm // Enable smart mode + | PIN2_bm // Respond to all TWI addresses | TWI_ENABLE_bm // Enable acting as a slave ; } // TODO: Figure out which interrupt does what -// Interrupt vector -ISR(TWI0_TWIS_vect) { - asm('nop'); +void i2c_write_handler(uint8_t data) { + printf("%u\n", data); } -// Interrupt vector -ISR(TWI0_TWIM_vect) { - asm('nop'); +void i2c_read_handler() { + printf("Master wanted to read.\n"); +} + +void i2c_stop_handler() { + printf("Stop, I guess\n"); +} + +// Address received +ISR(TWI0_TWIS_vect) { + // Check for the data interrupt flag + if (TWI0.SSTATUS & TWI_DIF_bm) { + uint8_t data = 0; + + if ( ((TWI0.SSTATUS & TWI_DIR_bm) >> TWI_DIR_bp) == 0 ) { + // Data write Master -> Slave + data = TWI0.SDATA; + + // Send the data to the write handler + i2c_write_handler(data); + } else { + // Data read Master <- Slave + i2c_read_handler(); + data = TWI0.SDATA; + } + + // Acknowledge having received + TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc; + } + + // Check for address match or STOP + if (TWI0.SSTATUS & TWI_APIF_bm) { + + if (TWI0.SSTATUS & TWI_AP_ADR_gc) { + // Address match, just send ack + TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc; + } else { + // STOP condition received + i2c_stop_handler(); + // Send ACK + TWI0.SCTRLB = TWI_ACKACT_ACK_gc | TWI_SCMD_RESPONSE_gc; + } + } } \ No newline at end of file diff --git a/prosjekt.X/i2c.h b/prosjekt.X/i2c.h index 7330fd8..0e8f64f 100644 --- a/prosjekt.X/i2c.h +++ b/prosjekt.X/i2c.h @@ -15,6 +15,8 @@ extern "C" { // Include the IO for I2C #include #include +#include "uart.h" +#include // Initialize the I2C bus void init_i2c(void); diff --git a/prosjekt.X/main.c b/prosjekt.X/main.c index b42afa9..25f1319 100644 --- a/prosjekt.X/main.c +++ b/prosjekt.X/main.c @@ -10,14 +10,18 @@ #include #include #include "uart.h" +#include "i2c.h" #include -int main() { +int main() { init_uart((uint16_t)9600); + init_i2c(); stdout = &USART_stream; + + sei(); while (1) { - printf("Hello, world!\n"); + printf("\n"); _delay_ms(500); } } \ No newline at end of file diff --git a/prosjekt.X/nbproject/configurations.xml b/prosjekt.X/nbproject/configurations.xml index 89c9ad4..528acb5 100644 --- a/prosjekt.X/nbproject/configurations.xml +++ b/prosjekt.X/nbproject/configurations.xml @@ -171,6 +171,9 @@ + + +