diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/ao_mpu6000.c | 42 | ||||
| -rw-r--r-- | src/drivers/ao_mr25.c | 172 | ||||
| -rw-r--r-- | src/drivers/ao_sdcard.c | 13 |
3 files changed, 215 insertions, 12 deletions
diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 6d47482c..c65aecbc 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -22,47 +22,71 @@ static uint8_t ao_mpu6000_wake; static uint8_t ao_mpu6000_configured; -static void -ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) -{ - ao_i2c_get(AO_MPU6000_I2C_INDEX); - ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); - ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX, TRUE); - ao_i2c_put(AO_MPU6000_I2C_INDEX); -} +#define ao_mpu6000_spi_get() ao_spi_get_bit(AO_MPU6000_SPI_CS_PORT, \ + AO_MPU6000_SPI_CS_PIN, \ + AO_MPU6000_SPI_CS, \ + AO_MPU6000_SPI_BUS, \ + AO_SPI_SPEED_1MHz) + +#define ao_mpu6000_spi_put() ao_spi_put_bit(AO_MPU6000_SPI_CS_PORT, \ + AO_MPU6000_SPI_CS_PIN, \ + AO_MPU6000_SPI_CS, \ + AO_MPU6000_SPI_BUS) + static void ao_mpu6000_reg_write(uint8_t addr, uint8_t value) { uint8_t d[2] = { addr, value }; +#ifdef AO_MPU6000_I2C_INDEX ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); ao_i2c_send(d, 2, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); +#else + ao_mpu6000_spi_get(); + ao_spi_send(d, 2, AO_MPU6000_SPI_BUS); + ao_mpu6000_spi_put(); +#endif } static void ao_mpu6000_read(uint8_t addr, void *data, uint8_t len) { +#ifdef AO_MPU6000_I2C_INDEX ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); +#else + addr |= 0x80; + ao_mpu6000_spi_get(); + ao_spi_send(&addr, 1, AO_MPU6000_SPI_BUS); + ao_spi_recv(data, len, AO_MPU6000_SPI_BUS); + ao_mpu6000_spi_put(); +#endif } static uint8_t ao_mpu6000_reg_read(uint8_t addr) { uint8_t value; +#ifdef AO_MPU6000_I2C_INDEX ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); ao_i2c_recv(&value, 1, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); +#else + addr |= 0x80; + ao_mpu6000_spi_get(); + ao_spi_send(&addr, 1, AO_MPU6000_SPI_BUS); + ao_spi_recv(&value, 1, AO_MPU6000_SPI_BUS); + ao_mpu6000_spi_put(); +#endif return value; } diff --git a/src/drivers/ao_mr25.c b/src/drivers/ao_mr25.c new file mode 100644 index 00000000..53cbf9d7 --- /dev/null +++ b/src/drivers/ao_mr25.c @@ -0,0 +1,172 @@ +/* + * Copyright © 2010 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__pdata uint16_t ao_storage_unit; + +/* + * MRAM is entirely random access; no erase operations are required, + * nor are reads or writes restricted to a particular alignment. + */ + +#define MR25_WREN 0x06 /* Write Enable */ +#define MR25_WRDI 0x04 /* Write Disable */ +#define MR25_RDSR 0x05 /* Read Status Register */ +#define MR25_WRSR 0x01 /* Write Status Register */ +#define MR25_READ 0x03 /* Read Data Bytes */ +#define MR25_WRITE 0x02 /* Write Data Bytes */ + +/* + * Status register bits + */ + +#define MR25_STATUS_SRWD (1 << 7) /* Status register write disable */ +#define MR25_STATUS_BP_MASK (3 << 2) /* Block protect bits */ +#define MR25_STATUS_BP_SHIFT (2) +#define MR25_STATUS_WEL (1 << 1) /* Write enable latch */ + +static __xdata uint8_t ao_mr25_mutex; + +/* + * This little array is abused to send and receive data. A particular + * caution -- the read and write addresses are written into the last + * three bytes of the array by ao_mr25_set_page_address and then the + * first byte is used by ao_mr25_write_enable, neither of which touch + * those last three bytes. + */ + +static __xdata uint8_t ao_mr25_instruction[4]; + +#define MR25_SELECT() ao_spi_get_mask(AO_MR25_SPI_CS_PORT,(1 << AO_MR25_SPI_CS_PIN),AO_MR25_SPI_BUS, AO_SPI_SPEED_FAST) +#define MR25_DESELECT() ao_spi_put_mask(AO_MR25_SPI_CS_PORT,(1 << AO_MR25_SPI_CS_PIN),AO_MR25_SPI_BUS) + +/* + * Set the write enable latch so that page program and sector + * erase commands will work. Also mark the chip as busy writing + * so that future operations will block until the WIP bit goes off + */ +static void +ao_mr25_write_enable(void) +{ + MR25_SELECT(); + ao_mr25_instruction[0] = MR25_WREN; + ao_spi_send(&ao_mr25_instruction, 1, AO_MR25_SPI_BUS); + MR25_DESELECT(); +} + + +static void +ao_mr25_set_address(uint32_t pos) +{ + ao_mr25_instruction[1] = pos >> 16; + ao_mr25_instruction[2] = pos >> 8; + ao_mr25_instruction[3] = pos; +} + +/* + * Erase the specified sector (no-op for MRAM) + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + return 1; +} + +/* + * Write to flash + */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + ao_mutex_get(&ao_mr25_mutex); + + ao_mr25_set_address(pos); + ao_mr25_write_enable(); + + ao_mr25_instruction[0] = MR25_WRITE; + MR25_SELECT(); + ao_spi_send(ao_mr25_instruction, 4, AO_MR25_SPI_BUS); + ao_spi_send(d, len, AO_MR25_SPI_BUS); + MR25_DESELECT(); + + ao_mutex_put(&ao_mr25_mutex); + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + ao_mutex_get(&ao_mr25_mutex); + + ao_mr25_set_address(pos); + + ao_mr25_instruction[0] = MR25_READ; + MR25_SELECT(); + ao_spi_send(ao_mr25_instruction, 4, AO_MR25_SPI_BUS); + ao_spi_recv(d, len, AO_MR25_SPI_BUS); + MR25_DESELECT(); + + ao_mutex_put(&ao_mr25_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Detected chips 1 size %d\n", ao_storage_total >> 8); +} + +void +ao_storage_device_init(void) +{ + ao_storage_total = 512 * 1024; /* 4Mb */ + ao_storage_block = 256; + ao_storage_config = ao_storage_total - ao_storage_block; + ao_storage_unit = 256; + ao_spi_init_cs (AO_MR25_SPI_CS_PORT, (1 << AO_MR25_SPI_CS_PIN)); +} diff --git a/src/drivers/ao_sdcard.c b/src/drivers/ao_sdcard.c index c13017f0..7806bc19 100644 --- a/src/drivers/ao_sdcard.c +++ b/src/drivers/ao_sdcard.c @@ -18,11 +18,18 @@ #include "ao.h" #include "ao_sdcard.h" +#if HAS_RADIO extern uint8_t ao_radio_mutex; +#define get_radio() ao_mutex_get(&ao_radio_mutex) +#define put_radio() ao_mutex_put(&ao_radio_mutex) +#else +#define get_radio() +#define put_radio() +#endif -#define ao_sdcard_get_slow() do { ao_mutex_get(&ao_radio_mutex); ao_spi_get(AO_SDCARD_SPI_BUS, AO_SPI_SPEED_250kHz); } while (0) -#define ao_sdcard_get() do { ao_mutex_get(&ao_radio_mutex); ao_spi_get(AO_SDCARD_SPI_BUS, AO_SPI_SPEED_FAST); } while (0) -#define ao_sdcard_put() do { ao_spi_put(AO_SDCARD_SPI_BUS); ao_mutex_put(&ao_radio_mutex); } while (0) +#define ao_sdcard_get_slow() do { get_radio(); ao_spi_get(AO_SDCARD_SPI_BUS, AO_SPI_SPEED_250kHz); } while (0) +#define ao_sdcard_get() do { get_radio(); ao_spi_get(AO_SDCARD_SPI_BUS, AO_SPI_SPEED_FAST); } while (0) +#define ao_sdcard_put() do { ao_spi_put(AO_SDCARD_SPI_BUS); put_radio(); } while (0) #define ao_sdcard_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_SDCARD_SPI_BUS) #define ao_sdcard_send(d,l) ao_spi_send((d), (l), AO_SDCARD_SPI_BUS) #define ao_sdcard_recv(d,l) ao_spi_recv((d), (l), AO_SDCARD_SPI_BUS) |
