X-Git-Url: https://git.karo-electronics.de/?p=oswald.git;a=blobdiff_plain;f=metawatch%2Fmw_acc.c;h=9c4b0f56572efde16f7adc2bbc26d0cf78f0715f;hp=270f2467304894237492941ebf905ce38960adc7;hb=133faed023f55592a87ee1b8dbc74bc4a8917006;hpb=a9be019ac653badc27a55c94b8d50122eadf8c5f diff --git a/metawatch/mw_acc.c b/metawatch/mw_acc.c index 270f246..9c4b0f5 100644 --- a/metawatch/mw_acc.c +++ b/metawatch/mw_acc.c @@ -1,12 +1,87 @@ #include #include #include +#include #include "mw_main.h" +#include "mw_uart.h" #include "mw_acc.h" -void mw_init_acc_i2c(void) +#include "oswald_main.h" + +#define ACCEL_STATE_DISABLED 0x00 +#define ACCEL_STATE_ENABLED 0x01 + +static uint8_t AccelState; +static uint8_t AccelerometerBusy; +static uint8_t LengthCount; +static uint8_t Index; +static uint8_t *pAccelerometerData; + +/* + * Accelerometer is a Kionix KXTF9-4100 connected to I2C + * I2C is pretty slow so reading and writing should be done non blocking + * using interrupts. + */ + +#define ACCELEROMETER_NO_INTERRUPTS 0x00 +#define ACCELEROMETER_ALIFG 0x02 +#define ACCELEROMETER_NACKIFG 0x04 +#define ACCELEROMETER_STTIFG 0x06 +#define ACCELEROMETER_STPIFG 0x08 +#define ACCELEROMETER_RXIFG 0x0a +#define ACCELEROMETER_TXIFG 0x0c + +#pragma vector=USCI_B1_VECTOR +__interrupt void ACCERLEROMETER_I2C_ISR(void) +{ + // debug_uart_tx("ACC i2c irq\n"); + switch (USCI_ACCELEROMETER_IV) { + case ACCELEROMETER_NO_INTERRUPTS: + break; + case ACCELEROMETER_ALIFG: + break; + case ACCELEROMETER_NACKIFG: + nop(); + break; + case ACCELEROMETER_STTIFG: + nop(); + break; + case ACCELEROMETER_STPIFG: + break; + case ACCELEROMETER_RXIFG: + if (LengthCount > 0) { + pAccelerometerData[Index++] = ACCELEROMETER_RXBUF; + LengthCount--; + if ( LengthCount == 1 ) { + /* All but one byte received. Send stop */ + ACCELEROMETER_CTL1 |= UCTXSTP; + } else if ( LengthCount == 0 ) { + /* Last byte received; disable rx interrupt */ + ACCELEROMETER_IE &= ~UCRXIE; + AccelerometerBusy = 0; + } + } + break; + case ACCELEROMETER_TXIFG: + if ( LengthCount > 0 ) { + ACCELEROMETER_TXBUF = pAccelerometerData[Index++]; + LengthCount--; + } else { + /* disable transmit interrupt and send stop */ + ACCELEROMETER_IE &= ~UCTXIE; + ACCELEROMETER_CTL1 |= UCTXSTP; + AccelerometerBusy = 0; + } + break; + default: + break; + } + +} + +void mw_acc_init_i2c(void) { /* enable reset before configuration */ ACCELEROMETER_CTL1 |= UCSWRST; @@ -23,49 +98,307 @@ void mw_init_acc_i2c(void) ACCELEROMETER_CTL1 &= ~UCSWRST; } -/* - * DMA2 = SPI for LCD - */ -static void mw_acc_i2c_write_byte(uint8_t byte) +void mw_acc_disable_i2c(void) { - ACCELEROMETER_TXBUF = byte; - while ((ACCELEROMETER_CTL1 & ACCELEROMETER_IFG) == 0) - nop(); + /* enable reset to hold it */ + ACCELEROMETER_CTL1 |= UCSWRST; } -/* OK this is polling write, but data is small and 400kHz I2C, it should "just work" :) */ -void mw_acc_i2c_write(const uint8_t addr, const void *data, const uint8_t len) +void mw_acc_i2c_write(uint8_t RegisterAddress, uint8_t *pData, uint8_t Length) { - int i; - - if (len == 0) { + if (Length == 0 || pData == 0) return; - } while (UCB1STAT & UCBBUSY) nop(); + AccelerometerBusy = 1; + LengthCount = Length; + Index = 0; + pAccelerometerData = pData; + /* + * enable transmit interrupt and * setup for write and send the start condition */ ACCELEROMETER_IFG = 0; ACCELEROMETER_CTL1 |= UCTR + UCTXSTT; - while (!(ACCELEROMETER_IFG & UCTXIFG)) + while(!(ACCELEROMETER_IFG & UCTXIFG)) nop(); /* - * clear transmit interrupt flag, + * clear transmit interrupt flag, enable interrupt, * send the register address */ ACCELEROMETER_IFG = 0; + ACCELEROMETER_IE |= UCTXIE; + ACCELEROMETER_TXBUF = RegisterAddress; - mw_acc_i2c_write_byte(addr); + while (AccelerometerBusy) + nop(); + + while (ACCELEROMETER_CTL1 & UCTXSTP) + nop(); - for (i=0; i