Skip to content
Snippets Groups Projects
Select Git revision
  • 214179b430ebc1101e28b19248b6166f5e511e6b
  • wip-bootstrap default
  • dualcore
  • ch3/leds
  • ch3/time
  • master
6 results

float1.py

Blame
  • main.c 8.91 KiB
    /*******************************************************************************
     * License: TBD
     ******************************************************************************/
    
    /***** Includes *****/
    #include <stdio.h>
    #include <stdint.h>
    #include <string.h>
    #include <stdlib.h>
    #include "mxc_config.h"
    #include "led.h"
    #include "board.h"
    #include "tmr_utils.h"
    #include "i2c.h"
    #include "rtc.h"
    #include "spi.h"
    #include "MAX30003.h"
    #include "GUI_DEV/GUI_Paint.h"
    #include "pmic.h"
    #include "card10.h"
    #include <stdbool.h>
    
    /***** Definitions *****/
    
    /***** Globals *****/
    static bool ecg_switch;
    static bool internal_pull;
    
    
    /***** Functions *****/
    static uint32_t ecg_read_reg(uint8_t reg)
    {
        spi_req_t req;
        uint8_t tx_data[] = {(reg << 1) | 1, 0, 0, 0};
        uint8_t rx_data[] = {0, 0, 0, 0};
        req.tx_data = tx_data;
        req.rx_data = rx_data;
        req.len = 4;
        req.bits = 8;
        req.width = SPI17Y_WIDTH_1;
        req.ssel = 0;
        req.deass = 1;
        req.ssel_pol = SPI17Y_POL_LOW;
        req.tx_num = 0;
        req.rx_num = 0;
    
        SPI_MasterTrans(SPI0, &req);
    
        return (rx_data[1] << 16) | (rx_data[2] << 8) | rx_data[3];
    }
    
    static void ecg_write_reg(uint8_t reg, uint32_t data)
    {
        printf("write %02x %06x\n", reg, data);
        spi_req_t req;
        uint8_t tx_data[] = {(reg << 1) | 0 , data >> 16, (data >> 8 ) & 0xFF, data & 0xFF};
        uint8_t rx_data[] = {0, 0, 0, 0};
        req.tx_data = tx_data;
        req.rx_data = rx_data;
        req.len = 4;
        req.bits = 8;
        req.width = SPI17Y_WIDTH_1;
        req.ssel = 0;
        req.deass = 1;
        req.ssel_pol = SPI17Y_POL_LOW;
        req.tx_num = 0;
        req.rx_num = 0;
    
        SPI_MasterTrans(SPI0, &req);
    }
    
    static void ecg_config(bool enable_internal_pull)
    {
        // Reset ECG to clear registers
        ecg_write_reg(SW_RST , 0);
    
        // General config register setting
        union GeneralConfiguration_u CNFG_GEN_r;
        CNFG_GEN_r.bits.en_ecg = 1;     // Enable ECG channel
        if(enable_internal_pull) {
            CNFG_GEN_r.bits.rbiasn = 1;     // Enable resistive bias on negative input
            CNFG_GEN_r.bits.rbiasp = 1;     // Enable resistive bias on positive input
            CNFG_GEN_r.bits.en_rbias = 1;   // Enable resistive bias
        } else {
            CNFG_GEN_r.bits.rbiasn = 0;     // Enable resistive bias on negative input
            CNFG_GEN_r.bits.rbiasp = 0;     // Enable resistive bias on positive input
            CNFG_GEN_r.bits.en_rbias = 0;   // Enable resistive bias
        }
    
        CNFG_GEN_r.bits.imag = 2;       // Current magnitude = 10nA
        CNFG_GEN_r.bits.en_dcloff = 1;  // Enable DC lead-off detection
        ecg_write_reg(CNFG_GEN , CNFG_GEN_r.all);
    
    
        // ECG Config register setting
        union ECGConfiguration_u CNFG_ECG_r;
        CNFG_ECG_r.bits.dlpf = 1;       // Digital LPF cutoff = 40Hz
        CNFG_ECG_r.bits.dhpf = 1;       // Digital HPF cutoff = 0.5Hz
        //CNFG_ECG_r.bits.gain = 3;       // ECG gain = 160V/V
        CNFG_ECG_r.bits.gain = 0;
        CNFG_ECG_r.bits.rate = 2;       // Sample rate = 128 sps
        ecg_write_reg(CNFG_ECG , CNFG_ECG_r.all);
    
    
        //R-to-R configuration
        union RtoR1Configuration_u CNFG_RTOR_r;
        CNFG_RTOR_r.bits.en_rtor = 1;           // Enable R-to-R detection
        ecg_write_reg(CNFG_RTOR1 , CNFG_RTOR_r.all);
    
    
        //Manage interrupts register setting
        union ManageInterrupts_u MNG_INT_r;
        MNG_INT_r.bits.efit = 0b00011;          // Assert EINT w/ 4 unread samples
        MNG_INT_r.bits.clr_rrint = 0b01;        // Clear R-to-R on RTOR reg. read back
        ecg_write_reg(MNGR_INT , MNG_INT_r.all);
    
    
        //Enable interrupts register setting
        union EnableInterrupts_u EN_INT_r;
        EN_INT_r.all = 0;
        EN_INT_r.bits.en_eint = 1;              // Enable EINT interrupt
        EN_INT_r.bits.en_rrint = 0;             // Disable R-to-R interrupt
        EN_INT_r.bits.intb_type = 3;            // Open-drain NMOS with internal pullup
        ecg_write_reg(EN_INT , EN_INT_r.all);
    
    
        //Dyanmic modes config
        union ManageDynamicModes_u MNG_DYN_r;
        MNG_DYN_r.bits.fast = 0;                // Fast recovery mode disabled
        ecg_write_reg(MNGR_DYN , MNG_DYN_r.all);
    
        // MUX Config
        union MuxConfiguration_u CNFG_MUX_r;
        CNFG_MUX_r.bits.openn = 0;          // Connect ECGN to AFE channel
        CNFG_MUX_r.bits.openp = 0;          // Connect ECGP to AFE channel
        ecg_write_reg(CNFG_EMUX , CNFG_MUX_r.all);
    
        return;
    }
    
    #define SIZE_X 160
    #define SIZE_Y 80
    
    static uint8_t prev;
    
    static void clear(void)
    {
        Paint_Clear(BLACK);
        prev = 32;
    }
    
    
    static void set(uint8_t index, int8_t val)
    {
    
        if(val < -31) val = -31;
        if(val > 32) val = 32;
    
        int8_t pos = 32 + val;
    
        int min, max;
        if(prev < pos) {
            min = prev;
            max = pos;
        } else {
            min = pos;
            max = prev;
        }
    
        for(int i = min; i < max + 1; i++) {
            LCD_SetUWORD(SIZE_X - index - 1, i, RED);
        }
    
        prev = pos;
    }
    
    static int16_t samples[SIZE_X];
    void update(void)
    {
        clear();
    
        char buf[128];
        sprintf(buf, "Switch: %d  Pull: %d", ecg_switch, internal_pull);
        Paint_DrawString_EN(0, 0, buf, &Font8, 0x0000, 0xffff);
    
    
        int16_t max = 0;
        for(int i=0; i<SIZE_X; i++) {
            if(abs(samples[i]) > max) {
                max = abs(samples[i]);
            }
        }
    
        int16_t scale = max / 32;
    
        for(int i=0; i<SIZE_X; i++) {
            set(i, (samples[i] / scale));
            //set(i, ((samples[i*2] + samples[i*2 + 1]) / scale) / 2);
        }
    
        LCD_Update();
    }
    
    static uint8_t sample_count = 0;
    
    static void add_sample(int16_t sample)
    {
        memmove(samples, samples + 1, sizeof(*samples) * (SIZE_X-1));
        samples[SIZE_X-1] = sample;
        sample_count++;
    
        if(sample_count == 5) {
            sample_count = 0;
            update();
        }
    }
    
    static volatile bool ecgFIFOIntFlag = false;
    static void ecgFIFO_callback(void *data) {
        ecgFIFOIntFlag = true;
    }
    
    // *****************************************************************************
    int main(void)
    {
    
        card10_init();
        card10_diag();
    
        const gpio_cfg_t interrupt_pin = {PORT_1, PIN_12, GPIO_FUNC_IN, GPIO_PAD_PULL_UP};
        GPIO_Config(&interrupt_pin);
        GPIO_RegisterCallback(&interrupt_pin, ecgFIFO_callback, NULL);
        GPIO_IntConfig(&interrupt_pin, GPIO_INT_EDGE, GPIO_INT_FALLING);
        GPIO_IntEnable(&interrupt_pin);
        NVIC_EnableIRQ(MXC_GPIO_GET_IRQ(PORT_1));
    
        const gpio_cfg_t analog_switch = {PORT_0, PIN_31, GPIO_FUNC_OUT, GPIO_PAD_NONE};
        GPIO_Config(&analog_switch);
    
    
        ecg_switch = false;
        GPIO_OutClr(&analog_switch); // Wrist
    
        internal_pull = true;
        ecg_config(internal_pull);
    
        for(int i=0; i<0x20; i++) {
            uint32_t val = ecg_read_reg(i);
            printf("%02x: 0x%06x\n", i, val);
        }
    
        ecg_write_reg(SYNCH, 0);
    
        uint32_t ecgFIFO, readECGSamples, idx, ETAG[32], status;
        int16_t ecgSample[32];
        const int EINT_STATUS_MASK =  1 << 23;
        const int FIFO_OVF_MASK =  0x7;
        const int FIFO_VALID_SAMPLE_MASK =  0x0;
        const int FIFO_FAST_SAMPLE_MASK =  0x1;
        const int ETAG_BITS_MASK = 0x7;
    
    
        while(1) {
            // Read back ECG samples from the FIFO
            if( ecgFIFOIntFlag ) {
                ecgFIFOIntFlag = false;
    
                if(PB_Get(0)) {
                    ecg_switch = !ecg_switch;
                    while(PB_Get(0));
                    if(ecg_switch) {
                        GPIO_OutSet(&analog_switch); // USB
                    } else {
                        GPIO_OutClr(&analog_switch); // Wrist
                    }
                }
    
                if(PB_Get(2)) {
                    internal_pull =! internal_pull;
                    while(PB_Get(2));
                    ecg_config(internal_pull);
                }
    
                //printf("Int\n");
                status = ecg_read_reg( STATUS );      // Read the STATUS register
    
                // Check if EINT interrupt asserted
                if ( ( status & EINT_STATUS_MASK ) == EINT_STATUS_MASK ) {
    
                    readECGSamples = 0;                        // Reset sample counter
    
                    do {
                        ecgFIFO = ecg_read_reg(ECG_FIFO );       // Read FIFO
                        ecgSample[readECGSamples] = ecgFIFO >> 8;                  // Isolate voltage data
                        ETAG[readECGSamples] = ( ecgFIFO >> 3 ) & ETAG_BITS_MASK;  // Isolate ETAG
                        readECGSamples++;                                          // Increment sample counter
    
                    // Check that sample is not last sample in FIFO
                    } while ( ETAG[readECGSamples-1] == FIFO_VALID_SAMPLE_MASK ||
                              ETAG[readECGSamples-1] == FIFO_FAST_SAMPLE_MASK );
    
                    // Check if FIFO has overflowed
                    if( ETAG[readECGSamples - 1] == FIFO_OVF_MASK ){
                        ecg_write_reg(FIFO_RST , 0); // Reset FIFO
                        //printf("OV\n");
                        // notifies the user that an over flow occured
                        //LED_On(0);
                        pmic_set_led(0, 31);
                    }
    
                    // Print results
                    for( idx = 0; idx < readECGSamples; idx++ ) {
                        //printf("%6d\r\n", ecgSample[idx]);
                        add_sample(ecgSample[idx]);
                    }
                }
            }
        }
    }