diff --git a/Makefile b/Makefile index a0a0c4f..8fabffa 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ AVD := avrdude MKDIR := mkdir -p RMR := rm -rf -CPPFLAGS := -DF_CPU=$(FREQ) +CPPFLAGS := -DF_CPU=$(FREQ) -I$(SRCDIR) CFLAGS := -mmcu=$(MCU) -Os -std=c99 -Wall -Wextra -Werror OCFLAGS := -j .text -j .data -O ihex LDFLAGS := -mmcu=$(MCU) diff --git a/docs/PCA9546.pdf b/docs/PCA9546.pdf new file mode 100755 index 0000000..73e84af Binary files /dev/null and b/docs/PCA9546.pdf differ diff --git a/opt/tools b/opt/tools index 53be5b3..19702a0 160000 --- a/opt/tools +++ b/opt/tools @@ -1 +1 @@ -Subproject commit 53be5b36f3828e7a7e180bba9f7935ff91f06bf2 +Subproject commit 19702a0bb547d6d43f3e88a9cd601e121148fb3c diff --git a/src/bus/twi.c b/src/bus/twi.c new file mode 100644 index 0000000..3ddee18 --- /dev/null +++ b/src/bus/twi.c @@ -0,0 +1,12 @@ +#include "bus/twi.h" +#include + +int TWI_Init(void) +{ + // Set SCL bit rate to 400kHz + + TWSR = 0x00; // TWI status register + TWBR = 0x0C; // TWI bit rate register + + return 0; +} diff --git a/src/bus/twi.h b/src/bus/twi.h new file mode 100644 index 0000000..f41bc18 --- /dev/null +++ b/src/bus/twi.h @@ -0,0 +1,6 @@ +#ifndef MAD_CORE_BUS_TWI_H +#define MAD_CORE_BUS_TWI_H + +int TWI_Init(void); + +#endif // MAD_CORE_BUS_TWI_H diff --git a/src/bus/usart.c b/src/bus/usart.c new file mode 100644 index 0000000..a5a88c0 --- /dev/null +++ b/src/bus/usart.c @@ -0,0 +1,93 @@ +#include "common.h" +#include "bus/usart.h" +#include +#include +//#include + +#define USART_BAUDRATE 9600 +#define USART_RXBUF_SIZE 512 +#define USART_TXBUF_SIZE 512 + +#define USART_RXBUF_MASK (USART_RXBUF_SIZE - 1) +#define USART_TXBUF_MASK (USART_TXBUF_SIZE - 1) +#define USART_BAUD_PRESCALE ((((F_CPU / 16) + \ + (USART_BAUDRATE / 2)) / (USART_BAUDRATE)) - 1) + +static volatile char rxbuf[USART_RXBUF_SIZE]; // RX ring buffer +static volatile char txbuf[USART_TXBUF_SIZE]; // TX ring buffer +static volatile short rxhead, txhead; // Current write position +static volatile short rxtail, txtail; // Current read position + +int USART_Init(void) +{ + rxhead = 0; + rxtail = 0; + txhead = 0; + txtail = 0; + + UCSRB = BIT(RXCIE); // Handle RXC interrupts + UCSRB |= BIT(RXEN) | BIT(TXEN); // Enable RX and TX circuitry + UCSRC = BIT(URSEL) | BIT(UCSZ0) | BIT(UCSZ1); // Using 8-bit chars + UBRRH = (USART_BAUD_PRESCALE >> 8); // Set baud rate upper byte + UBRRL = USART_BAUD_PRESCALE; // Set baud rate lower byte + + return 0; +} + +char USART_Getc(void) +{ + if (rxhead == rxtail) { + return -1; + } + + rxtail = (rxtail + 1) & USART_RXBUF_MASK; + return rxbuf[rxtail]; +} + +void USART_Putc(char ch) +{ + short head; + + head = (txhead + 1) & USART_TXBUF_MASK; + while (head == txtail); // Wait for space + + txbuf[head] = ch; + txhead = head; + + // Enable interrupt + UCSRB |= BIT(UDRIE); +} + +// INT: Rx complete +ISR(USART_RXC_vect) +{ + short head; + + // Next byte ready to read from serial + head = (rxhead + 1) & USART_RXBUF_MASK; + // Free space in RX buffer? + if (head != rxtail) { + // Copy from register + rxbuf[head] = UDR; + rxhead = head; + } else { + // XXX: Discard overflow + } +} + +// INT: Data register empty +ISR(USART_UDRE_vect) +{ + short tail; + + // Anything in TX buffer? + if (txhead != txtail) { + // Write next byte to data register + tail = (txtail + 1) & USART_TXBUF_MASK; + UDR = txbuf[tail]; + txtail = tail; + } else { + // Disable interrupt + UCSRB &= ~BIT(UDRIE); + } +} diff --git a/src/bus/usart.h b/src/bus/usart.h new file mode 100644 index 0000000..7b1d879 --- /dev/null +++ b/src/bus/usart.h @@ -0,0 +1,8 @@ +#ifndef MAD_CORE_BUS_USART_H +#define MAD_CORE_BUS_USART_H + +int USART_Init(void); +void USART_Putc(char ch); +char USART_Getc(void); + +#endif // MAD_CORE_BUS_USART_H diff --git a/src/common.c b/src/common.c deleted file mode 100644 index d32313f..0000000 --- a/src/common.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "common.h" -#include "serial.h" - -#define PREFIX_ERROR(fmt) "Error:" fmt - -static bool state; - -void Info(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - USART_Print(state, "", fmt, args); - va_end(args); -} - -void Error(const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - USART_Print(state, "Error: ", fmt, args); - va_end(args); -} - -void SetStateFlag(bool is_running) -{ - state = is_running; -} diff --git a/src/common.h b/src/common.h index 9a26b73..c190a6a 100644 --- a/src/common.h +++ b/src/common.h @@ -1,23 +1,12 @@ -#ifndef MAD_COMMON_H -#define MAD_COMMON_H +#ifndef MAD_CORE_COMMON_H +#define MAD_CORE_COMMON_H + +#include #define BIT(n) (0x1U << (n)) #define UNUSED(s) (void)(s) -#include -#include -#include - -#include -#define Sleep(ms) _delay_ms(ms) - void Info(const char *fmt, ...); void Error(const char *fmt, ...); -void SetStateFlag(bool is_running); -void Enable(void); -void Disable(void); -void SetTemp(long val); -void SetDewp(long val); - -#endif // MAD_COMMON_H +#endif // MAD_CORE_COMMON_H diff --git a/src/common/common.c b/src/common/common.c new file mode 100644 index 0000000..1e2cfaa --- /dev/null +++ b/src/common/common.c @@ -0,0 +1,24 @@ +#include "common.h" +#include "bus/usart.h" +#include + +static void Puts(const char *str) +{ + while (*str) { + USART_Putc(*str++); + } +} + +void Info(const char *fmt, ...) +{ + va_list ap; + char msg[256]; + + va_start(ap, fmt); + vsnprintf(msg, sizeof(msg), fmt, ap); + va_end(ap); + + Puts("[CORE] "); + Puts(msg); + Puts("\r\n"); +} diff --git a/src/main.c b/src/main.c index f03070a..7c1f3e4 100644 --- a/src/main.c +++ b/src/main.c @@ -1,78 +1,28 @@ #include "common.h" -#include "serial.h" -#include "parser.h" +#include "bus/usart.h" +#include "bus/twi.h" -bool running; +#include +#include +#define Sleep(ms) _delay_ms(ms) -int main(void) +int main(int argc, char **argv) { - char ch; - unsigned long i = 1; - USART_Init(); - Enable(); + TWI_Init(); - for (;;) { - // Process rx ring buffer - while ((ch = USART_GetChar())) { - CMD_Parse(ch); - } + sei(); - Sleep(3000); - if (running) { - // TODO: Main program - if (i >= 99999) i = 1; - Info("Fetching sensors #%05lu...", i++); - } - } + Info("Initializing..."); + Sleep(500); + + // ADS1115 (ADC) + // PCA9546 (Multiplexer TWI) + // ATH20 (3x) + // BMP280 (3x) + + UNUSED(argc); + UNUSED(argv); return 0; } - -void Enable(void) -{ - Info("Parsed 'CMD_RUN' token."); - if (running == true) { - Error("Already running."); - return; - } - running = true; - SetStateFlag(running); - Info("Program started."); -} - -void Disable(void) -{ - Info("Parsed 'CMD_STOP' token."); - if (running == false) { - Error("Already stopped."); - return; - } - running = false; - SetStateFlag(running); - Info("Program stopped."); -} - -void SetTemp(long val) -{ - Info("Parsed 'CMD_SET_TEMP', VAL='%ld'.", val); - if (val < 10) { - Error("Given temperature is too low."); - return; - } else if (val > 40) { - Error("Given temperature is too high."); - return; - } -} - -void SetDewp(long val) -{ - Info("Parsed 'CMD_SET_DEWP', VAL='%ld'.", val); - if (val < 10) { - Error("Given dew point is too low."); - return; - } else if (val > 80) { - Error("Given dew point is too high."); - return; - } -} diff --git a/src/parser.c b/src/parser.c deleted file mode 100644 index 24bcc35..0000000 --- a/src/parser.c +++ /dev/null @@ -1,217 +0,0 @@ -#include "common.h" -#include "serial.h" -#include "parser.h" - -/* - * # Supported Commands - * - * - RUN - * - STOP - * - TEMP - * - DEWP - */ - -static int state; -static char numbuf[8]; -static size_t numlen; - -#define PARSE_IDLE 0 -#define PARSE_CMD_RUN 1 -#define PARSE_CMD_STOP 2 -#define PARSE_CMD_SET_TEMP 3 -#define PARSE_CMD_SET_DEWP 4 - -void CMD_Parse(char ch) -{ - long num; - - #if 0 - switch (state) { - case PARSE_IDLE: - if (ch == 'R') - state = PARSE_CMD_RUN; - else if (ch == 'S') - state = PARSE_CMD_STOP; - else if (ch == 'T') - state = PARSE_CMD_SET_TEMP; - else if (ch == 'D') - state = PARSE_CMD_SET_DEWP; - } - break; - case PARSE_CMD_RUN: - break; - case PARSE_CMD_STOP: - break; - case PARSE_CMD_SET_TEMP: - break; - case PARSE_CMD_SET_DEWP: - break; - } - #endif - - // Placeholder - switch (state) { - case 0: - if (ch == 'T') // TEMP - state = 1; - if (ch == 'D') // DEWP - state = 6; - if (ch == 'R') // RUN - state = 11; - if (ch == 'S') // STOP - state = 14; - break; - - // Parse 'TEMP' - case 1: - if (ch == 'E') - state = 2; - else - state = 0; - break; - case 2: - if (ch == 'M') - state = 3; - else - state = 0; - break; - case 3: - if (ch == 'P') - state = 4; - else - state = 0; - break; - case 4: - if (ch == ' ') { - numlen = 0; - state = 5; - } else { - state = 0; - } - break; - case 5: - // Error: Number too long - if (numlen >= sizeof(numbuf) - 1) { - state = 0; - } - - // Parse numeric string - else if ((ch >= '0' && ch <= '9') || (!numlen && ch == '-')) { - numbuf[numlen++] = ch; - } - - // Parse terminator and strip decimal - else if (ch == '\n' || ch == '.' || ch == ',') { - numbuf[numlen] = '\0'; - num = strtol(numbuf, NULL, 10); - SetTemp(num); - state = 0; - } - - // Unexpected character - else { - Error("Unexpected character '%c'.", ch); - state = 0; - } - break; - - // Parse 'DEWP' - case 6: - if (ch == 'E') - state = 7; - else - state = 0; - break; - case 7: - if (ch == 'W') - state = 8; - else - state = 0; - break; - case 8: - if (ch == 'P') - state = 9; - else - state = 0; - break; - case 9: - if (ch == ' ') { - numlen = 0; - state = 10; - } else { - state = 0; - } - break; - case 10: - // Error: Number too long - if (numlen >= sizeof(numbuf) - 1) { - state = 0; - } - - // Parse numeric string - else if ((ch >= '0' && ch <= '9') || (!numlen && ch == '-')) { - numbuf[numlen++] = ch; - } - - // Parse terminator and strip decimal - else if (ch == '\n' || ch == '.' || ch == ',') { - numbuf[numlen] = '\0'; - num = strtol(numbuf, NULL, 10); - SetDewp(num); - state = 0; - } - - // Unexpected character - else { - Error("Unexpected character '%c'.", ch); - state = 0; - } - break; - - // Parse 'RUN' - case 11: - if (ch == 'U') - state = 12; - else - state = 0; - break; - case 12: - if (ch == 'N') - state = 13; - else - state = 0; - break; - case 13: - if (ch == '\n') { - Enable(); - } - state = 0; - break; - - // Parse 'STOP' - case 14: - if (ch == 'T') - state = 15; - else - state = 0; - break; - case 15: - if (ch == 'O') - state = 16; - else - state = 0; - break; - case 16: - if (ch == 'P') - state = 17; - else - state = 0; - break; - case 17: - if (ch == '\n') { - Disable(); - } - state = 0; - break; - } -} diff --git a/src/parser.h b/src/parser.h deleted file mode 100644 index ee28894..0000000 --- a/src/parser.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef MAD_PARSER_H -#define MAD_PARSER_H - -void CMD_Parse(char ch); - -#endif // MAD_PARSER_H diff --git a/src/serial.c b/src/serial.c deleted file mode 100644 index 4c46a9b..0000000 --- a/src/serial.c +++ /dev/null @@ -1,89 +0,0 @@ -#include "common.h" -#include "serial.h" - -#include -#include -#include - -#define USART_BUFSIZE 512 -#define USART_BAUDRATE 9600 -#define USART_RXBUF_MASK (USART_BUFSIZE - 1) -#define USART_BAUD_PRESCALE ((((F_CPU / 16) + \ - (USART_BAUDRATE / 2)) / (USART_BAUDRATE)) - 1) - -// TODO: TX ring buffer -static unsigned char rxbuf[USART_BUFSIZE]; -static unsigned char rxhead, rxtail; - -void USART_Init(void) -{ - rxhead = 0; - rxtail = 0; - - // Handle RXC interrupt - UCSRB |= (1 << RXCIE); - sei(); - - UCSRB |= BIT(RXEN) | BIT(TXEN); // Enable rx and tx circuitry - UCSRC |= BIT(URSEL) | BIT(UCSZ0) | BIT(UCSZ1); // 8-bit chars - UBRRH = (USART_BAUD_PRESCALE >> 8); // Baud Rate upper byte - UBRRL = USART_BAUD_PRESCALE; // Baud rate lower byte -} - -bool USART_IsDataAvailable(void) -{ - return rxhead != rxtail; -} - -char USART_GetChar(void) -{ - unsigned char newtail; - - if (!USART_IsDataAvailable()) { - return '\0'; // Non-blocking - } - - newtail = (rxtail + 1) & USART_RXBUF_MASK; - rxtail = newtail; - - return rxbuf[newtail]; -} - -void USART_PutChar(const char ch) -{ - // Wait until UDR can receive data - while ((UCSRA & BIT(UDRE)) == 0); - UDR = ch; -} - -void USART_Print(bool state, const char *pre, const char *fmt, va_list ap) -{ - int len; - char buf[256], *ptr; - - UNUSED(state); - len = sprintf(buf, "[CORE] %s", pre); //, state ? 'E' : 'D', pre); - vsnprintf(buf + len, sizeof(buf) - len, fmt, ap); - - ptr = buf; - while (*ptr != '\0') { - USART_PutChar(*ptr++); - } - - USART_PutChar('\r'); - USART_PutChar('\n'); -} - -// Interrupt Handler -ISR(USART_RXC_vect) -{ - unsigned char newhead; - - newhead = (rxhead + 1) & USART_RXBUF_MASK; - if (newhead == rxtail) { - // TODO: Handle overflow - } else { - rxhead = newhead; - rxbuf[newhead] = UDR; - } -} diff --git a/src/serial.h b/src/serial.h deleted file mode 100644 index 3a4c2b2..0000000 --- a/src/serial.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef MAD_SERIAL_H -#define MAD_SERIAL_H - -#include -#include - -void USART_Init(void); -char USART_GetChar(void); -void USART_PutChar(const char ch); -bool USART_IsDataAvailable(void); -void USART_Print(bool state, const char *pre, const char *fmt, va_list ap); - -#endif // MAD_SERIAL_H diff --git a/src/twibus.c b/src/twibus.c deleted file mode 100644 index e69de29..0000000 diff --git a/src/twibus.h b/src/twibus.h deleted file mode 100644 index e69de29..0000000