Explorar el Código

Подключил терминал.

TelenkovDmitry hace 10 meses
padre
commit
214f46aea8

+ 331 - 331
fw/modules/io/input.c

@@ -1,331 +1,331 @@
-#include "at32f403a_407.h"
-#include "input.h"
-#include "settings_api.h"
-#include "FreeRTOS.h"
-#include "task.h"
-#include "mux.h"
-#include <stdio.h>
-
-
-// *port; pin; mode; port_source; pin_source; deb_counter; p_flag; cnt;
-din_t inputs[DI_NUMBER] = {
-    {GPIOB, GPIO_PINS_11, 0, 0, 0, false, false}, // 1   
-    {GPIOB, GPIO_PINS_10, 0, 0, 0, false, false}, // 2
-    {GPIOE, GPIO_PINS_14, 0, 0, 0, false, false}, // 3 перенесли {GPIOB, GPIO_PINS_1,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE1,  0},
-    {GPIOE, GPIO_PINS_15, 0, 0, 0, false, false}, // 4 перенесли {GPIOB, GPIO_PINS_0,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE0,  0},
-    {GPIOA, GPIO_PINS_3,  0, 0, 0, false, false}, // 5
-    {GPIOA, GPIO_PINS_2,  0, 0, 0, false, false}, // 6
-    {GPIOA, GPIO_PINS_1,  0, 0, 0, false, false}, // 7
-    {GPIOA, GPIO_PINS_0,  0, 0, 0, false, false}  // 8
-};
-
-
-//
-void in_init(din_t *input)
-{
-    gpio_init_type gpio_init_struct;
-
-    gpio_default_para_init(&gpio_init_struct);
-        
-    gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
-    gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
-    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-    gpio_init_struct.gpio_pins           = input->pin;
-    gpio_init(input->port, &gpio_init_struct);
-
-#if 0    
-    // Вход
-    if (input->mode == 0)
-    {
-        gpio_default_para_init(&gpio_init_struct);
-        
-        gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
-        gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
-        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-        gpio_init_struct.gpio_pins           = input->pin;
-        gpio_init(input->port, &gpio_init_struct); 
-    }
-    // Счетный вход
-    else if (input->mode == 1)
-    {
-    }
-#endif
-}
-
-//
-void in_exint_init(void)
-{
-    exint_init_type exint_init_struct;
-    
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE11); // 11
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE10); // 10
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOE, GPIO_PINS_SOURCE14); // 14
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOE, GPIO_PINS_SOURCE15); // 15
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE3);  // 3
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE2);  // 2
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE1);  // 1
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE0);  // 0
-    
-    exint_default_para_init(&exint_init_struct);
-    
-    exint_init_struct.line_enable = TRUE;
-    exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
-    exint_init_struct.line_select = EXINT_LINE_0 | EXINT_LINE_1 | EXINT_LINE_2 |
-                                    EXINT_LINE_3 | EXINT_LINE_10 | 
-                                    EXINT_LINE_11| EXINT_LINE_14 | EXINT_LINE_15; 
-    
-    exint_init_struct.line_polarity = EXINT_TRIGGER_BOTH_EDGE;
-    exint_init(&exint_init_struct);
-    
-    exint_flag_clear(EXINT_LINE_0);
-    exint_flag_clear(EXINT_LINE_1);
-    exint_flag_clear(EXINT_LINE_2);
-    exint_flag_clear(EXINT_LINE_3);
-    exint_flag_clear(EXINT_LINE_10);
-    exint_flag_clear(EXINT_LINE_11);
-    exint_flag_clear(EXINT_LINE_14);
-    exint_flag_clear(EXINT_LINE_15);
-    
-    nvic_irq_enable(EXINT0_IRQn, 5, 0);
-    nvic_irq_enable(EXINT1_IRQn, 5, 0);
-    nvic_irq_enable(EXINT2_IRQn, 5, 0);
-    nvic_irq_enable(EXINT3_IRQn, 5, 0);
-    nvic_irq_enable(EXINT15_10_IRQn, 5, 0);
-}
-
-//
-void in_set(void)
-{
-    for (int i = 0; i < DI_NUMBER; i++)
-    {
-        if ((settings.di_mode_bits & (1 << i)) != inputs[i].mode) 
-        {
-            inputs[i].mode = settings.di_mode_bits & (1 << i);
-            if (inputs[i].mode == 0) 
-            {
-                inputs[i].cnt = 0;
-                inputs[i].p_flag = false;
-                input_cnt[i] = 0;
-            }
-            else
-            {
-                input_state_bit &= ~(1 << i);
-            }
-        }
-    }
-}
-
-//
-void io_test(void)
-{
-#if 0  
-    printf("IN_1: %u IN_2: %u IN_3: %u IN_4: %u IN_5: %u IN_6: %u IN_7: %u IN_8: %u\r\n", 
-           gpio_input_data_bit_read(inputs[0].port, inputs[0].pin),
-           gpio_input_data_bit_read(inputs[1].port, inputs[1].pin),
-           gpio_input_data_bit_read(inputs[2].port, inputs[2].pin),
-           gpio_input_data_bit_read(inputs[3].port, inputs[3].pin),
-           gpio_input_data_bit_read(inputs[4].port, inputs[4].pin),
-           gpio_input_data_bit_read(inputs[5].port, inputs[5].pin),
-           gpio_input_data_bit_read(inputs[6].port, inputs[6].pin), 
-           gpio_input_data_bit_read(inputs[7].port, inputs[7].pin));
-#endif    
-    
-    printf("IN_1: %u IN_2: %u IN_3: %u IN_4: %u IN_5: %u IN_6: %u IN_7: %u IN_8: %u\r\n", 
-           input_cnt[0], input_cnt[1], input_cnt[2], input_cnt[3], 
-           input_cnt[4], input_cnt[5], input_cnt[6], input_cnt[7]);
-    
-}
-
-//
-void input_task(void *params)
-{
-    for (;;)
-    {
-        
-        for (int i = 0; i < DI_NUMBER; i++)
-        {
-            // Режим обычного входа
-            if (inputs[i].mode == 0)
-            {
-                input_state[i] = (uint16_t)gpio_input_data_bit_read(inputs[i].port, inputs[i].pin);
-                
-                if (!input_state[i]) {
-                    input_state_bit &= ~(1 << i); // снять бит
-                    leds[i].state = LED_OFF;
-                }
-                else {
-                    input_state_bit |= input_state[i] << i;
-                    leds[i].state = LED_ON;
-                }
-            }
-        }
-            
-        vTaskDelay(100);
-    }
-}
-
-//
-inline void debounce(void)
-{
-    for (int i = 0; i < DI_NUMBER; i++)
-    {
-        if ((inputs[i].p_flag) && (inputs[i].mode == 0)){
-            if (++inputs[i].cnt == settings.di_debounce[i]) {
-                inputs[i].cnt = 0;
-                inputs[i].p_flag = false;
-                
-                input_state[i] = (uint16_t)gpio_input_data_bit_read(inputs[i].port, inputs[i].pin);
-                
-                if (!input_state[i]) {
-                    input_state_bit &= ~(1 << i); // снять бит
-                    leds[i].state = LED_OFF;
-                }
-                else {
-                    input_state_bit |= input_state[i] << i;
-                    leds[i].state = LED_ON;
-                }
-            }
-        }
-    }
-}
-
-// IN_8 GPIOA_0
-void EXINT0_IRQHandler(void)
-{
-    if (exint_flag_get(EXINT_LINE_0) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_0);
-        if (inputs[7].mode == 0)
-            inputs[7].p_flag = true;
-        else { 
-            if (inputs[7].cnt_flag) {
-                input_cnt[7]++;
-                inputs[7].cnt_flag = false;
-            }
-            else
-                inputs[7].cnt_flag = true;
-        }
-    }
-}
-
-// IN_7 GPIOA_1
-void EXINT1_IRQHandler(void)
-{
-    if(exint_flag_get(EXINT_LINE_1) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_1);
-        if (inputs[6].mode == 0)
-            inputs[6].p_flag = true;
-        else { 
-            if (inputs[6].cnt_flag) {
-                input_cnt[6]++;
-                inputs[6].cnt_flag = false;
-            }
-            else
-                inputs[6].cnt_flag = true;
-        }
-    }
-}
-
-// IN_6 GPIOA_2
-void EXINT2_IRQHandler(void)
-{
-    if(exint_flag_get(EXINT_LINE_2) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_2);
-        if (inputs[5].mode == 0)
-            inputs[5].p_flag = true;
-        else { 
-            if (inputs[5].cnt_flag) {
-                input_cnt[5]++;
-                inputs[5].cnt_flag = false;
-            }
-            else
-                inputs[5].cnt_flag = true;
-        }
-    }
-}
-
-// IN_5 GPIOA_3
-void EXINT3_IRQHandler(void)
-{
-    if(exint_flag_get(EXINT_LINE_3) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_3);
-        if (inputs[4].mode == 0)
-            inputs[4].p_flag = true;
-        else { 
-            if (inputs[4].cnt_flag) {
-                input_cnt[4]++;
-                inputs[4].cnt_flag = false;
-            }
-            else
-                inputs[4].cnt_flag = true;
-        }
-    }
-}
-
-// IN_1, IN_2, IN_3, IN_4
-void EXINT15_10_IRQHandler(void)
-{
-    // IN_2 GPIOB_10
-    if (exint_flag_get(EXINT_LINE_10) != RESET)  
-    {
-        exint_flag_clear(EXINT_LINE_10);
-        if (inputs[1].mode == 0)
-            inputs[1].p_flag = true;
-        else { 
-            if (inputs[1].cnt_flag) {
-                input_cnt[1]++;
-                inputs[1].cnt_flag = false;
-            }
-            else
-                inputs[1].cnt_flag = true;
-        }
-    }
-    // IN_1 GPIOB_11
-    else if (exint_flag_get(EXINT_LINE_11) != RESET)  
-    {
-        exint_flag_clear(EXINT_LINE_11);
-        if (inputs[0].mode == 0)
-            inputs[0].p_flag = true;
-        else { 
-            if (inputs[0].cnt_flag) {
-                input_cnt[0]++;
-                inputs[0].cnt_flag = false;
-            }
-            else
-                inputs[0].cnt_flag = true;
-        }
-    }
-    // IN_3 GPIOE_14
-    else if (exint_flag_get(EXINT_LINE_14) != RESET)  
-    {
-        exint_flag_clear(EXINT_LINE_14);
-        if (inputs[2].mode == 0)
-            inputs[2].p_flag = true;
-        else { 
-            if (inputs[2].cnt_flag) {
-                input_cnt[2]++;
-                inputs[2].cnt_flag = false;
-            }
-            else
-                inputs[2].cnt_flag = true;
-        }
-    }
-    // IN_4 GPIOE_15
-    else if (exint_flag_get(EXINT_LINE_15) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_15);
-        if (inputs[3].mode == 0)
-            inputs[3].p_flag = true;
-        else { 
-            if (inputs[3].cnt_flag) {
-                input_cnt[3]++;
-                inputs[3].cnt_flag = false;
-            }
-            else
-                inputs[3].cnt_flag = true;
-        }
-    }    
-}
+#include "at32f403a_407.h"
+#include "input.h"
+#include "settings_api.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "mux.h"
+#include <stdio.h>
+
+
+// *port; pin; mode; port_source; pin_source; deb_counter; p_flag; cnt;
+din_t inputs[DI_NUMBER] = {
+    {GPIOB, GPIO_PINS_11, 0, 0, 0, false, false}, // 1   
+    {GPIOB, GPIO_PINS_10, 0, 0, 0, false, false}, // 2
+    {GPIOE, GPIO_PINS_14, 0, 0, 0, false, false}, // 3 перенесли {GPIOB, GPIO_PINS_1,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE1,  0},
+    {GPIOE, GPIO_PINS_15, 0, 0, 0, false, false}, // 4 перенесли {GPIOB, GPIO_PINS_0,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE0,  0},
+    {GPIOA, GPIO_PINS_3,  0, 0, 0, false, false}, // 5
+    {GPIOA, GPIO_PINS_2,  0, 0, 0, false, false}, // 6
+    {GPIOA, GPIO_PINS_1,  0, 0, 0, false, false}, // 7
+    {GPIOA, GPIO_PINS_0,  0, 0, 0, false, false}  // 8
+};
+
+
+//
+void in_init(din_t *input)
+{
+    gpio_init_type gpio_init_struct;
+
+    gpio_default_para_init(&gpio_init_struct);
+        
+    gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
+    gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+    gpio_init_struct.gpio_pins           = input->pin;
+    gpio_init(input->port, &gpio_init_struct);
+
+#if 0    
+    // Вход
+    if (input->mode == 0)
+    {
+        gpio_default_para_init(&gpio_init_struct);
+        
+        gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
+        gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
+        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+        gpio_init_struct.gpio_pins           = input->pin;
+        gpio_init(input->port, &gpio_init_struct); 
+    }
+    // Счетный вход
+    else if (input->mode == 1)
+    {
+    }
+#endif
+}
+
+//
+void in_exint_init(void)
+{
+    exint_init_type exint_init_struct;
+    
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE11); // 11
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE10); // 10
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOE, GPIO_PINS_SOURCE14); // 14
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOE, GPIO_PINS_SOURCE15); // 15
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE3);  // 3
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE2);  // 2
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE1);  // 1
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE0);  // 0
+    
+    exint_default_para_init(&exint_init_struct);
+    
+    exint_init_struct.line_enable = TRUE;
+    exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
+    exint_init_struct.line_select = EXINT_LINE_0 | EXINT_LINE_1 | EXINT_LINE_2 |
+                                    EXINT_LINE_3 | EXINT_LINE_10 | 
+                                    EXINT_LINE_11| EXINT_LINE_14 | EXINT_LINE_15; 
+    
+    exint_init_struct.line_polarity = EXINT_TRIGGER_BOTH_EDGE;
+    exint_init(&exint_init_struct);
+    
+    exint_flag_clear(EXINT_LINE_0);
+    exint_flag_clear(EXINT_LINE_1);
+    exint_flag_clear(EXINT_LINE_2);
+    exint_flag_clear(EXINT_LINE_3);
+    exint_flag_clear(EXINT_LINE_10);
+    exint_flag_clear(EXINT_LINE_11);
+    exint_flag_clear(EXINT_LINE_14);
+    exint_flag_clear(EXINT_LINE_15);
+    
+    nvic_irq_enable(EXINT0_IRQn, 5, 0);
+    nvic_irq_enable(EXINT1_IRQn, 5, 0);
+    nvic_irq_enable(EXINT2_IRQn, 5, 0);
+    nvic_irq_enable(EXINT3_IRQn, 5, 0);
+    nvic_irq_enable(EXINT15_10_IRQn, 5, 0);
+}
+
+//
+void in_set(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        if ((settings.di_mode_bits & (1 << i)) != inputs[i].mode) 
+        {
+            inputs[i].mode = settings.di_mode_bits & (1 << i);
+            if (inputs[i].mode == 0) 
+            {
+                inputs[i].cnt = 0;
+                inputs[i].p_flag = false;
+                input_cnt[i] = 0;
+            }
+            else
+            {
+                input_state_bit &= ~(1 << i);
+            }
+        }
+    }
+}
+
+//
+void io_test(void)
+{
+#if 0  
+    printf("IN_1: %u IN_2: %u IN_3: %u IN_4: %u IN_5: %u IN_6: %u IN_7: %u IN_8: %u\r\n", 
+           gpio_input_data_bit_read(inputs[0].port, inputs[0].pin),
+           gpio_input_data_bit_read(inputs[1].port, inputs[1].pin),
+           gpio_input_data_bit_read(inputs[2].port, inputs[2].pin),
+           gpio_input_data_bit_read(inputs[3].port, inputs[3].pin),
+           gpio_input_data_bit_read(inputs[4].port, inputs[4].pin),
+           gpio_input_data_bit_read(inputs[5].port, inputs[5].pin),
+           gpio_input_data_bit_read(inputs[6].port, inputs[6].pin), 
+           gpio_input_data_bit_read(inputs[7].port, inputs[7].pin));
+#endif    
+    
+    printf("IN_1: %u IN_2: %u IN_3: %u IN_4: %u IN_5: %u IN_6: %u IN_7: %u IN_8: %u\r\n", 
+           input_cnt[0], input_cnt[1], input_cnt[2], input_cnt[3], 
+           input_cnt[4], input_cnt[5], input_cnt[6], input_cnt[7]);
+    
+}
+
+//
+void input_task(void *params)
+{
+    for (;;)
+    {
+        
+        for (int i = 0; i < DI_NUMBER; i++)
+        {
+            // Режим обычного входа
+            if (inputs[i].mode == 0)
+            {
+                input_state[i] = (uint16_t)gpio_input_data_bit_read(inputs[i].port, inputs[i].pin);
+                
+                if (!input_state[i]) {
+                    input_state_bit &= ~(1 << i); // снять бит
+                    leds[i].state = LED_OFF;
+                }
+                else {
+                    input_state_bit |= input_state[i] << i;
+                    leds[i].state = LED_ON;
+                }
+            }
+        }
+            
+        vTaskDelay(100);
+    }
+}
+
+//
+void debounce(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        if ((inputs[i].p_flag) && (inputs[i].mode == 0)){
+            if (++inputs[i].cnt == settings.di_debounce[i]) {
+                inputs[i].cnt = 0;
+                inputs[i].p_flag = false;
+                
+                input_state[i] = (uint16_t)gpio_input_data_bit_read(inputs[i].port, inputs[i].pin);
+                
+                if (!input_state[i]) {
+                    input_state_bit &= ~(1 << i); // снять бит
+                    leds[i].state = LED_OFF;
+                }
+                else {
+                    input_state_bit |= input_state[i] << i;
+                    leds[i].state = LED_ON;
+                }
+            }
+        }
+    }
+}
+
+// IN_8 GPIOA_0
+void EXINT0_IRQHandler(void)
+{
+    if (exint_flag_get(EXINT_LINE_0) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_0);
+        if (inputs[7].mode == 0)
+            inputs[7].p_flag = true;
+        else { 
+            if (inputs[7].cnt_flag) {
+                input_cnt[7]++;
+                inputs[7].cnt_flag = false;
+            }
+            else
+                inputs[7].cnt_flag = true;
+        }
+    }
+}
+
+// IN_7 GPIOA_1
+void EXINT1_IRQHandler(void)
+{
+    if(exint_flag_get(EXINT_LINE_1) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_1);
+        if (inputs[6].mode == 0)
+            inputs[6].p_flag = true;
+        else { 
+            if (inputs[6].cnt_flag) {
+                input_cnt[6]++;
+                inputs[6].cnt_flag = false;
+            }
+            else
+                inputs[6].cnt_flag = true;
+        }
+    }
+}
+
+// IN_6 GPIOA_2
+void EXINT2_IRQHandler(void)
+{
+    if(exint_flag_get(EXINT_LINE_2) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_2);
+        if (inputs[5].mode == 0)
+            inputs[5].p_flag = true;
+        else { 
+            if (inputs[5].cnt_flag) {
+                input_cnt[5]++;
+                inputs[5].cnt_flag = false;
+            }
+            else
+                inputs[5].cnt_flag = true;
+        }
+    }
+}
+
+// IN_5 GPIOA_3
+void EXINT3_IRQHandler(void)
+{
+    if(exint_flag_get(EXINT_LINE_3) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_3);
+        if (inputs[4].mode == 0)
+            inputs[4].p_flag = true;
+        else { 
+            if (inputs[4].cnt_flag) {
+                input_cnt[4]++;
+                inputs[4].cnt_flag = false;
+            }
+            else
+                inputs[4].cnt_flag = true;
+        }
+    }
+}
+
+// IN_1, IN_2, IN_3, IN_4
+void EXINT15_10_IRQHandler(void)
+{
+    // IN_2 GPIOB_10
+    if (exint_flag_get(EXINT_LINE_10) != RESET)  
+    {
+        exint_flag_clear(EXINT_LINE_10);
+        if (inputs[1].mode == 0)
+            inputs[1].p_flag = true;
+        else { 
+            if (inputs[1].cnt_flag) {
+                input_cnt[1]++;
+                inputs[1].cnt_flag = false;
+            }
+            else
+                inputs[1].cnt_flag = true;
+        }
+    }
+    // IN_1 GPIOB_11
+    else if (exint_flag_get(EXINT_LINE_11) != RESET)  
+    {
+        exint_flag_clear(EXINT_LINE_11);
+        if (inputs[0].mode == 0)
+            inputs[0].p_flag = true;
+        else { 
+            if (inputs[0].cnt_flag) {
+                input_cnt[0]++;
+                inputs[0].cnt_flag = false;
+            }
+            else
+                inputs[0].cnt_flag = true;
+        }
+    }
+    // IN_3 GPIOE_14
+    else if (exint_flag_get(EXINT_LINE_14) != RESET)  
+    {
+        exint_flag_clear(EXINT_LINE_14);
+        if (inputs[2].mode == 0)
+            inputs[2].p_flag = true;
+        else { 
+            if (inputs[2].cnt_flag) {
+                input_cnt[2]++;
+                inputs[2].cnt_flag = false;
+            }
+            else
+                inputs[2].cnt_flag = true;
+        }
+    }
+    // IN_4 GPIOE_15
+    else if (exint_flag_get(EXINT_LINE_15) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_15);
+        if (inputs[3].mode == 0)
+            inputs[3].p_flag = true;
+        else { 
+            if (inputs[3].cnt_flag) {
+                input_cnt[3]++;
+                inputs[3].cnt_flag = false;
+            }
+            else
+                inputs[3].cnt_flag = true;
+        }
+    }    
+}

+ 37 - 30
fw/modules/io/input.h

@@ -1,30 +1,37 @@
-#ifndef __INPUT_H
-#define __INPUT_H
-
-
-#include "io.h"
-
-
-extern din_t inputs[];
-
-//
-void in_init(din_t *input);
-
-//
-void in_exint_init(void);
-
-//
-void in_set(void);
-
-//
-void io_test(void);
-
-//
-void input_task(void *params);
-
-//
-void debounce(void);
-
-
-#endif  // __INPUT_H
-
+#ifndef __INPUT_H
+#define __INPUT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "io.h"
+
+
+
+extern din_t inputs[];
+
+//
+void in_init(din_t *input);
+
+//
+void in_exint_init(void);
+
+//
+void in_set(void);
+
+//
+void io_test(void);
+
+//
+void input_task(void *params);
+
+//
+void debounce(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // __INPUT_H
+

+ 128 - 128
fw/modules/io/io.c

@@ -1,128 +1,128 @@
-#include "at32f403a_407.h"
-#include "io.h"
-#include "FreeRTOS.h"
-#include "task.h"
-#include "input.h"
-#include "output.h"
-#include "settings_api.h"
-#include "io_utils.h"
-#include <stdio.h>
-
-
-uint16_t input_state[DI_NUMBER];     // состояние входа
-uint16_t input_state_bit;
-
-
-//uint16_t output_state[DO_NUMBER];     // состояние входа
-uint16_t output_state_bit;
-uint16_t output_mode_bit;
-uint16_t output_pwm[DO_NUMBER];
-uint16_t output_pwm_save[DO_NUMBER];
-uint16_t output_pwm_period[DO_NUMBER];
-uint16_t output_pwm_period_save[DO_NUMBER];
-
-// -------------------------------------------------------------------------- //
-// Текущие параметры
-
-//uint16_t input_state[DI_NUMBER];     // состояние входа
-uint32_t input_cnt[DI_NUMBER];       // счетчики входов
-
-
-//
-void io_port_init(void)
-{
-    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
-    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
-    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
-    crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
-    crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
-    
-    crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
-    
-    crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
-    crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
-    pwc_battery_powered_domain_access(TRUE);
-    
-    io_tim_init();
-}
-
-//
-void io_init(void)
-{
-    for (int i = 0; i < DI_NUMBER; i++)
-    {
-        in_init(&inputs[i]);
-    }
-
-    output_state_bit = settings.do_bits;
-    output_mode_bit = settings.do_mode_bits;
-    
-    // Таймер для выходов в режиме PWM
-    out_pwm_tim_init();
-    
-    for (int i = 0; i < DO_NUMBER; i++)
-    {
-        output_pwm[i] = settings.do_pwm[i];
-        output_pwm_save[i] = settings.do_pwm_save[i];
-        output_pwm_period[i] = settings.do_pwm_period[i];
-        output_pwm_period_save[i] = settings.do_pwm_period_save[i];
-
-        if (save_mode_get()) {
-            outputs[i].pwm_duty = settings.do_pwm_save[i];
-            outputs[i].pwm_period = settings.do_pwm_period_save[i];
-        }
-        else {
-            outputs[i].pwm_duty = settings.do_pwm[i];
-            outputs[i].pwm_period = settings.do_pwm_period[i];
-        }
-        
-        out_gpio_init(&outputs[i], i);
-        load_sens_init(&load_sens[i]);
-    }
-}
-
-// Таймер для антидребезга
-void io_tim_init(void)
-{
-    crm_clocks_freq_type crm_clocks_freq_struct = {0};
-    
-    crm_clocks_freq_get(&crm_clocks_freq_struct);
-    
-    nvic_irq_disable(TMR8_BRK_TMR12_IRQn);
-    
-    crm_periph_clock_enable(CRM_TMR12_PERIPH_CLOCK, TRUE);
-
-    // 1 Hz
-    tmr_base_init(TMR12, 9, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
-    tmr_cnt_dir_set(TMR12, TMR_COUNT_UP);
-    
-    NVIC_ClearPendingIRQ(TMR8_BRK_TMR12_IRQn);
-    nvic_irq_enable(TMR8_BRK_TMR12_IRQn, 5, 0);
-    
-    tmr_flag_clear(TMR12, TMR_OVF_FLAG);
-    tmr_interrupt_enable(TMR12, TMR_OVF_INT, TRUE);
-    tmr_counter_value_set(TMR12, 0);
-    tmr_counter_enable(TMR12, TRUE);  
-}
-
-
-void TMR8_BRK_TMR12_IRQHandler(void)
-{
-    //static int i = 0;
-    //static int cnt = 0;
-
-    if(tmr_flag_get(TMR12, TMR_OVF_FLAG) != RESET)
-    {
-        tmr_flag_clear(TMR12, TMR_OVF_FLAG);
-
-        debounce();
-#if 0        
-        if (i++ == 1000) {
-            i = 0;
-            cnt++;
-            printf("CNT: %u\r\n");
-        }
-#endif        
-    }
-}
-
+#include "at32f403a_407.h"
+#include "io.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "input.h"
+#include "output.h"
+#include "settings_api.h"
+#include "io_utils.h"
+#include <stdio.h>
+
+
+uint16_t input_state[DI_NUMBER];     // состояние входа
+uint16_t input_state_bit;
+
+
+//uint16_t output_state[DO_NUMBER];     // состояние входа
+uint16_t output_state_bit;
+uint16_t output_mode_bit;
+uint16_t output_pwm[DO_NUMBER];
+uint16_t output_pwm_save[DO_NUMBER];
+uint16_t output_pwm_period[DO_NUMBER];
+uint16_t output_pwm_period_save[DO_NUMBER];
+
+// -------------------------------------------------------------------------- //
+// Текущие параметры
+
+//uint16_t input_state[DI_NUMBER];     // состояние входа
+uint32_t input_cnt[DI_NUMBER];       // счетчики входов
+
+
+//
+void io_port_init(void)
+{
+    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
+    
+    crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
+    
+    crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
+    pwc_battery_powered_domain_access(TRUE);
+    
+    io_tim_init();
+}
+
+//
+void io_init(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        in_init(&inputs[i]);
+    }
+
+    output_state_bit = settings.do_bits;
+    output_mode_bit = settings.do_mode_bits;
+    
+    // Таймер для выходов в режиме PWM
+    out_pwm_tim_init();
+    
+    for (int i = 0; i < DO_NUMBER; i++)
+    {
+        output_pwm[i] = settings.do_pwm[i];
+        output_pwm_save[i] = settings.do_pwm_save[i];
+        output_pwm_period[i] = settings.do_pwm_period[i];
+        output_pwm_period_save[i] = settings.do_pwm_period_save[i];
+
+        if (save_mode_get()) {
+            outputs[i].pwm_duty = settings.do_pwm_save[i];
+            outputs[i].pwm_period = settings.do_pwm_period_save[i];
+        }
+        else {
+            outputs[i].pwm_duty = settings.do_pwm[i];
+            outputs[i].pwm_period = settings.do_pwm_period[i];
+        }
+        
+        out_gpio_init(&outputs[i], i);
+        load_sens_init(&load_sens[i]);
+    }
+}
+
+// Таймер для антидребезга
+void io_tim_init(void)
+{
+    crm_clocks_freq_type crm_clocks_freq_struct = {0};
+    
+    crm_clocks_freq_get(&crm_clocks_freq_struct);
+    
+    nvic_irq_disable(TMR8_BRK_TMR12_IRQn);
+    
+    crm_periph_clock_enable(CRM_TMR12_PERIPH_CLOCK, TRUE);
+
+    // 1 Hz
+    tmr_base_init(TMR12, 9, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
+    tmr_cnt_dir_set(TMR12, TMR_COUNT_UP);
+    
+    NVIC_ClearPendingIRQ(TMR8_BRK_TMR12_IRQn);
+    nvic_irq_enable(TMR8_BRK_TMR12_IRQn, 5, 0);
+    
+    tmr_flag_clear(TMR12, TMR_OVF_FLAG);
+    tmr_interrupt_enable(TMR12, TMR_OVF_INT, TRUE);
+    tmr_counter_value_set(TMR12, 0);
+    tmr_counter_enable(TMR12, TRUE);  
+}
+
+
+void TMR8_BRK_TMR12_IRQHandler(void)
+{
+    //static int i = 0;
+    //static int cnt = 0;
+
+    if(tmr_flag_get(TMR12, TMR_OVF_FLAG) != RESET)
+    {
+        tmr_flag_clear(TMR12, TMR_OVF_FLAG);
+
+        debounce();
+#if 0        
+        if (i++ == 1000) {
+            i = 0;
+            cnt++;
+            printf("CNT: %u\r\n");
+        }
+#endif        
+    }
+}
+

+ 745 - 0
fw/modules/terminal/terminal.cpp

@@ -0,0 +1,745 @@
+#include "terminal.h"
+#include <string.h>
+#include <stdarg.h>
+
+static char tmpCommand[40];
+
+//-----------------------------------------------------------------------------
+// Microrl callbacks
+//-----------------------------------------------------------------------------
+extern "C" {
+
+    //Configure terminal
+    void configure_terminal() {
+        pTerminal->configure();
+    }
+
+    //Print micrrl callback
+    void print_terminal(const char *str) {
+        pTerminal->print(str);
+    }
+
+    //Execute microrl callback
+    int execute_terminal(int argc, const char * const * argv) {
+        return pTerminal->execute(argc, argv);}
+
+    //Sigint microrl callback
+    void sigint_terminal (void) {
+        pTerminal->sigint();}
+    
+    //Complete microrl callback
+    char** completion_terminal (int argc, const char * const * argv) {
+        return pTerminal->completion(argc, argv);}
+
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Terminal class
+//-----------------------------------------------------------------------------
+
+Terminal::Terminal():
+    m_countPrintFunction(0),
+    prl(&rl)
+{
+    memset(&f_print, 0, sizeof(f_print));
+    memset(tmpCommand, 0, sizeof(tmpCommand));
+}
+
+
+
+
+//Configure microrl callbacks
+void Terminal::configure()
+{
+  
+    m_countPrintFunction = 0;
+    prl = &rl;
+
+    memset(&f_print, 0, sizeof(f_print));
+    memset(tmpCommand, 0, sizeof(tmpCommand));
+	
+    microrl_init (prl, ::print_terminal);
+    microrl_set_execute_callback (prl, ::execute_terminal);
+    microrl_set_sigint_callback (prl, ::sigint_terminal);
+    microrl_set_complete_callback (prl, ::completion_terminal);
+}
+
+
+void Terminal::connectCallback() {
+    printeol();
+    printll("Hello stranger. It is goot day for work :)");    
+}
+
+
+//Insert char to microrl
+void Terminal::insert(int ch) {
+    microrl_insert_char(prl, ch);
+}
+
+
+//Out message to all terminals
+void Terminal::print(const char *str) {
+    for (int i = 0; i < m_countPrintFunction; i++) {
+        if (f_print[i] != 0) {
+            f_print[i](str);
+        }
+    }
+}
+
+
+void Terminal::printl(const char * str) {
+    print(str);
+    print(EOL);
+}
+
+void Terminal::printll(const char * str) {
+    print(str);
+    print(EOL);
+    print(EOL);
+}
+
+
+void Terminal::eol() {
+    print(EOL);
+}
+
+void Terminal::printeol() {
+    print(EOL);
+}
+
+
+//Execute microrl callbacks
+int Terminal::execute(int argc, const char * const *argv) {
+    return 0;
+}
+
+char* helloNull[] = {0};
+
+//Comletion microrl callbacks
+char ** Terminal::completion(int argc, const char * const * argv) {
+    int i = 0;
+    i++;
+    return helloNull;
+}
+
+//Sigint microrl callbacks
+void Terminal::sigint()
+{
+}
+
+
+//Add external print function
+void Terminal::addPrint(InterfacePrint print_func) {
+    if (m_countPrintFunction < COUNT_TERMINAL_INTERFACE) {
+        f_print[m_countPrintFunction] = print_func;
+        m_countPrintFunction++;
+    }
+}
+
+
+
+
+
+//-----------------------------------------------------------------------------
+// Вывод команд в терминал
+//-----------------------------------------------------------------------------
+
+//Очистка экрана
+void Terminal::clearScreen() {
+    //Clear
+    print("\033[2J");        
+    //Move to up left corner
+    print("\033[H");    
+}
+
+
+//Сдвинуть в указанную позицию
+void Terminal::moveToPos(uint32_t h, uint32_t v)
+{
+    uint32_t sizeCommand = 0;
+    getCommand_MoveToPos(tmpCommand, sizeCommand, h, v);
+    print(tmpCommand);
+}
+
+
+//Сдвинуть в верхний левый угол
+void Terminal::moveToUpLeftCorner() {
+    //Move to up left corner
+    print("\033[H");    
+}
+
+
+//Reset terminal to initial state 
+void Terminal::reset() {
+    //Сбросить настройки терминала
+    print("\033c");
+}
+
+//Сбросить аттрибуты текста
+void Terminal::resetAttribute() {
+    print("\033[0m");
+}
+
+//Сохранить позицию курсора и атрибуты
+void Terminal::saveCursorPos() {
+    //Save cursor position and attributes 
+    print("\0337");    
+}
+
+//Востановить позицию курсора и аттрибуты
+void Terminal::restoreCursorPos() {
+    //Restore cursor position and attributes 
+    print("\0338");    
+}
+
+//Скрыть курсов
+void Terminal::hideCursor() {
+    print("\033[8m");
+}
+
+//Очистить строку
+void Terminal::clearCurrentLine() {
+    print("\033[2K");
+}
+
+
+
+
+
+void write(const char* src, int src_size, char* dst, uint32_t& size) {
+    memcpy(&dst[size], src, src_size);
+    size += src_size;
+}
+
+
+//Формирование команды для установки курсора в заданную позицию
+uint32_t Terminal::getCommand_MoveToPos(
+    char* res_command, uint32_t& res_size, uint32_t h, uint32_t v
+)
+{    
+    //Esc[Line;ColumnH
+    res_size = 0;
+    
+    write("\x1B[", 2, res_command, res_size);
+    
+        
+    char* vStr = utoa(v);
+    uint32_t sizeV = strlen(vStr);
+    write(vStr, sizeV, res_command, res_size);
+    
+    write(";", 1, res_command, res_size);
+    
+    char* hStr = utoa(h);
+    uint32_t sizeH = strlen(hStr);
+    write(hStr, sizeH, res_command, res_size);
+
+    write("H", 1, res_command, res_size);
+    write("\0", 1, res_command, res_size); 
+
+    return res_size;
+}
+
+
+
+
+//Формирование команды для сдвига курсора вверх на n позиций
+uint32_t Terminal::getCommand_MoveUpNLines(
+    char* res_command, uint32_t& res_size, uint32_t n)
+{
+    return 0;
+}
+
+
+
+//Формирование команды для сдвига курсора вниз на n позиций
+uint32_t Terminal::getCommand_MoveDownNLines(
+    char* res_command, uint32_t& res_size, uint32_t n)
+{
+    return 0;
+}
+
+
+
+//Формирование команды для сдвига курсора вправо на n позиций
+uint32_t Terminal::getCommand_MoveRightNLines(
+    char* res_command, uint32_t& res_size, uint32_t n)
+{
+    return 0;
+}
+
+
+//Формирование команды для сдвига курсора влево на n позиций
+uint32_t Terminal::getCommand_MoveLeftNLines(
+    char* res_command, uint32_t& res_size, uint32_t n)
+{
+    return 0;
+}
+
+
+//Формирование команды для установки цвета текста
+uint32_t Terminal::getCommand_SetTextColor(char* res_command, uint32_t& res_size, TextColor color)
+{
+    //Esc[3ColorH
+    res_size = 0;    
+    write("\x1B[3", 3, res_command, res_size);
+        
+    char* vStr = utoa(color);
+    write(vStr, 1, res_command, res_size);
+    write("m", 1, res_command, res_size);   
+    write("\0", 1, res_command, res_size); 
+        
+    return res_size;
+}
+
+
+//Формирование команды для установки аттрибута подчёркивания
+uint32_t Terminal::getCommand_UnderlineText(char* res_command, uint32_t& res_size)
+{
+    res_size = 0;    
+    write("\x1B[4m", 4, res_command, res_size);
+    write("\0", 1, res_command, res_size); 
+    return res_size;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//-----------------------------------------------------------------------------
+// Класс реализации таблицы
+//-----------------------------------------------------------------------------
+Table::Table() {
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Вывод элементов таблицы
+//-----------------------------------------------------------------------------
+
+//Вывод сктроки в заданную ячейку
+void Table::outToCell(uint8_t col, uint8_t row, const char* str) 
+{
+    //CellAttribute &cell = cells[col][row];
+    //print(cell.pos_command);
+    //print(cell.color_command);
+    pTerminal->resetAttribute();
+    
+    //Выводим атрибуты
+    CellAttribute &cell = cells[col][row];    
+    print(cell.attributes);
+    
+    //Выводим строку
+    print(str);
+    
+    //Выводим пробелы на до конца ячейки
+    int32_t countSpace = m_width[col] - strlen(str) - 1; 
+    for (uint8_t i = 0; i < countSpace; i++)
+        print(" ");
+    
+    
+}
+
+
+//Вывод значения в заданную ячейку
+void Table::outToCell(uint8_t col, uint8_t row, uint32_t val)  {
+    outToCell(col, row, utoa(val));
+}
+
+
+//Выводим в нужную строку разделяющую линию
+void Table::outCrossLine(uint8_t row) {    
+    uint32_t line = m_y + row;
+    pTerminal->moveToPos(m_x, line);
+    printCrossLine(line);        
+}
+
+
+
+//Вывод внешней границы в строке
+void Table::outExternalBorder() {
+    
+    uint32_t line = m_y;        
+        
+    printTopLine(line);        
+    for (uint8_t r = 0; r < m_row; r++)
+        printTextLine(line);    
+    printBottomLine(line);                                              
+        
+}
+
+
+//Печать статической части таблицы
+void Table::outStatic() 
+{
+    pTerminal->saveCursorPos();
+    outExternalBorder();
+    pTerminal->restoreCursorPos();    
+}
+
+
+//Печатает в таблице счётчик ячеек
+void Table::outCellNumber()
+{
+    uint32_t count = 0;
+    for (uint8_t c = 0; c < m_col; c ++) {
+        for (uint8_t r = 0; r < m_row; r++) {
+            print(cells[c][r].attributes);            
+            print(utoa(count));
+            count ++;
+        }
+    }
+}
+
+
+void Table::startUpdate() {
+    pTerminal->saveCursorPos();
+}
+
+
+void Table::endUpdate() {
+    pTerminal->restoreCursorPos();
+}
+
+//-----------------------------------------------------------------------------
+// Конфигурация талицы
+//-----------------------------------------------------------------------------
+
+//Задать геометрию таблицы 
+void Table::setGeometry(uint8_t x, uint8_t y, uint8_t col, uint8_t row, uint32_t width, ...)
+{   
+    setPos(x, y);
+    setSize(col, row);
+    
+    if ((m_col == 0) || (m_row == 0))
+        return;
+    
+    //Читаем ширину колонок
+    va_list ap;
+    va_start(ap, width); 
+    
+    uint8_t c = 0;
+    m_width[c] = width;    
+    do {
+        c++;
+        m_width[c] = va_arg(ap, int32_t);
+    } while (c < m_col);        
+    
+    va_end(ap);  
+    
+    resetAttributes();    
+}
+
+
+//Задать геометрию таблицы 
+void Table::setGeometry(uint8_t x, uint8_t y, uint8_t col, uint8_t row, const uint32_t* width) 
+{
+    setPos(x, y);
+    setSize(col, row);
+    
+    if ((m_col == 0) || (m_row == 0))
+        return;
+    
+    for (int c = 0; c < m_col; c++)
+        m_width[c] = width[c];
+           
+    resetAttributes();    
+}
+
+
+//Установить позицию таблицы
+void Table::setPos(uint8_t x, uint8_t y) {
+     m_x = x; m_y = y;
+}
+
+//Установить размеры таблицы
+void Table::setSize(uint8_t col, uint8_t row) {
+    m_col = col;
+    m_row = row;
+    
+    if (m_col > MAX_COL)
+        m_col = MAX_COL;
+    
+    if (m_row > MAX_ROW)
+        m_row = MAX_ROW;
+}
+
+
+//Сброс аттрибутов для ячеек
+void Table::resetAttributes()
+{
+    //Добавляем аттрибут для перемещения
+    //курсора в начало каждой ячейки
+    for (uint8_t c = 0; c < m_col; c ++) {
+        for (uint8_t r = 0; r < m_row; r++) {
+            clearCellAttributes(c, r);
+            
+            addCellPosAttribute(c, r);              
+        }
+    }
+}
+
+
+//-----------------------------------------------------------------------------
+// Работа с аттрибутами
+//-----------------------------------------------------------------------------
+
+//Атрибуты - строка с управляющими командами для
+//терминала VT100, которые выводятся в терминал
+//перед выводом в ячейку (перемещение курсора
+//на ячейку, установка цвета)
+
+static char tmpAttr[20];
+static uint32_t tmpAttrSize = 0; 
+
+//Расчитать для начала ячейки позицию курсора 
+void Table::addCellPosAttribute(uint8_t col, uint8_t row) {
+         
+    //Расчитываем позицию курсора для ячейки
+    uint32_t y = m_y + 1;
+    uint32_t x = m_x + 1;
+    
+    for (uint32_t c = 0; c < col; c++)
+        x += m_width[c];
+    
+    x += col;
+    y += row;
+    
+    //Формируем команду перемещения курсора в рассчитанную позицию
+    pTerminal->getCommand_MoveToPos(tmpAttr, tmpAttrSize, x, y);    
+    addCellAttribute(col, row, tmpAttr);        
+}
+
+
+
+//Добавить аттрибут цвета текста
+void Table::addCellColorAttribute(uint8_t col, uint8_t row, TextColor color) {
+    pTerminal->getCommand_SetTextColor(tmpAttr, tmpAttrSize, color); 
+    addCellAttribute(col, row, tmpAttr);     
+}
+
+
+//Добавить аттрибут цвета текста
+void Table::addCellUnderlineAttribute(uint8_t col, uint8_t row) {
+    pTerminal->getCommand_UnderlineText(tmpAttr, tmpAttrSize); 
+    addCellAttribute(col, row, tmpAttr);     
+}
+
+
+//Очистить аттрибуты ячейки 
+void Table::clearCellAttributes(uint8_t col, uint8_t row) {          
+    CellAttribute& cell = cells[col][row];
+    
+    cell.text = 0;
+        
+    char* attributes = cell.attributes;
+    uint32_t attrSize = sizeof(cell.attributes);
+    
+    memset(attributes, 0, attrSize);
+}
+
+
+//Дописать аттрибут к ячейке
+void Table::addCellAttribute(uint8_t col, uint8_t row, const char* attr) {
+    CellAttribute& cell = cells[col][row];    
+    
+    uint8_t attrSize = strlen(cell.attributes);    
+    char* dst = &cell.attributes[attrSize];
+    
+    attrSize = strlen(attr);
+    memcpy(dst, attr, attrSize);
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Работа с выводом элементов рамки
+//-----------------------------------------------------------------------------
+
+
+//Символы псевдографики
+//----------------------------------------
+//─│┌┐└┘├┤┬┴┼═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡╢╣╤╥╦╧╨╩╪╫╬
+//----------------------------------------
+
+
+//Печать верхней границы рамки
+void Table::printTopLine(uint32_t& line) {
+    printFrameLine(line, "┌", "┐", "┬", "─");
+}
+
+//Печать линии в таблице
+void Table::printCrossLine(uint32_t& line) {
+    printFrameLine(line, "├", "┤", "┼", "─");
+}
+
+//Печать рамки для отдельной строки
+void Table::printTextLine(uint32_t& line) {
+    printFrameLine(line, "│", "│", "│", " ");
+}
+
+//Печать нижней границы рамки таблицы
+void Table::printBottomLine(uint32_t& line) {
+    printFrameLine(line, "└", "┘", "┴", "─");
+}
+
+
+////Печать верхней границы рамки
+//void Table::printTopLine(uint32_t& line) {
+//    printFrameLine(line, "╔", "╗", "╤", "═");
+//}
+
+////Печать линии в таблице
+//void Table::printCrossLine(uint32_t& line) {
+//    printFrameLine(line, "╟", "╢", "┼", "─");
+//}
+
+////Печать рамки для отдельной строки
+//void Table::printTextLine(uint32_t& line) {
+//    printFrameLine(line, "║", "║", "│", " ");
+//}
+
+////Печать нижней границы рамки таблицы
+//void Table::printBottomLine(uint32_t& line) {
+//    printFrameLine(line, "╚", "╝", "╧", "═");
+//}
+
+
+
+
+//Выводит строку рамки таблицы
+void Table::printFrameLine(uint32_t& line, 
+    const char* lc, const char* rc, const char* cr, const char* ln)
+{
+    pTerminal->moveToPos(m_x, line);
+    
+    //Left corner
+    print(lc);
+    
+    for (uint8_t c = 0; c < m_col; c++) 
+    {
+        //Print line charachter
+        uint8_t width = 0;
+        while (width < m_width[c]) {
+            print(ln);
+            width++;
+        }
+        if (c < (m_col - 1)) 
+            //Print cross character
+            print(cr);
+        else
+            //Print right corner
+            print(rc);  
+    }
+    line++;
+}
+
+
+
+
+void Table::print(const char* str) {
+    pTerminal->print(str);
+}
+
+
+
+
+//-----------------------------------------------------------------------------
+// Преобразование числа в строку ANSI C через быстрое деление
+//-----------------------------------------------------------------------------
+
+struct divmod10_t
+{
+    uint32_t quot;
+    uint8_t rem;
+};
+
+
+
+inline static divmod10_t divmodu10(uint32_t n)
+{
+    divmod10_t res;
+
+    res.quot = n >> 1;
+    res.quot += res.quot >> 1;
+    res.quot += res.quot >> 4;
+    res.quot += res.quot >> 8;
+    res.quot += res.quot >> 16;
+    uint32_t qq = res.quot;
+
+    res.quot >>= 3;
+    res.rem = uint8_t(n - ((res.quot << 1) + (qq & ~7ul)));
+    if(res.rem > 9)
+    {
+        res.rem -= 10;
+        res.quot++;
+    }
+    return res;
+}
+
+
+static char utoaBuffer[13];
+
+//utoa fast div
+char * utoa(uint32_t value)
+{
+    char* buffer = &utoaBuffer[1];
+    buffer += 11;
+    *--buffer = 0;
+    do
+    {
+        divmod10_t res = divmodu10(value);
+        *--buffer = res.rem + '0';
+        value = res.quot;
+    }
+    while (value != 0);
+    return buffer;
+}
+
+
+
+
+//utoa fast div
+char * itoa(int32_t value)
+{
+    //Чёто неохото было гуглить. Мой
+    //тупой вариант взятия модуля
+    uint32_t unsignedValue = value;
+    if (value < 0)
+        unsignedValue = (uint32_t)(value - (2*value));
+    
+    char* unsignedStr = utoa(unsignedValue);
+    
+    //Добавляем знак минус в начало
+    if (value < 0) {
+        unsignedStr--;
+        *unsignedStr = '-';       
+    }
+           
+    return unsignedStr;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 161 - 0
fw/modules/terminal/terminal.h

@@ -0,0 +1,161 @@
+#ifndef __TERMINAL_H
+#define __TERMINAL_H
+
+
+#include "at32f403a_407.h"
+#include "microrl.h"
+
+#define EOL "\n\r"
+#define COUNT_TERMINAL_INTERFACE  2
+
+//Function for print on concrete interface
+typedef void (*InterfacePrint)(const char * str);
+
+typedef struct {
+    InterfacePrint print;
+    char* description[10];
+} TerminalInterface;
+
+
+
+
+//-----------------------------------------------------------------------------
+// Базовый класс терминала
+//-----------------------------------------------------------------------------
+
+typedef enum { 
+    tc_Black = 0x0, tc_Red, tc_Green, tc_Yello, tc_Blue, tc_Magenta, tc_Cyan, tc_White
+} TextColor;
+
+
+class Terminal
+{
+public:
+    Terminal();
+
+    virtual void connectCallback();
+
+    void addPrint(InterfacePrint print_func);
+    void clearScreen();   
+    void moveToPos(uint32_t h, uint32_t v);
+    void moveToUpLeftCorner();
+    void reset();
+    void resetAttribute();
+    void saveCursorPos();
+    void restoreCursorPos();
+    void hideCursor();
+    void clearCurrentLine();
+    
+
+    //Формирование команд терминала
+    uint32_t getCommand_MoveToPos(char* res_command, uint32_t& res_size, uint32_t h, uint32_t v);
+    uint32_t getCommand_MoveUpNLines(char* res_command, uint32_t& res_size, uint32_t n);
+    uint32_t getCommand_MoveDownNLines(char* res_command, uint32_t& res_size, uint32_t n);
+    uint32_t getCommand_MoveRightNLines(char* res_command, uint32_t& res_size, uint32_t n);
+    uint32_t getCommand_MoveLeftNLines(char* res_command, uint32_t& res_size, uint32_t n);
+    uint32_t getCommand_SetTextColor(char* res_command, uint32_t& res_size, TextColor color);
+    uint32_t getCommand_UnderlineText(char* res_command, uint32_t& res_size);
+
+public:
+    virtual void configure();
+    void insert(int ch);
+    void print(const char * str);
+    void printl(const char * str);
+    void printll(const char * str);
+    void eol();
+    void printeol();
+    
+    virtual int execute(int argc, const char * const * argv);
+    virtual char ** completion(int argc, const char * const * argv);
+    virtual void sigint (void);
+    
+    
+private:
+    InterfacePrint f_print[COUNT_TERMINAL_INTERFACE];
+    int m_countPrintFunction;
+
+    microrl_t rl;
+    microrl_t * prl;
+};
+
+
+
+
+
+//-----------------------------------------------------------------------------
+// Класс таблицы
+//-----------------------------------------------------------------------------    
+#define MAX_COL 8
+#define MAX_ROW 10    
+    
+class Table {
+public:
+    Table();
+    
+    void outToCell(uint8_t col, uint8_t row, const char* str);
+    void outToCell(uint8_t col, uint8_t row, uint32_t val);
+    void outCellNumber();
+    virtual void outStatic();
+    void outExternalBorder();    
+    void outCrossLine(uint8_t row);
+
+    void startUpdate();
+    void endUpdate();
+
+    //virtual void refreshData();
+    
+    void setGeometry(uint8_t x, uint8_t y, uint8_t col, uint8_t row, uint32_t width, ...);
+    void setGeometry(uint8_t x, uint8_t y, uint8_t col, uint8_t row, const uint32_t* width);
+
+private:
+    void setPos(uint8_t x, uint8_t y);
+    void setSize(uint8_t col, uint8_t row);
+    void resetAttributes();
+
+public:
+    void addCellPosAttribute(uint8_t col, uint8_t row);
+    void addCellColorAttribute(uint8_t col, uint8_t row, TextColor color);
+    void addCellUnderlineAttribute(uint8_t col, uint8_t row);
+    inline void clearCellAttributes(uint8_t col, uint8_t row);
+
+protected:
+    inline void addCellAttribute(uint8_t col, uint8_t row, const char* attr);
+
+private:
+    inline void printTopLine(uint32_t& line);
+    inline void printCrossLine(uint32_t& line);
+    inline void printTextLine(uint32_t& line);
+    inline void printBottomLine(uint32_t& line);
+
+    void printFrameLine(uint32_t& line, 
+        const char* lc, const char* rc,
+        const char* cr, const char* ln);
+            
+    inline void print(const char* str);    
+
+private:
+    uint8_t m_x, m_y;
+    uint8_t m_col, m_row;    
+    uint8_t m_width[MAX_COL];    
+
+    typedef struct {
+        char    attributes[40]; 
+        char*   text;
+    } CellAttribute;
+    
+    CellAttribute cells[MAX_COL][MAX_ROW];    
+}; 
+
+
+
+
+
+
+
+extern Terminal* pTerminal;
+char * utoa(uint32_t value);
+char * itoa(int32_t value);
+
+
+
+#endif // __TERMINAL_H

+ 122 - 0
fw/modules/terminal/terminal_sbs.cpp

@@ -0,0 +1,122 @@
+#include "terminal_sbs.h"
+#include "common_config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+
+SbsTerminal sbsTerminal;
+Terminal* pTerminal; //Глобальный указатель на терминал
+
+void vTerminal(void *params);
+
+
+//
+SbsTerminal::SbsTerminal() :
+    Terminal()
+{}
+
+//
+void SbsTerminal::configure()
+{
+    Terminal::configure();
+    pTerminal = &sbsTerminal;
+    
+    m_dataQueue = xQueueCreate(20, 1);
+    xTaskCreate(vTerminal, "terminal", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);    
+}
+
+//
+int SbsTerminal::execute(int argc, const char * const *argv)
+{
+    //char str[20];
+  
+    if (argc <= 0) {
+        return -1;
+    }
+    
+    if (strcmp(argv[0], "help") == 0) {
+        return help(argc, argv);
+    }
+    // ---------------------------------------------------------------------- //
+    else {
+        printeol();
+        printll("Uncknown command [oO]");
+        return -1;
+    }
+    
+}
+
+void SbsTerminal::sigint() {
+}
+
+//Колбэк, который может быть вызван при подключении
+void SbsTerminal::connectCallback() 
+{
+    clearScreen();
+    printll("SBS terminal.");
+  
+    //Тут выводим полезную при подключении информацию
+    printeol();
+    printll("For help type 'help'.");
+    insert('\r');    
+}
+    
+
+//
+int SbsTerminal::help(int argc, const char * const *argv)
+{
+    printeol();
+    printeol();
+    printl ("You can use the following commands:");
+    printll("  version        Print software version");
+    printeol();
+
+    return 0;
+}
+
+//
+int SbsTerminal::version(int argc, const char * const *argv) 
+{
+    printeol();
+    print(VERSION);
+    printeol();
+    return 0;
+}
+
+//
+int SbsTerminal::clear(int argc, const char * const *argv)
+{
+    if ((argc > 1) && (strcmp(argv[1], "help") == 0))  
+    {
+        printeol();
+        printl("Clear terminal screen");      
+        printeol();
+        printeol();
+        return 0;
+    }
+    clearScreen();
+    return 0;
+}
+
+//
+void SbsTerminal::put_byte(char byte)
+{
+    portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
+    xQueueSendFromISR(m_dataQueue, &byte, &xHigherPriorityTaskWoken);
+}
+
+//
+void vTerminal(void *params)
+{
+    char val;
+    
+    for (;;)
+    {
+        if (xQueueReceive(sbsTerminal.m_dataQueue, &val, 1000 ) == pdPASS)
+        {
+            sbsTerminal.insert(val);
+        }
+    }  
+}

+ 42 - 0
fw/modules/terminal/terminal_sbs.h

@@ -0,0 +1,42 @@
+#ifndef __TERMINAL_SBS_H
+#define __TERMINAL_SBS_H
+
+#include "terminal.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+
+class SbsTerminal : public Terminal
+{
+public:
+    SbsTerminal();
+
+    virtual void configure();
+    virtual int execute(int argc, const char * const * argv);
+    virtual void sigint (void);
+    virtual void connectCallback();
+
+
+public:
+    int help(int argc, const char * const * argv);
+    int help_connection();
+    int version(int argc, const char * const * argv);
+    int clear(int argc, const char * const * argv);
+    int reset(int argc, const char * const * argv);
+    
+    
+public:
+    
+    void put_byte(char byte);
+    
+public :
+    
+    QueueHandle_t m_dataQueue;
+};
+
+extern SbsTerminal sbsTerminal;
+
+
+#endif // __TERMINAL_SBS_H

+ 150 - 0
fw/modules/terminal/terminal_usartbridge.cpp

@@ -0,0 +1,150 @@
+#include "terminal_usartbridge.h"
+#include "terminal_sbs.h"
+#include <string.h>
+#include <stdio.h>
+
+//Usart bridge object for global terminal
+UsartBridgeTerminal terminalUsartBridge;
+
+//Pointer to global terminal object
+extern Terminal* pTerminal;
+
+
+#ifdef __GNUC__    
+  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)    
+#else    
+  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)    
+#endif  
+
+PUTCHAR_PROTOTYPE   
+{   
+    while (usart_flag_get(USART_BRIDGE_USART, USART_TDBE_FLAG) == RESET);
+    usart_data_transmit(USART_BRIDGE_USART, (uint16_t)ch);
+    while (usart_flag_get(USART_BRIDGE_USART, USART_TDC_FLAG) == RESET);
+    
+    return ch;
+}  
+
+
+//-----------------------------------------------------------------------------
+// Connect usartBridge objectt with ANSI C Interfaces
+//-----------------------------------------------------------------------------
+
+//Configure usart bridge
+void configure_usartbridge() {
+    terminalUsartBridge.configure();
+}
+
+//Print callback for terminal object
+void print_usartbridge(const char * str) {
+    terminalUsartBridge.print(str);
+}
+
+//-----------------------------------------------------------------------------
+// Usart Bridge for terminal
+//-----------------------------------------------------------------------------
+UsartBridgeTerminal::UsartBridgeTerminal():
+    m_readIndex(0),
+    m_state(true)
+{
+}
+
+UsartBridgeTerminal::~UsartBridgeTerminal()
+{
+}
+
+//Configure hardware and link with terminal
+void UsartBridgeTerminal::configure()
+{
+    m_sizeCache = 0;
+    m_readIndex = 0;
+	
+    InitUsart();
+
+    //Add usart print to global terminal object
+    pTerminal->addPrint(::print_usartbridge);
+}
+
+//print function
+void UsartBridgeTerminal::print(const char *str)
+{
+    uint16_t index = 0;
+    uint16_t len = strlen(str);
+    if (len <= 0)
+      return;
+    
+    while (index < len) {
+        sendByte(str[index++]);
+    }
+}
+
+
+//-----------------------------------------------------------------------------
+// Hardware usart function
+//-----------------------------------------------------------------------------
+
+extern "C" {
+
+void USART_BRIDGE_IRQHandler(void) 
+{
+    if (usart_flag_get(USART_BRIDGE_USART, USART_RDBF_FLAG) != RESET)
+    {
+        if (terminalUsartBridge.m_state) {
+            terminalUsartBridge.recvByte();
+        }
+    }  
+}
+
+}
+
+// Recv byte from usart
+void UsartBridgeTerminal::recvByte()
+{
+    sbsTerminal.put_byte((char)USART_BRIDGE_USART->dt);
+}
+
+// Send byte to usart
+void UsartBridgeTerminal::sendByte(uint8_t byte)
+{
+    USART_BRIDGE_USART->dt = (byte & 0x01FF);
+    while (usart_flag_get(USART_BRIDGE_USART, USART_TDC_FLAG) == RESET) {}
+}
+
+// Init USART
+void UsartBridgeTerminal::InitUsart()
+{
+    gpio_init_type gpio_init_struct;
+    
+    
+    USART_BRIDGE_TX_PORT_CLK_ENABLE
+    USART_BRIDGE_RX_PORT_CLK_ENABLE
+      
+    USART_BRIDGE_CLK_ENABLE
+  
+    gpio_default_para_init(&gpio_init_struct);
+
+    /* configure the uart tx pin */
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
+    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
+    gpio_init_struct.gpio_pins = USART_BRIDGE_TX_PIN | USART_BRIDGE_RX_PIN;
+    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
+    gpio_init(USART_BRIDGE_TX_PORT, &gpio_init_struct);
+    
+    gpio_init_struct.gpio_pins = USART_BRIDGE_RX_PIN;
+    gpio_init(USART_BRIDGE_RX_PORT, &gpio_init_struct);
+    
+    /* configure uart param */
+    usart_init(USART_BRIDGE_USART, USART_BRIDGE_SPEED, 
+               USART_DATA_8BITS, USART_STOP_1_BIT);
+    
+    usart_transmitter_enable(USART_BRIDGE_USART, TRUE);
+    usart_receiver_enable(USART_BRIDGE_USART, TRUE);
+    usart_enable(USART_BRIDGE_USART, TRUE);
+    
+    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
+    NVIC_ClearPendingIRQ(USART_BRIDGE_IRQn);
+    nvic_irq_enable(USART_BRIDGE_IRQn, 6, 0);
+    
+    usart_interrupt_enable(USART_BRIDGE_USART, USART_RDBF_INT, TRUE);
+}

+ 81 - 0
fw/modules/terminal/terminal_usartbridge.h

@@ -0,0 +1,81 @@
+#ifndef __USARTBRIDGETERMINAL_H
+#define __USARTBRIDGETERMINAL_H
+
+#include "at32f403a_407.h"
+#include "terminal.h"
+
+
+#define USART_BRIDGE_USART            USART1
+#define USART_BRIDGE_SPEED            115200 
+#define USART_BRIDGE_IRQn             USART1_IRQn
+#define USART_BRIDGE_IRQHandler       USART1_IRQHandler
+#define USART_BRIDGE_TX_PIN           GPIO_PINS_9
+#define USART_BRIDGE_RX_PIN           GPIO_PINS_10
+#define USART_BRIDGE_TX_PORT          GPIOA
+#define USART_BRIDGE_RX_PORT          GPIOA
+#define USART_BRIDGE_CLK_ENABLE       crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
+#define USART_BRIDGE_TX_PORT_CLK_ENABLE  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+#define USART_BRIDGE_RX_PORT_CLK_ENABLE  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+
+
+//-----------------------------------------------------------------------------
+
+// Connect usartBridge objectt with ANSI C Interfaces
+
+//-----------------------------------------------------------------------------
+
+
+//Task for freertos function
+void task_usartbridge(void *pvParameters);
+
+//Ansi C interface for usartBridge object
+
+void configure_usartbridge();
+void processing_usartbridge();
+void print_usartbridge(const char * str);
+void vTaskUsartBridge(void *params);
+void HAL_UART_RxCpltCallbackTerminal(void);
+void HAL_UART_TxCpltCallbackTerminal(void);
+
+//-----------------------------------------------------------------------------
+
+// Usart bridge class for terminal
+
+//-----------------------------------------------------------------------------
+
+class UsartBridgeTerminal
+{
+public:
+
+    UsartBridgeTerminal();
+    ~UsartBridgeTerminal();
+
+    void configure();
+    void print(const char *str);
+
+public:
+
+    void recvByte();
+    void sendByte(uint8_t byte);
+
+private:
+
+    void InitUsart();
+
+public:
+    
+    char               m_uartByte;
+    bool               m_state;
+    
+private:
+
+    uint32_t m_sizeCache;
+    uint32_t m_readIndex;
+};
+
+
+extern UsartBridgeTerminal terminalUsartBridge;
+
+
+#endif // USARTBRIDGETERMINAL_H
+

+ 105 - 0
fw/user/MicroRLConfig.h

@@ -0,0 +1,105 @@
+/*
+Microrl library config files
+Autor: Eugene Samoylov aka Helius (ghelius@gmail.com)
+*/
+#ifndef _MICRORL_CONFIG_H_
+#define _MICRORL_CONFIG_H_
+
+#define MICRORL_LIB_VER "1.5.1"
+
+/*********** CONFIG SECTION **************/
+/*
+Command line length, define cmdline buffer size. Set max number of chars + 1,
+because last byte of buffer need to contain '\0' - NULL terminator, and 
+not use for storing inputed char.
+If user input chars more then it parametrs-1, chars not added to command line.*/
+#define _COMMAND_LINE_LEN (1+100)									// for 32 chars
+
+/*
+Command token number, define max token it command line, if number of token 
+typed in command line exceed this value, then prints message about it and
+command line not to be parced and 'execute' callback will not calls.
+Token is word separate by white space, for example 3 token line:
+"IRin> set mode test" */
+#define _COMMAND_TOKEN_NMB 8
+
+/*
+Define you prompt string here. You can use colors escape code, for highlight you prompt,
+for example this prompt will green color (if you terminal supports color)*/
+//#define _PROMPT_DEFAULT "\033[32mIRin >\033[0m "	// green color
+#define _PROMPT_DEFAULT "\033[32mrotek: $\033[0m "	// green color
+//#define _PROMPT_DEFAULT "IRin > "
+
+/*
+Define prompt text (without ESC sequence, only text) prompt length, it needs because if you use
+ESC sequence, it's not possible detect only text length*/
+#define _PROMPT_LEN       9
+
+/*Define it, if you wanna use completion functional, also set completion callback in you code,
+now if user press TAB calls 'copmlitetion' callback. If you no need it, you can just set 
+NULL to callback ptr and do not use it, but for memory saving tune, 
+if you are not going to use it - disable this define.*/
+//#define _USE_COMPLETE
+
+/*Define it, if you wanna use history. It s work's like bash history, and
+set stored value to cmdline, if UP and DOWN key pressed. Using history add
+memory consuming, depends from _RING_HISTORY_LEN parametr */
+#define _USE_HISTORY
+
+/*
+History ring buffer length, define static buffer size.
+For saving memory, each entered cmdline store to history in ring buffer,
+so we can not say, how many line we can store, it depends from cmdline len,
+but memory using more effective. We not prefer dinamic memory allocation for
+small and embedded devices. Overhead is 2 char on each saved line*/
+#define _RING_HISTORY_LEN 64
+
+/*
+Enable Handling terminal ESC sequence. If disabling, then cursor arrow, HOME, END will not work,
+use Ctrl+A(B,F,P,N,A,E,H,K,U,C) see README, but decrease code memory.*/
+#define _USE_ESC_SEQ
+
+/*
+Use snprintf from you standard complier library, but it gives some overhead.
+If not defined, use my own u16int_to_str variant, it's save about 800 byte of code size
+on AVR (avr-gcc build).
+Try to build with and without, and compare total code size for tune library.
+*/
+//#define _USE_LIBC_STDIO
+
+/*
+Enable 'interrupt signal' callback, if user press Ctrl+C */
+#define _USE_CTLR_C
+
+/*
+Print prompt at 'microrl_init', if enable, prompt will print at startup, 
+otherwise first prompt will print after first press Enter in terminal
+NOTE!: Enable it, if you call 'microrl_init' after your communication subsystem 
+already initialize and ready to print message */
+#undef _ENABLE_INIT_PROMPT
+
+/*
+New line symbol */
+#define _ENDL_CR //Putty 0x0D
+//#define _ENDL_LF //netcat 0x0A 
+
+#if defined(_ENDL_CR)
+#define ENDL "\r"
+#elif defined(_ENDL_CRLF)
+#define ENDL "\r\n"
+#elif defined(_ENDL_LF)
+#define ENDL "\n"
+#elif defined(_ENDL_LFCR)
+#define ENDL "\n\r"
+#else
+#error "You must define new line symbol."
+#endif
+
+/********** END CONFIG SECTION ************/
+
+
+#if _RING_HISTORY_LEN > 256
+#error "This history implementation (ring buffer with 1 byte iterator) allow 256 byte buffer size maximum"
+#endif
+
+#endif

+ 46 - 4
fw/user/main.c → fw/user/main.cpp

@@ -1,5 +1,45 @@
-#include "main.h"
-
+//#include "main.h"
+#include "at32f403a_407.h"
+#include "at32f403a_407_board.h"
+#include "at32f403a_407_clock.h"
+#include "common_config.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+extern "C" {
+#include "usb_eth.h"
+#include "mux.h"
+#include "misc.h"
+#include "spi_common.h"
+#include "user_fatfs.h"
+#include "spi_flash.h"
+#include "usb_eth.h"
+#include "extended_sram.h"
+#include "modbus.h"
+#include "common_gpio.h"
+#include "io.h"
+#include "input.h"
+#include "output.h"
+#include "sys_api.h"
+#include "settings_api.h"
+#include "update.h"
+#include "uptime.h"
+#include "rtc.h"
+#include "mb.h"
+#include "io_utils.h"
+#include "buttons.h"
+#include "adc_transport.h"
+#include "shift_reg.h"
+#include "analog_input.h"
+#include "dac_transport.h"
+#include "log.h"
+}
+#include "terminal_sbs.h"
+#include "terminal_usartbridge.h"
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
 
 void init_task(void *argument);
 void test_hw_task(void *argument);
@@ -25,8 +65,10 @@ int main(void)
 
     // -------------------------------------------------------------------------
     // Debug
-    uart_print_init(115200);
-
+    //uart_print_init(115200);
+    sbsTerminal.configure();
+    terminalUsartBridge.configure();
+    
     
     //usb_clock48m_select(USB_CLK_HEXT);
     

+ 1 - 37
fw/user/main.h

@@ -1,43 +1,7 @@
 #ifndef __MAIN_H
 #define __MAIN_H
 
-#include "at32f403a_407.h"
-#include "at32f403a_407_board.h"
-#include "at32f403a_407_clock.h"
-#include "common_config.h"
-#include "FreeRTOS.h"
-#include "task.h"
-#include "queue.h"
-#include "semphr.h"
-#include "usb_eth.h"
-#include "mux.h"
-#include "misc.h"
-#include "spi_common.h"
-#include "user_fatfs.h"
-#include "spi_flash.h"
-#include "usb_eth.h"
-#include "extended_sram.h"
-#include "modbus.h"
-#include "common_gpio.h"
-#include "io.h"
-#include "input.h"
-#include "output.h"
-#include "sys_api.h"
-#include "settings_api.h"
-#include "update.h"
-#include "uptime.h"
-#include "rtc.h"
-#include "mb.h"
-#include "io_utils.h"
-#include "buttons.h"
-#include "adc_transport.h"
-#include "shift_reg.h"
-#include "analog_input.h"
-#include "dac_transport.h"
-#include "log.h"
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
+
 
 
 

+ 684 - 0
libs/thirdparty/microrl/microrl.c

@@ -0,0 +1,684 @@
+/*
+Author: Samoylov Eugene aka Helius (ghelius@gmail.com)
+BUGS and TODO:
+-- add echo_off feature
+-- rewrite history for use more than 256 byte buffer
+*/
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "microrl.h"
+#ifdef _USE_LIBC_STDIO
+#include <stdio.h>
+#endif
+
+//#define DBG(...) fprintf(stderr, "\033[33m");fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\033[0m");
+
+char * prompt_default = _PROMPT_DEFAULT;
+
+#ifdef _USE_HISTORY
+
+#ifdef _HISTORY_DEBUG
+//*****************************************************************************
+// print buffer content on screen
+static void print_hist (ring_history_t * pThis)
+{
+	printf ("\n");
+	for (int i = 0; i < _RING_HISTORY_LEN; i++) {
+		if (i == pThis->begin)
+			printf ("b");
+		else 
+			printf (" ");
+	}
+	printf ("\n");
+	for (int i = 0; i < _RING_HISTORY_LEN; i++) {
+		if (isalpha(pThis->ring_buf[i]))
+			printf ("%c", pThis->ring_buf[i]);
+		else 
+			printf ("%d", pThis->ring_buf[i]);
+	}
+	printf ("\n");
+	for (int i = 0; i < _RING_HISTORY_LEN; i++) {
+		if (i == pThis->end)
+			printf ("e");
+		else 
+			printf (" ");
+	}
+	printf ("\n");
+}
+#endif
+
+//*****************************************************************************
+// remove older message from ring buffer
+static void hist_erase_older (ring_history_t * pThis)
+{
+	int new_pos = pThis->begin + pThis->ring_buf [pThis->begin] + 1;
+	if (new_pos >= _RING_HISTORY_LEN)
+		new_pos = new_pos - _RING_HISTORY_LEN;
+	
+	pThis->begin = new_pos;
+}
+
+//*****************************************************************************
+// check space for new line, remove older while not space
+static int hist_is_space_for_new (ring_history_t * pThis, int len)
+{
+	if (pThis->ring_buf [pThis->begin] == 0)
+		return true;
+	if (pThis->end >= pThis->begin) {
+		if (_RING_HISTORY_LEN - pThis->end + pThis->begin - 1 > len)
+			return true;
+	}	else {
+		if (pThis->begin - pThis->end - 1> len)
+			return true;
+	}
+	return false;
+}
+
+//*****************************************************************************
+// put line to ring buffer
+static void hist_save_line (ring_history_t * pThis, char * line, int len)
+{
+	if (len > _RING_HISTORY_LEN - 2)
+		return;
+	while (!hist_is_space_for_new (pThis, len)) {
+		hist_erase_older (pThis);
+	}
+	// if it's first line
+	if (pThis->ring_buf [pThis->begin] == 0) 
+		pThis->ring_buf [pThis->begin] = len;
+	
+	// store line
+	if (len < _RING_HISTORY_LEN-pThis->end-1)
+		memcpy (pThis->ring_buf + pThis->end + 1, line, len);
+	else {
+		int part_len = _RING_HISTORY_LEN-pThis->end-1;
+		memcpy (pThis->ring_buf + pThis->end + 1, line, part_len);
+		memcpy (pThis->ring_buf, line + part_len, len - part_len);
+	}
+	pThis->ring_buf [pThis->end] = len;
+	pThis->end = pThis->end + len + 1;
+	if (pThis->end >= _RING_HISTORY_LEN)
+		pThis->end -= _RING_HISTORY_LEN;
+	pThis->ring_buf [pThis->end] = 0;
+	pThis->cur = 0;
+#ifdef _HISTORY_DEBUG
+	print_hist (pThis);
+#endif
+}
+
+//*****************************************************************************
+// copy saved line to 'line' and return size of line
+static int hist_restore_line (ring_history_t * pThis, char * line, int dir)
+{
+	int cnt = 0;
+	// count history record	
+	int header = pThis->begin;
+	while (pThis->ring_buf [header] != 0) {
+		header += pThis->ring_buf [header] + 1;
+		if (header >= _RING_HISTORY_LEN)
+			header -= _RING_HISTORY_LEN; 
+		cnt++;
+	}
+
+	if (dir == _HIST_UP) {
+		if (cnt >= pThis->cur) {
+			int header = pThis->begin;
+			int j = 0;
+			// found record for 'pThis->cur' index
+			while ((pThis->ring_buf [header] != 0) && (cnt - j -1 != pThis->cur)) {
+				header += pThis->ring_buf [header] + 1;
+				if (header >= _RING_HISTORY_LEN)
+					header -= _RING_HISTORY_LEN;
+				j++;
+			}
+			if (pThis->ring_buf[header]) {
+					pThis->cur++;
+				// obtain saved line
+				if (pThis->ring_buf [header] + header + 1< _RING_HISTORY_LEN) {
+					memset (line, 0, _COMMAND_LINE_LEN);
+					memcpy (line, pThis->ring_buf + header + 1, pThis->ring_buf[header]);
+				} else {
+					int part0 = _RING_HISTORY_LEN - header - 1;
+					memset (line, 0, _COMMAND_LINE_LEN);
+					memcpy (line, pThis->ring_buf + header + 1, part0);
+					memcpy (line + part0, pThis->ring_buf, pThis->ring_buf[header] - part0);
+				}
+				return pThis->ring_buf[header];
+			}
+		}
+	} else {
+		if (pThis->cur > 0) {
+				pThis->cur--;
+			int header = pThis->begin;
+			int j = 0;
+
+			while ((pThis->ring_buf [header] != 0) && (cnt - j != pThis->cur)) {
+				header += pThis->ring_buf [header] + 1;
+				if (header >= _RING_HISTORY_LEN)
+					header -= _RING_HISTORY_LEN;
+				j++;
+			}
+			if (pThis->ring_buf [header] + header < _RING_HISTORY_LEN) {
+				memcpy (line, pThis->ring_buf + header + 1, pThis->ring_buf[header]);
+			} else {
+				int part0 = _RING_HISTORY_LEN - header - 1;
+				memcpy (line, pThis->ring_buf + header + 1, part0);
+				memcpy (line + part0, pThis->ring_buf, pThis->ring_buf[header] - part0);
+			}
+			return pThis->ring_buf[header];
+		} else {
+			/* empty line */
+			return 0;
+		}
+	}
+	return -1;
+}
+#endif
+
+
+
+
+
+
+
+
+//*****************************************************************************
+// split cmdline to tkn array and return nmb of token
+static int split (microrl_t * pThis, int limit, char const ** tkn_arr)
+{
+	int i = 0;
+	int ind = 0;
+	while (1) {
+		// go to the first whitespace (zerro for us)
+		while ((pThis->cmdline [ind] == '\0') && (ind < limit)) {
+			ind++;
+		}
+		if (!(ind < limit)) return i;
+		tkn_arr[i++] = pThis->cmdline + ind;
+		if (i >= _COMMAND_TOKEN_NMB) {
+			return -1;
+		}
+		// go to the first NOT whitespace (not zerro for us)
+		while ((pThis->cmdline [ind] != '\0') && (ind < limit)) {
+			ind++;
+		}
+		if (!(ind < limit)) return i;
+	}
+	//return i;
+}
+
+
+//*****************************************************************************
+inline static void print_prompt (microrl_t * pThis)
+{
+	pThis->print (pThis->prompt_str);
+}
+
+//*****************************************************************************
+inline static void terminal_backspace (microrl_t * pThis)
+{
+		pThis->print ("\033[D \033[D");
+}
+
+//*****************************************************************************
+inline static void terminal_newline (microrl_t * pThis)
+{
+	pThis->print (ENDL);
+}
+
+#ifndef _USE_LIBC_STDIO
+//*****************************************************************************
+// convert 16 bit value to string
+// 0 value not supported!!! just make empty string
+// Returns pointer to a buffer tail
+static char *u16bit_to_str (unsigned int nmb, char * buf)
+{
+	char tmp_str [6] = {0,};
+	int i = 0, j;
+	if (nmb <= 0xFFFF) {
+		while (nmb > 0) {
+			tmp_str[i++] = (nmb % 10) + '0';
+			nmb /=10;
+		}
+		for (j = 0; j < i; ++j)
+			*(buf++) = tmp_str [i-j-1];
+	}
+	*buf = '\0';
+	return buf;
+}
+#endif
+
+
+//*****************************************************************************
+// set cursor at position from begin cmdline (after prompt) + offset
+static void terminal_move_cursor (microrl_t * pThis, int offset)
+{
+	char str[16];
+#ifdef _USE_LIBC_STDIO 
+	if (offset > 0) {
+		snprintf (str, 16, "\033[%dC", offset);
+	} else if (offset < 0) {
+		snprintf (str, 16, "\033[%dD", -(offset));
+	}
+#else 
+	char *endstr;
+	strcpy (str, "\033[");
+	if (offset > 0) {
+		endstr = u16bit_to_str (offset, str+2);
+		strcpy (endstr, "C");
+	} else if (offset < 0) {
+		endstr = u16bit_to_str (-(offset), str+2);
+		strcpy (endstr, "D");
+	} else
+		return;
+#endif	
+	pThis->print (str);
+}
+
+//*****************************************************************************
+static void terminal_reset_cursor (microrl_t * pThis)
+{
+	char str[16];
+#ifdef _USE_LIBC_STDIO
+	snprintf (str, 16, "\033[%dD\033[%dC", \
+						_COMMAND_LINE_LEN + _PROMPT_LEN + 2, _PROMPT_LEN);
+
+#else
+	char *endstr;
+	strcpy (str, "\033[");
+	endstr = u16bit_to_str ( _COMMAND_LINE_LEN + _PROMPT_LEN + 2,str+2);
+	strcpy (endstr, "D\033["); endstr += 3;
+	endstr = u16bit_to_str (_PROMPT_LEN, endstr);
+	strcpy (endstr, "C");
+#endif
+	pThis->print (str);
+}
+
+//*****************************************************************************
+// print cmdline to screen, replace '\0' to wihitespace 
+static void terminal_print_line (microrl_t * pThis, int pos, int cursor)
+{
+	pThis->print ("\033[K");    // delete all from cursor to end
+
+	char nch [] = {0,0};
+	int i;
+	for (i = pos; i < pThis->cmdlen; i++) {
+		nch [0] = pThis->cmdline [i];
+		if (nch[0] == '\0')
+			nch[0] = ' ';
+		pThis->print (nch);
+	}
+	
+	terminal_reset_cursor (pThis);
+	terminal_move_cursor (pThis, cursor);
+}
+
+//*****************************************************************************
+void microrl_init (microrl_t * pThis, void (*print) (const char *)) 
+{
+	memset(pThis->cmdline, 0, _COMMAND_LINE_LEN);
+#ifdef _USE_HISTORY
+	memset(pThis->ring_hist.ring_buf, 0, _RING_HISTORY_LEN);
+	pThis->ring_hist.begin = 0;
+	pThis->ring_hist.end = 0;
+	pThis->ring_hist.cur = 0;
+#endif
+	pThis->cmdlen =0;
+	pThis->cursor = 0;
+	pThis->execute = NULL;
+	pThis->get_completion = NULL;
+#ifdef _USE_CTLR_C
+	pThis->sigint = NULL;
+#endif
+	pThis->prompt_str = prompt_default;
+	pThis->print = print;
+#ifdef _ENABLE_INIT_PROMPT
+	print_prompt (pThis);
+#endif
+}
+
+//*****************************************************************************
+void microrl_set_complete_callback (microrl_t * pThis, char ** (*get_completion)(int, const char* const*))
+{
+	pThis->get_completion = get_completion;
+}
+
+//*****************************************************************************
+void microrl_set_execute_callback (microrl_t * pThis, int (*execute)(int, const char* const*))
+{
+	pThis->execute = execute;
+}
+#ifdef _USE_CTLR_C
+//*****************************************************************************
+void microrl_set_sigint_callback (microrl_t * pThis, void (*sigintf)(void))
+{
+	pThis->sigint = sigintf;
+}
+#endif
+
+#ifdef _USE_ESC_SEQ
+static void hist_search (microrl_t * pThis, int dir)
+{
+	int len = hist_restore_line (&pThis->ring_hist, pThis->cmdline, dir);
+	if (len >= 0) {
+		pThis->cursor = pThis->cmdlen = len;
+		terminal_reset_cursor (pThis);
+		terminal_print_line (pThis, 0, pThis->cursor);
+	}
+}
+
+//*****************************************************************************
+// handling escape sequences
+static int escape_process (microrl_t * pThis, char ch)
+{
+	if (ch == '[') {
+		pThis->escape_seq = _ESC_BRACKET;
+		return 0;
+	} else if (pThis->escape_seq == _ESC_BRACKET) {
+		if (ch == 'A') {
+#ifdef _USE_HISTORY
+			hist_search (pThis, _HIST_UP);
+#endif
+			return 1;
+		} else if (ch == 'B') {
+#ifdef _USE_HISTORY
+			hist_search (pThis, _HIST_DOWN);
+#endif
+			return 1;
+		} else if (ch == 'C') {
+			if (pThis->cursor < pThis->cmdlen) {
+				terminal_move_cursor (pThis, 1);
+				pThis->cursor++;
+			}
+			return 1;
+		} else if (ch == 'D') {
+			if (pThis->cursor > 0) {
+				terminal_move_cursor (pThis, -1);
+				pThis->cursor--;
+			}
+			return 1;
+		} else if (ch == '7') {
+			pThis->escape_seq = _ESC_HOME;
+			return 0;
+		} else if (ch == '8') {
+			pThis->escape_seq = _ESC_END;
+			return 0;
+		} 
+	} else if (ch == '~') {
+		if (pThis->escape_seq == _ESC_HOME) {
+			terminal_reset_cursor (pThis);
+			pThis->cursor = 0;
+			return 1;
+		} else if (pThis->escape_seq == _ESC_END) {
+			terminal_move_cursor (pThis, pThis->cmdlen-pThis->cursor);
+			pThis->cursor = pThis->cmdlen;
+			return 1;
+		}
+	}
+
+	/* unknown escape sequence, stop */
+	return 1;
+}
+#endif
+
+//*****************************************************************************
+// insert len char of text at cursor position
+static int microrl_insert_text (microrl_t * pThis, char * text, int len)
+{
+	int i;
+	if (pThis->cmdlen + len < _COMMAND_LINE_LEN) {
+		memmove (pThis->cmdline + pThis->cursor + len,
+						 pThis->cmdline + pThis->cursor,
+						 pThis->cmdlen - pThis->cursor);
+		for (i = 0; i < len; i++) {
+			pThis->cmdline [pThis->cursor + i] = text [i];
+			if (pThis->cmdline [pThis->cursor + i] == ' ') {
+				pThis->cmdline [pThis->cursor + i] = 0;
+			}
+		}
+		pThis->cursor += len;
+		pThis->cmdlen += len;
+		pThis->cmdline [pThis->cmdlen] = '\0';
+		return true;
+	}
+	return false;
+}
+
+//*****************************************************************************
+// remove one char at cursor
+static void microrl_backspace (microrl_t * pThis)
+{
+	if (pThis->cursor > 0) {
+		terminal_backspace (pThis);
+		memmove (pThis->cmdline + pThis->cursor-1,
+						 pThis->cmdline + pThis->cursor,
+						 pThis->cmdlen-pThis->cursor+1);
+		pThis->cursor--;
+		pThis->cmdline [pThis->cmdlen] = '\0';
+		pThis->cmdlen--;
+	}
+}
+
+
+#ifdef _USE_COMPLETE
+
+//*****************************************************************************
+static int common_len (char ** arr)
+{
+	int i;
+	int j;
+	char *shortest = arr[0];
+	int shortlen = strlen(shortest);
+
+	for (i = 0; arr[i] != NULL; ++i)
+		if (strlen(arr[i]) < shortlen) {
+			shortest = arr[i];
+			shortlen = strlen(shortest);
+		}
+
+	for (i = 0; i < shortlen; ++i)
+		for (j = 0; arr[j] != 0; ++j)
+			if (shortest[i] != arr[j][i])
+				return i;
+
+	return i;
+}
+
+//*****************************************************************************
+static void microrl_get_complite (microrl_t * pThis) 
+{
+	char const * tkn_arr[_COMMAND_TOKEN_NMB];
+	char ** compl_token; 
+	
+	if (pThis->get_completion == NULL) // callback was not set
+		return;
+	
+	int status = split (pThis, pThis->cursor, tkn_arr);
+	if (pThis->cmdline[pThis->cursor-1] == '\0')
+		tkn_arr[status++] = "";
+	compl_token = pThis->get_completion (status, tkn_arr);
+	if (compl_token[0] != NULL) {
+		int i = 0;
+		int len;
+
+		if (compl_token[1] == NULL) {
+			len = strlen (compl_token[0]);
+		} else {
+			len = common_len (compl_token);
+			terminal_newline (pThis);
+			while (compl_token [i] != NULL) {
+				pThis->print (compl_token[i]);
+				pThis->print (" ");
+				i++;
+			}
+			terminal_newline (pThis);
+			print_prompt (pThis);
+		}
+		
+		if (len) {
+			microrl_insert_text (pThis, compl_token[0] + strlen(tkn_arr[status-1]), 
+																	len - strlen(tkn_arr[status-1]));
+			if (compl_token[1] == NULL) 
+				microrl_insert_text (pThis, " ", 1);
+		}
+		terminal_reset_cursor (pThis);
+		terminal_print_line (pThis, 0, pThis->cursor);
+	} 
+}
+#endif
+
+//*****************************************************************************
+void new_line_handler(microrl_t * pThis){
+	char const * tkn_arr [_COMMAND_TOKEN_NMB];
+	int status;
+
+	terminal_newline (pThis);
+#ifdef _USE_HISTORY
+	if (pThis->cmdlen > 0)
+		hist_save_line (&pThis->ring_hist, pThis->cmdline, pThis->cmdlen);
+#endif
+	status = split (pThis, pThis->cmdlen, tkn_arr);
+	if (status == -1){
+		//          pThis->print ("ERROR: Max token amount exseed\n");
+		pThis->print ("ERROR:too many tokens");
+		pThis->print (ENDL);
+	}
+	if ((status > 0) && (pThis->execute != NULL))
+		pThis->execute (status, tkn_arr);
+	print_prompt (pThis);
+	pThis->cmdlen = 0;
+	pThis->cursor = 0;
+	memset(pThis->cmdline, 0, _COMMAND_LINE_LEN);
+#ifdef _USE_HISTORY
+	pThis->ring_hist.cur = 0;
+#endif
+}
+
+//*****************************************************************************
+
+void microrl_insert_char (microrl_t * pThis, int ch)
+{
+#ifdef _USE_ESC_SEQ
+	if (pThis->escape) {
+		if (escape_process(pThis, ch))
+			pThis->escape = 0;
+	} else {
+#endif
+		switch (ch) {
+			//-----------------------------------------------------
+#ifdef _ENDL_CR
+			case KEY_CR:
+				new_line_handler(pThis);
+			break;
+			case KEY_LF:
+			break;
+#elif defined(_ENDL_CRLF)
+			case KEY_CR:
+				pThis->tmpch = KEY_CR;
+			break;
+			case KEY_LF:
+			if (pThis->tmpch == KEY_CR)
+				new_line_handler(pThis);
+			break;
+#elif defined(_ENDL_LFCR)
+			case KEY_LF:
+				pThis->tmpch = KEY_LF;
+			break;
+			case KEY_CR:
+			if (pThis->tmpch == KEY_LF)
+				new_line_handler(pThis);
+			break;
+#else
+			case KEY_CR:
+			break;
+			case KEY_LF:
+				new_line_handler(pThis);
+			break;
+#endif
+			//-----------------------------------------------------
+#ifdef _USE_COMPLETE
+			case KEY_HT:
+				microrl_get_complite (pThis);
+			break;
+#endif
+			//-----------------------------------------------------
+			case KEY_ESC:
+#ifdef _USE_ESC_SEQ
+				pThis->escape = 1;
+#endif
+			break;
+			//-----------------------------------------------------
+			case KEY_NAK: // ^U
+					while (pThis->cursor > 0) {
+					microrl_backspace (pThis);
+				}
+				terminal_print_line (pThis, 0, pThis->cursor);
+			break;
+			//-----------------------------------------------------
+			case KEY_VT:  // ^K
+				pThis->print ("\033[K");
+				pThis->cmdlen = pThis->cursor;
+			break;
+			//-----------------------------------------------------
+			case KEY_ENQ: // ^E
+				terminal_move_cursor (pThis, pThis->cmdlen-pThis->cursor);
+				pThis->cursor = pThis->cmdlen;
+			break;
+			//-----------------------------------------------------
+			case KEY_SOH: // ^A
+				terminal_reset_cursor (pThis);
+				pThis->cursor = 0;
+			break;
+			//-----------------------------------------------------
+			case KEY_ACK: // ^F
+			if (pThis->cursor < pThis->cmdlen) {
+				terminal_move_cursor (pThis, 1);
+				pThis->cursor++;
+			}
+			break;
+			//-----------------------------------------------------
+			case KEY_STX: // ^B
+			if (pThis->cursor) {
+				terminal_move_cursor (pThis, -1);
+				pThis->cursor--;
+			}
+			break;
+			//-----------------------------------------------------
+			case KEY_DLE: //^P
+#ifdef _USE_HISTORY
+			hist_search (pThis, _HIST_UP);
+#endif
+			break;
+			//-----------------------------------------------------
+			case KEY_SO: //^N
+#ifdef _USE_HISTORY
+			hist_search (pThis, _HIST_DOWN);
+#endif
+			break;
+			//-----------------------------------------------------
+			case KEY_DEL: // Backspace
+			case KEY_BS: // ^U
+				microrl_backspace (pThis);
+				terminal_print_line (pThis, pThis->cursor, pThis->cursor);
+			break;
+#ifdef _USE_CTLR_C
+			case KEY_ETX:
+			if (pThis->sigint != NULL)
+				pThis->sigint();
+			break;
+#endif
+			//-----------------------------------------------------
+			default:
+			if (((ch == ' ') && (pThis->cmdlen == 0)) || IS_CONTROL_CHAR(ch))
+				break;
+			if (microrl_insert_text (pThis, (char*)&ch, 1))
+				terminal_print_line (pThis, pThis->cursor-1, pThis->cursor);
+			
+			break;
+		}
+#ifdef _USE_ESC_SEQ
+	}
+#endif
+}

+ 128 - 0
libs/thirdparty/microrl/microrl.h

@@ -0,0 +1,128 @@
+#ifndef _MICRORL_H_
+#define _MICRORL_H_
+
+#include "MicroRLConfig.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+
+#define true  1
+#define false 0
+
+ /* define the Key codes */
+#define KEY_NUL 0 /**< ^@ Null character */
+#define KEY_SOH 1 /**< ^A Start of heading, = console interrupt */
+#define KEY_STX 2 /**< ^B Start of text, maintenance mode on HP console */
+#define KEY_ETX 3 /**< ^C End of text */
+#define KEY_EOT 4 /**< ^D End of transmission, not the same as ETB */
+#define KEY_ENQ 5 /**< ^E Enquiry, goes with ACK; old HP flow control */
+#define KEY_ACK 6 /**< ^F Acknowledge, clears ENQ logon hand */
+#define KEY_BEL 7 /**< ^G Bell, rings the bell... */
+#define KEY_BS  8 /**< ^H Backspace, works on HP terminals/computers */
+#define KEY_HT  9 /**< ^I Horizontal tab, move to next tab stop */
+#define KEY_LF  10  /**< ^J Line Feed */
+#define KEY_VT  11  /**< ^K Vertical tab */
+#define KEY_FF  12  /**< ^L Form Feed, page eject */
+#define KEY_CR  13  /**< ^M Carriage Return*/
+#define KEY_SO  14  /**< ^N Shift Out, alternate character set */
+#define KEY_SI  15  /**< ^O Shift In, resume defaultn character set */
+#define KEY_DLE 16  /**< ^P Data link escape */
+#define KEY_DC1 17  /**< ^Q XON, with XOFF to pause listings; "okay to send". */
+#define KEY_DC2 18  /**< ^R Device control 2, block-mode flow control */
+#define KEY_DC3 19  /**< ^S XOFF, with XON is TERM=18 flow control */
+#define KEY_DC4 20  /**< ^T Device control 4 */
+#define KEY_NAK 21  /**< ^U Negative acknowledge */
+#define KEY_SYN 22  /**< ^V Synchronous idle */
+#define KEY_ETB 23  /**< ^W End transmission block, not the same as EOT */
+#define KEY_CAN 24  /**< ^X Cancel line, MPE echoes !!! */
+#define KEY_EM  25  /**< ^Y End of medium, Control-Y interrupt */
+#define KEY_SUB 26  /**< ^Z Substitute */
+#define KEY_ESC 27  /**< ^[ Escape, next character is not echoed */
+#define KEY_FS  28  /**< ^\ File separator */
+#define KEY_GS  29  /**< ^] Group separator */
+#define KEY_RS  30  /**< ^^ Record separator, block-mode terminator */
+#define KEY_US  31  /**< ^_ Unit separator */
+
+#define KEY_DEL 127 /**< Delete (not a real control character...) */
+
+#define IS_CONTROL_CHAR(x) ((x)<=31)
+
+// direction of history navigation
+#define _HIST_UP   0
+#define _HIST_DOWN 1
+// esc seq internal codes
+#define _ESC_BRACKET  1
+#define _ESC_HOME     2
+#define _ESC_END      3
+
+#ifdef _USE_HISTORY
+// history struct, contain internal variable
+// history store in static ring buffer for memory saving
+typedef struct {
+	char ring_buf [_RING_HISTORY_LEN];
+	int begin;
+	int end;
+	int cur;
+} ring_history_t;
+#endif
+
+// microrl struct, contain internal library data
+typedef struct {
+#ifdef _USE_ESC_SEQ
+	char escape_seq;
+	char escape;
+#endif
+#if (defined(_ENDL_CRLF) || defined(_ENDL_LFCR))
+	char tmpch;
+#endif
+#ifdef _USE_HISTORY
+	ring_history_t ring_hist;          // history object
+#endif
+	char * prompt_str;                 // pointer to prompt string
+	char cmdline [_COMMAND_LINE_LEN];  // cmdline buffer
+	int cmdlen;                        // last position in command line
+	int cursor;                        // input cursor
+	int (*execute) (int argc, const char * const * argv );            // ptr to 'execute' callback
+	char ** (*get_completion) (int argc, const char * const * argv ); // ptr to 'completion' callback
+	void (*print) (const char *);                                     // ptr to 'print' callback
+#ifdef _USE_CTLR_C
+	void (*sigint) (void);
+#endif
+} microrl_t;
+
+// init internal data, calls once at start up
+void microrl_init (microrl_t * pThis, void (*print)(const char*));
+
+// set echo mode (true/false), using for disabling echo for password input
+// echo mode will enabled after user press Enter.
+void microrl_set_echo (int);
+
+// set pointer to callback complition func, that called when user press 'Tab'
+// callback func description:
+//   param: argc - argument count, argv - pointer array to token string
+//   must return NULL-terminated string, contain complite variant splitted by 'Whitespace'
+//   If complite token found, it's must contain only one token to be complitted
+//   Empty string if complite not found, and multiple string if there are some token
+void microrl_set_complete_callback (microrl_t * pThis, char ** (*get_completion)(int, const char* const*));
+
+// pointer to callback func, that called when user press 'Enter'
+// execute func param: argc - argument count, argv - pointer array to token string
+void microrl_set_execute_callback (microrl_t * pThis, int (*execute)(int, const char* const*));
+
+// set callback for Ctrl+C terminal signal
+#ifdef _USE_CTLR_C
+void microrl_set_sigint_callback (microrl_t * pThis, void (*sigintf)(void));
+#endif
+
+// insert char to cmdline (for example call in usart RX interrupt)
+void microrl_insert_char (microrl_t * pThis, int ch);
+
+
+#ifdef  __cplusplus
+}
+#endif
+
+
+#endif

+ 2 - 1
libs/thirdparty/ringfs/ringfs.c

@@ -18,7 +18,8 @@
 #include <inttypes.h>
 #include <stdbool.h>
 #include <stddef.h>
-#include "main.h"
+//#include "main.h"
+#include "common_config.h"
 
 
 /**

BIN
output/fw.bin


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 400 - 390
project/ewarm/iap/iap.dep


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 745 - 568
project/ewarm/module_universal_io.dep


+ 29 - 6
project/ewarm/module_universal_io.ewp

@@ -225,7 +225,7 @@
                     <state>AT_START_F403A_V1</state>
                     <state>PRINTF_STDLIB</state>
                     <state>DEBUG</state>
-                    <state>MAI_12</state>
+                    <state>MDIO_88</state>
                 </option>
                 <option>
                     <name>CCPreprocFile</name>
@@ -383,6 +383,7 @@
                     <state>$PROJ_DIR$\..\..\fw\modules\dac</state>
                     <state>$PROJ_DIR$\..\..\fw\modules\shift_reg</state>
                     <state>$PROJ_DIR$\..\..\fw\modules\log</state>
+                    <state>$PROJ_DIR$\..\..\fw\modules\terminal</state>
                     <state>$PROJ_DIR$\..\..\fw\user</state>
                     <state>$PROJ_DIR$\..\..\libs\thirdparty\freertos\include</state>
                     <state>$PROJ_DIR$\..\..\libs\thirdparty\freertos\portable\IAR\ARM_CM4F</state>
@@ -399,6 +400,7 @@
                     <state>$PROJ_DIR$\..\..\libs\thirdparty\LwIP\system</state>
                     <state>$PROJ_DIR$\..\..\libs\thirdparty\LwIP\system\arch</state>
                     <state>$PROJ_DIR$\..\..\libs\thirdparty\ringfs</state>
+                    <state>$PROJ_DIR$\..\..\libs\thirdparty\microrl</state>
                 </option>
                 <option>
                     <name>CCStdIncCheck</name>
@@ -449,7 +451,7 @@
                 </option>
                 <option>
                     <name>IccLang</name>
-                    <state>0</state>
+                    <state>2</state>
                 </option>
                 <option>
                     <name>IccCDialect</name>
@@ -465,7 +467,7 @@
                 </option>
                 <option>
                     <name>IccCppInlineSemantics</name>
-                    <state>0</state>
+                    <state>1</state>
                 </option>
                 <option>
                     <name>IccCmsis</name>
@@ -498,11 +500,11 @@
                 </option>
                 <option>
                     <name>CCEncOutput</name>
-                    <state>0</state>
+                    <state>2</state>
                 </option>
                 <option>
                     <name>CCEncOutputBom</name>
-                    <state>1</state>
+                    <state>0</state>
                 </option>
                 <option>
                     <name>CCEncInput</name>
@@ -2250,6 +2252,18 @@
                     <name>$PROJ_DIR$\..\..\fw\modules\spi_flash\spi_flash.c</name>
                 </file>
             </group>
+            <group>
+                <name>terminal</name>
+                <file>
+                    <name>$PROJ_DIR$\..\..\fw\modules\terminal\terminal.cpp</name>
+                </file>
+                <file>
+                    <name>$PROJ_DIR$\..\..\fw\modules\terminal\terminal_sbs.cpp</name>
+                </file>
+                <file>
+                    <name>$PROJ_DIR$\..\..\fw\modules\terminal\terminal_usartbridge.cpp</name>
+                </file>
+            </group>
             <group>
                 <name>usb</name>
                 <file>
@@ -2278,11 +2292,14 @@
                 <name>$PROJ_DIR$\..\..\fw\user\lwipopts.h</name>
             </file>
             <file>
-                <name>$PROJ_DIR$\..\..\fw\user\main.c</name>
+                <name>$PROJ_DIR$\..\..\fw\user\main.cpp</name>
             </file>
             <file>
                 <name>$PROJ_DIR$\..\..\fw\user\main.h</name>
             </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\fw\user\MicroRLConfig.h</name>
+            </file>
             <file>
                 <name>$PROJ_DIR$\..\..\fw\user\usb_conf.h</name>
             </file>
@@ -2407,6 +2424,12 @@
                 </file>
             </group>
         </group>
+        <group>
+            <name>microrl</name>
+            <file>
+                <name>$PROJ_DIR$\..\..\libs\thirdparty\microrl\microrl.c</name>
+            </file>
+        </group>
         <group>
             <name>thirdparty</name>
             <group>

+ 22 - 1
project/ewarm/module_universal_io.ewt

@@ -2463,6 +2463,18 @@
                     <name>$PROJ_DIR$\..\..\fw\modules\spi_flash\spi_flash.c</name>
                 </file>
             </group>
+            <group>
+                <name>terminal</name>
+                <file>
+                    <name>$PROJ_DIR$\..\..\fw\modules\terminal\terminal.cpp</name>
+                </file>
+                <file>
+                    <name>$PROJ_DIR$\..\..\fw\modules\terminal\terminal_sbs.cpp</name>
+                </file>
+                <file>
+                    <name>$PROJ_DIR$\..\..\fw\modules\terminal\terminal_usartbridge.cpp</name>
+                </file>
+            </group>
             <group>
                 <name>usb</name>
                 <file>
@@ -2491,11 +2503,14 @@
                 <name>$PROJ_DIR$\..\..\fw\user\lwipopts.h</name>
             </file>
             <file>
-                <name>$PROJ_DIR$\..\..\fw\user\main.c</name>
+                <name>$PROJ_DIR$\..\..\fw\user\main.cpp</name>
             </file>
             <file>
                 <name>$PROJ_DIR$\..\..\fw\user\main.h</name>
             </file>
+            <file>
+                <name>$PROJ_DIR$\..\..\fw\user\MicroRLConfig.h</name>
+            </file>
             <file>
                 <name>$PROJ_DIR$\..\..\fw\user\usb_conf.h</name>
             </file>
@@ -2620,6 +2635,12 @@
                 </file>
             </group>
         </group>
+        <group>
+            <name>microrl</name>
+            <file>
+                <name>$PROJ_DIR$\..\..\libs\thirdparty\microrl\microrl.c</name>
+            </file>
+        </group>
         <group>
             <name>thirdparty</name>
             <group>

+ 426 - 423
shared/utils/at32f403a_407_board.c

@@ -1,423 +1,426 @@
-/**
-  **************************************************************************
-  * @file     at32f403a_407_board.c
-  * @brief    set of firmware functions to manage leds and push-button.
-  *           initialize delay function.
-  **************************************************************************
-  *                       Copyright notice & Disclaimer
-  *
-  * The software Board Support Package (BSP) that is made available to
-  * download from Artery official website is the copyrighted work of Artery.
-  * Artery authorizes customers to use, copy, and distribute the BSP
-  * software and its related documentation for the purpose of design and
-  * development in conjunction with Artery microcontrollers. Use of the
-  * software is governed by this copyright notice and the following disclaimer.
-  *
-  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
-  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
-  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
-  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
-  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
-  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
-  *
-  **************************************************************************
-  */
-
-#include "at32f403a_407_board.h"
-
-/** @addtogroup AT32F403A_407_board
-  * @{
-  */
-
-/** @defgroup BOARD
-  * @brief onboard periph driver
-  * @{
-  */
-
-/* delay macros */
-#define STEP_DELAY_MS                    50
-
-/* at-start led resouce array */
-gpio_type *led_gpio_port[LED_NUM]        = {LED2_GPIO, LED3_GPIO, LED4_GPIO};
-uint16_t led_gpio_pin[LED_NUM]           = {LED2_PIN, LED3_PIN, LED4_PIN};
-crm_periph_clock_type led_gpio_crm_clk[LED_NUM] = {LED2_GPIO_CRM_CLK, LED3_GPIO_CRM_CLK, LED4_GPIO_CRM_CLK};
-
-/* delay variable */
-static __IO uint32_t fac_us;
-static __IO uint32_t fac_ms;
-
-/* support printf function, usemicrolib is unnecessary */
-#if (__ARMCC_VERSION > 6000000)
-  __asm (".global __use_no_semihosting\n\t");
-  void _sys_exit(int x)
-  {
-    x = x;
-  }
-  /* __use_no_semihosting was requested, but _ttywrch was */
-  void _ttywrch(int ch)
-  {
-    ch = ch;
-  }
-  FILE __stdout;
-#else
- #ifdef __CC_ARM
-  #pragma import(__use_no_semihosting)
-  struct __FILE
-  {
-    int handle;
-  };
-  FILE __stdout;
-  void _sys_exit(int x)
-  {
-    x = x;
-  }
-  /* __use_no_semihosting was requested, but _ttywrch was */
-  void _ttywrch(int ch)
-  {
-    ch = ch;
-  }
- #endif
-#endif
-
-#if defined (__GNUC__) && !defined (__clang__)
-  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
-#else
-  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
-#endif
-
-/**
-  * @brief  retargets the c library printf function to the usart.
-  * @param  none
-  * @retval none
-  */
-PUTCHAR_PROTOTYPE
-{
-  while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET);
-  usart_data_transmit(PRINT_UART, (uint16_t)ch);
-  while(usart_flag_get(PRINT_UART, USART_TDC_FLAG) == RESET);
-  return ch;
-}
-
-#if (defined (__GNUC__) && !defined (__clang__)) || (defined (__ICCARM__))
-#if defined (__GNUC__) && !defined (__clang__)
-int _write(int fd, char *pbuffer, int size)
-#elif defined ( __ICCARM__ )
-#pragma module_name = "?__write"
-int __write(int fd, char *pbuffer, int size)
-#endif
-{
-  for(int i = 0; i < size; i ++)
-  {
-    while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET);
-    usart_data_transmit(PRINT_UART, (uint16_t)(*pbuffer++));
-    while(usart_flag_get(PRINT_UART, USART_TDC_FLAG) == RESET);
-  }
-
-  return size;
-}
-#endif
-
-/**
-  * @brief  initialize uart
-  * @param  baudrate: uart baudrate
-  * @retval none
-  */
-void uart_print_init(uint32_t baudrate)
-{
-  gpio_init_type gpio_init_struct;
-
-#if defined (__GNUC__) && !defined (__clang__)
-  setvbuf(stdout, NULL, _IONBF, 0);
-#endif
-
-  /* enable the uart and gpio clock */
-  crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE);
-  crm_periph_clock_enable(PRINT_UART_TX_GPIO_CRM_CLK, TRUE);
-
-/*  
-  crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
-  gpio_pin_remap_config(USART3_GMUX_0011, TRUE);
-*/  
-  
-  
-  gpio_default_para_init(&gpio_init_struct);
-
-  /* configure the uart tx pin */
-  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
-  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
-  gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN;
-  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
-  gpio_init(PRINT_UART_TX_GPIO, &gpio_init_struct);
-
-  /* configure uart param */
-  usart_init(PRINT_UART, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
-  usart_transmitter_enable(PRINT_UART, TRUE);
-  usart_receiver_enable(PRINT_UART, TRUE);
-  usart_enable(PRINT_UART, TRUE);
-  
-  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
-  NVIC_ClearPendingIRQ(USART1_IRQn);
-  nvic_irq_enable(USART1_IRQn, 0, 5);
-    
-  usart_interrupt_enable(USART1, USART_RDBF_INT, TRUE);
-}
-
-#if 0
-void USART1_IRQHandler(void)
-{   
-    static char data = 0;
-      
-    if (USART1->ctrl1_bit.rdbfien == SET)
-    {
-        if (usart_flag_get(USART1, USART_RDBF_FLAG) == SET) 
-        {
-            data = usart_data_receive(USART1);
-        }
-    }  
-}
-#endif
-
-/**
-  * @brief  board initialize interface init led and button
-  * @param  none
-  * @retval none
-  */
-void at32_board_init()
-{
-  /* initialize delay function */
-  delay_init();
-
-  /* configure led in at_start_board */
-  at32_led_init(LED2);
-  at32_led_init(LED3);
-  at32_led_init(LED4);
-  at32_led_off(LED2);
-  at32_led_off(LED3);
-  at32_led_off(LED4);
-
-  /* configure button in at_start board */
-  at32_button_init();
-}
-
-/**
-  * @brief  configure button gpio
-  * @param  button: specifies the button to be configured.
-  * @retval none
-  */
-void at32_button_init(void)
-{
-  gpio_init_type gpio_init_struct;
-
-  /* enable the button clock */
-  crm_periph_clock_enable(USER_BUTTON_CRM_CLK, TRUE);
-
-  /* set default parameter */
-  gpio_default_para_init(&gpio_init_struct);
-
-  /* configure button pin as input with pull-up/pull-down */
-  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
-  gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
-  gpio_init_struct.gpio_pins = USER_BUTTON_PIN;
-  gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
-  gpio_init(USER_BUTTON_PORT, &gpio_init_struct);
-}
-
-/**
-  * @brief  returns the selected button state
-  * @param  none
-  * @retval the button gpio pin value
-  */
-uint8_t at32_button_state(void)
-{
-  return gpio_input_data_bit_read(USER_BUTTON_PORT, USER_BUTTON_PIN);
-}
-
-/**
-  * @brief  returns which button have press down
-  * @param  none
-  * @retval the button have press down
-  */
-button_type at32_button_press()
-{
-  static uint8_t pressed = 1;
-  /* get button state in at_start board */
-  if((pressed == 1) && (at32_button_state() != RESET))
-  {
-    /* debounce */
-    pressed = 0;
-    delay_ms(10);
-    if(at32_button_state() != RESET)
-      return USER_BUTTON;
-  }
-  else if(at32_button_state() == RESET)
-  {
-    pressed = 1;
-  }
-  return NO_BUTTON;
-}
-
-/**
-  * @brief  configure led gpio
-  * @param  led: specifies the led to be configured.
-  * @retval none
-  */
-void at32_led_init(led_type led)
-{
-  gpio_init_type gpio_init_struct;
-
-  /* enable the led clock */
-  crm_periph_clock_enable(led_gpio_crm_clk[led], TRUE);
-
-  /* set default parameter */
-  gpio_default_para_init(&gpio_init_struct);
-
-  /* configure the led gpio */
-  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
-  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
-  gpio_init_struct.gpio_pins = led_gpio_pin[led];
-  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
-  gpio_init(led_gpio_port[led], &gpio_init_struct);
-}
-
-/**
-  * @brief  turns selected led on.
-  * @param  led: specifies the led to be set on.
-  *   this parameter can be one of following parameters:
-  *     @arg LED2
-  *     @arg LED3
-  *     @arg LED4
-  * @retval none
-  */
-void at32_led_on(led_type led)
-{
-  if(led > (LED_NUM - 1))
-    return;
-  if(led_gpio_pin[led])
-    led_gpio_port[led]->clr = led_gpio_pin[led];
-}
-
-/**
-  * @brief  turns selected led off.
-  * @param  led: specifies the led to be set off.
-  *   this parameter can be one of following parameters:
-  *     @arg LED2
-  *     @arg LED3
-  *     @arg LED4
-  * @retval none
-  */
-void at32_led_off(led_type led)
-{
-  if(led > (LED_NUM - 1))
-    return;
-  if(led_gpio_pin[led])
-    led_gpio_port[led]->scr = led_gpio_pin[led];
-}
-
-/**
-  * @brief  turns selected led toggle.
-  * @param  led: specifies the led to be set off.
-  *   this parameter can be one of following parameters:
-  *     @arg LED2
-  *     @arg LED3
-  *     @arg LED4
-  * @retval none
-  */
-void at32_led_toggle(led_type led)
-{
-  if(led > (LED_NUM - 1))
-    return;
-  if(led_gpio_pin[led])
-    led_gpio_port[led]->odt ^= led_gpio_pin[led];
-}
-
-/**
-  * @brief  initialize delay function
-  * @param  none
-  * @retval none
-  */
-void delay_init()
-{
-  /* configure systick */
-  systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV);
-  fac_us = system_core_clock / (1000000U);
-  fac_ms = fac_us * (1000U);
-}
-
-/**
-  * @brief  inserts a delay time.
-  * @param  nus: specifies the delay time length, in microsecond.
-  * @retval none
-  */
-void delay_us(uint32_t nus)
-{
-  uint32_t temp = 0;
-  SysTick->LOAD = (uint32_t)(nus * fac_us);
-  SysTick->VAL = 0x00;
-  SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk ;
-  do
-  {
-    temp = SysTick->CTRL;
-  }while((temp & 0x01) && !(temp & (1 << 16)));
-
-  SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
-  SysTick->VAL = 0x00;
-}
-
-/**
-  * @brief  inserts a delay time.
-  * @param  nms: specifies the delay time length, in milliseconds.
-  * @retval none
-  */
-void delay_ms(uint16_t nms)
-{
-  uint32_t temp = 0;
-  while(nms)
-  {
-    if(nms > STEP_DELAY_MS)
-    {
-      SysTick->LOAD = (uint32_t)(STEP_DELAY_MS * fac_ms);
-      nms -= STEP_DELAY_MS;
-    }
-    else
-    {
-      SysTick->LOAD = (uint32_t)(nms * fac_ms);
-      nms = 0;
-    }
-    SysTick->VAL = 0x00;
-    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
-    do
-    {
-      temp = SysTick->CTRL;
-    }while((temp & 0x01) && !(temp & (1 << 16)));
-
-    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
-    SysTick->VAL = 0x00;
-  }
-}
-
-/**
-  * @brief  inserts a delay time.
-  * @param  sec: specifies the delay time, in seconds.
-  * @retval none
-  */
-void delay_sec(uint16_t sec)
-{
-  uint16_t index;
-  for(index = 0; index < sec; index++)
-  {
-    delay_ms(500);
-    delay_ms(500);
-  }
-}
-
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
+/**
+  **************************************************************************
+  * @file     at32f403a_407_board.c
+  * @brief    set of firmware functions to manage leds and push-button.
+  *           initialize delay function.
+  **************************************************************************
+  *                       Copyright notice & Disclaimer
+  *
+  * The software Board Support Package (BSP) that is made available to
+  * download from Artery official website is the copyrighted work of Artery.
+  * Artery authorizes customers to use, copy, and distribute the BSP
+  * software and its related documentation for the purpose of design and
+  * development in conjunction with Artery microcontrollers. Use of the
+  * software is governed by this copyright notice and the following disclaimer.
+  *
+  * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
+  * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
+  * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
+  * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
+  * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
+  * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
+  *
+  **************************************************************************
+  */
+
+#include "at32f403a_407_board.h"
+
+/** @addtogroup AT32F403A_407_board
+  * @{
+  */
+
+/** @defgroup BOARD
+  * @brief onboard periph driver
+  * @{
+  */
+
+/* delay macros */
+#define STEP_DELAY_MS                    50
+
+/* at-start led resouce array */
+gpio_type *led_gpio_port[LED_NUM]        = {LED2_GPIO, LED3_GPIO, LED4_GPIO};
+uint16_t led_gpio_pin[LED_NUM]           = {LED2_PIN, LED3_PIN, LED4_PIN};
+crm_periph_clock_type led_gpio_crm_clk[LED_NUM] = {LED2_GPIO_CRM_CLK, LED3_GPIO_CRM_CLK, LED4_GPIO_CRM_CLK};
+
+/* delay variable */
+static __IO uint32_t fac_us;
+static __IO uint32_t fac_ms;
+
+/* support printf function, usemicrolib is unnecessary */
+#if (__ARMCC_VERSION > 6000000)
+  __asm (".global __use_no_semihosting\n\t");
+  void _sys_exit(int x)
+  {
+    x = x;
+  }
+  /* __use_no_semihosting was requested, but _ttywrch was */
+  void _ttywrch(int ch)
+  {
+    ch = ch;
+  }
+  FILE __stdout;
+#else
+ #ifdef __CC_ARM
+  #pragma import(__use_no_semihosting)
+  struct __FILE
+  {
+    int handle;
+  };
+  FILE __stdout;
+  void _sys_exit(int x)
+  {
+    x = x;
+  }
+  /* __use_no_semihosting was requested, but _ttywrch was */
+  void _ttywrch(int ch)
+  {
+    ch = ch;
+  }
+ #endif
+#endif
+
+#if 0
+#if defined (__GNUC__) && !defined (__clang__)
+  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
+#else
+  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
+#endif
+
+/**
+  * @brief  retargets the c library printf function to the usart.
+  * @param  none
+  * @retval none
+  */
+PUTCHAR_PROTOTYPE
+{
+  while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET);
+  usart_data_transmit(PRINT_UART, (uint16_t)ch);
+  while(usart_flag_get(PRINT_UART, USART_TDC_FLAG) == RESET);
+  return ch;
+}
+#endif
+
+
+#if (defined (__GNUC__) && !defined (__clang__)) || (defined (__ICCARM__))
+#if defined (__GNUC__) && !defined (__clang__)
+int _write(int fd, char *pbuffer, int size)
+#elif defined ( __ICCARM__ )
+#pragma module_name = "?__write"
+int __write(int fd, char *pbuffer, int size)
+#endif
+{
+  for(int i = 0; i < size; i ++)
+  {
+    while(usart_flag_get(PRINT_UART, USART_TDBE_FLAG) == RESET);
+    usart_data_transmit(PRINT_UART, (uint16_t)(*pbuffer++));
+    while(usart_flag_get(PRINT_UART, USART_TDC_FLAG) == RESET);
+  }
+
+  return size;
+}
+#endif
+
+/**
+  * @brief  initialize uart
+  * @param  baudrate: uart baudrate
+  * @retval none
+  */
+void uart_print_init(uint32_t baudrate)
+{
+  gpio_init_type gpio_init_struct;
+
+#if defined (__GNUC__) && !defined (__clang__)
+  setvbuf(stdout, NULL, _IONBF, 0);
+#endif
+
+  /* enable the uart and gpio clock */
+  crm_periph_clock_enable(PRINT_UART_CRM_CLK, TRUE);
+  crm_periph_clock_enable(PRINT_UART_TX_GPIO_CRM_CLK, TRUE);
+
+/*  
+  crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
+  gpio_pin_remap_config(USART3_GMUX_0011, TRUE);
+*/  
+  
+  
+  gpio_default_para_init(&gpio_init_struct);
+
+  /* configure the uart tx pin */
+  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
+  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
+  gpio_init_struct.gpio_pins = PRINT_UART_TX_PIN;
+  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
+  gpio_init(PRINT_UART_TX_GPIO, &gpio_init_struct);
+
+  /* configure uart param */
+  usart_init(PRINT_UART, baudrate, USART_DATA_8BITS, USART_STOP_1_BIT);
+  usart_transmitter_enable(PRINT_UART, TRUE);
+  usart_receiver_enable(PRINT_UART, TRUE);
+  usart_enable(PRINT_UART, TRUE);
+  
+  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
+  NVIC_ClearPendingIRQ(USART1_IRQn);
+  nvic_irq_enable(USART1_IRQn, 0, 5);
+    
+  usart_interrupt_enable(USART1, USART_RDBF_INT, TRUE);
+}
+
+#if 0
+void USART1_IRQHandler(void)
+{   
+    static char data = 0;
+      
+    if (USART1->ctrl1_bit.rdbfien == SET)
+    {
+        if (usart_flag_get(USART1, USART_RDBF_FLAG) == SET) 
+        {
+            data = usart_data_receive(USART1);
+        }
+    }  
+}
+#endif
+
+/**
+  * @brief  board initialize interface init led and button
+  * @param  none
+  * @retval none
+  */
+void at32_board_init()
+{
+  /* initialize delay function */
+  delay_init();
+
+  /* configure led in at_start_board */
+  at32_led_init(LED2);
+  at32_led_init(LED3);
+  at32_led_init(LED4);
+  at32_led_off(LED2);
+  at32_led_off(LED3);
+  at32_led_off(LED4);
+
+  /* configure button in at_start board */
+  at32_button_init();
+}
+
+/**
+  * @brief  configure button gpio
+  * @param  button: specifies the button to be configured.
+  * @retval none
+  */
+void at32_button_init(void)
+{
+  gpio_init_type gpio_init_struct;
+
+  /* enable the button clock */
+  crm_periph_clock_enable(USER_BUTTON_CRM_CLK, TRUE);
+
+  /* set default parameter */
+  gpio_default_para_init(&gpio_init_struct);
+
+  /* configure button pin as input with pull-up/pull-down */
+  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
+  gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
+  gpio_init_struct.gpio_pins = USER_BUTTON_PIN;
+  gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
+  gpio_init(USER_BUTTON_PORT, &gpio_init_struct);
+}
+
+/**
+  * @brief  returns the selected button state
+  * @param  none
+  * @retval the button gpio pin value
+  */
+uint8_t at32_button_state(void)
+{
+  return gpio_input_data_bit_read(USER_BUTTON_PORT, USER_BUTTON_PIN);
+}
+
+/**
+  * @brief  returns which button have press down
+  * @param  none
+  * @retval the button have press down
+  */
+button_type at32_button_press()
+{
+  static uint8_t pressed = 1;
+  /* get button state in at_start board */
+  if((pressed == 1) && (at32_button_state() != RESET))
+  {
+    /* debounce */
+    pressed = 0;
+    delay_ms(10);
+    if(at32_button_state() != RESET)
+      return USER_BUTTON;
+  }
+  else if(at32_button_state() == RESET)
+  {
+    pressed = 1;
+  }
+  return NO_BUTTON;
+}
+
+/**
+  * @brief  configure led gpio
+  * @param  led: specifies the led to be configured.
+  * @retval none
+  */
+void at32_led_init(led_type led)
+{
+  gpio_init_type gpio_init_struct;
+
+  /* enable the led clock */
+  crm_periph_clock_enable(led_gpio_crm_clk[led], TRUE);
+
+  /* set default parameter */
+  gpio_default_para_init(&gpio_init_struct);
+
+  /* configure the led gpio */
+  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+  gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
+  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
+  gpio_init_struct.gpio_pins = led_gpio_pin[led];
+  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
+  gpio_init(led_gpio_port[led], &gpio_init_struct);
+}
+
+/**
+  * @brief  turns selected led on.
+  * @param  led: specifies the led to be set on.
+  *   this parameter can be one of following parameters:
+  *     @arg LED2
+  *     @arg LED3
+  *     @arg LED4
+  * @retval none
+  */
+void at32_led_on(led_type led)
+{
+  if(led > (LED_NUM - 1))
+    return;
+  if(led_gpio_pin[led])
+    led_gpio_port[led]->clr = led_gpio_pin[led];
+}
+
+/**
+  * @brief  turns selected led off.
+  * @param  led: specifies the led to be set off.
+  *   this parameter can be one of following parameters:
+  *     @arg LED2
+  *     @arg LED3
+  *     @arg LED4
+  * @retval none
+  */
+void at32_led_off(led_type led)
+{
+  if(led > (LED_NUM - 1))
+    return;
+  if(led_gpio_pin[led])
+    led_gpio_port[led]->scr = led_gpio_pin[led];
+}
+
+/**
+  * @brief  turns selected led toggle.
+  * @param  led: specifies the led to be set off.
+  *   this parameter can be one of following parameters:
+  *     @arg LED2
+  *     @arg LED3
+  *     @arg LED4
+  * @retval none
+  */
+void at32_led_toggle(led_type led)
+{
+  if(led > (LED_NUM - 1))
+    return;
+  if(led_gpio_pin[led])
+    led_gpio_port[led]->odt ^= led_gpio_pin[led];
+}
+
+/**
+  * @brief  initialize delay function
+  * @param  none
+  * @retval none
+  */
+void delay_init()
+{
+  /* configure systick */
+  systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV);
+  fac_us = system_core_clock / (1000000U);
+  fac_ms = fac_us * (1000U);
+}
+
+/**
+  * @brief  inserts a delay time.
+  * @param  nus: specifies the delay time length, in microsecond.
+  * @retval none
+  */
+void delay_us(uint32_t nus)
+{
+  uint32_t temp = 0;
+  SysTick->LOAD = (uint32_t)(nus * fac_us);
+  SysTick->VAL = 0x00;
+  SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk ;
+  do
+  {
+    temp = SysTick->CTRL;
+  }while((temp & 0x01) && !(temp & (1 << 16)));
+
+  SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
+  SysTick->VAL = 0x00;
+}
+
+/**
+  * @brief  inserts a delay time.
+  * @param  nms: specifies the delay time length, in milliseconds.
+  * @retval none
+  */
+void delay_ms(uint16_t nms)
+{
+  uint32_t temp = 0;
+  while(nms)
+  {
+    if(nms > STEP_DELAY_MS)
+    {
+      SysTick->LOAD = (uint32_t)(STEP_DELAY_MS * fac_ms);
+      nms -= STEP_DELAY_MS;
+    }
+    else
+    {
+      SysTick->LOAD = (uint32_t)(nms * fac_ms);
+      nms = 0;
+    }
+    SysTick->VAL = 0x00;
+    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
+    do
+    {
+      temp = SysTick->CTRL;
+    }while((temp & 0x01) && !(temp & (1 << 16)));
+
+    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
+    SysTick->VAL = 0x00;
+  }
+}
+
+/**
+  * @brief  inserts a delay time.
+  * @param  sec: specifies the delay time, in seconds.
+  * @retval none
+  */
+void delay_sec(uint16_t sec)
+{
+  uint16_t index;
+  for(index = 0; index < sec; index++)
+  {
+    delay_ms(500);
+    delay_ms(500);
+  }
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio