From 9a5753f23fb7d55a7a72c8cf9846cc72349c65de Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Thu, 13 Feb 2014 16:45:48 +0100 Subject: Split up main.c --- .gitignore | 3 + Makefile | 4 +- i2c.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++ i2c.h | 51 ++++++++++ main.c | 327 ++----------------------------------------------------------- uart.c | 46 +++++++++ uart.h | 7 ++ 7 files changed, 367 insertions(+), 323 deletions(-) create mode 100644 .gitignore create mode 100644 i2c.c create mode 100644 i2c.h create mode 100644 uart.c create mode 100644 uart.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..99b6aae --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.sw? +sanduhr.elf +sanduhr.hex diff --git a/Makefile b/Makefile index 452e05e..1863525 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,8 @@ MCU = atmega88 all: sanduhr.hex -sanduhr.elf: main.c - avr-gcc -std=gnu99 -mmcu=$(MCU) -Os -o $@ $< +sanduhr.elf: main.c i2c.c i2c.h uart.c + avr-gcc -std=gnu99 -mmcu=$(MCU) -Os -o $@ $^ sanduhr.hex: sanduhr.elf avr-objcopy -O ihex -R .eeprom $< $@ diff --git a/i2c.c b/i2c.c new file mode 100644 index 0000000..4368158 --- /dev/null +++ b/i2c.c @@ -0,0 +1,252 @@ +#include +#include +#include + +#include "i2c.h" + +volatile twReq twr; + +static void twStartRaw () { + /* disable stop, enable interrupt, reset twint, enable start, enable i2c */ + TWCR = (TWCR & ~(1 << TWSTO)) | (1 << TWIE) | (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); +} + +static void twStopRaw () { + /* disable start, enable interrupt, reset twint, enable stop, enable i2c */ + TWCR = (TWCR & ~(1 << TWSTA)) | (1 << TWIE) | (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); +} + +static void twFlushRaw () { + /* disable start/stop, enable interrupt, reset twint, enable i2c */ + TWCR = (TWCR & ~((1 << TWSTA) | (1 << TWSTO) | (1 << TWEA))) | (1 << TWIE) | (1 << TWINT) | (1 << TWEN); +} + +/* flush and send master ack */ +static void twFlushContRaw () { + /* disable start/stop, enable interrupt, reset twint, enable i2c, send master ack */ + TWCR = (TWCR & ~((1 << TWSTA) | (1 << TWSTO))) | (1 << TWIE) | (1 << TWINT) | (1 << TWEN) | (1 << TWEA); +} + +static void twWaitRaw () { + while (!(TWCR & (1 << TWINT))); +} + +static bool twWriteRaw (const uint8_t data) { + TWDR = data; + if (TWCR & (1 << TWWC)) { + printf("write collision\n"); + return false; + } else { + return true; + } +} + +void twInit () { + /* set scl to 3.6 kHz (at 1Mhz CPU speed)*/ + TWBR = 2; + TWSR |= 0x3; /* set prescaler to 64 */ + + twr.mode = TWM_INVALID; + twr.status = TWST_ERR; +} + +/* high-level write + */ +bool twWrite (const uint8_t address, const uint8_t subaddress, + const uint8_t data) { + /* do not start if request is pending */ + if (twr.status == TWST_WAIT) { + return false; + } + + twr.mode = TWM_WRITE; + twr.address = address; + twr.subaddress = subaddress; + twr.data = data; + twr.step = 0; + twr.status = TWST_WAIT; + /* wait for stop finish */ + while (TW_STATUS != 0xf8); + twStartRaw (); + + return true; +} + +/* high-level read for multiple bytes/addresses + */ +bool twReadMulti (const uint8_t address, const uint8_t subaddress, + uint8_t * const retData, const uint8_t count) { + /* do not start if request is pending */ + if (twr.status == TWST_WAIT) { + return false; + } + + twr.mode = TWM_READ_MULTI; + twr.address = address; + twr.subaddress = subaddress; + twr.retData = retData; + twr.count = count; + twr.i = 0; + twr.step = 0; + twr.status = TWST_WAIT; + /* wait for stop finish */ + while (TW_STATUS != 0xf8); + twStartRaw (); + + return true; +} + +/* handle interrupt, write request + */ +static void twIntWrite () { + switch (twr.step) { + case 0: + if (TW_STATUS == TW_START) { + twWriteRaw (twr.address | TW_WRITE); + twFlushRaw (); + } else { + twr.status = TWST_ERR; + } + break; + + case 1: + if (TW_STATUS == TW_MT_SLA_ACK) { + twWriteRaw (twr.subaddress); + twFlushRaw (); + } else { + twr.status = TWST_ERR; + } + break; + + case 2: + if (TW_STATUS == TW_MT_DATA_ACK) { + twWriteRaw (twr.data); + twFlushRaw (); + } else { + twr.status = TWST_ERR; + } + break; + + case 3: + if (TW_STATUS == TW_MT_DATA_ACK) { + twStopRaw (); + twr.status = TWST_OK; + } else { + twr.status = TWST_ERR; + } + break; + + default: + printf ("nope\n"); + break; + } + ++twr.step; +} + +/* handle interrupt, read request + */ +static void twIntReadMulti () { + switch (twr.step) { + case 0: + if (TW_STATUS == TW_START) { + /* write device address */ + twWriteRaw (twr.address | TW_WRITE); + twFlushRaw (); + ++twr.step; + } else { + twr.status = TWST_ERR; + } + break; + + case 1: + if (TW_STATUS == TW_MT_SLA_ACK) { + /* write subaddress, enable auto-increment */ + twWriteRaw ((1 << 7) | twr.subaddress); + twFlushRaw (); + ++twr.step; + } else { + twr.status = TWST_ERR; + } + break; + + case 2: + if (TW_STATUS == TW_MT_DATA_ACK) { + /* send repeated start */ + twStartRaw (); + ++twr.step; + } else { + twr.status = TWST_ERR; + } + break; + + case 3: + if (TW_STATUS == TW_REP_START) { + /* now start the actual read request */ + twWriteRaw (twr.address | TW_READ); + twFlushRaw (); + ++twr.step; + } else { + twr.status = TWST_ERR; + } + break; + + case 4: + if (TW_STATUS == TW_MR_SLA_ACK) { + /* send master ack if next data block is received */ + twFlushContRaw (); + ++twr.step; + } else { + twr.status = TWST_ERR; + } + + case 5: + if (TW_STATUS == TW_MR_DATA_ACK) { + twr.retData[twr.i] = TWDR; + ++twr.i; + if (twr.i < twr.count-1) { + /* read another byte, not the last one */ + twFlushContRaw (); + /* step stays the same */ + } else { + /* read last byte, send master nack */ + twFlushRaw (); + ++twr.step; + } + } else { + twr.status = TWST_ERR; + } + break; + + case 6: + if (TW_STATUS == TW_MR_DATA_NACK) { + /* receive final byte, send stop */ + twr.retData[twr.i] = TWDR; + twStopRaw (); + twr.status = TWST_OK; + } else { + twr.status = TWST_ERR; + } + break; + + default: + printf ("twIntReadMulti: nope\n"); + break; + } +} + +ISR(TWI_vect) { + switch (twr.mode) { + case TWM_WRITE: + twIntWrite (); + break; + + case TWM_READ_MULTI: + twIntReadMulti (); + break; + + default: + printf ("nope\n"); + break; + } +} + diff --git a/i2c.h b/i2c.h new file mode 100644 index 0000000..1381663 --- /dev/null +++ b/i2c.h @@ -0,0 +1,51 @@ +#ifndef TW_H +#define TW_H + +typedef enum { + TWM_INVALID = 0, + TWM_WRITE, + TWM_READ_MULTI, +} twMode; + +typedef enum { + TWST_WAIT = 0, + TWST_OK = 1, + TWST_ERR = 2, +} twStatus; + +#include + +typedef struct { + twMode mode; + uint8_t address; + uint8_t subaddress; + uint8_t data; + uint8_t step; + /* read data store */ + uint8_t *retData; + /* number of bytes to be read */ + uint8_t count; + /* current byte */ + uint8_t i; + twStatus status; +} twReq; + +extern volatile twReq twr; + +/* i2c device addresses */ +#define L3GD20 0b11010100 +#define L3GD20_WHOAMI 0xf +#define L3GD20_CTRLREG1 0x20 +#define LIS302DL 0b00111000 +#define LIS302DL_WHOAMI 0xf +#define LIS302DL_CTRLREG1 0x20 + +#include + +void twInit (); +bool twWrite (const uint8_t address, const uint8_t subaddress, + const uint8_t data); +bool twReadMulti (const uint8_t address, const uint8_t subaddress, + uint8_t * const retData, const uint8_t count); + +#endif /* TW_H */ diff --git a/main.c b/main.c index 62e10d3..6bda270 100644 --- a/main.c +++ b/main.c @@ -5,135 +5,13 @@ #include #include #include -#include #include #include -/* i2c device addresses */ -#define L3GD20 0b11010100 -#define L3GD20_WHOAMI 0xf -#define L3GD20_CTRLREG1 0x20 -#define LIS302DL 0b00111000 -#define LIS302DL_WHOAMI 0xf -#define LIS302DL_CTRLREG1 0x20 +#include "i2c.h" +#include "uart.h" -typedef enum { - TWM_INVALID = 0, - TWM_WRITE, - TWM_READ_MULTI, -} twMode; - -typedef enum { - TWST_WAIT = 0, - TWST_OK = 1, - TWST_ERR = 2, -} twStatus; - -typedef struct { - twMode mode; - uint8_t address; - uint8_t subaddress; - uint8_t data; - uint8_t step; - /* read data store */ - uint8_t *retData; - /* number of bytes to be read */ - uint8_t count; - /* current byte */ - uint8_t i; - twStatus status; -} twReq; - -volatile twReq twr; - -void twStartRaw () { - /* disable stop, enable interrupt, reset twint, enable start, enable i2c */ - TWCR = (TWCR & ~(1 << TWSTO)) | (1 << TWIE) | (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); -} - -void twStopRaw () { - /* disable start, enable interrupt, reset twint, enable stop, enable i2c */ - TWCR = (TWCR & ~(1 << TWSTA)) | (1 << TWIE) | (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); -} - -void twFlushRaw () { - /* disable start/stop, enable interrupt, reset twint, enable i2c */ - TWCR = (TWCR & ~((1 << TWSTA) | (1 << TWSTO) | (1 << TWEA))) | (1 << TWIE) | (1 << TWINT) | (1 << TWEN); -} - -/* flush and send master ack */ -void twFlushContRaw () { - /* disable start/stop, enable interrupt, reset twint, enable i2c, send master ack */ - TWCR = (TWCR & ~((1 << TWSTA) | (1 << TWSTO))) | (1 << TWIE) | (1 << TWINT) | (1 << TWEN) | (1 << TWEA); -} - -void twWaitRaw () { - while (!(TWCR & (1 << TWINT))); -} - -bool twWriteRaw (uint8_t data) { - TWDR = data; - if (TWCR & (1 << TWWC)) { - printf("write collision\n"); - return false; - } else { - return true; - } -} - -void twInit () { - /* set scl to 3.6 kHz (at 1Mhz CPU speed)*/ - TWBR = 2; - TWSR |= 0x3; /* set prescaler to 64 */ - - twr.mode = TWM_INVALID; - twr.status = TWST_ERR; -} - -/* high-level write - */ -static bool twWrite (uint8_t address, uint8_t subaddress, uint8_t data) { - /* do not start if request is pending */ - if (twr.status == TWST_WAIT) { - return false; - } - - twr.mode = TWM_WRITE; - twr.address = address; - twr.subaddress = subaddress; - twr.data = data; - twr.step = 0; - twr.status = TWST_WAIT; - /* wait for stop finish */ - while (TW_STATUS != 0xf8); - twStartRaw (); - - return true; -} - -static bool twReadMulti (uint8_t address, uint8_t subaddress, - uint8_t *retData, uint8_t count) { - /* do not start if request is pending */ - if (twr.status == TWST_WAIT) { - return false; - } - - twr.mode = TWM_READ_MULTI; - twr.address = address; - twr.subaddress = subaddress; - twr.retData = retData; - twr.count = count; - twr.i = 0; - twr.step = 0; - twr.status = TWST_WAIT; - /* wait for stop finish */ - while (TW_STATUS != 0xf8); - twStartRaw (); - - return true; -} - -void ledInit () { +static void ledInit () { /* set led1,led2 to output */ DDRB |= (1 << PB6) | (1 << PB7); /* set led3,led4,led5,led6 to output */ @@ -141,208 +19,18 @@ void ledInit () { } /* show data with leds */ -void ledShow (unsigned char val) { +static void ledShow (const unsigned char val) { PORTB = (PORTB & ~((1 << PB6) | (1 << PB7))) | ((val & 0x3) << PB6); PORTD = (PORTD & ~((1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5))) | (((val >> 2) & 0xf) << PD2); } -void uartInit () { - /* Set baud rate (9600, double speed, at 1mhz) */ - UBRR0H = 0; - UBRR0L = 12; - /* enable double speed mode */ - UCSR0A = (1 << U2X0); - /* Enable receiver and transmitter */ - UCSR0B = (1< +#include + +#include "uart.h" + +/* blocking uart send + */ +static void uartSend (unsigned char data) { + /* Wait for empty transmit buffer */ + while (!( UCSR0A & (1<