From f603b1398eae720b54d185215b977fff774cb6d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Mon, 3 May 2021 12:39:46 +0200 Subject: [PATCH] application: show multiple changes when monitoring (and rate limit output) --- application.c | 68 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/application.c b/application.c index 5c4b8d1..565417b 100644 --- a/application.c +++ b/application.c @@ -424,7 +424,8 @@ static void command_monitor(void* argument) } } - // get initial state + // show help + puts("'x' shows multiple changes\n"); puts("press any key to stop monitoring\n"); puts("time (s) "); for (uint8_t i = channel_start; i <= channel_stop; i++) { @@ -438,15 +439,22 @@ static void command_monitor(void* argument) timer_disable_counter(TIM(MONITOR_TIMER)); // disable timer to configure it timer_set_mode(TIM(MONITOR_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up timer_set_prescaler(TIM(MONITOR_TIMER), (rcc_ahb_frequency / 2000) - 1); // generate half millisecond ticks (prescaler is not large enough for milliseconds) - timer_set_period(TIM(MONITOR_TIMER), 2000 - 1); // set period to seconds + timer_set_period(TIM(MONITOR_TIMER), 200 - 1); // set period to 0.1 seconds timer_clear_flag(TIM(MONITOR_TIMER), TIM_SR_UIF); // clear update (overflow) flag timer_update_on_overflow(TIM(MONITOR_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout) - uint32_t seconds = 0; // count the seconds using the overflow + uint32_t seconds = 0; // count the 0.1 seconds using the overflow timer_enable_counter(TIM(MONITOR_TIMER)); // enable timer // start monitoring - uint16_t gpioa_data = UINT16_MAX; - uint16_t gpiob_data = UINT16_MAX; + uint16_t gpioa_old = UINT16_MAX; // the current level on the port where some channels are + uint16_t gpiob_old = UINT16_MAX; // since not all pins of the port care used for the channel, initializing to 0xffff will force an update to the actual data + bool channel_changed = false; // if a channel changed + uint8_t channels_changed[CHANNEL_NUMBERS] = {0}; // how many times a channel changed + bool channels_level[CHANNEL_NUMBERS]; // the level of the channels + for (uint8_t i = channel_start; i <= channel_stop; i++) { // initialize level of channels + const uint16_t port = (GPIOA == channel_ports[i] ? gpioa_old : gpiob_old); // get the port on which the channel is + channels_level[i] = (port & channel_pins[i]); // get the pin level on which the channel is + } while (!user_input_available) { // run until user breaks it // time to do periodic checks if (wakeup_flag || second_flag) { @@ -454,31 +462,47 @@ static void command_monitor(void* argument) wakeup_flag = false; // clear flag second_flag = false; // clear flag } - // one second has passed - if (timer_get_flag(TIM(MONITOR_TIMER), TIM_SR_UIF)) { + if (timer_get_flag(TIM(MONITOR_TIMER), TIM_SR_UIF)) { // 0.1 second has passed timer_clear_flag(TIM(MONITOR_TIMER), TIM_SR_UIF); // clear flag - seconds++; // count the second + seconds++; // count the 0.1 seconds + if (channel_changed) { // there was some activity + // we print the change every 0.1 s instead of synchronously to rate limit the print (and overfill the buffer) + printf("%04u.%01u ", seconds / 10, seconds % 10); // print current time stamp (change time stamp with 0.1s precision + + for (uint8_t i = channel_start; i <= channel_stop; i++) { // print level of each change + putc(' '); // start new channel + if (channels_changed[i] > 1) { // channel changed more than once + putc('x'); // show multiple changes + } else { + putc(' '); // show no or single change + } + if (channels_level[i]) { // high level + putc('1'); + } else { + putc('0'); + } + channels_changed[i] = 0; // clear number of changes + } + puts("\n"); + channel_changed = false; // clear flag + } } // check is there is a change on a channel const uint16_t gpioa_new = gpio_get(GPIOA, gpioa_mask); const uint16_t gpiob_new = gpio_get(GPIOB, gpioa_mask); - if (gpioa_new != gpioa_data || gpiob_new != gpiob_data) { - // print data - printf("%04u.%03u", seconds, timer_get_counter(TIM(MONITOR_TIMER)) / 2); - for (uint8_t i = channel_start; i <= channel_stop; i++) { - const uint16_t port = (GPIOA == channel_ports[i] ? gpioa_new : gpiob_new); - const uint8_t high = ((port & channel_pins[i]) ? 1 : 0); - if (high) { - puts(" 1"); - } else { - puts(" 0"); + if (gpioa_new != gpioa_old || gpiob_new != gpiob_old) { // some GPIO changed (should be channel data) + for (uint8_t i = channel_start; i <= channel_stop; i++) { // check which channel changed + const uint16_t port = (GPIOA == channel_ports[i] ? gpioa_new : gpiob_new); // get the port on which the channel is + const bool pin = (port & channel_pins[i]); // get the pin level on which the channel is + if (pin != channels_level[i]) { // data on this channel changed + channel_changed = true; // remember one channel changed + channels_changed[i]++; // remember how many times this channel changed + channels_level[i] = pin; // save new level } } - puts("\n"); // save change - gpioa_data = gpioa_new; - gpiob_data = gpiob_new; - // do we need a rate limit? + gpioa_old = gpioa_new; + gpiob_old = gpiob_new; } } user_input_get(); // clean input