Code for the project of LELEC2811 2017
Dependencies: FreescaleIAP MMA8491Q_PG mbed
Fork of LELEC_2811_Accelerometer by
main.cpp
- Committer:
- Salamandre
- Date:
- 2016-11-23
- Revision:
- 1:1406d318a3b7
- Parent:
- 0:a18d6e69c993
- Child:
- 2:f146ae6546b5
File content as of revision 1:1406d318a3b7:
/* LELEC_2811 Accelerometer Project UCL 2014 - P. Gérard */ #include "mbed.h" #include "FreescaleIAP.h" // Library for Flash Access #include "MMA8491Q_PG.h" // Accelerometer #define MMA8491_I2C_ADDRESS (0x55<<1) #define NO_JUMPER 0 #define JUMPER_PRESENT 1 #define LEVEL_0 0 #define LEVEL_1 1 #define LED_ON 0 #define LED_OFF 1 #define DISABLE_STATE 0 #define ENABLE_STATE 1 #define REG_OUT_X_MSB 0x01 #define REG_OUT_Y_MSB 0x03 #define REG_OUT_Z_MSB 0x05 #define FLASH_NO_ACQ_DONE 0 #define FLASH_ACQ_DONE 1 #define ERASE_FLASH_ERROR -1 #define WRITE_FLASH_ERROR -2 #define SECTOR_SIZE 1024 #define RESERVED_SECTOR 32 #define ACQ_TIMER_PERIOD 0.01 // Time between 2 acquisitions (here 10 mSec) typedef struct{ int16_t X; int16_t Y; int16_t Z; } Accel_Data; // --- Setup I2C for MMA8491 MMA8491Q my8491(PTE0, PTE1, MMA8491_I2C_ADDRESS); // --- Set Serial Port Serial Host_Comm(USBTX, USBRX); // tx, rxSerial pc(USBTX, USBRX); // tx, rx Ticker myTick_Acq; // Periodical timer for Acquisition DigitalOut Led_Red(LED1); // Define I/O for Leds DigitalOut Led_Green(LED2); DigitalOut Led_Blue(LED3); DigitalOut Accel_Enable(PTA13); DigitalOut Start_Pulse_Out(PTC9); // Used to enter/exit Acquisition mode DigitalIn Start_Pulse_In(PTC11); // ShortPin J1_15 and J1_16 to enter in Acq_Mode // Globale variable volatile bool bTimer; // 1 means a Timer tick is done int Flash_Base_Address = RESERVED_SECTOR * SECTOR_SIZE ; // Store Flash Base Adresse with 32K reserved for Application Code int Nb_Sector; uint32_t KL25_Flash_Size; // Function Declaration void Clear_Led(void); int Acquisition_Flash(void); int Read_Data_Logging(void); bool Check_Jumper(void); void myTimer_Acq_Task(void); void Acquisition_Task(void); void Read_Task(void); extern IAPCode verify_erased(int address, unsigned int length); int main() { uint8_t Count; Start_Pulse_In.mode(PullNone); // Input Pin is programmed as floating Accel_Enable = DISABLE_STATE; // Turn Accel Enable to disabled state // --- Baud rate setting Host_Comm.baud(115200); Clear_Led(); KL25_Flash_Size = flash_size(); // Get Size of KL25 Embedded Flash Nb_Sector = (KL25_Flash_Size / SECTOR_SIZE) - RESERVED_SECTOR; // Reserve Max 32K for App Code myTick_Acq.attach(&myTimer_Acq_Task, ACQ_TIMER_PERIOD); Host_Comm.printf("\n\rLELEC2811 Accelerometer Logger V1.0 UCL 2014\n\r"); for (;;) { if (Check_Jumper() == JUMPER_PRESENT) { Clear_Led(); Count = 5; while (Count !=0) { if (Check_Jumper() == JUMPER_PRESENT) { Led_Blue = LED_ON; // Blink to alert user "Enter in Acquisition" wait_ms(900); Led_Blue = LED_OFF; wait_ms(100); Count --; if (Count == 0) { Acquisition_Task(); } } else { Count = 0; } } } else { Read_Task(); } } } void Read_Task() { char host_cmd; IAPCode Flash_State; bool bAcq_Done; Flash_State = verify_erased(Flash_Base_Address, KL25_Flash_Size - (RESERVED_SECTOR * SECTOR_SIZE)); if (Flash_State == 0) // Virgin Flash ? { bAcq_Done = 0; } else { bAcq_Done = 1; } Clear_Led(); wait_ms(500); if (bAcq_Done == 1) { Led_Green = LED_ON; Host_Comm.putc('1'); } else { Led_Red = LED_ON; Host_Comm.putc('0'); } if(Host_Comm.readable()) // Did we receive a char from Host ? { host_cmd = Host_Comm.getc(); // Get it if ((host_cmd == 'R') || (host_cmd == 'r')) // Read Flash Command ? { Read_Data_Logging(); // Read and send acquisition data } } wait_ms(50); } void Acquisition_Task() { int Acq_Status; Clear_Led(); Acq_Status = Acquisition_Flash(); Clear_Led(); while (Check_Jumper() == JUMPER_PRESENT) { if (Acq_Status != FLASH_ACQ_DONE) { Led_Red = !Led_Red; } else { Led_Green = !Led_Green; } wait_ms(100); } } void Clear_Led(void) { Led_Red = LED_OFF; Led_Green = LED_OFF; Led_Blue = LED_OFF ; // Bug on board : Turning On Blue Led decrease consumption... } bool Check_Jumper() // If J1_15 and J1_16 connected together -> return JUMPER_PRESENT { uint8_t i; for (i = 0 ; i < 2 ; i ++) { Start_Pulse_Out = LEVEL_1; wait_ms(1); if (Start_Pulse_In != LEVEL_1) { return NO_JUMPER; } Start_Pulse_Out = LEVEL_0; wait_ms(1); if (Start_Pulse_In != LEVEL_0) { return NO_JUMPER; } } return JUMPER_PRESENT; } int Acquisition_Flash(void) { int Status; int Flash_Ptr ; uint8_t Data_Ptr; Accel_Data myData[2]; uint8_t Ready; int Led_Counter; for (Flash_Ptr = Flash_Base_Address ; Flash_Ptr < KL25_Flash_Size ; Flash_Ptr += 0x400) { Status = erase_sector(Flash_Ptr); // Erase sector if (Status !=0) { return ERASE_FLASH_ERROR; } } Flash_Ptr = Flash_Base_Address; Led_Blue = LED_ON; Led_Counter = 0; Data_Ptr = 0; while (Flash_Ptr < KL25_Flash_Size ) // Acq Loop { while (bTimer == 0) // Wait Acq Tick Timer { } bTimer = 0; Accel_Enable = ENABLE_STATE; // Rising Edge -> Start Accel Measure if ((float) Led_Counter * ACQ_TIMER_PERIOD == 1.0) // Blink at 1 Hz { Led_Counter = 0; Led_Blue = !Led_Blue; } Ready = 0; while((Ready && 0x10) == 0) // Wait Accelerometer have new data's { Ready = my8491.Read_Status(); } myData[Data_Ptr].X = my8491.getAccAxis(REG_OUT_X_MSB); myData[Data_Ptr].Y = my8491.getAccAxis(REG_OUT_Y_MSB); myData[Data_Ptr].Z = my8491.getAccAxis(REG_OUT_Z_MSB); Led_Counter++; Accel_Enable = DISABLE_STATE; //Host_Comm.printf("\n\r%x\tX = %f", Flash_Ptr, float(myData[Data_Ptr].X)*4.0/4096.0 ); //Host_Comm.printf("\tY = %f", float(myData[Data_Ptr].Y)*4.0/4096.0 ); //Host_Comm.printf("\tZ = %f", float(myData[Data_Ptr].Z)*4.0/4096.0 ); Data_Ptr ++; if (Data_Ptr == 2)// Save 2 acquistions -> 2 * 3 * 2 bytes = 12 bytes { Data_Ptr = 0; Status = program_flash(Flash_Ptr, (char *) &myData[0].X, 4); // Write 4 bytes in the Flash if (Status !=0) { return WRITE_FLASH_ERROR; } Flash_Ptr += 4; Status = program_flash(Flash_Ptr, (char *) &myData[0].Z, 4); // Write 4 bytes in the Flash if (Status !=0) { return WRITE_FLASH_ERROR; } Flash_Ptr += 4; //Status = program_flash(Flash_Ptr, (char *) &myData[1].Y, 4); // Write 4 bytes in the Flash Status = program_flash(Flash_Ptr, (char *) &myData[0].Y, 4); // Bug corrected 23/11/2016 if (Status !=0) { return WRITE_FLASH_ERROR; } Flash_Ptr += 4; if ((Flash_Ptr & 0x3FC) == 0x3FC) { Flash_Ptr += 4; //170 * 6 = 1020 ---> skip 4 last bytes of each sector of 1024 bytes } } if (Check_Jumper() != JUMPER_PRESENT) // If Jumper remoded -> Stop Acquisition { return FLASH_ACQ_DONE ; } } return FLASH_ACQ_DONE ; } int Read_Data_Logging() { int16_t *data = (int16_t *) Flash_Base_Address; // uint16 pointer of data stored in Flash int Flash_Ptr; char cmd; int Record_Counter; float X_Val, Y_Val, Z_Val; int16_t Raw_X, Raw_Y, Raw_Z; int Max_Record; Clear_Led(); Max_Record = Nb_Sector * (SECTOR_SIZE / sizeof(Accel_Data)); Record_Counter = 0; Flash_Ptr = 0; //Host_Comm.printf("\n\rBegin of Data"); while (Record_Counter < Max_Record) { Led_Green = !Led_Green; Led_Blue = !Led_Green; if(Host_Comm.readable()) { cmd = Host_Comm.getc(); if ((cmd == 'S') || (cmd == 's')) // Receiving 'S' or 's' means stop Read Flash { Clear_Led(); return 0; } } Record_Counter ++; Raw_X = data[Flash_Ptr++]; Raw_Y = data[Flash_Ptr++]; Raw_Z = data[Flash_Ptr++]; if ((Raw_X == -1) && (Raw_Y == -1) && (Raw_Z == -1)) // Valid data ? (!= 0xFFFFFFFF from empty Flash sector) { } else { X_Val = float(Raw_X) * 4.0/4096.0; Y_Val = float(Raw_Y) * 4.0/4096.0; Z_Val = float(Raw_Z) * 4.0/4096.0; Host_Comm.printf("\n\r%d\tX=%.4f\tY=%.4f\tZ=%.4f", Record_Counter, X_Val, Y_Val, Z_Val); } if ((Flash_Ptr & 0x1FE) == 0x1FE) { Flash_Ptr +=2; // skip the last bytes at the end of a sector } } //Host_Comm.printf("\n\rEnd of Data"); Clear_Led(); return 0; } /* Interrupt Task */ void myTimer_Acq_Task() { bTimer = 1; }