Merge branch 'display'
- merge display branch with outsourced and reworked display code - resolve merge conflict caused by new ENCODER_TEST feature in main
This commit is contained in:
		
						commit
						5a3c6b15bc
					
				| @ -236,7 +236,7 @@ esp_err_t max7219_draw_text_7seg(max7219_t *dev, uint8_t pos, const char *s) | |||||||
| { | { | ||||||
|     CHECK_ARG(dev && s); |     CHECK_ARG(dev && s); | ||||||
| 
 | 
 | ||||||
|     while (s && pos < dev->digits) |     while (*s != '\0' && pos < dev->digits) | ||||||
|     { |     { | ||||||
|         uint8_t c = get_char(dev, *s); |         uint8_t c = get_char(dev, *s); | ||||||
|         if (*(s + 1) == '.') |         if (*(s + 1) == '.') | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ idf_component_register( | |||||||
|         "control.cpp" |         "control.cpp" | ||||||
|         "buzzer.cpp" |         "buzzer.cpp" | ||||||
|         "vfd.cpp" |         "vfd.cpp" | ||||||
|  |         "display.cpp" | ||||||
|     INCLUDE_DIRS  |     INCLUDE_DIRS  | ||||||
|         "." |         "." | ||||||
|     ) |     ) | ||||||
|  | |||||||
							
								
								
									
										159
									
								
								main/control.cpp
									
									
									
									
									
								
							
							
						
						
									
										159
									
								
								main/control.cpp
									
									
									
									
									
								
							| @ -1,32 +1,5 @@ | |||||||
| #include "control.hpp" | #include "control.hpp" | ||||||
| 
 | 
 | ||||||
| //========================
 |  | ||||||
| //===== init display =====
 |  | ||||||
| //========================
 |  | ||||||
| max7219_t init_display(){ |  | ||||||
|     // Configure SPI bus
 |  | ||||||
|     spi_bus_config_t cfg; |  | ||||||
|     cfg.mosi_io_num = DISPLAY_PIN_NUM_MOSI; |  | ||||||
|     cfg.miso_io_num = -1; |  | ||||||
|     cfg.sclk_io_num = DISPLAY_PIN_NUM_CLK; |  | ||||||
|     cfg.quadwp_io_num = -1; |  | ||||||
|     cfg.quadhd_io_num = -1; |  | ||||||
|     cfg.max_transfer_sz = 0; |  | ||||||
|     cfg.flags = 0; |  | ||||||
|     ESP_ERROR_CHECK(spi_bus_initialize(HOST, &cfg, 1)); |  | ||||||
| 
 |  | ||||||
|     // Configure device
 |  | ||||||
|     max7219_t dev; |  | ||||||
|     dev.cascade_size = 2; |  | ||||||
|     dev.digits = 0; |  | ||||||
|     dev.mirrored = true; |  | ||||||
|     ESP_ERROR_CHECK(max7219_init_desc(&dev, HOST, MAX7219_MAX_CLOCK_SPEED_HZ, DISPLAY_PIN_NUM_CS)); |  | ||||||
|     ESP_ERROR_CHECK(max7219_init(&dev)); |  | ||||||
|     //0...15
 |  | ||||||
|     ESP_ERROR_CHECK(max7219_set_brightness(&dev, 12)); |  | ||||||
|     return dev; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| //========================
 | //========================
 | ||||||
| //===== init encoder =====
 | //===== init encoder =====
 | ||||||
| @ -81,7 +54,6 @@ static const char *TAG = "control"; //tag for logging | |||||||
| const char* systemStateStr[5] = {"COUNTING", "WINDING_START", "WINDING", "TARGET_REACHED", "MANUAL"}; | const char* systemStateStr[5] = {"COUNTING", "WINDING_START", "WINDING", "TARGET_REACHED", "MANUAL"}; | ||||||
| systemState_t controlState = COUNTING; | systemState_t controlState = COUNTING; | ||||||
| 
 | 
 | ||||||
| max7219_t display; //display device
 |  | ||||||
| char buf_disp[20]; //both displays
 | char buf_disp[20]; //both displays
 | ||||||
| char buf_disp1[10];// 8 digits + decimal point + \0
 | char buf_disp1[10];// 8 digits + decimal point + \0
 | ||||||
| char buf_disp2[10];// 8 digits + decimal point + \0
 | char buf_disp2[10];// 8 digits + decimal point + \0
 | ||||||
| @ -91,7 +63,6 @@ rotary_encoder_info_t encoder; //encoder device/info | |||||||
| QueueHandle_t encoder_queue = NULL; //encoder event queue
 | QueueHandle_t encoder_queue = NULL; //encoder event queue
 | ||||||
| rotary_encoder_state_t encoderState; | rotary_encoder_state_t encoderState; | ||||||
| 
 | 
 | ||||||
| uint8_t count = 0; //count for testing
 |  | ||||||
| uint32_t timestamp_pageSwitched = 0; | uint32_t timestamp_pageSwitched = 0; | ||||||
| bool page = false; //store page number currently displayed
 | bool page = false; //store page number currently displayed
 | ||||||
| int lengthNow = 0; //length measured in mm
 | int lengthNow = 0; //length measured in mm
 | ||||||
| @ -120,19 +91,25 @@ void changeState (systemState_t stateNew) { | |||||||
| //===== handle Stop Condition =====
 | //===== handle Stop Condition =====
 | ||||||
| //function that checks whether start button is released or target is reached (used in multiple states)
 | //function that checks whether start button is released or target is reached (used in multiple states)
 | ||||||
| //returns true when stopped, false when no action
 | //returns true when stopped, false when no action
 | ||||||
| bool handleStopCondition(){ | bool handleStopCondition(handledDisplay * displayTop, handledDisplay * displayBot){ | ||||||
|     //--- stop conditions ---
 |     //--- stop conditions ---
 | ||||||
|     //stop conditions that are checked in any mode
 |     //stop conditions that are checked in any mode
 | ||||||
|     //target reached
 |     //target reached
 | ||||||
|     if (lengthRemaining <= 0 ) { |     if (lengthRemaining <= 0 ) { | ||||||
|         changeState(TARGET_REACHED); |         changeState(TARGET_REACHED); | ||||||
|         vfd_setState(false); |         vfd_setState(false); | ||||||
|  |         displayTop->blink(1, 0, 1500, "  S0LL  "); | ||||||
|  |         displayBot->blink(1, 0, 1500, "ERREICHT"); | ||||||
|  |         buzzer.beep(2, 100, 100); | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|     //start button released
 |     //start button released
 | ||||||
|     else if (SW_START.state == false) { |     else if (SW_START.state == false) { | ||||||
|         changeState(COUNTING); |         changeState(COUNTING); | ||||||
|         vfd_setState(false); |         vfd_setState(false); | ||||||
|  |         displayTop->blink(2, 900, 1000, "- STOP -"); | ||||||
|  |         displayBot->blink(2, 900, 1000, " TASTER "); | ||||||
|  |         buzzer.beep(3, 200, 100); | ||||||
|         return true; |         return true; | ||||||
|     } else { |     } else { | ||||||
|         return false; |         return false; | ||||||
| @ -171,28 +148,19 @@ void setDynSpeedLvl(uint8_t lvlMax = 3){ | |||||||
| //========================
 | //========================
 | ||||||
| void task_control(void *pvParameter) | void task_control(void *pvParameter) | ||||||
| { | { | ||||||
|     //initialize display
 |  | ||||||
|     display = init_display(); |  | ||||||
|     //initialize encoder
 |     //initialize encoder
 | ||||||
|     encoder_queue = init_encoder(&encoder); |     encoder_queue = init_encoder(&encoder); | ||||||
| 
 | 
 | ||||||
|     //-----------------------------------
 |     //initialize display
 | ||||||
|     //------- display welcome msg -------
 |     max7219_t two7SegDisplays = display_init(); | ||||||
|     //-----------------------------------
 |     //create two separate handled display instances
 | ||||||
|  |     handledDisplay displayTop(two7SegDisplays, 0); | ||||||
|  |     handledDisplay displayBot(two7SegDisplays, 8); | ||||||
|  | 
 | ||||||
|  |     //--- display welcome msg ---
 | ||||||
|     //display welcome message on two 7 segment displays
 |     //display welcome message on two 7 segment displays
 | ||||||
|     //show name and date
 |     //currently show name and date and scrolling 'hello'
 | ||||||
|     ESP_LOGI(TAG, "showing startup message..."); |     display_ShowWelcomeMsg(two7SegDisplays); | ||||||
|     max7219_clear(&display); |  | ||||||
|     max7219_draw_text_7seg(&display, 0, "CUTTER  20.08.2022"); |  | ||||||
|     //                                   1234567812 34 5678
 |  | ||||||
|     vTaskDelay(pdMS_TO_TICKS(700)); |  | ||||||
|     //scroll "hello" over 2 displays
 |  | ||||||
|     for (int offset = 0; offset < 23; offset++) { |  | ||||||
|         max7219_clear(&display); |  | ||||||
|         char hello[23] = "                HELL0 "; |  | ||||||
|         max7219_draw_text_7seg(&display, 0, hello + (22 - offset) ); |  | ||||||
|         vTaskDelay(pdMS_TO_TICKS(50)); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     //================
 |     //================
 | ||||||
| @ -278,6 +246,7 @@ void task_control(void *pvParameter) | |||||||
|         } |         } | ||||||
|         if (SW_SET.fallingEdge) { |         if (SW_SET.fallingEdge) { | ||||||
|             buzzer.beep(2, 70, 50); |             buzzer.beep(2, 70, 50); | ||||||
|  |             displayBot.blink(2, 100, 100, "S0LL    "); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -286,14 +255,17 @@ void task_control(void *pvParameter) | |||||||
|             if (SW_PRESET1.risingEdge){ |             if (SW_PRESET1.risingEdge){ | ||||||
|                 lengthTarget = 1000; |                 lengthTarget = 1000; | ||||||
|                 buzzer.beep(lengthTarget/1000, 25, 30); |                 buzzer.beep(lengthTarget/1000, 25, 30); | ||||||
|  |                 displayBot.blink(3, 100, 100, "S0LL    "); | ||||||
|             } |             } | ||||||
|             else if (SW_PRESET2.risingEdge) { |             else if (SW_PRESET2.risingEdge) { | ||||||
|                 lengthTarget = 5000; |                 lengthTarget = 5000; | ||||||
|                 buzzer.beep(lengthTarget/1000, 25, 30); |                 buzzer.beep(lengthTarget/1000, 25, 30); | ||||||
|  |                 displayBot.blink(2, 100, 100, "S0LL    "); | ||||||
|             } |             } | ||||||
|             else if (SW_PRESET3.risingEdge) { |             else if (SW_PRESET3.risingEdge) { | ||||||
|                 lengthTarget = 10000; |                 lengthTarget = 10000; | ||||||
|                 buzzer.beep(lengthTarget/1000, 25, 30); |                 buzzer.beep(lengthTarget/1000, 25, 30); | ||||||
|  |                 displayBot.blink(2, 100, 100, "S0LL    "); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -309,6 +281,7 @@ void task_control(void *pvParameter) | |||||||
|         switch (controlState) { |         switch (controlState) { | ||||||
|             case COUNTING: //no motor action
 |             case COUNTING: //no motor action
 | ||||||
|                 vfd_setState(false); |                 vfd_setState(false); | ||||||
|  |                 //TODO check stop condition before starting - prevents motor from starting 2 cycles when 
 | ||||||
|                 //--- start winding to length ---
 |                 //--- start winding to length ---
 | ||||||
|                 if (SW_START.risingEdge) { |                 if (SW_START.risingEdge) { | ||||||
|                     changeState(WINDING_START); |                     changeState(WINDING_START); | ||||||
| @ -326,14 +299,14 @@ void task_control(void *pvParameter) | |||||||
|                 if (esp_log_timestamp() - timestamp_motorStarted > 2000) { |                 if (esp_log_timestamp() - timestamp_motorStarted > 2000) { | ||||||
|                     changeState(WINDING); |                     changeState(WINDING); | ||||||
|                 } |                 } | ||||||
|                 handleStopCondition(); //stops if button released or target reached
 |                 handleStopCondition(&displayTop, &displayBot); //stops if button released or target reached
 | ||||||
|                 //TODO: cancel when there was no cable movement during start time?
 |                 //TODO: cancel when there was no cable movement during start time?
 | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case WINDING: //wind fast, slow down when close
 |             case WINDING: //wind fast, slow down when close
 | ||||||
|                 //set vfd speed depending on remaining distance 
 |                 //set vfd speed depending on remaining distance 
 | ||||||
|                 setDynSpeedLvl(); //slow down when close to target
 |                 setDynSpeedLvl(); //slow down when close to target
 | ||||||
|                 handleStopCondition(); //stops if button released or target reached
 |                 handleStopCondition(&displayTop, &displayBot); //stops if button released or target reached
 | ||||||
|                 //TODO: cancel when there is no cable movement anymore e.g. empty / timeout?
 |                 //TODO: cancel when there is no cable movement anymore e.g. empty / timeout?
 | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
| @ -343,6 +316,12 @@ void task_control(void *pvParameter) | |||||||
|                 if ( lengthRemaining > 0 ) { |                 if ( lengthRemaining > 0 ) { | ||||||
|                     changeState(COUNTING); |                     changeState(COUNTING); | ||||||
|                 } |                 } | ||||||
|  |                 //show msg when trying to start, but target is reached
 | ||||||
|  |                 if (SW_START.risingEdge){ | ||||||
|  |                     buzzer.beep(3, 40, 30); | ||||||
|  |                     displayTop.blink(2, 600, 800, "  S0LL  "); | ||||||
|  |                     displayBot.blink(2, 600, 800, "ERREICHT"); | ||||||
|  |                 } | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case MANUAL: //manually control motor via preset buttons + poti
 |             case MANUAL: //manually control motor via preset buttons + poti
 | ||||||
| @ -359,48 +338,84 @@ void task_control(void *pvParameter) | |||||||
|                 else if ( SW_PRESET1.state && !SW_PRESET3.state ) { |                 else if ( SW_PRESET1.state && !SW_PRESET3.state ) { | ||||||
|                     vfd_setSpeedLevel(level); //TODO: use poti input for level
 |                     vfd_setSpeedLevel(level); //TODO: use poti input for level
 | ||||||
|                     vfd_setState(true, REV); |                     vfd_setState(true, REV); | ||||||
|  |                     sprintf(buf_disp2, "[--%02i   ", level); | ||||||
|  |                     //                  123 45 678
 | ||||||
|                 } |                 } | ||||||
|                 //P2 + P3 -> turn right
 |                 //P2 + P3 -> turn right
 | ||||||
|                 else if ( SW_PRESET3.state && !SW_PRESET1.state ) { |                 else if ( SW_PRESET3.state && !SW_PRESET1.state ) { | ||||||
|                     vfd_setSpeedLevel(level); //TODO: use poti input for level
 |                     vfd_setSpeedLevel(level); //TODO: use poti input for level
 | ||||||
|                     vfd_setState(true, FWD); |                     vfd_setState(true, FWD); | ||||||
|  |                     sprintf(buf_disp2, "   %02i--]", level); | ||||||
|                 } |                 } | ||||||
|                 //no valid switch combination -> turn off motor
 |                 //no valid switch combination -> turn off motor
 | ||||||
|                 else { |                 else { | ||||||
|                     vfd_setState(false); |                     vfd_setState(false); | ||||||
|  |                     sprintf(buf_disp2, "   %02i   ", level); | ||||||
|                 } |                 } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         //---------------------------
 |         //--------------------------
 | ||||||
|         //--------- display ---------
 |         //------ encoder test ------
 | ||||||
|         //---------------------------
 |         //--------------------------
 | ||||||
| #ifdef ENCODER_TEST | #ifdef ENCODER_TEST | ||||||
|  |         //run display handle functions
 | ||||||
|  |         displayTop.handle(); | ||||||
|  |         displayBot.handle(); | ||||||
|         //-- show encoder steps on display1 ---
 |         //-- show encoder steps on display1 ---
 | ||||||
|         sprintf(buf_disp1, "EN %05d", encoderState.position); //count
 |         sprintf(buf_disp1, "EN %05d", encoderState.position); //count
 | ||||||
|  |         displayTop.showString(buf_disp1); | ||||||
|         //--- show converted distance on display2 ---
 |         //--- show converted distance on display2 ---
 | ||||||
|         sprintf(buf_disp2, "Met %5.3f", (float)lengthNow/1000); //m
 |         sprintf(buf_disp2, "Met %5.3f", (float)lengthNow/1000); //m
 | ||||||
|  |         displayBot.showString(buf_disp2); | ||||||
|         //--- beep every 1m ---
 |         //--- beep every 1m ---
 | ||||||
|         //note: only works precicely in forward/positive direction
 |         //note: only works precicely in forward/positive direction
 | ||||||
|         if (lengthNow % 1000 < 50) { //with tolerance in case of missed exact value
 |         if (lengthNow % 1000 < 50) { //with tolerance in case of missed exact value
 | ||||||
|             if (fabs(lengthNow - lengthBeeped) >= 900) { //dont beep multiple times at same meter
 |             if (fabs(lengthNow - lengthBeeped) >= 900) { //dont beep multiple times at same meter
 | ||||||
|                 //TODO: add case for reverse direction. currently beeps 0.1 too early
 |                 //TODO: add case for reverse direction. currently beeps 0.1 too early
 | ||||||
|                 buzzer.beep(1, 400, 100); |                 buzzer.beep(1, 400, 100 ); | ||||||
|                 lengthBeeped = lengthNow; |                 lengthBeeped = lengthNow; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| #else | #else | ||||||
|         //-- show current position on display1 ---
 | 
 | ||||||
|         //sprintf(buf_tmp, "%06.1f cm", (float)lengthNow/10); //cm
 |         //--------------------------
 | ||||||
|         sprintf(buf_tmp, "1ST %5.4f", (float)lengthNow/1000); //m
 |         //-------- display1 --------
 | ||||||
|  |         //--------------------------
 | ||||||
|  |         //run handle function
 | ||||||
|  |         displayTop.handle(); | ||||||
|  |         //show current position on display
 | ||||||
|  |         sprintf(buf_tmp, "1ST %5.4f", (float)lengthNow/1000); | ||||||
|  |         //                123456789
 | ||||||
|         //limit length to 8 digits + decimal point (drop decimal places when it does not fit)
 |         //limit length to 8 digits + decimal point (drop decimal places when it does not fit)
 | ||||||
|         sprintf(buf_disp1, "%.9s", buf_tmp); |         sprintf(buf_disp1, "%.9s", buf_tmp); | ||||||
|  |         displayTop.showString(buf_disp1); | ||||||
| 
 | 
 | ||||||
|         //--- show target length on display2 ---
 | 
 | ||||||
|  |         //--------------------------
 | ||||||
|  |         //-------- display2 --------
 | ||||||
|  |         //--------------------------
 | ||||||
|  |         //run handle function
 | ||||||
|  |         displayBot.handle(); | ||||||
|  |         //setting target length: blink target length
 | ||||||
|  |         if (SW_SET.state == true){ | ||||||
|  |             sprintf(buf_tmp, "S0LL%5.3f", (float)lengthTarget/1000); | ||||||
|  |             displayBot.blinkStrings(buf_tmp, "S0LL    ", 300, 100); | ||||||
|  |         } | ||||||
|  |         //manual state: blink "manual"
 | ||||||
|  |         else if (controlState == MANUAL) { | ||||||
|  |             displayBot.blinkStrings(" MANUAL ", buf_disp2, 1000, 1000); | ||||||
|  |         } | ||||||
|  |         //otherwise show target length
 | ||||||
|  |         else { | ||||||
|             //sprintf(buf_disp2, "%06.1f cm", (float)lengthTarget/10); //cm
 |             //sprintf(buf_disp2, "%06.1f cm", (float)lengthTarget/10); //cm
 | ||||||
|         sprintf(buf_disp2, "S0LL%5.3f", (float)lengthTarget/1000); //m
 |             sprintf(buf_tmp, "S0LL%5.3f", (float)lengthTarget/1000); //m
 | ||||||
|         //                  123456789
 |             //                1234  5678
 | ||||||
|  |             displayBot.showString(buf_tmp); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|          |          | ||||||
|         //TODO: blink disp2 when set button pressed
 |         //TODO: blink disp2 when set button pressed
 | ||||||
| @ -408,30 +423,6 @@ void task_control(void *pvParameter) | |||||||
|         //TODO: write "MAN CTL" to disp2 when in manual mode
 |         //TODO: write "MAN CTL" to disp2 when in manual mode
 | ||||||
|         //TODO: display or blink "REACHED" when reached state and start pressed
 |         //TODO: display or blink "REACHED" when reached state and start pressed
 | ||||||
| 
 | 
 | ||||||
|         //--- write to display ---
 |  | ||||||
|         //max7219_clear(&display); //results in flickering display if same value anyways
 |  | ||||||
|         max7219_draw_text_7seg(&display, 0, buf_disp1); |  | ||||||
|         max7219_draw_text_7seg(&display, 8, buf_disp2); |  | ||||||
| 
 |  | ||||||
|         //  //switch between two display pages
 |  | ||||||
|         //  if (esp_log_timestamp() - timestamp_pageSwitched > 1000){
 |  | ||||||
|         //      timestamp_pageSwitched = esp_log_timestamp();
 |  | ||||||
|         //      page = !page;
 |  | ||||||
|         //  }
 |  | ||||||
|         //  max7219_clear(&display);
 |  | ||||||
|         //  if (page){
 |  | ||||||
|         //      //display current position
 |  | ||||||
|         //      display_current_distance(&display, &encoder);
 |  | ||||||
|         //  } else {
 |  | ||||||
|         //      //display counter
 |  | ||||||
|         //      sprintf(display_buf, "lvl: %02d", count);
 |  | ||||||
|         //      max7219_draw_text_7seg(&display, 0, display_buf);
 |  | ||||||
|         //      //count++;
 |  | ||||||
|         //  }
 |  | ||||||
| 
 |  | ||||||
|         //sprintf(display_buf, "S0LL 12.3");
 |  | ||||||
|         //max7219_draw_text_7seg(&display, 8, display_buf);
 |  | ||||||
| 
 |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -10,8 +10,9 @@ extern "C" | |||||||
| #include "esp_log.h" | #include "esp_log.h" | ||||||
| #include "driver/adc.h" | #include "driver/adc.h" | ||||||
| 
 | 
 | ||||||
| #include <max7219.h> |  | ||||||
| #include "rotary_encoder.h" | #include "rotary_encoder.h" | ||||||
|  | #include "max7219.h" | ||||||
|  | 
 | ||||||
| } | } | ||||||
| #include <cmath> | #include <cmath> | ||||||
| 
 | 
 | ||||||
| @ -19,6 +20,7 @@ extern "C" | |||||||
| #include "gpio_evaluateSwitch.hpp" | #include "gpio_evaluateSwitch.hpp" | ||||||
| #include "buzzer.hpp" | #include "buzzer.hpp" | ||||||
| #include "vfd.hpp" | #include "vfd.hpp" | ||||||
|  | #include "display.hpp" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										198
									
								
								main/display.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										198
									
								
								main/display.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,198 @@ | |||||||
|  | #include "display.hpp" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //=== variables ===
 | ||||||
|  | static const char *TAG = "display"; //tag for logging
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //==============================
 | ||||||
|  | //======== init display ========
 | ||||||
|  | //==============================
 | ||||||
|  | //initialize display with parameters defined in config.hpp
 | ||||||
|  | //TODO: dont use global variables/macros here
 | ||||||
|  | max7219_t display_init(){ | ||||||
|  |      | ||||||
|  |     ESP_LOGI(TAG, "initializing display..."); | ||||||
|  |     // Configure SPI bus
 | ||||||
|  |     spi_bus_config_t cfg; | ||||||
|  |     memset(&cfg, 0, sizeof(spi_bus_config_t)); //init bus config with 0 to prevent bugs with random flags
 | ||||||
|  |     cfg.mosi_io_num = DISPLAY_PIN_NUM_MOSI; | ||||||
|  |     cfg.miso_io_num = -1; | ||||||
|  |     cfg.sclk_io_num = DISPLAY_PIN_NUM_CLK; | ||||||
|  |     cfg.quadwp_io_num = -1; | ||||||
|  |     cfg.quadhd_io_num = -1; | ||||||
|  |     cfg.max_transfer_sz = 0; | ||||||
|  |     cfg.flags = 0; | ||||||
|  |     ESP_ERROR_CHECK(spi_bus_initialize(HOST, &cfg, 1)); | ||||||
|  | 
 | ||||||
|  |     // Configure device
 | ||||||
|  |     max7219_t dev; | ||||||
|  |     dev.cascade_size = 2; | ||||||
|  |     dev.digits = 0; | ||||||
|  |     dev.mirrored = true; | ||||||
|  |     ESP_ERROR_CHECK(max7219_init_desc(&dev, HOST, MAX7219_MAX_CLOCK_SPEED_HZ, DISPLAY_PIN_NUM_CS)); | ||||||
|  |     ESP_ERROR_CHECK(max7219_init(&dev)); | ||||||
|  |     //0...15
 | ||||||
|  |     ESP_ERROR_CHECK(max7219_set_brightness(&dev, 8)); | ||||||
|  |     return dev; | ||||||
|  |     //display = dev;
 | ||||||
|  |     ESP_LOGI(TAG, "initializing display - done"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //===================================
 | ||||||
|  | //======= display welcome msg =======
 | ||||||
|  | //===================================
 | ||||||
|  | void display_ShowWelcomeMsg(max7219_t dev){ | ||||||
|  |     //display welcome message on two 7 segment displays
 | ||||||
|  |     //show name and date
 | ||||||
|  |     ESP_LOGI(TAG, "showing startup message..."); | ||||||
|  |     max7219_clear(&dev); | ||||||
|  |     max7219_draw_text_7seg(&dev, 0, "CUTTER  20.08.2022"); | ||||||
|  |     //                                   1234567812 34 5678
 | ||||||
|  |     vTaskDelay(pdMS_TO_TICKS(700)); | ||||||
|  |     //scroll "hello" over 2 displays
 | ||||||
|  |     for (int offset = 0; offset < 23; offset++) { | ||||||
|  |         max7219_clear(&dev); | ||||||
|  |         char hello[40] = "                HELL0                 "; | ||||||
|  |         max7219_draw_text_7seg(&dev, 0, hello + (22 - offset) ); | ||||||
|  |         vTaskDelay(pdMS_TO_TICKS(50)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //---------------------------------
 | ||||||
|  | //---------- constructor ----------
 | ||||||
|  | //---------------------------------
 | ||||||
|  | handledDisplay::handledDisplay(max7219_t displayDevice, uint8_t posStart_f) { | ||||||
|  |     ESP_LOGI(TAG, "Creating handledDisplay instance with startPos at %i", posStart); | ||||||
|  |     //copy variables
 | ||||||
|  |     dev = displayDevice; | ||||||
|  |     posStart = posStart_f; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //--------------------------------
 | ||||||
|  | //---------- showString ----------
 | ||||||
|  | //--------------------------------
 | ||||||
|  | //function that displays a given string on the display
 | ||||||
|  | void handledDisplay::showString(const char * buf, uint8_t pos_f){ | ||||||
|  |     //calculate actual absolute position
 | ||||||
|  |     posCurrent = posStart + pos_f; | ||||||
|  |     //copy the desired string
 | ||||||
|  |     strcpy(strOn, buf); | ||||||
|  |     //exit blinking mode
 | ||||||
|  |     if (mode == displayMode::BLINK_STRINGS){ | ||||||
|  |         mode = displayMode::NORMAL; | ||||||
|  |         ESP_LOGI(TAG, "pos:%i - disable blink strings mode -> normal mode str='%s'", posStart, strOn); | ||||||
|  |     } | ||||||
|  |     handle(); //draws the text depending on mode
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //TODO: blinkStrings() and blink() are very similar - can be optimized?
 | ||||||
|  | //only difficulty currently is the reset behaivor of blinkStrings through showString (blink does not reset)
 | ||||||
|  | 
 | ||||||
|  | //----------------------------------
 | ||||||
|  | //---------- blinkStrings ----------
 | ||||||
|  | //----------------------------------
 | ||||||
|  | //function switches between two strings in a given interval
 | ||||||
|  | void handledDisplay::blinkStrings(const char * strOn_f, const char * strOff_f, uint32_t msOn_f, uint32_t msOff_f){ | ||||||
|  |     //copy/update variables
 | ||||||
|  |     strcpy(strOn, strOn_f); | ||||||
|  |     strcpy(strOff, strOff_f); | ||||||
|  |     msOn = msOn_f; | ||||||
|  |     msOff = msOff_f; | ||||||
|  |     //if changed to blink mode just now:
 | ||||||
|  |     if (mode != displayMode::BLINK_STRINGS) { | ||||||
|  |         //switch mode
 | ||||||
|  |         ESP_LOGI(TAG, "pos:%i - toggle blink strings mode on/off=%d/%d stings='%s'/'%s'", posStart, msOn, msOff, strOn, strOff); | ||||||
|  |         mode = displayMode::BLINK_STRINGS; | ||||||
|  |         //start with on state
 | ||||||
|  |         state = true; | ||||||
|  |         timestampOn = esp_log_timestamp(); | ||||||
|  |     } | ||||||
|  |     //run handle function for display update
 | ||||||
|  |     handle(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //-------------------------------
 | ||||||
|  | //------------ blink ------------
 | ||||||
|  | //-------------------------------
 | ||||||
|  | //function triggers certain count and interval of off durations
 | ||||||
|  | void handledDisplay::blink(uint8_t count_f, uint32_t msOn_f, uint32_t msOff_f, const char * strOff_f) { | ||||||
|  |     //copy/update parameters
 | ||||||
|  |     count = count_f; | ||||||
|  |     msOn = msOn_f; | ||||||
|  |     msOff = msOff_f; | ||||||
|  |     strcpy(strOff, strOff_f); | ||||||
|  |     //FIXME this strings length must be dynamic depending on display size (posEnd - posStart) -> otherwise overwrites next segments if other display size or start pos
 | ||||||
|  |     //if changed to blink mode just now:
 | ||||||
|  |     if (mode != displayMode::BLINK) { | ||||||
|  |         //set to blink mode
 | ||||||
|  |         mode = displayMode::BLINK; | ||||||
|  |         ESP_LOGI(TAG, "pos:%i - start blinking: count=%i  on/off=%d/%d sting='%s'",posStart, count, msOn, msOff, strOff); | ||||||
|  |         //start with off state
 | ||||||
|  |         state = false; | ||||||
|  |         timestampOff = esp_log_timestamp(); | ||||||
|  |     } | ||||||
|  |     //run handle function for display update
 | ||||||
|  |     handle(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | //--------------------------------
 | ||||||
|  | //------------ handle ------------
 | ||||||
|  | //--------------------------------
 | ||||||
|  | //function that handles time based modes
 | ||||||
|  | //writes text to the 7 segment display depending on the current mode
 | ||||||
|  | void handledDisplay::handle() { | ||||||
|  |     switch (mode){ | ||||||
|  |         case displayMode::NORMAL: | ||||||
|  |             //daw given string
 | ||||||
|  |             max7219_draw_text_7seg(&dev, posCurrent, strOn); | ||||||
|  |             break; | ||||||
|  | 
 | ||||||
|  |         case displayMode::BLINK: | ||||||
|  |         case displayMode::BLINK_STRINGS: | ||||||
|  |             //--- define state on/off ---
 | ||||||
|  |             if (state == true){ //display in ON state
 | ||||||
|  |                 if (esp_log_timestamp() - timestampOn > msOn){ | ||||||
|  |                     state = false; | ||||||
|  |                     timestampOff = esp_log_timestamp(); | ||||||
|  |                     //decrement remaining counts in BLINK mode each cycle
 | ||||||
|  |                     if (mode == displayMode::BLINK) count--; | ||||||
|  |                 } | ||||||
|  |             } else { //display in OFF state
 | ||||||
|  |                 if (esp_log_timestamp() - timestampOff > msOff) { | ||||||
|  |                     state = true; | ||||||
|  |                     timestampOn = esp_log_timestamp(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             //--- draw text of current state ---
 | ||||||
|  |             if (state) { | ||||||
|  |                 max7219_draw_text_7seg(&dev, posStart, strOn); | ||||||
|  |             } else { | ||||||
|  |                 max7219_draw_text_7seg(&dev, posStart, strOff); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             //--- check finished condition in BLINK mode ---
 | ||||||
|  |             if (mode == displayMode::BLINK){ | ||||||
|  |                 if (count == 0) { | ||||||
|  |                     mode = displayMode::NORMAL; | ||||||
|  |                     ESP_LOGI(TAG, "pos:%i - finished blinking -> normal mode", posStart); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										65
									
								
								main/display.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								main/display.hpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | |||||||
|  | #pragma once | ||||||
|  | extern "C" | ||||||
|  | { | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <freertos/FreeRTOS.h> | ||||||
|  | #include <freertos/task.h> | ||||||
|  | #include <esp_idf_version.h> | ||||||
|  | #include "freertos/queue.h" | ||||||
|  | #include "esp_system.h" | ||||||
|  | #include "esp_log.h" | ||||||
|  | #include "driver/adc.h" | ||||||
|  | 
 | ||||||
|  | #include <max7219.h> | ||||||
|  | #include "rotary_encoder.h" | ||||||
|  | } | ||||||
|  | #include <cstring> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | #include "config.hpp" | ||||||
|  | 
 | ||||||
|  | //function for initializing the display using configuration from macros in config.hpp
 | ||||||
|  | max7219_t display_init(); | ||||||
|  | 
 | ||||||
|  | //show welcome message on the entire display
 | ||||||
|  | void display_ShowWelcomeMsg(max7219_t displayDevice); | ||||||
|  | 
 | ||||||
|  | enum class displayMode {NORMAL, BLINK_STRINGS, BLINK}; | ||||||
|  | 
 | ||||||
|  | class handledDisplay { | ||||||
|  |     public: | ||||||
|  |         //--- constructor ---
 | ||||||
|  |         //TODO add posMax to prevent writing in segments of other instance
 | ||||||
|  |         handledDisplay(max7219_t displayDevice, uint8_t posStart); | ||||||
|  | 
 | ||||||
|  |         //--- methods ---
 | ||||||
|  |         void showString(const char * buf, uint8_t pos = 0); | ||||||
|  |         //function switches between two strings in a given interval
 | ||||||
|  |         void blinkStrings(const char * strOn, const char * strOff, uint32_t msOn, uint32_t msOff); | ||||||
|  |         //triggers certain count of blinking between currently shown string and off or optional certain string
 | ||||||
|  |         void blink(uint8_t count, uint32_t msOn, uint32_t msOff, const char * strOff = "        "); | ||||||
|  |         //function that handles time based modes and writes text to display
 | ||||||
|  |         void handle(); //has to be run regularly when blink method is used
 | ||||||
|  | 
 | ||||||
|  |         //TODO: blinkStrings and blink are very similar - optimize?
 | ||||||
|  |         //TODO: add 'scroll string' method
 | ||||||
|  | 
 | ||||||
|  |     private: | ||||||
|  | 
 | ||||||
|  |         //--- variables ---
 | ||||||
|  |         //config
 | ||||||
|  |         max7219_t dev; | ||||||
|  |         uint8_t posStart; //absolute position this display instance starts (e.g. multiple or very long 7 segment display)
 | ||||||
|  |         uint8_t posCurrent; | ||||||
|  | 
 | ||||||
|  |         displayMode mode = displayMode::NORMAL; | ||||||
|  |         //blink modes
 | ||||||
|  |         uint8_t count = 0; | ||||||
|  |         char strOn[20]; | ||||||
|  |         char strOff[20]; | ||||||
|  |         bool state = false; | ||||||
|  |         uint32_t msOn; | ||||||
|  |         uint32_t msOff; | ||||||
|  |         uint32_t timestampOn; | ||||||
|  |         uint32_t timestampOff; | ||||||
|  | }; | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user