Refactored for SPI integration, debugged until I2C is working again.

SPI
Philipp Klaus 11 years ago
parent 59bacd2b5a
commit c4ef15134f

@ -3,7 +3,10 @@
#include <TinyWireS.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <util/delay.h>
// Debug Mode
//#define DBGME
@ -31,9 +34,25 @@
#define CONTRAST_PIN 2
#define BACKLIGHT_PIN 3
#define SPI_SS 10
#define EEBASE_ADDR 24
extern void usiTwiSlaveOvlHandler(); // from usiTwiSlave.c
// SPI RX buffer
#define USI_SPI_RX_BUFFER_SIZE ( 32 )
#define USI_SPI_RX_BUFFER_MASK ( USI_SPI_RX_BUFFER_SIZE - 1 )
#if ( USI_SPI_RX_BUFFER_SIZE & USI_SPI_RX_BUFFER_MASK )
# error USI SPI RX buffer size is not a power of 2
#endif
uint8_t spiRxHead = 0;
uint8_t spiRxTail = 0;
uint8_t spiRxBuf[USI_SPI_RX_BUFFER_SIZE];
uint8_t spiRxEndBlock = 0;
// Timeout in us after which we close the buffer and write it out
#define CHARBUF_TIMEOUT 150
@ -52,6 +71,7 @@ unsigned int buf_ix = 0;
unsigned long lastwrite = 0;
// more data expected
volatile byte data_expected = 0;
volatile byte interface_mode = 0; // I2C
// initialize the library with the numbers of the interface pins
@ -63,34 +83,111 @@ LiquidCrystal lcd(3, 1, 9, 8, 7, 5);
uint8_t slave_address;
void setup() {
slave_address = read_address();
if (! slave_address) {
slave_address = I2C_SLAVE_ADDRESS;
}
TinyWireS.begin(slave_address);
TinyWireS.onReceive(receive_event);
//TinyWireS.onRequest(requestEvent);
slave_address = read_address();
if (! slave_address) {
slave_address = I2C_SLAVE_ADDRESS;
}
TinyWireS.begin(slave_address);
TinyWireS.onReceive(receive_event);
//TinyWireS.onRequest(requestEvent);
analogWrite(CONTRAST_PIN, 10);
analogWrite(BACKLIGHT_PIN, 255);
lcd.begin(16,2);
lcd.clear();
//test_lcd();
analogWrite(CONTRAST_PIN, 10);
analogWrite(BACKLIGHT_PIN, 255);
lcd.begin(16,2);
lcd.clear();
// check SPI status
pinMode(SPI_SS, INPUT);
if (digitalRead(SPI_SS) == HIGH) {
interface_mode = 1; // SPI
init_spi();
#ifdef DBGME
lcd.setCursor(0,0);
lcd.print("Init 10 HIGH");
#endif
}
// enable pin change interrupt
PCMSK0 = _BV(PCINT0);
GIMSK = _BV(PCIE0);
//test_lcd();
}
uint32_t last = 0;
uint32_t count = 0;
void loop() {
TinyWireS_stop_check();
#ifdef DBGME
if (millis() - last >= 1000) {
last = millis();
lcd.setCursor(8,1);
lcd.print(count++);
}
#endif
if (interface_mode) {
if (spiRxEndBlock) {
spiRxEndBlock = 0;
receive_event(available());
}
} else {
TinyWireS_stop_check();
}
}
void init_spi() {
#ifdef DBGME
lcd.setCursor(0,0);
lcd.print("INIT SPI");
#endif
pinMode(4, INPUT); // DI
pinMode(6, INPUT_PULLUP); // USCK
}
// not used yet:
void request_event()
{
TinyWireS.send(i2c_regs[reg_position]);
// Increment the reg position on each read, and loop back to zero
reg_position = (reg_position+1) % sizeof(i2c_regs);
lcd.setCursor(3, 1);
lcd.print("=");
uint8_t spi_transfer(uint8_t data) {
USICR = _BV(USIWM0) | _BV(USICS1); // setup SPI mode 0, external clock
USIDR = data;
USISR = _BV(USIOIF); // clear flag and counter value
while ( (USISR & _BV(USIOIF)) == 0 );
USICR = 0; // reset SPI hardware, allowing DO to be used for LCD
return USIDR;
}
void spi_buffer_write(uint8_t data) {
spiRxHead = ( spiRxHead + 1 ) & USI_SPI_RX_BUFFER_MASK;
// check buffer size
if (spiRxHead == spiRxTail) {
// overrun
spiRxHead = (spiRxHead + USI_SPI_RX_BUFFER_SIZE - 1) & USI_SPI_RX_BUFFER_MASK;
} else {
spiRxBuf[ spiRxHead ] = data;
}
}
uint8_t spi_buffer_read() {
// wait for Rx data
while ( spiRxHead == spiRxTail );
// calculate buffer index
spiRxTail = ( spiRxTail + 1 ) & USI_SPI_RX_BUFFER_MASK;
// return data from the buffer.
return spiRxBuf[ spiRxTail ];
}
ISR(PCINT0_vect) {
if (interface_mode) {
if (digitalRead(10) == HIGH) {
// finished reading bytes, set flag and stop interrupt
spiRxEndBlock = 1;
USICR &= ~ _BV(USIOIE);
} else {
// SS activated, start receiving and activate interrupt
USICR |= _BV(USIOIE);
}
} else {
if (digitalRead(10) == HIGH) {
interface_mode = 1;
init_spi();
}
}
}
void receive_event(uint8_t howMany) {
@ -100,10 +197,10 @@ void receive_event(uint8_t howMany) {
return;
}
while (TinyWireS.available()) {
char cmd = TinyWireS.receive();
char cmd = read_byte();
// wait for a command
if ( cmd == 0 && howMany > 1 ) {
char rxbuffer = TinyWireS.receive();
char rxbuffer = read_byte();
command_byte(rxbuffer, howMany - 2);
} else if ( cmd > 1 ) {
lcd.print(cmd);
@ -113,12 +210,16 @@ void receive_event(uint8_t howMany) {
void command_byte(char c, byte bytesInBuffer) {
uint8_t col, row, addr, val;
#ifdef DBGME
lcd.setCursor(0,0);
lcd.print("Got command");
#endif
if (c & 0xC0 == LCD_SETCGRAMADDR) {
// construct character
uint8_t cdata[8];
uint8_t i;
for (i = 0; i < 8; i++) {
cdata[i] = TinyWireS.receive();
cdata[i] = read_byte();
}
lcd.createChar((c & 0x38) >> 3, cdata);
} else if (c & 0xF8 == LCD_DISPLAYCONTROL || c & 0xF0 == LCD_CURSORSHIFT || c & 0xFC == LCD_ENTRYMODESET) {
@ -138,28 +239,28 @@ void command_byte(char c, byte bytesInBuffer) {
analogWrite(BACKLIGHT_PIN, 0);
break;
case LCD_SETBACKLIGHT:
val = TinyWireS.receive();
val = read_byte();
analogWrite(BACKLIGHT_PIN, val);
break;
case LCD_SETCONTRAST:
val = TinyWireS.receive();
val = read_byte();
analogWrite(CONTRAST_PIN, val);
break;
case LCD_SETDIMENSION:
col = TinyWireS.receive();
row = TinyWireS.receive();
col = read_byte();
row = read_byte();
lcd_begin(col, row);
break;
case LCD_SETCURSOR:
col = TinyWireS.receive();
row = TinyWireS.receive();
col = read_byte();
row = read_byte();
lcd.setCursor(col, row);
break;
case LCD_SHOWFIRMWAREREVISION:
lcd_revision();
break;
case LCD_SETADDRESS:
addr = TinyWireS.receive();
addr = read_byte();
if (addr && ! (addr & 0x80)) {
write_address(addr);
}
@ -174,6 +275,36 @@ void command_byte(char c, byte bytesInBuffer) {
}
}
uint8_t available() {
if (interface_mode) {
if (spiRxHead == spiRxTail) {
return 0;
}
if (spiRxHead < spiRxTail) {
return ((int8_t)spiRxHead - (int8_t)spiRxTail) + USI_SPI_RX_BUFFER_SIZE;
}
return spiRxHead - spiRxTail;
} else {
return TinyWireS.available();
}
}
uint8_t read_byte() {
if (interface_mode) {
return spi_buffer_read();
} else {
return TinyWireS.receive();
}
}
ISR(USI_OVF_vect) {
if (interface_mode) {
spi_buffer_write(USIDR);
} else {
usiTwiSlaveOvlHandler();
}
}
// start the display, helper for init()
void lcd_begin(uint8_t cols, uint8_t rows) {
lcd.begin(cols,rows);

@ -38,6 +38,9 @@
#include <inttypes.h>
extern "C" {
void usiTwiSlaveOvlHandler();
}
class USI_TWI_S
{

@ -566,7 +566,8 @@ Only disabled when waiting for a new Start Condition.
********************************************************************************/
volatile uint8_t last_unknown_address = 0;
ISR( USI_OVERFLOW_VECTOR )
//ISR( USI_OVERFLOW_VECTOR )
void usiTwiSlaveOvlHandler()
{
switch ( overflowState )

Loading…
Cancel
Save