/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** ** This notice applies to any and all portions of this file * that are not between comment pairs USER CODE BEGIN and * USER CODE END. Other portions of this file, whether * inserted by the user or by software development tools * are owned by their respective copyright owners. * * COPYRIGHT(c) 2020 STMicroelectronics * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "EPD_1in54.h" #include "DEV_Config.h" #include "GUI_Paint.h" #include "ImageData.h" #include "eeprom.h" #include #include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ RTC_HandleTypeDef hrtc; SPI_HandleTypeDef hspi1; UART_HandleTypeDef huart1; /* USER CODE BEGIN PV */ PAINT_TIME sPaint_time; RTC_TimeTypeDef sTime; RTC_TimeTypeDef sTimeSet = {0,0,0}; RTC_TimeTypeDef sSetStart[7] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; RTC_TimeTypeDef sSetEnd[7] = {{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; RTC_DateTypeDef sDate = {0,1,1,20}; const uint8_t WeekLetter[7][2]={ "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So" }; enum Mode{Running, Choose, Set, Offscreen}; uint8_t system_mode = Running; uint8_t setWeekday,weekday,hour,minsec; uint8_t selector_pos = 0; //Create a new image cache UBYTE *BlackImage; UWORD Imagesize = ((EPD_WIDTH % 8 == 0) ? (EPD_WIDTH / 8) : (EPD_WIDTH / 8 + 1)) * EPD_HEIGHT; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_SPI1_Init(void); static void MX_USART1_UART_Init(void); static void MX_RTC_Init(void); /* USER CODE BEGIN PFP */ void Paint_DrawArray(void); void Paint_DrawCurrent(void); void Paint_Drawonoff(bool); void Paint_Selector(bool, uint8_t,uint8_t); void System_bjt_output(bool); void System_screenfullupdate(bool); bool System_fire(void); bool System_CustomHeartbeat(uint8_t); void ButtonLeft_Pressed(void); void ButtonPress_Pressed(void); void ButtonRight_Pressed(void); void Change_systemsetmode(void); void Change_systemmode(void); void Change_selectorpos(bool); void Change_time(uint8_t,bool); void Read_intosettime(void); void Write_intostime(void); void Eeprom_loadsettings(void); void Eeprom_savesettings(void); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_SPI1_Init(); MX_USART1_UART_Init(); MX_RTC_Init(); /* USER CODE BEGIN 2 */ if (EPD_Init(lut_full_update) != 0){ printf("e-Paper init failed\r\n"); } EPD_Clear(); DEV_Delay_ms(500); if ((BlackImage = (UBYTE *)malloc(Imagesize)) == NULL){ printf("Failed to apply for black memory...\r\n"); return 1; } Paint_NewImage(BlackImage, EPD_WIDTH, EPD_HEIGHT, 270, WHITE); Paint_SelectImage(BlackImage); Paint_Clear(WHITE); sPaint_time.Hour = 0; sPaint_time.Min = 0; sPaint_time.Sec = 0; //Partial refresh, example shows time if (EPD_Init(lut_partial_update) != 0){ printf("e-Paper init failed\r\n"); } Paint_SelectImage(BlackImage); Eeprom_loadsettings(); for (;;){ HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN); // Get Time HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN); // Get Date sPaint_time.Hour = sTime.Hours; sPaint_time.Min = sTime.Minutes; sPaint_time.Sec = sTime.Seconds; if(system_mode!=Offscreen){ // System_screenfullupdate(System_CustomHeartbeat(1)); Paint_SelectImage(BlackImage); Paint_Clear(WHITE); Paint_DrawArray(); Paint_DrawCurrent(); Paint_Selector(System_CustomHeartbeat(2),selector_pos, system_mode); Paint_Drawonoff(System_fire()); EPD_Display(BlackImage); DEV_Delay_ms(50); //Analog clock 1s } System_bjt_output(System_fire()); // else{ // Paint_Clear(WHITE); // Paint_DrawString_EN(0,0,"You can remove the monitor",&Font16,WHITE,BLACK); // EPD_Display(BlackImage); // DEV_Delay_ms(50); //Analog clock 1s // EPD_Sleep(); // } // printf("500ms..\r\n"); if(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12)){ ButtonLeft_Pressed(); } if(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13)){ ButtonPress_Pressed(); } if(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14)){ ButtonRight_Pressed(); } if(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_15)){ HAL_Delay(100); if(!HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_15)){ if(system_mode == Running){ for(uint8_t i = 0 ; i<3 ;i++){ system_mode = Offscreen; Paint_Clear(WHITE); Paint_DrawString_EN(0,0,"You can remove the monitor",&Font16,WHITE,BLACK); EPD_Display(BlackImage); DEV_Delay_ms(200); //Analog clock 1s } EPD_Sleep(); }else{ // for(uint8_t i = 0 ; i<2 ;i++){ //Partial refresh, example shows time if (EPD_Init(lut_partial_update) != 0){ printf("e-Paper init failed\r\n"); } Paint_SelectImage(BlackImage); EPD_Display(BlackImage); DEV_Delay_ms(200); // } system_mode = Running; } } } } /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /**Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.LSEState = RCC_LSE_ON; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /**Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC; PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } /** * @brief RTC Initialization Function * @param None * @retval None */ static void MX_RTC_Init(void) { /* USER CODE BEGIN RTC_Init 0 */ /* USER CODE END RTC_Init 0 */ RTC_TimeTypeDef sTime = {0}; RTC_DateTypeDef DateToUpdate = {0}; /* USER CODE BEGIN RTC_Init 1 */ /* USER CODE END RTC_Init 1 */ /**Initialize RTC Only */ hrtc.Instance = RTC; hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND; hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE; if (HAL_RTC_Init(&hrtc) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN Check_RTC_BKUP */ /* USER CODE END Check_RTC_BKUP */ /**Initialize RTC and set the Time and Date */ sTime.Hours = 0x0; sTime.Minutes = 0x0; sTime.Seconds = 0x0; if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK) { Error_Handler(); } DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY; DateToUpdate.Month = RTC_MONTH_JANUARY; DateToUpdate.Date = 0x1; DateToUpdate.Year = 0x0; if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN RTC_Init 2 */ /* USER CODE END RTC_Init 2 */ } /** * @brief SPI1 Initialization Function * @param None * @retval None */ static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ /* SPI1 parameter configuration*/ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } /** * @brief USART1 Initialization Function * @param None * @retval None */ static void MX_USART1_UART_Init(void) { /* USER CODE BEGIN USART1_Init 0 */ /* USER CODE END USART1_Init 0 */ /* USER CODE BEGIN USART1_Init 1 */ /* USER CODE END USART1_Init 1 */ huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART1_Init 2 */ /* USER CODE END USART1_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, RST_Pin|DC_Pin|BUSY_Pin|SPI_CS_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, TimerControl_Pin|LED_Pin, GPIO_PIN_RESET); /*Configure GPIO pins : RST_Pin DC_Pin BUSY_Pin SPI_CS_Pin */ GPIO_InitStruct.Pin = RST_Pin|DC_Pin|BUSY_Pin|SPI_CS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pins : TimerControl_Pin LED_Pin */ GPIO_InitStruct.Pin = TimerControl_Pin|LED_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : ButtonLeft_Pin ButtonPress_Pin ButtonRight_Pin system_mode_Pin */ GPIO_InitStruct.Pin = ButtonLeft_Pin|ButtonPress_Pin|ButtonRight_Pin|system_mode_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ void Paint_DrawArray(){ for(int i=0; i<7; i++){ sPaint_time.Hour = sSetStart[i].Hours; sPaint_time.Min = sSetStart[i].Minutes; sPaint_time.Sec = sSetStart[i].Seconds; Paint_ClearWindows(5, i*25 + 5, 5 + Font20.Width * 7, i*25 + 5 + Font20.Height, WHITE); Paint_DrawTime(5, i*25 + 5, &sPaint_time, &Font20, WHITE, BLACK); sPaint_time.Hour = sSetEnd[i].Hours; sPaint_time.Min = sSetEnd[i].Minutes; sPaint_time.Sec = sSetEnd[i].Seconds; Paint_ClearWindows(100, i*25 + 5, 100 + Font20.Width * 7, i*25 + 5 + Font20.Height, WHITE); Paint_DrawTime(100, i*25 + 5, &sPaint_time, &Font20, WHITE, BLACK); } for(uint8_t i=0; i<7 ; i++){ Paint_DrawChar(176,25*i+5,WeekLetter[i][0],&Font20,WHITE,BLACK); Paint_DrawChar(187,25*i+5,WeekLetter[i][1],&Font20,WHITE,BLACK); } } void Paint_DrawCurrent(){ weekday = sDate.WeekDay; sPaint_time.Hour = sTime.Hours; sPaint_time.Min = sTime.Minutes; sPaint_time.Sec = sTime.Seconds; if(system_mode == Set && (selector_pos == 28 || selector_pos == 29 || selector_pos == 30)){ sPaint_time.Hour = sTimeSet.Hours; sPaint_time.Min = sTimeSet.Minutes; sPaint_time.Sec = sTimeSet.Seconds; weekday = setWeekday; } Paint_ClearWindows(50, 175, 50 + Font24.Width * 7, 175 + Font24.Height, WHITE); uint8_t value[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; UWORD Dx = Font24.Width; //Write data into the cache Paint_DrawChar(50 , 175, value[sPaint_time.Hour / 10], &Font24, WHITE, BLACK); Paint_DrawChar(50 + Dx , 175, value[sPaint_time.Hour % 10], &Font24, WHITE, BLACK); if(System_CustomHeartbeat(2)){ Paint_DrawChar(50 + Dx + Dx / 4 + Dx / 2 , 175, ':' , &Font24, WHITE, BLACK); }else{ Paint_ClearWindows(80 , 175, 80 + Font24.Width * 7, 175 + Font24.Height, WHITE); } Paint_DrawChar(50 + Dx * 2 + Dx / 2 , 175, value[sPaint_time.Min / 10] , &Font24, WHITE, BLACK); Paint_DrawChar(50 + Dx * 3 + Dx / 2 , 175, value[sPaint_time.Min % 10] , &Font24, WHITE, BLACK); // Paint_DrawTime(50,175, &sPaint_time, &Font24, WHITE, BLACK); Paint_DrawChar(140,175,WeekLetter[weekday][0],&Font20,WHITE,BLACK); Paint_DrawChar(152,175,WeekLetter[weekday][1],&Font20,WHITE,BLACK); //debug Paint_DrawChar(0 , 175, value[sPaint_time.Sec / 10] , &Font24, WHITE, BLACK); Paint_DrawChar(15 , 175, value[sPaint_time.Sec % 10] , &Font24, WHITE, BLACK); } void Paint_Drawonoff(bool draw_yes){ Paint_ClearWindows(180, 180, 190, 190, WHITE); Paint_DrawRectangle(180, 180, 190, 190, BLACK, draw_yes, DOT_PIXEL_1X1); } void Paint_Selector(bool heartbeat,uint8_t pos, uint8_t runningmode){ if(runningmode == Choose || runningmode == Set){ if(runningmode == Choose){ heartbeat = true; } if(pos< MAX_SSET_POS){ const uint8_t sset_selectorpos[4]={10,45,105,140}; const uint8_t sset_selectorlength=20; uint8_t sset_selectorrow= pos/4 + 1; Paint_DrawLine(sset_selectorpos[pos%4],25*sset_selectorrow,sset_selectorpos[pos%4]+sset_selectorlength,25*sset_selectorrow,BLACK,heartbeat,DOT_PIXEL_2X2); } if(pos == 28){ Paint_DrawLine(55,195,80,195,BLACK,heartbeat,DOT_PIXEL_2X2); } if(pos == 29){ Paint_DrawLine(95,195,120,195,BLACK,heartbeat,DOT_PIXEL_2X2); } if(pos == 30){ Paint_DrawLine(140,195,165,195,BLACK,heartbeat,DOT_PIXEL_2X2); } for(uint8_t i=1 ; i<8 ; i++){ Paint_ClearWindows(0, 25*i, 200, 25*i + 2, WHITE); } } } void System_bjt_output(bool on){ if(on){ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET); }else{ HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET); } } void System_screenfullupdate(bool heartbeat){ if(heartbeat){ if (EPD_Init(lut_full_update) != 0){ printf("e-Paper init failed\r\n"); } }else{ if (EPD_Init(lut_partial_update) != 0){ printf("e-Paper init failed\r\n"); } } } bool System_fire(){ uint16_t Activetime_length_min=0, Currenttime_length_min=0; if(sSetEnd[weekday].Hours > sSetStart[weekday].Hours){ Activetime_length_min = (sSetEnd[weekday].Hours * 60 + sSetEnd[weekday].Minutes) - (sSetStart[weekday].Hours * 60 + sSetStart[weekday].Minutes); } if(sSetEnd[weekday].Hours == sSetStart[weekday].Hours){ if(sSetEnd[weekday].Minutes > sSetStart[weekday].Minutes){ Activetime_length_min = sSetEnd[weekday].Minutes - sSetStart[weekday].Minutes; } if(sSetEnd[weekday].Minutes < sSetStart[weekday].Minutes){ Activetime_length_min = 60 * 24 - (sSetStart[weekday].Minutes - sSetEnd[weekday].Minutes); } } if(sSetEnd[weekday].Hours < sSetStart[weekday].Hours){ Activetime_length_min = ( (sSetEnd[weekday].Hours + 24) * 60 + sSetEnd[weekday].Minutes ) - (sSetStart[weekday].Hours*60 + sSetStart[weekday].Minutes); } if(sTime.Hours > sSetStart[weekday].Hours){ Currenttime_length_min = (sTime.Hours * 60 + sTime.Minutes) - (sSetStart[weekday].Hours * 60 + sSetStart[weekday].Minutes); } if(sTime.Hours == sSetStart[weekday].Hours){ if(sTime.Minutes > sSetStart[weekday].Minutes){ Currenttime_length_min = sTime.Minutes - sSetStart[weekday].Minutes; } if(sTime.Minutes < sSetStart[weekday].Minutes){ Currenttime_length_min = 60 * 24 - (sSetStart[weekday].Minutes - sTime.Minutes); } } if(sTime.Hours < sSetStart[weekday].Hours){ Currenttime_length_min = ( (sTime.Hours + 24) * 60 + sTime.Minutes ) - (sSetStart[weekday].Hours*60 + sSetStart[weekday].Minutes); } if(Currenttime_length_min < Activetime_length_min){ return true; } return false; // if(sTime.Hours > sSetStart[weekday].Hours && sTime.Hours < sSetEnd[weekday].Hours){ // return true; // }else{ // if(sTime.Hours == sSetStart[weekday].Hours && sTime.Minutes >= sSetStart[weekday].Minutes){ // if(sTime.Hours <= sSetEnd[weekday].Hours){ // return true; // } // if(sTime.Hours == sSetEnd[weekday].Hours && sTime.Minutes <= sSetEnd[weekday].Minutes){ // return true; // } // } // if(sTime.Hours == sSetEnd[weekday].Hours && sTime.Minutes <= sSetEnd[weekday].Minutes){ // if(sTime.Hours >= sSetStart[weekday].Hours){ // return true; // } // if(sTime.Hours == sSetStart[weekday].Hours && sTime.Minutes >= sSetStart[weekday].Minutes){ // return true; // } // } // } // // return false; } bool System_CustomHeartbeat(uint8_t var){ if(sTime.Seconds%var == 0){ return true; }else{ return false; } } //keep it short, executed in ISR void ButtonLeft_Pressed(void){ if(system_mode==Choose){ Change_selectorpos(false); } if(system_mode==Set){ Change_time(selector_pos,false); } }; //keep it short, executed in ISR void ButtonPress_Pressed(void){ if(selector_pos==28 || selector_pos == 29 || selector_pos == 30){ if(system_mode == Choose){ //read time to sTimeSet Read_intosettime(); } if(system_mode == Set){ //write time back to RTC Write_intostime(); if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK) { Error_Handler(); } if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK) { Error_Handler(); } } } if(system_mode == Set){ Eeprom_savesettings(); } Change_systemmode(); }; //keep it short, executed in ISR void ButtonRight_Pressed(void){ if(system_mode==Choose){ Change_selectorpos(true); } if(system_mode==Set){ Change_time(selector_pos,true); } }; void Change_systemsetmode(){ if(system_mode == Choose){ system_mode = Set; } if(system_mode == Set){ system_mode = Choose; } } void Change_systemmode(){ system_mode == 2 ? system_mode = 0 : system_mode++; } void Change_time(uint8_t selectorpos, bool increase){ if(selectorpos < 28){ uint8_t setrow = selectorpos/4; uint8_t setpos = selectorpos%4; if(increase){ //ssetstart if(setpos<2){ if(setpos==0){ sSetStart[setrow].Hours == 23 ? sSetStart[setrow].Hours = 0 : sSetStart[setrow].Hours ++; } if(setpos==1){ sSetStart[setrow].Minutes == 59 ? sSetStart[setrow].Minutes = 0 : sSetStart[setrow].Minutes ++; } }else{ //ssetend if(setpos==2){ sSetEnd[setrow].Hours == 23 ? sSetEnd[setrow].Hours = 0 : sSetEnd[setrow].Hours ++; } if(setpos==3){ sSetEnd[setrow].Minutes == 59 ? sSetEnd[setrow].Minutes = 0 : sSetEnd[setrow].Minutes ++; } } }else{ //ssetstart if(setpos<2){ if(setpos==0){ sSetStart[setrow].Hours == 0 ? sSetStart[setrow].Hours = 23 : sSetStart[setrow].Hours --; } if(setpos==1){ sSetStart[setrow].Minutes == 0 ? sSetStart[setrow].Minutes = 59 : sSetStart[setrow].Minutes --; } }else{ //ssetend if(setpos==2){ sSetEnd[setrow].Hours == 0 ? sSetEnd[setrow].Hours = 23 : sSetEnd[setrow].Hours --; } if(setpos==3){ sSetEnd[setrow].Minutes == 0 ? sSetEnd[setrow].Minutes = 59 : sSetEnd[setrow].Minutes --; } } } } if(selectorpos >= 28 && selectorpos < 31){ if(selectorpos == 28){ if(increase){ sTimeSet.Hours == 23 ? sTimeSet.Hours = 0 : sTimeSet.Hours++; }else{ sTimeSet.Hours == 0 ? sTimeSet.Hours = 23 : sTimeSet.Hours--; } } if(selectorpos == 29){ if(increase){ sTimeSet.Minutes == 59 ? sTimeSet.Minutes = 0 : sTimeSet.Minutes++; }else{ sTimeSet.Minutes == 0 ? sTimeSet.Minutes = 59 : sTimeSet.Minutes--; } } if(selectorpos == 30){ if(increase){ setWeekday == 6 ? setWeekday = 0 : setWeekday++; }else{ setWeekday == 0 ? setWeekday = 6 : setWeekday--; } } } } void Change_selectorpos(bool increase){ if(increase){ selector_pos == 30 ? selector_pos = 0 : selector_pos++; }else{ selector_pos == 0 ? selector_pos = 30 : selector_pos--; } }; void Read_intosettime(){ sTimeSet = sTime; setWeekday = sDate.WeekDay; }; void Write_intostime(){ sTime = sTimeSet; sDate.Date = setWeekday + 2; //date hack because the RTC auto detect the weekday from the date } void Eeprom_loadsettings(){ for(uint8_t i=0 ; i < 7 ; i++){ if((uint8_t) (readEEPROMHalfWord(2*i) >> 8) >= 0 && (uint8_t) (readEEPROMHalfWord(2*i) >> 8) < 24){ sSetStart[i].Hours = (uint8_t) (readEEPROMHalfWord(2*i) >> 8); }else{ sSetStart[i].Hours = 0; } if((uint8_t) readEEPROMHalfWord(2*i) >= 0 && (uint8_t) readEEPROMHalfWord(2*i) < 60){ sSetStart[i].Minutes = (uint8_t) readEEPROMHalfWord(2*i); }else{ sSetStart[i].Minutes = 0; } if((uint8_t) (readEEPROMHalfWord(2*i + 14) >> 8) >= 0 && (uint8_t) (readEEPROMHalfWord(2*i + 14) >> 8) < 24){ sSetEnd[i].Hours = (uint8_t) (readEEPROMHalfWord(2*i + 14) >> 8); }else{ sSetEnd[i].Hours = 0; } if((uint8_t) readEEPROMHalfWord(2*i + 14) >= 0 && (uint8_t) readEEPROMHalfWord(2*i + 14) < 60){ sSetEnd[i].Minutes = (uint8_t) readEEPROMHalfWord(2*i + 14); }else{ sSetEnd[i].Minutes = 0; } } } void Eeprom_savesettings(){ enableEEPROMWriting(); for(uint8_t i = 0; i < 7; i++){ writeEEPROMHalfWord(2*i,sSetStart[i].Hours << 8 | sSetStart[i].Minutes); writeEEPROMHalfWord(2*i + 14,sSetEnd[i].Hours << 8 | sSetEnd[i].Minutes); } disableEEPROMWriting(); } int __io_putchar(int ch){ uint8_t c[1]; c[0] = ch & 0x00FF; HAL_UART_Transmit(&huart1, &*c, 1, 10); return ch; } int _write(int file, char *ptr, int len){ int DataIdx; for (DataIdx = 0; DataIdx < len; DataIdx++){ __io_putchar(*ptr++); } return len; } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/