/** ****************************************************************************** * File Name : main.c * Description : Main program body ****************************************************************************** * * COPYRIGHT(c) 2017 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. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "stm32f3xx_hal.h" /* USER CODE BEGIN Includes */ #include "globals.h" #include #include #include "led_driver.h" #include "image_generator.h" #include "image_filter.h" #include "commands.h" /* USER CODE END Includes */ /* Private variables ---------------------------------------------------------*/ ADC_HandleTypeDef hadc1; TIM_HandleTypeDef htim2; TIM_HandleTypeDef htim6; TIM_HandleTypeDef htim7; DMA_HandleTypeDef hdma_tim2_ch1; /* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); void Error_Handler(void); static void MX_GPIO_Init(void); static void MX_DMA_Init(void); static void MX_TIM6_Init(void); static void MX_TIM7_Init(void); static void MX_TIM2_Init(void); static void MX_ADC1_Init(void); /* USER CODE BEGIN PFP */ /* Private function prototypes -----------------------------------------------*/ /* USER CODE END PFP */ /* USER CODE BEGIN 0 */ uint8_t raw[RAW_SIZE]; uint8_t raw_out[RAW_SIZE]; uint8_t rxWifi_raw[RAW_SIZE]; uint8_t myColor[3]; uint16_t t0,t1,t2; float frameRate; #pragma pack(4) uint8_t portamem_flip[NB_DMA_WRITES]; uint8_t portamem_flop[NB_DMA_WRITES]; uint8_t *portamem_ff[2]; uint8_t *portamem; float offsetX; float goffsetX; int ioffsetX; uint32_t currentMode; uint8_t dynamicGenerator; uint8_t intensity; // AUTO MODE // On startup or In absence of remote commands for 10 minutes, const uint8_t modTable[]={10, 1,10,19,10, 2,10,20,10, 3,10, 5,10, 4,10,12,10, 1,10,13,10, 2,10,14,10,16,10,15,10,17,10,18}; uint32_t durationTable[]={ 1,10, 2,10, 2,10, 1,10, 1,10, 2,10, 2,10, 1,10, 1,10, 2,10, 2,10, 1,10, 1,10, 2,10, 2,10, 1,10}; int findInTable(uint32_t timeSec) { int i; for (i=0;i3600)|(neverReceivedACommand)) { // which mode ??? modTime = dt % modulo; intensity = 64; currentMode = modTable[findInTable(modTime)]; switch(currentMode) { case 10 : setSpeedRPS(0.025f,speeded_time); break; default : setSpeedRPS(0,speeded_time); setOffsetX(0); break; } if (currentMode!=lastMode) // detects the cycler wants to change mode { if (lastMode!=20) { currentMode = 20; // one frame black for cleanup, just one frame } dynamicGenerator = 1; } lastMode = currentMode; } } void dmaQuickBlack(void) { initLedResetCodeInMemoryForDMA2(portamem_flip); dmaLedDrive2(portamem_flip); HAL_DMA_PollForTransfer(&hdma_tim2_ch1, HAL_DMA_FULL_TRANSFER, 20); dmaPostLedDrive(); } /* USER CODE END 0 */ int main(void) { /* USER CODE BEGIN 1 */ int firstPass; int flip_flop; int cmd_id; uint8_t receivedCommand; float time, last_time, time_speed_coeff; portamem_ff[0] = portamem_flip; portamem_ff[1] = portamem_flop; // on veut être sûr que lorsque les pin RST et EN WIFI passent en sortie, elles sont bien à 0. // Pour qu'il ne se mette pas à démarrer sans notre contrôle. GPIOA->ODR = 0; // tant que la clock n'est pas activée, ne sera pas latché (pas vérifié si c'est vraiment latché) /* USER CODE END 1 */ /* MCU Configuration----------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_TIM6_Init(); MX_TIM7_Init(); MX_TIM2_Init(); MX_ADC1_Init(); /* USER CODE BEGIN 2 */ // HAL_TIM_Base_Start(&htim2); GPIOA->ODR = 0; __HAL_DBGMCU_FREEZE_TIM2(); __HAL_DBGMCU_FREEZE_TIM6(); __HAL_DBGMCU_FREEZE_TIM7(); HAL_TIM_Base_Start(&htim6); // pour la base de temps principale. Avec une it par seconde. Secondes et 0.1ms step HAL_TIM_Base_Start(&htim7); // TIM7 à la micro seconde // on a besoin de TIM7 pour les délais power up sequence clig(); //rose 0x80, 0x40, 0x40 myColor[0] = 0xFF; myColor[1] = 0xFF; myColor[2] = 0xFF; myColor[0] = 0x80; myColor[1] = 0x40; myColor[2] = 0x40; generateUniformColor(raw,myColor); // generateBlack(raw); // generate3RGBSpaceInvaders(raw); HAL_NVIC_DisableIRQ(TIM6_DAC_IRQn); HAL_NVIC_SetPriority(TIM6_DAC_IRQn,2,2); // just below LED driver DMA TIM6->SR = 0; // Clear IT Flag HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn); TIM6->DIER |= TIM_DIER_UIE; // enable interrupt firstPass = 1; flip_flop = 0; // init DMA memory flip and flop initLedResetCodeInMemoryForDMA2(portamem_ff[0]); initLedResetCodeInMemoryForDMA2(portamem_ff[1]); currentMode = 1; dynamicGenerator = 1; intensity = 50; time_speed_coeff = 1; time = speeded_time = getTime(); // to have the current time from the start setSpeedRPS(0.0f,0); setOffsetX(0.0f); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { // setOffsetX(cos(time)); // for play receivedCommand = 0; while (commandRx(&cmd_id,rxWifi_raw, time)) { receivedCommand = 1; switch(cmd_id) { case CMD_POS : setOffsetX(*((float*)(rxWifi_raw))); RunLedToggle(); break; // case CMD_SPD : setSpeedRPS(*((float*)(rxWifi_raw)),speeded_time); RunLedToggle(); break; case CMD_SPD : time_speed_coeff = 1+9*(*((float*)(rxWifi_raw))); RunLedToggle(); break; case CMD_MOD : currentMode = *((uint32_t*)(rxWifi_raw)); setOffsetX(0); if (currentMode==10) setSpeedRPS(0.1f,speeded_time); else setSpeedRPS(0,speeded_time); dynamicGenerator = 1; RunLedToggle(); break; case CMD_RAW : memcpy(raw,rxWifi_raw,RAW_SIZE); currentMode = 0; #ifdef POWER_LIMITER powerLimiter(raw,POWER_LIMIT); #endif RunLedToggle(); break; // double copie, à éviter case CMD_INT : intensity = (uint8_t) *((uint32_t*)(rxWifi_raw)); dynamicGenerator = 1; RunLedToggle(); break; case CMD_OFF : dmaWait(); // sweet stop dmaQuickBlack(); // pour éviter la rémanence image HAL_PWR_EnterSTANDBYMode(); break; } } // memcpy(raw,rxWifi_raw,RAW_SIZE+16);checkUpdateFlash(raw); // readImageFromFlash(raw,2); // get current offset to apply. Need it to compute the partial offset on gaussian // also gets the time last_time = time; time = getTime(); speeded_time += (time-last_time)*time_speed_coeff; offsetX = updateOffsetX(speeded_time); // garanties 0<=offsetX0.5f) { goffsetX = goffsetX - 1.0f; // float part in ]-0.5;0.5] ioffsetX++; //integer part in [1;NB_COLUMNS] if (ioffsetX == NB_COLUMNS) ioffsetX = 0; //integer part in [0;NB_COLUMNS-1] } // Generate Image into raw if (currentMode!=0) { if (dynamicGenerator) { dynamicGenerator = imageGenerator(currentMode,raw,speeded_time,intensity); } } // Process Image // Requires -0.5<=goffsetX<=0.5 // needs the updated goffsetX filtreGaussienX(0.7f,NB_COLUMNS,NB_LINES, raw, raw_out,-goffsetX); // Format Data for DMA // requires 0 <= ioffset < NB_COLUMNS portamem = portamem_ff[flip_flop]; formatMemoryForDMA2(raw_out,portamem,ioffsetX); // Wait for end of previous image DMA transfer before restarting a DMA transfer if (!firstPass) { dmaWait(); t2 = TIM7->CNT; // 1787µs. OK ! Mesuré 1.7ms à l'oscillo. } // Position importante, cela assure que le DMA ne tourne plus au moment du power down. // Si PWM télécommande pas détectée, STOP sans Wifi #ifdef REMOTE_MANAGER remoteManager(); #endif // Position importante, cela assure que le DMA ne tourne plus au moment du power down. // go to sleep anyway after 10 hours, with Wifi if (time>60*60*10) { // powerDownListeningWifi(); } // Start Send Image by DMA dmaLedDrive2(portamem); // Ne prend que 2µs YES !! do { t1 = TIM7->CNT; } while(t1<10000); TIM7->CNT = 0; frameRate = 1e6/t1; firstPass = 0; flip_flop = 1 - flip_flop; } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ /* USER CODE END 3 */ } /** System Clock Configuration */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct; RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = 16; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } 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(); } HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); } /* ADC1 init function */ static void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig; /**Common config */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 2; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait = ENABLE; hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_11; sConfig.Rank = 1; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.SamplingTime = ADC_SAMPLETIME_7CYCLES_5; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /**Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_12; sConfig.Rank = 2; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } /* TIM2 init function */ static void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig; TIM_MasterConfigTypeDef sMasterConfig; TIM_OC_InitTypeDef sConfigOC; htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 25; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } if (HAL_TIM_OC_Init(&htim2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } sConfigOC.OCMode = TIM_OCMODE_TOGGLE; sConfigOC.Pulse = 10; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } } /* TIM6 init function */ static void MX_TIM6_Init(void) { TIM_MasterConfigTypeDef sMasterConfig; htim6.Instance = TIM6; htim6.Init.Prescaler = 6400; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; htim6.Init.Period = 9999; if (HAL_TIM_Base_Init(&htim6) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK) { Error_Handler(); } } /* TIM7 init function */ static void MX_TIM7_Init(void) { TIM_MasterConfigTypeDef sMasterConfig; htim7.Instance = TIM7; htim7.Init.Prescaler = 64; htim7.Init.CounterMode = TIM_COUNTERMODE_UP; htim7.Init.Period = 0xFFFF; if (HAL_TIM_Base_Init(&htim7) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim7, &sMasterConfig) != HAL_OK) { Error_Handler(); } } /** * Enable DMA controller clock */ static void MX_DMA_Init(void) { /* DMA controller clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ /* DMA1_Channel5_IRQn interrupt configuration */ HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); } /** Configure pins as * Analog * Input * Output * EVENT_OUT * EXTI */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : PA0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; 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 pin : LD3_Pin */ GPIO_InitStruct.Pin = LD3_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LD3_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : BOUTON_POUSSOIR_Pin */ GPIO_InitStruct.Pin = BOUTON_POUSSOIR_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(BOUTON_POUSSOIR_GPIO_Port, &GPIO_InitStruct); } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @param None * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler */ /* User can add his own implementation to report the HAL error return state */ while(1) { } /* USER CODE END Error_Handler */ } #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, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/