application: add single channel monitoring
This commit is contained in:
parent
611f5f6683
commit
3370e35dc5
120
application.c
120
application.c
|
@ -77,6 +77,15 @@ static uint8_t channel_stop = CHANNEL_NUMBERS - 1; /**< last signal of range to
|
|||
/** timer ID for timer to measure activity timing */
|
||||
#define MONITOR_TIMER 2
|
||||
|
||||
/** UART peripheral for signal reading (TX and RX are connected together)
|
||||
* @{
|
||||
*/
|
||||
#define UART_ID 2 /**< USART peripheral */
|
||||
#define UART_TX PA2 /**< pin used for USART TX */
|
||||
#define UART_RX PA3 /**< pin used for USART RX */
|
||||
#define UART_AF GPIO_AF7 /**< alternate function for UART pins */
|
||||
/** @} */
|
||||
|
||||
size_t putc(char c)
|
||||
{
|
||||
size_t length = 0; // number of characters printed
|
||||
|
@ -516,6 +525,109 @@ static void command_monitor(void* argument)
|
|||
rcc_periph_clock_disable(RCC_TIM(MONITOR_TIMER)); // disable clock for timer peripheral
|
||||
}
|
||||
|
||||
/** monitor single channel for activity
|
||||
* @param[in] argument channel number
|
||||
*/
|
||||
static void command_monitor_single(void* argument)
|
||||
{
|
||||
(void)argument; // we won't use the argument
|
||||
|
||||
// get input channel
|
||||
if (NULL == argument) {
|
||||
puts("provide channel to monitor\n");
|
||||
return;
|
||||
}
|
||||
const uint32_t channel = *(uint32_t*)argument; // get channel argument
|
||||
if (!(channel < CHANNEL_NUMBERS)) { // verify argument
|
||||
printf("channel %u out of range (0-%u)\n", channel, CHANNEL_NUMBERS - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// verify target voltage is OK
|
||||
const float* voltages = measure_voltages(); // get target voltage
|
||||
if (voltages[1] < 1.5) {
|
||||
puts("target voltage too low: ");
|
||||
print_fpu(voltages[1], 2);
|
||||
puts(" < 1.5V\n");
|
||||
return;
|
||||
} else {
|
||||
puts("target voltage: ");
|
||||
print_fpu(voltages[1], 2);
|
||||
puts("V\n");
|
||||
}
|
||||
|
||||
// select channel
|
||||
rcc_periph_clock_enable(GPIO_RCC(UART_RX)); // enable clock for USART RX pin port peripheral
|
||||
gpio_mode_setup(GPIO_PORT(UART_RX), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(UART_RX)); // use as input (it is pulled up by level shifter)
|
||||
mux_select(channel); // select channel
|
||||
gpio_clear(GPIO_PORT(SHIFT_EN_PIN), GPIO_PIN(SHIFT_EN_PIN)); // connect target voltage to level shifters pull-up
|
||||
|
||||
// show help
|
||||
printf("CH%02u is pulled to target voltage by 10 kOhm\n", channel);
|
||||
puts("high = 1.5-5.5V, 'X' shows multiple changes\n");
|
||||
puts("press any key to stop monitoring\n");
|
||||
puts("time (s) CH\n");
|
||||
|
||||
// setup timer to measure milliseconds
|
||||
rcc_periph_clock_enable(RCC_TIM(MONITOR_TIMER)); // enable clock for timer peripheral
|
||||
rcc_periph_reset_pulse(RST_TIM(MONITOR_TIMER)); // reset timer state
|
||||
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), 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 0.1 seconds using the overflow
|
||||
timer_enable_counter(TIM(MONITOR_TIMER)); // enable timer
|
||||
|
||||
// start monitoring
|
||||
bool channel_level = gpio_get(GPIO_PORT(UART_RX), GPIO_PIN(UART_RX)); // get initial level
|
||||
uint8_t channel_changes = 1; // how many times the channel changed
|
||||
while (!user_input_available) { // run until user breaks it
|
||||
// time to do periodic checks
|
||||
if (wakeup_flag || second_flag) {
|
||||
iwdg_reset(); // kick the dog
|
||||
wakeup_flag = false; // clear flag
|
||||
second_flag = false; // clear flag
|
||||
}
|
||||
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 0.1 seconds
|
||||
if (channel_changes) { // 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
|
||||
|
||||
if (channel_changes > 1) { // channel changed more than once
|
||||
putc('X'); // show multiple changes
|
||||
} else {
|
||||
putc(' '); // show no or single change
|
||||
}
|
||||
if (channel_level) { // high level
|
||||
putc('1');
|
||||
} else {
|
||||
putc('0');
|
||||
}
|
||||
puts("\n");
|
||||
channel_changes = 0; // clear changes
|
||||
}
|
||||
}
|
||||
// check is there is a change on a channel
|
||||
const bool level_new = gpio_get(GPIO_PORT(UART_RX), GPIO_PIN(UART_RX)); // get new level
|
||||
if (level_new != channel_level) { // channel changed
|
||||
channel_changes = addu8_safe(channel_changes, 1);
|
||||
channel_level = level_new; // save new level
|
||||
}
|
||||
}
|
||||
user_input_get(); // clean input
|
||||
|
||||
// clean up
|
||||
gpio_set(GPIO_PORT(SHIFT_EN_PIN), GPIO_PIN(SHIFT_EN_PIN)); // remove power from level shifters pull-up
|
||||
mux_select(-1); // disable multiplexer
|
||||
timer_disable_counter(TIM(MONITOR_TIMER)); // disable timer
|
||||
rcc_periph_reset_pulse(RST_TIM(MONITOR_TIMER)); // reset timer state
|
||||
rcc_periph_clock_disable(RCC_TIM(MONITOR_TIMER)); // disable clock for timer peripheral
|
||||
}
|
||||
|
||||
/** set first channel of range to scan
|
||||
* @param[in] argument optional pointer to first channel number
|
||||
*/
|
||||
|
@ -702,6 +814,14 @@ static const struct menu_command_t menu_commands[] = {
|
|||
.argument_description = "[0|3]",
|
||||
.command_handler = &command_monitor,
|
||||
},
|
||||
{
|
||||
.shortcut = 'M',
|
||||
.name = "monitor_single",
|
||||
.command_description = "monitor single channel activity",
|
||||
.argument = MENU_ARGUMENT_UNSIGNED,
|
||||
.argument_description = "channel",
|
||||
.command_handler = &command_monitor_single,
|
||||
},
|
||||
{
|
||||
.shortcut = 'c',
|
||||
.name = "start",
|
||||
|
|
Loading…
Reference in New Issue