diff options
| author | Joey Castillo <joeycastillo@utexas.edu> | 2022-02-18 00:05:57 -0500 | 
|---|---|---|
| committer | Joey Castillo <joeycastillo@utexas.edu> | 2022-02-18 00:05:57 -0500 | 
| commit | df2cc7e94f91a15a41c36935875f6f9be42cdabd (patch) | |
| tree | 63add75f7e9435d2a569f173e35eb9957dd73b04 | |
| parent | 0c59c972e7296ac8c23049e713da9350a9af39a5 (diff) | |
| download | Sensor-Watch-df2cc7e94f91a15a41c36935875f6f9be42cdabd.tar.gz Sensor-Watch-df2cc7e94f91a15a41c36935875f6f9be42cdabd.tar.bz2 Sensor-Watch-df2cc7e94f91a15a41c36935875f6f9be42cdabd.zip | |
WIP accelerometer logging to flash
| -rw-r--r-- | apps/accelerometer-test/app.c | 4 | ||||
| -rw-r--r-- | apps/spi-test/app.c | 229 | ||||
| -rw-r--r-- | watch-library/shared/config/hpl_sercom_config.h | 2 | ||||
| -rw-r--r-- | watch-library/shared/driver/spiflash.h | 2 | 
4 files changed, 226 insertions, 11 deletions
| diff --git a/apps/accelerometer-test/app.c b/apps/accelerometer-test/app.c index 1a3acafa..bd4cdaaa 100644 --- a/apps/accelerometer-test/app.c +++ b/apps/accelerometer-test/app.c @@ -28,6 +28,10 @@ static void cb_tick(void) {      bool overrun = lis2dw_read_fifo(&fifo);      printf("FIFO captured %d readings.\n", fifo.count);      if (overrun) printf("\tThere was an overrun!\n\n"); + +    printf("%d, %d, %d\n", fifo.readings[0].x, fifo.readings[0].y, fifo.readings[0].z); +    printf("%d, %d, %d\n", fifo.readings[10].x, fifo.readings[10].y, fifo.readings[10].z); +    printf("%d, %d, %d\n", fifo.readings[20].x, fifo.readings[20].y, fifo.readings[20].z);  }  void app_init(void) { diff --git a/apps/spi-test/app.c b/apps/spi-test/app.c index 428f55d3..c1818200 100644 --- a/apps/spi-test/app.c +++ b/apps/spi-test/app.c @@ -1,10 +1,35 @@  #include <stdio.h> +#include <stdlib.h>  #include <string.h>  #include <peripheral_clk_config.h>  #include "watch.h" +#include "watch_utility.h"  #include "spiflash.h" -// this is a very basic app to confirm that SPI is working, tested with board OSO-MISC-21-017 and a GD25Q16C Flash chip. +#define ACCELEROMETER_TRAINING_RECORD_DELETED ((uint64_t)(0b00)) +#define ACCELEROMETER_TRAINING_RECORD_DATA ((uint64_t)(0b01)) +#define ACCELEROMETER_TRAINING_RECORD_HEADER ((uint64_t)(0b10)) +#define ACCELEROMETER_TRAINING_RECORD_INVALID ((uint64_t)(0b11)) + +typedef union { +    struct { +        int16_t temperature : 16; +        int8_t char1 : 8; +        int8_t char2 : 8; +        int32_t timestamp : 32; +    } header; +    struct { +        int16_t x_accel : 16; +        int16_t y_accel : 16; +        int16_t z_accel : 16; +        int32_t counter : 16; +    } data; +    uint64_t value; +} acceleromter_training_record_t; + +static void cb_alarm_pressed(void) { +    printf("Alarm button was pressed!\n"); +}  static bool wait_for_flash_ready(void) {      watch_set_pin_level(A3, false); @@ -12,14 +37,96 @@ static bool wait_for_flash_ready(void) {      uint8_t read_status_response[1] = {0x00};      do {          ok = spi_flash_read_command(CMD_READ_STATUS, read_status_response, 1); -    } while (ok && (read_status_response[0] & 0x3) != 0); +    } while ((read_status_response[0] & 0x3) != 0); +    delay_ms(10);      watch_set_pin_level(A3, true);      return ok;  } +static void print_records_at_page(uint16_t page) { +    if (page < 477) return; +    acceleromter_training_record_t records[32]; +    static uint32_t timestamp; +    static uint16_t temperature; +    wait_for_flash_ready(); +    spi_flash_read_data(page * 256, (void *)records, 256); +    for(int i = 0; i < 32; i++) { +        switch (records[i].header.temperature >> 14) { +            case ACCELEROMETER_TRAINING_RECORD_DELETED: +                break; +            case ACCELEROMETER_TRAINING_RECORD_DATA: +                printf("%ld,%d,%d,%d,%d\n", timestamp + records[i].data.counter, records[i].data.x_accel, records[i].data.y_accel, records[i].data.z_accel, temperature); +                break; +            case ACCELEROMETER_TRAINING_RECORD_HEADER: +                printf("=== BEGIN %c%c EVENT AT %d ===\n", records[i].header.char1, records[i].header.char2, records[i].header.timestamp); +                printf("timestamp,x_raw,y_raw,z_raw,temperature\n"); +                timestamp = records[i].header.timestamp; +                temperature = records[i].header.temperature & 0x3FFF; +                break; +            case ACCELEROMETER_TRAINING_RECORD_INVALID: +                printf(",,,,\n"); +                break; +        } +    } +} + +static void print_records() { +    printf("printing records\n"); +    uint8_t buf[256]; +    for(int16_t i = 0; i < 4; i++) { +        wait_for_flash_ready(); +        spi_flash_read_data(i * 256, buf, 256); +        for(int16_t j = 0; j < 256; j++) { +            uint8_t pages_written = buf[j]; +            uint8_t start = 0; +            if (i == 0 && j == 0) { +                pages_written <<= 4; +                start = 4; +            } +            for(int k = start; k < 7; k++) { +                if ((pages_written & 0x80) == 0) { +                    print_records_at_page(i * 2048 + j * 8 + k); +                } +                pages_written <<= 1; +            } +        } +    } + +} +  void app_init(void) { -    spi_flash_init();      delay_ms(5000); +    spi_flash_init(); +    watch_register_extwake_callback(BTN_ALARM, cb_alarm_pressed, true); + +    bool erase = false; +    if (erase) { +        printf("Erasing...\n"); +        wait_for_flash_ready(); +        watch_set_pin_level(A3, false); +        spi_flash_command(CMD_ENABLE_WRITE); +        wait_for_flash_ready(); +        watch_set_pin_level(A3, false); +        spi_flash_command(CMD_CHIP_ERASE); +        delay_ms(10000); +    } + +    uint8_t buf[256] = {0xFF}; + +    wait_for_flash_ready(); +    spi_flash_read_data(0, buf, 256); +    printf("byte 0 was %02x\n", buf[0]); +    if (buf[0] & 0xF0) { +        buf[0] = 0x0F; +        printf("setting it to 0x0F\n"); +        wait_for_flash_ready(); +        watch_set_pin_level(A3, false); +        spi_flash_command(CMD_ENABLE_WRITE); +        wait_for_flash_ready(); +        spi_flash_write_data(0, buf, 256); +    } + +    print_records();  }  void app_wake_from_backup(void) { @@ -34,20 +141,122 @@ void app_prepare_for_standby(void) {  void app_wake_from_standby(void) {  } +static int16_t get_next_available_page(void) { +    uint8_t buf[256] = {0}; -bool app_loop(void) { -    uint8_t buf[3] = {0}; -    printf("loop\n"); +    uint16_t page = 0; +    for(int16_t i = 0; i < 4; i++) { +        wait_for_flash_ready(); +        spi_flash_read_data(i * 256, buf, 256); +        for(int16_t j = 0; j < 256; j++) { +            if(buf[j] == 0) { +                page += 8; +            } else { +                page += __builtin_clz(((uint32_t)buf[j]) << 24); +                break; +            } +        } +    } + +    if (page >= 8192) return -1; + +    return page; +} + +static void write_buffer_to_page(uint8_t *buf, uint16_t page) { +    uint32_t address = 256 * page;      wait_for_flash_ready();      watch_set_pin_level(A3, false); -    spi_flash_read_command(CMD_READ_JEDEC_ID, buf, 3); -    printf("ident: %x, %x, %x\n", buf[0], buf[1], buf[2]); +    spi_flash_command(CMD_ENABLE_WRITE); +    wait_for_flash_ready(); +    watch_set_pin_level(A3, false); +    spi_flash_write_data(address, buf, 256); +    wait_for_flash_ready(); -    watch_set_pin_level(A3, true); +    uint8_t buf2[256]; +    watch_set_pin_level(A3, false); +    spi_flash_read_data(address, buf2, 256);      wait_for_flash_ready(); -    delay_ms(10000); +    uint8_t used_pages[256] = {0xFF}; +    uint16_t address_to_mark_used = page / 8; +    uint8_t header_page = address_to_mark_used / 256; +    uint8_t used_byte = 0x7F >> (page % 8); +    uint8_t offset_in_buf = address_to_mark_used % 256; + +    printf("\tWe wrote 256 bytes to address %ld, which was page %d.\n", address, page); + +    for(int i = 0; i < 256; i++) { +        if (buf[i] != buf2[i]) { +            printf("\tData mismatch detected at offset  %d: %d != %d.\n", i, buf[i], buf2[i]); +        } +    } + +    watch_set_pin_level(A3, false); +    spi_flash_read_data(header_page * 256, used_pages, 256); +    used_pages[offset_in_buf] = used_byte; +    watch_set_pin_level(A3, false); +    spi_flash_command(CMD_ENABLE_WRITE); +    wait_for_flash_ready(); +    watch_set_pin_level(A3, false); +    spi_flash_write_data(header_page * 256, used_pages, 256); +    wait_for_flash_ready(); +} + +bool app_loop(void) { +    // delay_ms(5000); + +    return; +         +    // simulate logging 15 seconds of data +    watch_date_time date_time = watch_rtc_get_date_time(); +    acceleromter_training_record_t record; + +    record.header.temperature = 0xC30; +    record.header.temperature |= (ACCELEROMETER_TRAINING_RECORD_HEADER << 14); +    record.header.char1 = 'W'; +    record.header.char2 = 'A'; +    record.header.timestamp = watch_utility_date_time_to_unix_time(date_time, 0);; + +    acceleromter_training_record_t records[32]; +    memset(records, 0xFF, sizeof(records)); +    records[0] = record; +    uint16_t pos = 1; +    uint32_t counter = 0; + +    printf("logging 15*25 data points for timestamp %ld\n", record.header.timestamp); +    for(uint8_t i = 0; i < 15; i++) { +        for(uint8_t j = 0; j < 25; j++) { +            record.data.x_accel = arc4random() & 0x3FFF; +            record.data.x_accel |= ACCELEROMETER_TRAINING_RECORD_DATA << 14; +            record.data.y_accel = arc4random() & 0x3FFF; +            record.data.z_accel = arc4random() & 0x3FFF; +            record.data.counter = i; +            records[pos++] = record; +            if (pos >= 32) { +                printf("pos overflowed at counter %ld\n", counter); +                int16_t next_available_page = get_next_available_page(); +                if (next_available_page > 0) { +                    write_buffer_to_page((uint8_t *)records, next_available_page); +                    wait_for_flash_ready(); +                } +                pos = 0; +                memset(records, 0xFF, sizeof(records)); +            } +        } +    } +    if (records[0].header.temperature >> 14 != ACCELEROMETER_TRAINING_RECORD_INVALID) { +        int16_t next_available_page = get_next_available_page(); +        if (next_available_page > 0) { +            printf("Partial write\n"); +            write_buffer_to_page((uint8_t *)records, next_available_page); +            wait_for_flash_ready(); +            delay_ms(10); +        } +    } + +    delay_ms(60000);      return false;  } diff --git a/watch-library/shared/config/hpl_sercom_config.h b/watch-library/shared/config/hpl_sercom_config.h index 6df4b08e..24525fbe 100644 --- a/watch-library/shared/config/hpl_sercom_config.h +++ b/watch-library/shared/config/hpl_sercom_config.h @@ -172,7 +172,7 @@  // <i> The SPI data transfer rate  // <id> spi_master_baud_rate  #ifndef CONF_SERCOM_3_SPI_BAUD -#define CONF_SERCOM_3_SPI_BAUD 50000 +#define CONF_SERCOM_3_SPI_BAUD 1000000  #endif  // </h> diff --git a/watch-library/shared/driver/spiflash.h b/watch-library/shared/driver/spiflash.h index 0d8641a7..9b1d00f5 100644 --- a/watch-library/shared/driver/spiflash.h +++ b/watch-library/shared/driver/spiflash.h @@ -33,6 +33,8 @@  #define CMD_FAST_READ_DATA 0x0B  #define CMD_SECTOR_ERASE 0x20  // #define CMD_SECTOR_ERASE CMD_READ_JEDEC_ID +#define CMD_CHIP_ERASE 0xC7 +// #define CMD_CHIP_ERASE CMD_READ_JEDEC_ID  #define CMD_DISABLE_WRITE 0x04  #define CMD_ENABLE_WRITE 0x06  #define CMD_PAGE_PROGRAM 0x02 | 
