anfractuosity 2 лет назад
Родитель
Сommit
cc7927fdc4
2 измененных файлов с 55 добавлено и 23 удалено
  1. 3 1
      application.fam
  2. 52 22
      scenes/scope_scene_run.c

+ 3 - 1
application.fam

@@ -11,7 +11,9 @@ App(
         Lib(name="adc",
             fap_include_paths=["inc"],
             sources=[
-                "stm32wbxx_hal_adc.c", "stm32wbxx_hal_adc_ex.c", "stm32wbxx_hal_rcc_ex.c", "stm32wbxx_hal_gpio.c", "stm32wbxx_hal_pwr.c", "stm32wbxx_hal.c", "stm32wbxx_hal_tim.c", "stm32wbxx_hal_tim_ex.c", "stm32wbxx_hal_cortex.c", "stm32wbxx_hal_dma.c", "stm32wbxx_hal_rcc.c"
+                "stm32wbxx_hal_adc.c", "stm32wbxx_hal_adc_ex.c", "stm32wbxx_hal_rcc_ex.c", "stm32wbxx_hal_gpio.c",
+                "stm32wbxx_hal_pwr.c", "stm32wbxx_hal.c", "stm32wbxx_hal_tim.c", "stm32wbxx_hal_tim_ex.c",
+                "stm32wbxx_hal_cortex.c", "stm32wbxx_hal_dma.c", "stm32wbxx_hal_rcc.c"
             ],
     )]
 )

+ 52 - 22
scenes/scope_scene_run.c

@@ -32,11 +32,12 @@ const uint32_t AHBPrescTable[16UL] = {1UL, 3UL, 5UL, 1UL, 1UL, 6UL, 10UL, 32UL,
 const uint32_t APBPrescTable[8UL]  = {0UL, 0UL, 0UL, 0UL, 1UL, 2UL, 3UL, 4UL};
 const uint32_t MSIRangeTable[16UL] = {100000UL, 200000UL, 400000UL, 800000UL, 1000000UL, 2000000UL, \
                                       4000000UL, 8000000UL, 16000000UL, 24000000UL, 32000000UL, 48000000UL, 0UL, 0UL, 0UL, 0UL}; /* 0UL values are incorrect cases */
-char * time;
-double freq;
-uint8_t pause=0;
-enum measureenum type;
-int toggle = 0;
+
+char * time;            // Current time period text
+double freq;            // Current samplerate
+uint8_t pause=0;        // Whether we want to pause output or not
+enum measureenum type;  // Type of measurement we are performing
+int toggle = 0;         // Used for toggling output GPIO, only used in testing
 
 void Error_Handler()
 {
@@ -47,12 +48,14 @@ void Error_Handler()
 static ADC_HandleTypeDef hadc1;
 static DMA_HandleTypeDef hdma_adc1;
 static TIM_HandleTypeDef htim2;
-__IO uint16_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE];       /* ADC group regular conversion data (array of data) */
-__IO uint16_t aADCxConvertedData_Voltage_mVoltA[ADC_CONVERTED_DATA_BUFFER_SIZE]; /* Value of voltage calculated from ADC conversion data (unit: mV) (array of data) */
-__IO uint16_t aADCxConvertedData_Voltage_mVoltB[ADC_CONVERTED_DATA_BUFFER_SIZE]; /* Value of voltage calculated from ADC conversion data (unit: mV) (array of data) */
-__IO uint8_t ubDmaTransferStatus = 2;   /* Variable set into DMA interruption callback */
-__IO uint16_t *mvoltWrite = &aADCxConvertedData_Voltage_mVoltA[0];
-__IO uint16_t *mvoltDisplay = &aADCxConvertedData_Voltage_mVoltB[0];
+
+__IO uint16_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFER_SIZE];                   // Array that ADC data is copied to, via DMA
+__IO uint16_t aADCxConvertedData_Voltage_mVoltA[ADC_CONVERTED_DATA_BUFFER_SIZE];    // Data is converted to range from 0 to 3300
+__IO uint16_t aADCxConvertedData_Voltage_mVoltB[ADC_CONVERTED_DATA_BUFFER_SIZE];    // Data is converted to range from 0 to 3300
+__IO uint8_t ubDmaTransferStatus = 2;                                               // DMA transfer status
+
+__IO uint16_t *mvoltWrite = &aADCxConvertedData_Voltage_mVoltA[0];                  // Pointer to area we write converted voltage data to
+__IO uint16_t *mvoltDisplay = &aADCxConvertedData_Voltage_mVoltB[0];                // Pointer to area of memory we display
 
 void HAL_ADC_MspInit(ADC_HandleTypeDef * hadc)
 {
@@ -124,6 +127,7 @@ void TIM2_IRQHandler(void)
     HAL_TIM_IRQHandler(&htim2);
 }
 
+// Setup ADC1 to be triggered by timer2
 static void MX_ADC1_Init(void)
 {
     ADC_ChannelConfTypeDef sConfig = { 0 };
@@ -156,6 +160,7 @@ static void MX_ADC1_Init(void)
     }
 }
 
+// Only used in testing, for toggling GPIO pin, to measure timer frequency
 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 {
     if (htim->Instance == TIM2){
@@ -164,6 +169,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
     }
 }
 
+// Init timer2
 static void MX_TIM2_Init(uint32_t period)
 {
     TIM_ClockConfigTypeDef sClockSourceConfig = { 0 };
@@ -201,6 +207,7 @@ static void MX_GPIO_Init(void)
     __HAL_RCC_GPIOC_CLK_ENABLE();
 }
 
+// Swap pointer addresses, used for double buffer
 void swap(__IO uint16_t **a, __IO uint16_t **b){
     __IO uint16_t *tmp;
     tmp = *a;
@@ -208,6 +215,7 @@ void swap(__IO uint16_t **a, __IO uint16_t **b){
     *b = tmp;
 }
 
+// Write end half of DMA buffer to converted output
 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef * hadc)
 {
     UNUSED(hadc);
@@ -216,10 +224,12 @@ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef * hadc)
         mvoltWrite[tmp_index] = __ADC_CALC_DATA_VOLTAGE(VDDA_APPLI, aADCxConvertedData[tmp_index]);
     }
     ubDmaTransferStatus = 1;
+    // Swap double buffer, so new data can be displayed, provided we're not paused
     if(!pause)
         swap(&mvoltWrite, &mvoltDisplay);
 }
 
+// Write first half of DMA buffer to converted output
 void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef * hadc)
 {
     UNUSED(hadc);
@@ -236,6 +246,7 @@ void HAL_ADC_ErrorCallback(ADC_HandleTypeDef * hadc)
     Error_Handler();
 }
 
+// Used to draw to display
 static void app_draw_callback(Canvas * canvas, void *ctx)
 {
     UNUSED(ctx);
@@ -248,6 +259,7 @@ static void app_draw_callback(Canvas * canvas, void *ctx)
     int count = 0;
     char buf1[50];
 
+    // Calculate voltage measurements
     for(uint32_t x = 0; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++){
         if(mvoltDisplay[x] < min)
             min = mvoltDisplay[x];
@@ -260,20 +272,25 @@ static void app_draw_callback(Canvas * canvas, void *ctx)
     switch(type){
         case m_time:
             {
+                // Display current time period
                 snprintf(buf1, 50, "Time: %s", time);
                 canvas_draw_str(canvas, 10, 10, buf1);
+                // Shift waveform across a virtual 0 line, so it crosses 0
                 for(uint32_t x = 0; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++){
                     index[x] = -1;
                     crossings[x] = -1.0;
                     data[x] = ((float)mvoltDisplay[x] / 1000) - min;
                     data[x] = ((2 / (max - min)) * data[x]) - 1;
                 }
+                // Find points at which waveform crosses virtual 0 line
                 for(uint32_t x = 1; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++){
                     if(data[x] >= 0 && data[x-1] < 0){
                         index[count++] = x - 1;
                     }
                 }
                 count=0;
+                // Linear interpolation to find zero crossings
+                // see https://gist.github.com/endolith/255291 for Python version
                 for(uint32_t x = 0; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++){
                     if(index[x] == -1)
                         break;
@@ -282,20 +299,22 @@ static void app_draw_callback(Canvas * canvas, void *ctx)
                 float avg = 0.0;
                 float countv = 0.0;
                 for(uint32_t x = 0; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++){
-                    if(crossings[x] == -1 || crossings[x+1] == -1)
-                        break;
                     if(x + 1 >= ADC_CONVERTED_DATA_BUFFER_SIZE)
                        break;
+                    if(crossings[x] == -1 || crossings[x+1] == -1)
+                        break;
                     avg += crossings[x+1] - crossings[x];
                     countv += 1;
                 }
                 avg /= countv;
+                // Display frequency of waveform
                 snprintf(buf1, 50, "Freq: %.1f Hz", (double)((float)freq / avg));
                 canvas_draw_str(canvas, 10, 20, buf1);
             }
             break;
         case m_voltage:
             {
+                // Display max, min, peak-to-peak voltages
                 snprintf(buf1, 50, "Max: %.2fV", (double)max);
                 canvas_draw_str(canvas, 10, 10, buf1);
                 snprintf(buf1, 50, "Min: %.2fV", (double)min);
@@ -308,12 +327,14 @@ static void app_draw_callback(Canvas * canvas, void *ctx)
             break;
     }
 
+    // Draw lines between each data point
     for(uint32_t x = 1; x < ADC_CONVERTED_DATA_BUFFER_SIZE; x++){
         uint32_t prev = 64 - (mvoltDisplay[x-1] / (VDDA_APPLI / 64));
         uint32_t cur = 64 - (mvoltDisplay[x] / (VDDA_APPLI / 64));
         canvas_draw_line(canvas, x - 1, prev, x, cur);
     }
 
+    // Draw graph lines
     canvas_draw_line(canvas, 0, 0, 0, 63);
     canvas_draw_line(canvas, 0, 63, 128, 63);
 }
@@ -337,21 +358,26 @@ void scope_scene_run_widget_callback(
 
 void scope_scene_run_on_enter(void* context) {
     ScopeApp* app = context;
+
+    // Find string representation of time period we're using
     for (uint32_t i = 0; i < COUNT_OF(time_list); i++){
         if(time_list[i].time == app->time){
             time = time_list[i].str;
             break;
         }
     }
+
+    // Currently un-paused
     pause = 0;
+
+    // What type of measurement are we performing
     type = app->measurement;
 
     // Test purposes
-    /*
-    furi_hal_gpio_write(&gpio_ext_pa7, false);
-    furi_hal_gpio_init( &gpio_ext_pa7, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
-    */
+    //furi_hal_gpio_write(&gpio_ext_pa7, false);
+    //furi_hal_gpio_init( &gpio_ext_pa7, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
 
+    // Copy vector table, modify to use our own IRQ handlers
     __disable_irq();
     memcpy(ramVector, (uint32_t*)(FLASH_BASE | SCB->VTOR), sizeof(uint32_t) * TABLE_SIZE);
     SCB->VTOR = (uint32_t)ramVector;
@@ -360,6 +386,8 @@ void scope_scene_run_on_enter(void* context) {
     ramVector[44] = (uint32_t)TIM2_IRQHandler;
     __enable_irq();
 
+    // Found this recommended by https://www.freertos.org/RTOS-Cortex-M3-M4.html
+    // although we're using after RTOS started
     HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
 
     FuriMessageQueue *event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
@@ -374,6 +402,7 @@ void scope_scene_run_on_enter(void* context) {
 
     MX_TIM2_Init(period);
 
+    // Set VREFBUF, as vref isn't connected to 3.3V itself in the flipper zero
     VREFBUF->CSR |= VREFBUF_CSR_ENVR;
     VREFBUF->CSR &= ~VREFBUF_CSR_HIZ;
     VREFBUF->CSR |= VREFBUF_CSR_VRS;
@@ -382,11 +411,11 @@ void scope_scene_run_on_enter(void* context) {
 
     MX_ADC1_Init();
 
+    // Setup initial values from ADC
     for (tmp_index_adc_converted_data = 0;
          tmp_index_adc_converted_data < ADC_CONVERTED_DATA_BUFFER_SIZE;
          tmp_index_adc_converted_data++) {
-        aADCxConvertedData[tmp_index_adc_converted_data] =
-            VAR_CONVERTED_DATA_INIT_VALUE;
+        aADCxConvertedData[tmp_index_adc_converted_data] = VAR_CONVERTED_DATA_INIT_VALUE;
         aADCxConvertedData_Voltage_mVoltA[tmp_index_adc_converted_data] = 0;
         aADCxConvertedData_Voltage_mVoltB[tmp_index_adc_converted_data] = 0;
     }
@@ -395,14 +424,13 @@ void scope_scene_run_on_enter(void* context) {
         Error_Handler();
     }
 
-    /*
     // Use to generate interrupt to toggle GPIO for testing
-    if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK) {
-    */
+    //if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK) {
     if (HAL_TIM_Base_Start(&htim2) != HAL_OK) {
         Error_Handler();
     }
 
+    // Start DMA transfer
     if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *) aADCxConvertedData, ADC_CONVERTED_DATA_BUFFER_SIZE) != HAL_OK) {
         Error_Handler();
     }
@@ -440,6 +468,7 @@ void scope_scene_run_on_enter(void* context) {
         view_port_update(view_port);
     }
 
+    // Stop DMA and switch back to original vector table
     HAL_ADC_Stop_DMA (&hadc1);
     __disable_irq();
     SCB->VTOR = 0;
@@ -449,6 +478,7 @@ void scope_scene_run_on_enter(void* context) {
     gui_remove_view_port(gui, view_port);
     view_port_free(view_port);
 
+    // Switch back to original scene
     furi_record_close(RECORD_GUI);
     scene_manager_previous_scene(app->scene_manager);
     submenu_set_selected_item(app->submenu, 0);