/*********************************************************************************/ /** * File: dvoraj42.c * Author: Jan Dvorak z Vozerovic * FEL-ID: dvoraj42 * e-mail: dvorkaman@gmail.com * site: dvorkaman.php5.cz */ #ifndef __dvoraj42_c__ #define __dvoraj42_c__ /*********************************************************************************/ /** * INCLUDES */ #include "dvoraj42.h" #include "letters.h" //#include "states.c" #include "sckit_eval_lcd.h" #include "stm32_eval_spi_accel.h" #include "stdio.h" #include "FreeRTOS.h" #include "task.h" #include "stm32_eval_spi_flash.h" /*********************************************************************************/ /** * Private variables */ // Encoder - handled in interrupt - volatile volatile int encoderLastA = 0; volatile int encoderLastB = 0; volatile unsigned int encoderPosition = ENCODER_MIDDLE; int encoderLastReadPosition = ENCODER_MIDDLE >> ENCODER_BITS_PER_TICK; // System clock extern volatile uint32_t SYSTEM_S; uint32_t lastShownTime = -1; // State extern volatile int state; // Settings extern volatile settings configuration; extern volatile materialInfo material; // Lcd uint8_t singleLCDRow[LCD_WIDTH]; uint8_t lcdGraph[LCD_WIDTH * LCD_HEIGHT]; volatile int lastDrawnState = -1; // upper part int forceRedraw = 0; // whole screen volatile int buttonIndexState = 0; // button part volatile int lastDrawnButtonIndexState = -1; int drawEncoderButton = 1; // wheter redraw encoder button int encoderButtonType = 0; // input method 1 int actualEncoderButtonType = 0; int graphZoomOfX = 0; int graphOffsetOfX = 0; // Input data int enableSpecialFunctionalityOnPress = 0; // allow second type of input // Accelerometer volatile int disableAccelerometerWrite = 0; volatile int accelerometerX = 0; // with calibration volatile int accelerometerY = 0; volatile int accelerometerRealX = 0; // without calibration volatile int accelerometerRealY = 0; volatile int accelerometer = 0; // modul of value // Measured data data measuredData[ACCELEROMETER_MAX_VALUES]; /*********************************************************************************/ /** * Graphic images and buttons */ uint8_t LCDImageBackground[] = { #include "Img_Background.c" }; uint8_t LCDImageAbout[] = { #include "Img_About.c" }; uint8_t LCDImageSettings[] = { #include "Img_Settings.c" }; uint8_t LCDImageLogOK[] = { #include "Img_LogOK.c" }; uint8_t LCDImageLogBroken[] = { #include "Img_LogBroken.c" }; uint8_t LCDImageGraph[] = { #include "Img_Graph.c" }; uint8_t LCDImageButtonEncoder[] = { #include "Img_ButtonEncoder.c" }; uint8_t LCDImageButtonEncoderFn2[] = { #include "Img_ButtonEncoderFn2.c" }; uint8_t LCDImageButtonSettings[] = { #include "Img_ButtonSettings.c" }; uint8_t LCDImageButtonLog[] = { #include "Img_ButtonLog.c" }; uint8_t LCDImageButtonGraph[] = { #include "Img_ButtonGraph.c" }; uint8_t LCDImageButtonAbout[] = { #include "Img_ButtonAbout.c" }; uint8_t LCDImageButtonEmpty[] = { #include "Img_ButtonEmpty.c" }; uint8_t LCDImageButtonBack[] = { #include "Img_ButtonBack.c" }; uint8_t LCDImageButtonCalibration[] = { #include "Img_ButtonCalibration.c" }; uint8_t LCDImageButtonClearData[] = { #include "Img_ButtonClearData.c" }; uint8_t LCDImageButtonClearMax[] = { #include "Img_ButtonClearMax.c" }; uint8_t LCDImageButtonMinA[] = { #include "Img_ButtonMinA.c" }; uint8_t LCDImageButtonZoom[] = { #include "Img_ButtonZoom.c" }; uint8_t LCDImageButtonShift[] = { #include "Img_ButtonShift.c" }; /*********************************************************************************/ /** * LCD show image * @pamam{uint8_t} representation of the image */ void LCDDrawFullImage(uint8_t image[]) { LCDDrawImage(image, 0, 0, LCD_WIDTH, LCD_HEIGHT); } /*********************************************************************************/ /** * LCD show image * @pamam{uint8_t} representation of the image * @pamam{int} offset on axis X <0..WIDTH) * @pamam{int} offset on axis Y <0..HEIGHT) * @pamam{int} width of input image * @pamam{int} height of input image */ void LCDDrawImage(uint8_t image[], int offsetX, int offsetY, int width, int height) { /* LCD: 65 (8 page x 8 bit +1) x 132 bit structure. One page = 8 rows; -> 8bits in one column Page addr and column addr column addr: auto increment after read / write First pixel - row 0 at page 0 is in right upper corner */ //printf("IMG REQUEST\r\n"); //return; // page bounds int page, column; int adrLow, adrHigh; int fromPage = (int) (offsetY / LCD_PAGE_SIZE); int toPage = (int) ((offsetY + height) / LCD_PAGE_SIZE); LCD_CS_LOW(); // reset bits // for each page for (page = fromPage; page < toPage; page++) { // 1) Set page and columnt addr LCD_Command(CMD_SET_PAGE | page); adrLow = offsetX & 0xF; adrHigh = (offsetX >> 4) & 0xF; LCD_Command(CMD_SET_COLUMN_LOWER | adrLow); LCD_Command(CMD_SET_COLUMN_UPPER | adrHigh); LCD_Command(CMD_RMW); // 2) For each column for (column = 0; column < width; column++) { // 3) Write 8bits = 1 column LCD_Data(image[width * (page - fromPage) + column]); // get offset within smaller Array } } LCD_CS_HIGH(); // set bits } /*********************************************************************************/ /* LCD button on given BUTTON position * @pamam{uint8_t} representation of the image * @pamam{int} offset on axis X <0..WIDTH) * @pamam{int} offset on axis Y <0..HEIGHT) */ void LCDDrawButton(uint8_t image[], int x, int y) { int offsetX; if (x < 0 || x >= LCD_WIDTH / LCD_BUTTON_WIDTH || y < 0 || y >= LCD_HEIGHT / LCD_BUTTON_HEIGHT) return; offsetX = LCD_WIDTH - (x + 1) * LCD_BUTTON_WIDTH; LCDDrawImage(image, offsetX, y * LCD_BUTTON_HEIGHT, LCD_BUTTON_WIDTH, LCD_BUTTON_HEIGHT); } /*********************************************************************************/ /** * Get state of button 1 * @return{bool} true if pressed */ int getButton1State() { return 1 - STM_EVAL_PBGetState(BUTTON_SW2); // negated value } /*********************************************************************************/ /** * Get state of button 2 * @return{bool} true if pressed */ int getButton2State() { return 1 - STM_EVAL_PBGetState(BUTTON_SW1); // negated value } /*********************************************************************************/ /** * Initialization of encoder */ void initializeEncoder() { GPIO_InitTypeDef init; EXTI_InitTypeDef exti; NVIC_InitTypeDef nvic; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // Encoder has two inputs init.GPIO_Mode = GPIO_Mode_IN; init.GPIO_PuPd = GPIO_PuPd_NOPULL; init.GPIO_Speed = GPIO_Speed_100MHz; init.GPIO_Pin = GPIO_Pin_12; GPIO_Init(GPIOD, &init); init.GPIO_Pin = GPIO_Pin_13; GPIO_Init(GPIOD, &init); // Configure interrupt exti.EXTI_Mode = EXTI_Mode_Interrupt; exti.EXTI_Trigger = EXTI_Trigger_Rising_Falling; exti.EXTI_LineCmd = ENABLE; SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource12); exti.EXTI_Line = EXTI_Line12; EXTI_Init(&exti); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOD, EXTI_PinSource13); exti.EXTI_Line = EXTI_Line13; EXTI_Init(&exti); nvic.NVIC_IRQChannel = EXTI15_10_IRQn; nvic.NVIC_IRQChannelPreemptionPriority = 0x0F; nvic.NVIC_IRQChannelSubPriority = 0x0F; nvic.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic); } /*********************************************************************************/ /** * Gets encoder direction * @returns{int} direction {-1, 0, 1} */ int getEncoderDirection() { int encoder = encoderPosition >> ENCODER_BITS_PER_TICK; int diff = encoder - encoderLastReadPosition; encoderLastReadPosition = encoder; if( diff<0 )return -1; if( diff>0 )return 1; return 0; } /*********************************************************************************/ /** * Gets encoder position * @returns{int} position */ int getEncoderPosition() { return encoderPosition; } /*********************************************************************************/ /** * Handle encoder position * @param{int} pin {0 = pin 12; 1 = pin 13} */ void handleEncoderPosition(int pin) { int stateA, stateB; (int) pin; // read state stateA = 1 - GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_12); stateB = 1 - GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_13); // decode state if( (encoderLastA==0 && encoderLastB== 0 && stateA==0 && stateB==1) || (encoderLastA==0 && encoderLastB== 1 && stateA==1 && stateB==1) || (encoderLastA==1 && encoderLastB== 0 && stateA==0 && stateB==0) || (encoderLastA==1 && encoderLastB== 1 && stateA==1 && stateB==0) )encoderPosition--; if( (encoderLastA==0 && encoderLastB== 0 && stateA==1 && stateB==0) || (encoderLastA==0 && encoderLastB== 1 && stateA==0 && stateB==0) || (encoderLastA==1 && encoderLastB== 0 && stateA==1 && stateB==1) || (encoderLastA==1 && encoderLastB== 1 && stateA==0 && stateB==1) )encoderPosition++; //save encoderLastA = stateA; encoderLastB = stateB; } /*********************************************************************************/ /** * Handler for interrupt on line 10 to 15 */ void EXTI15_10_IRQHandler(void) { // First encoder switch - State A if (EXTI_GetITStatus(EXTI_Line12) != RESET) { EXTI_ClearITPendingBit(EXTI_Line12); handleEncoderPosition(0); } // Second encoder switch - State B if (EXTI_GetITStatus(EXTI_Line13) != RESET) { EXTI_ClearITPendingBit(EXTI_Line13); handleEncoderPosition(1); } // Accelerometer if (EXTI_GetITStatus(EXTI_Line15) != RESET) { EXTI_ClearITPendingBit(EXTI_Line15); //handleAccelerometerData(); //printf("ACCEL IT\r\n"); } } /*********************************************************************************/ /** * Delay cycles * @param{int} cycles */ void delayCycles(unsigned int cycles) { unsigned int i; for (i = 0; i < cycles; i++) { } } /*********************************************************************************/ /** * Merge two LCD images * @param{Array.uint8_t} source image * @param{Array.uint8_t} merge source with image */ void LCDMergeImages(uint8_t source[], uint8_t mergeWith[]) { unsigned int i; for (i = 0; i= 0; x--) { number = 0; // for each Y in page for (y = LCD_PAGE_SIZE - 1; y >= 0; y--) { number = (number << 1) | (bitmapGetPixelAt(bitmap, x, y + p * LCD_PAGE_SIZE, width) & 0x1); } // store image[index++] = number; } } } /*********************************************************************************/ /** * Get pixel within bitmap * @param{Array.uint8_t} bitmap * @param{int} x * @param{int} y * @param{int} width */ int bitmapGetPixelAt(uint8_t bitmap[], int x, int y, int width) { return (int)bitmap[x + y * width]; } /*********************************************************************************/ /** * Set pixel within bitmap * @param{Array.uint8_t} bitmap * @param{int} value * @param{int} x * @param{int} y * @param{int} width */ void bitmapSetPixelAt(uint8_t bitmap[], int value, int x, int y, int width) { bitmap[x + y * width] = value; } /*********************************************************************************/ /** * Print string to LCD * @param{char *} string * @param{int} x position within display * @param{int} row number */ void LCDPrintString(char *string, int x, int row) { int length = 0; char *start = string; int imageLength, index, i, c; letter l; int column, offsetX; // check input if (x < 0 || row < 0 || row >= LCD_HEIGHT / LCD_PAGE_SIZE) return; // calculate length while (*string != '\0') { length++; string++; // move to another char } // calculate ending of the string imageLength = length * (LETTER_WIDTH + 1) - 1; // index of last row in string (+1 stands for gab between numbers) if (imageLength + x > LCD_WIDTH) imageLength = LCD_WIDTH - x; // check overflow index = imageLength - 1; // index 0 is right; we start filling from the left border string = start; // for each letter for (i = 0; i < length; i++) { l = LCDASCII[(int) (*string)]; string++; // for each column in letter for (c = 1; c <= 5; c++) { if (c == 1)column = l.columnA; else if (c == 2)column = l.columnB; else if (c == 3)column = l.columnC; else if (c == 4)column = l.columnD; else if (c == 5)column = l.columnE; singleLCDRow[index--] = column << 1; // skip top most pixel if (index < 0)break; } // space between if (index < 0)break; singleLCDRow[index--] = 0; if (index < 0)break; } // display offsetX = LCD_WIDTH - imageLength - x; // from right border LCDDrawImage(singleLCDRow, offsetX, row * LCD_PAGE_SIZE, imageLength, LCD_PAGE_SIZE); } /*********************************************************************************/ /** * Get encoder ticks * @returns{int} ticks */ unsigned int getEncoderTicks() { return (encoderPosition >> ENCODER_BITS_PER_TICK); } /*********************************************************************************/ /** * Print number to LCD * @param{int} number * @param{int} digits * @param{int} x * @param{int} row */ void LCDPrintNumber(int number, int digits, int x, int row) { char c[40]; // longer then possible display amount // format char format[10] = {'%', '\0', '\0', '\0', '\0', '\0', '\0'}; format[1] = '0' + (digits % 10); format[2] = 'd'; if( digits>=10) { format[3] = format[2]; format[2] = format[1]; format[1] = '0' + (digits / 10); } // convert and display sprintf(c, format, number); LCDPrintString(c, x, row); } /*********************************************************************************/ /** * Initialize accelerometer */ void initializeAccelerometer(void) { GPIO_InitTypeDef init; EXTI_InitTypeDef exti; NVIC_InitTypeDef nvic; sACCEL_Init(); // accelerometer INIT // set configuration sACCEL_WriteReg(0x20, 0xA3); // REG 1: 10 (on) | 10 (decimate 32) | 0 self test | x | enable xy 11 sACCEL_WriteReg(0x21, 0x85); // REG2: 1 +- 6G | 0 BDU | 0 BLE | 0 BOOT || 0 EN interrupt | 1 DRDY | 0 SIM | 1 16BIT // set RDY pin and interrupt RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); init.GPIO_Mode = GPIO_Mode_IN; init.GPIO_PuPd = GPIO_PuPd_NOPULL; init.GPIO_Speed = GPIO_Speed_100MHz; init.GPIO_Pin = GPIO_Pin_15; GPIO_Init(GPIOB, &init); exti.EXTI_Mode = EXTI_Mode_Interrupt; exti.EXTI_Trigger = EXTI_Trigger_Rising; exti.EXTI_LineCmd = ENABLE; SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource15); exti.EXTI_Line = EXTI_Line15; EXTI_Init(&exti); nvic.NVIC_IRQChannel = EXTI15_10_IRQn; nvic.NVIC_IRQChannelPreemptionPriority = 0x0F; nvic.NVIC_IRQChannelSubPriority = 0x0F; nvic.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&nvic); handleAccelerometerData(); } /******************************************************************************/ /** * Accelerometer data handle */ void handleAccelerometerData() { uint32_t tm; int length; int rewrite = 0; // read accelerometerRealX = convertMeasuredAccelerometer( sACCEL_ReadWord(sACCEL_CMD_OUTX) ); accelerometerRealY = convertMeasuredAccelerometer( sACCEL_ReadWord(sACCEL_CMD_OUTY) ); accelerometerX = accelerometerRealX - configuration.calibrationX; accelerometerY = accelerometerRealY - configuration.calibrationY; //printf("%d\r\n", accelerometer); accelerometer = sqrt(accelerometerX * accelerometerX + accelerometerY * accelerometerY); if( disableAccelerometerWrite==0 ) { // test if broken if( material.brokenAtTime==0 && accelerometer >= configuration.accelMinValue) { material.brokenAtTime = SYSTEM_S; setMaterialBroken(); } // Write length = material.measuredValuesCount; if( length>=ACCELEROMETER_MAX_VALUES )return; // buffer full tm = SYSTEM_S; rewrite = 0; if (length > 0) { // compare with last - update last if higher value if (measuredData[length - 1].time == tm) { if (measuredData[length - 1].value >= accelerometer) return; rewrite = 1; } } // append or rewrite if (rewrite == 0) { measuredData[length].value = accelerometer; measuredData[length].time = tm; material.measuredValuesCount++; } else { measuredData[length - 1].value = accelerometer; measuredData[length - 1].time = tm; } } } /******************************************************************************/ /** * User task */ void UserTask(void* arg) { getEncoderDirection(); // clear flags LCDDrawButton(LCDImageButtonEmpty, 2, 3); // clear last but one button space printf("User task STARTED\r\n"); setMaterialBroken(); // if broken flag saved in memory (void)arg; // ignore arg parameter while(1) { // clock if( SYSTEM_S!= lastShownTime && state!=12 ) { lastShownTime = SYSTEM_S; LCDShowTime(lastShownTime); material.systemTime = lastShownTime; if( SYSTEM_S%30 == 29 ) { FLASHSaveData(); } } // check state switch(state) { case 0: stateMainMenu(); break; case 10: stateAbout(); break; case 11: stateLog(); break; case 12: stateGraph(); break; case 13: stateSettings(); break; } // sleep vTaskDelay(150); } printf("User task ENDED\r\n"); } /******************************************************************************/ /** * Convert measured value of accelerometer * @param {unsigned int} value * @returns {int converted value} */ int convertMeasuredAccelerometer(unsigned int value) { int treshold = 0x1<<15; int v = value; if( v >= treshold ) { v = v - (treshold << 1); } return v >> ACCELEROMETER_VALUE_SHIFT; } /******************************************************************************/ /** * Draw actual state to LCD */ void drawActualState() { // Upper part of the LCD if (lastDrawnState != state || forceRedraw != 0) { switch (state) { case 0: LCDDrawImage(LCDImageBackground, 0, 0, LCD_WIDTH, LCD_HEIGHT - LCD_BUTTON_HEIGHT); break; case 10: LCDDrawImage(LCDImageAbout, 0, 0, LCD_WIDTH, LCD_HEIGHT - LCD_BUTTON_HEIGHT); break; case 11: setMaterialBroken(); break; // draw equivalent screen case 12: break; case 13: LCDDrawImage(LCDImageSettings, 0, 0, LCD_WIDTH, LCD_HEIGHT - LCD_BUTTON_HEIGHT); break; } lastDrawnState = state; } // Button part of the LCD if (lastDrawnButtonIndexState != buttonIndexState || forceRedraw != 0) { // Left buttons switch(state) { // Main menu case 0: switch(buttonIndexState) { case 0: LCDDrawButton(LCDImageButtonAbout, 0, 3); LCDDrawButton(LCDImageButtonLog, 1, 3); break; case 1: LCDDrawButton(LCDImageButtonLog, 0, 3); LCDDrawButton(LCDImageButtonGraph, 1, 3); break; case 2: LCDDrawButton(LCDImageButtonGraph, 0, 3); LCDDrawButton(LCDImageButtonSettings, 1, 3); break; case 3: LCDDrawButton(LCDImageButtonSettings, 0, 3); LCDDrawButton(LCDImageButtonAbout, 1, 3); break; } break; // About case 10: LCDDrawButton(LCDImageButtonBack, 0, 3); LCDDrawButton(LCDImageButtonEmpty, 1, 3); break; // Log case 11: LCDDrawButton(LCDImageButtonBack, 0, 3); LCDDrawButton(LCDImageButtonEmpty, 1, 3); break; // Graph case 12: switch(buttonIndexState) { case 0: LCDDrawButton(LCDImageButtonZoom, 0, 3); LCDDrawButton(LCDImageButtonShift, 1, 3); break; case 1: LCDDrawButton(LCDImageButtonShift, 0, 3); LCDDrawButton(LCDImageButtonBack, 1, 3); break; case 2: LCDDrawButton(LCDImageButtonBack, 0, 3); LCDDrawButton(LCDImageButtonZoom, 1, 3); break; } break; // Settings case 13: switch(buttonIndexState) { case 0: LCDDrawButton(LCDImageButtonMinA, 0, 3); LCDDrawButton(LCDImageButtonClearMax, 1, 3); break; case 1: LCDDrawButton(LCDImageButtonClearMax, 0, 3); LCDDrawButton(LCDImageButtonCalibration, 1, 3); break; case 2: LCDDrawButton(LCDImageButtonCalibration, 0, 3); LCDDrawButton(LCDImageButtonClearData, 1, 3); break; case 3: LCDDrawButton(LCDImageButtonClearData, 0, 3); LCDDrawButton(LCDImageButtonBack, 1, 3); break; case 4: LCDDrawButton(LCDImageButtonBack, 0, 3); LCDDrawButton(LCDImageButtonMinA, 1, 3); break; } break; } lastDrawnButtonIndexState = buttonIndexState; } // Encoder if (drawEncoderButton != 0) { if( encoderButtonType==0 )LCDDrawButton(LCDImageButtonEncoder, 3, 3); else LCDDrawButton(LCDImageButtonEncoderFn2, 3, 3); drawEncoderButton = 0; } } /******************************************************************************/ /** * Read input * @param{int} 'button ID' if allow press of button and encoder rolling; 0x80 if return when no press * @returns{input} read input */ input readInput(int allowPress) { input i = {0, 0, 0, 0}; int but1, but2; /* 1) Wait for key down */ while(1) { // get data i.button1 = getButton1State(); i.button2 = getButton2State(); i.direction = getEncoderDirection(); // test validity if (i.button1 == 0 && i.button2 == 0 && i.direction == 0) { if (i.button1 == 0 && (allowPress & 0x01) == 0x01)return i; // end of pressing button 1 if (i.button2 == 0 && (allowPress & 0x02) == 0x02)return i; // end of pressing button 1 if( allowPress== 0x80 )return i; continue; // no input } if (i.button1 == 1 && i.button2 == 1) continue; // invalid input if (i.button1 == 0 && i.button2 == 0 && i.direction != 0)return i; // encoder rolled if ((i.button1 == 1 || i.button2 == 1) && allowPress != 0) { i.pressed = 1; if (i.button1 == 1 && (allowPress & 0x1) == 0x1)return i; // special functionality in progress if (i.button2 == 1 && (allowPress & 0x2) == 0x2)return i; // special functionality in progress break; // to second phase with button with special functionality } break; // move to second phase } /* 2) Wait for release of button */ i.pressed = 0; // clear special functionality while (1) { but1 = getButton1State(); but2 = getButton2State(); if (but1 == 0) { if (i.button1 == 1)return i; // button 1 released } if (but2 == 0) { if (i.button2 == 1)return i; // button 2 released } } // clear i.button1 = 0; i.button2 = 0; i.direction = 0; return i; } /*********************************************************************************/ /** * Create Default flash entries */ void FLASHRestoreToDefault() { // create default values configuration.accelMinValue = 100; configuration.preambule = FLASH_PREAMB; configuration.calibrationX = 0; configuration.calibrationY = 0; material.preambule = FLASH_PREAMB; material.systemTime = 0; material.brokenAtTime = 0; material.measuredValuesCount = 0; // persist FLASHSaveData(); } /******************************************************************************/ /** * Load setting from flash memory */ void FLASHLoadData() { uint32_t* data; uint32_t addr = FLASH_START; unsigned int i; uint16_t o; // Configuration data = (uint32_t*)(&configuration); for (i = 0; i=FLASH_END )break; data ++; } else { printf("FLASH WRITE ERROR \r\n"); return; } if (FLASH_ProgramWord(addr, *data) == FLASH_COMPLETE) { addr += 4; if( addr>=FLASH_END )break; data ++; } else { printf("FLASH WRITE ERROR \r\n"); return; } } // lock flash FLASH_Lock(); } /******************************************************************************/ /** * Erase Flash memory */ void FLASHErase() { uint32_t i; //clear eny pending operation FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); // for each sector and its part in FLASH memory for (i = FLASH_START_SECTOR; i < FLASH_END_SECTOR; i += 8) { if (FLASH_EraseSector(i, VoltageRange_3) != FLASH_COMPLETE) { printf("FLASH CLEAR ERROR \r\n"); return; } } } /******************************************************************************/ /** * Initialize flash memory */ void initializeFLASH() { FLASH_SetLatency(FLASH_Latency_3); FLASH_PrefetchBufferCmd(ENABLE); } /******************************************************************************/ /** * Clear measuered data */ void clearMearusedData() { /* 1) Clear */ material.brokenAtTime = 0; material.measuredValuesCount = 0; setMaterialBroken(); /* 2) Save */ FLASHSaveData(); } /******************************************************************************/ /** * Action after material state is set */ void setMaterialBroken() { char str[6], strH[6]; // LED DIODE if (material.brokenAtTime > 0) STM_EVAL_LEDOn(LED8); else STM_EVAL_LEDOff(LED8); // LCD if( state==11 ) { if( material.brokenAtTime==0) { LCDDrawImage(LCDImageLogOK, 0, 0, LCD_WIDTH, LCD_HEIGHT - LCD_BUTTON_HEIGHT); }else{ LCDDrawImage(LCDImageLogBroken, 0, 0, LCD_WIDTH, LCD_HEIGHT - LCD_BUTTON_HEIGHT); // set time convertSecToTime(material.brokenAtTime, str, strH); LCDPrintString(strH, 0, 5); LCDPrintString(str, 32, 5); } } } /******************************************************************************/ /** * Convert seconds to time string * @param{int} seconds * @param{char* } output string for minutes and seconds * @param{char* } output string for hours */ void convertSecToTime(int seconds, char* outputMinSec, char* outputHour) { int s, m, h; m = (seconds / 60) % 60; s = seconds % 60; h = seconds / 3600; sprintf(outputMinSec, "%2d:%2d", m, s); if( s<10 )outputMinSec[3] = '0'; sprintf(outputHour, "%4dh", h); } /******************************************************************************/ /** * Show time on LCD * @param{int} seconds * @param{int} x * @param{int} row */ void LCDShowTime(int seconds) { char str[6]; char strH[6]; convertSecToTime(seconds, str, strH); LCDPrintString(str, 66, 6); LCDPrintString(strH, 66, 7); } /******************************************************************************/ /** * Show graph of measured values on LCD * @param{int} timeOffset * @param{int} zoom */ void LCDShowMeasuredValues(uint32_t timeOffset, int zoom) { uint32_t time; int32_t value; int size = LCD_WIDTH * LCD_HEIGHT; int i, o, minY = 0, maxY = LCD_HEIGHT - 2 * LCD_PAGE_SIZE; int x, y, lx, ly, lastX = -1, maxFoundY = 0, lastY = maxY; float yAxisFactor = ((float)configuration.accelMinValue * 1.3 / maxY); // convertion to lcd size if (yAxisFactor < 1)yAxisFactor = 1; timeOffset++; // fix glitch in graphics timeOffset += measuredData[0].time; /* 1) set as empty graph a template */ for (i = 0; i < size; i++) { lcdGraph[i] = LCDImageGraph[i]; } /* 2) Treshold */ y = maxY - (configuration.accelMinValue / yAxisFactor); for( i = 0; i> zoom; if (x >= LCD_WIDTH) break; // reached end of LCD y = maxY - (value / yAxisFactor); // local Y // find max Y for same x values o = i; maxFoundY = y; while(1) { if( o>=material.measuredValuesCount )break; lx = (measuredData[o].time - timeOffset) >> zoom; // local X if (lx >= LCD_WIDTH) break; // reached end of LCD ly = maxY - (measuredData[o].value / yAxisFactor); // local Y if (lx==x) { lastX = x; if (ly > maxFoundY)maxFoundY = ly; }else{ break; } o++; } i = o; // first value different then actual //draw maximum Y y = maxFoundY; if (y < minY ) y = minY; if( y > maxY) y = maxY; // set all between previous X and actual X for (o = lastX + 1; o <= x - 1; o++) { LCDSetPixel(lcdGraph, o, lastY, 1); } lastX = x; // set all between last Y and actual Y if (lastY < y) { for (o = lastY + 1; o <= y - 1; o++) LCDSetPixel(lcdGraph, x, o, 1); } else { for (o = y + 1; o <= lastY - 1; o++) LCDSetPixel(lcdGraph, x, o, 1); } LCDSetPixel(lcdGraph, x, y, 1); lastY = y; maxFoundY = value; // set as actual value (different X now) } /* 3) Draw */ LCDDrawImage(lcdGraph, 0, 0, LCD_WIDTH, LCD_HEIGHT - 2 * LCD_PAGE_SIZE); LCDPrintString("+:", 66, 6); LCDPrintNumber(graphZoomOfX, 3, 78, 6); LCDPrintString("<:", 66, 7); LCDPrintNumber(graphOffsetOfX, 3, 78, 7); } /******************************************************************************/ /** * Sets value of single pixel in image * @param{Array.uint_8} input image * @param{int} x * @param{int} y * @param{int} value */ void LCDSetPixel(uint8_t image[], int x, int y, int value) { int col, page, row, index; col = LCD_WIDTH - 1 - x; page = y / 8; row = ~(0x1 << (y % 8)); index = col + LCD_WIDTH * page; image[index] = (image[index] & row) | ((value & 0x1)<<( y % 8)); } /*********************************************************************************/ #endif