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 */
|
/** timer ID for timer to measure activity timing */
|
||||||
#define MONITOR_TIMER 2
|
#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 putc(char c)
|
||||||
{
|
{
|
||||||
size_t length = 0; // number of characters printed
|
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
|
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
|
/** set first channel of range to scan
|
||||||
* @param[in] argument optional pointer to first channel number
|
* @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]",
|
.argument_description = "[0|3]",
|
||||||
.command_handler = &command_monitor,
|
.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',
|
.shortcut = 'c',
|
||||||
.name = "start",
|
.name = "start",
|
||||||
|
|
Loading…
Reference in New Issue