Mercurial > templog
diff bma180.c @ 111:cdb26addf4f2 tilt
Add bma180 code, untested
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 19 Sep 2012 22:40:49 +0800 |
parents | |
children | 5234ccc416e8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/bma180.c Wed Sep 19 22:40:49 2012 +0800 @@ -0,0 +1,146 @@ +#include <avr/io.h> +#include <util/delay.h> + +#include "bma180.h" +#include "bma180_internal.h" + +static void +bma180_init_SPI(void) +{ + //make SPI master + //SCL idle high, sample data on rising edge + //Fosc/4 is SPI frequency + //enable SPI + SPCR = _BV(MSTR) | _BV(SPE) | _BV(CPHA) | _BV(CPOL); +} + +static char +bma180_rxdata(void) +{ + //while((SPSR&0x80) == 0x80); + SPDR = 0x55; + while((SPSR&0x80) == 0x00); + + return SPDR; +} + +static void +bma180_txdata(char data) +{ + //while((SPSR&0x80) == 0x80); + SPDR = data; + while((SPSR&0x80) == 0x00); +} + +static void +bma180_write(uint8_t address, char data) +{ + //write any data byte to any single address + //adds a 0 to the MSB of the address byte (WRITE mode) + + address &= 0x7F; + + //printf("\nWriting 0x%x to 0x%x\n", data, address); + + BMA180_CS_PORT &= ~_BV(BMA180_CS_PIN); + _delay_ms(1); + bma180_txdata(address); + _delay_ms(1); + bma180_txdata(data); + _delay_ms(1); + BMA180_CS_PORT |= _BV(BMA180_CS_PIN); +} + +static char +bma180_read(uint8_t address) +{ + //returns the contents of any 1 byte register from any address + //sets the MSB for every address byte (READ mode) + + char byte; + + address |= 0x80; + + BMA180_CS_PORT &= ~_BV(BMA180_CS_PIN); + bma180_txdata(address); + byte = bma180_rxdata(); + BMA180_CS_PORT |= _BV(BMA180_CS_PIN); + + return byte; +} + +static int +bma180_set_config(uint8_t range, uint8_t bw) +{ + char temp, temp1; + + // if connected correctly, ID register should be 3 + if(bma180_read(ID) != 3) + return -1; + + + // Set ee_w bit + temp = bma180_read(CTRLREG0); + temp |= 0x10; + bma180_write(CTRLREG0, temp); // Have to set ee_w to write any other registers + + // Set BW + temp = bma180_read(BWTCS); + temp1 = bw; + temp1 = temp1<<4; + temp &= (~BWMASK); + temp |= temp1; + bma180_write(BWTCS, temp); // Keep tcs<3:0> in BWTCS, but write new BW + + // Set Range + temp = bma180_read(OLSB1); + temp1 = range; + temp1 = (temp1<<RANGESHIFT); + temp &= (~RANGEMASK); + temp |= temp1; + bma180_write(OLSB1, temp); //Write new range data, keep other bits the same + + return 0; +} + +void +bma180_init(uint8_t range, uint8_t bw) +{ + bma180_init_SPI(); + + // CS output + // XXX checkme, sample code has the opposite? + BMA180_CS_DDR |= _BV(BMA180_CS_PIN); + + bma180_set_config(range, bw); + +} + +static uint16_t +bma_get_reading_n(uint8_t reg_lsb, uint8_t reg_msb) +{ + uint16_t ret; + uint8_t val = 0; + while (val != 1) + { + val = bma180_read(reg_lsb) & 0x01; + } + val = bma180_read(reg_msb); + ret = val << 8; + + val = bma180_read(reg_lsb); + ret |= val; + // low bits aren't the reading + ret >>= 2; + return ret; +} + +void +bma180_get_reading(uint16_t *x, uint16_t *y, uint16_t *z, uint8_t *temperature) +{ + *x = bma_get_reading_n(ACCXLSB, ACCXMSB); + *y = bma_get_reading_n(ACCYLSB, ACCYMSB); + *z = bma_get_reading_n(ACCZLSB, ACCZMSB); + + *temperature = bma180_read(TEMPERATURE); +}