Created low-level driver for management of channel selector knobs with quadrature encoder

replace/5af60c1c112d35339008331adc8abe65f41738cb
Silvano Seva 2021-04-10 19:29:35 +02:00
rodzic 26eb381ca2
commit 944a597d33
6 zmienionych plików z 274 dodań i 70 usunięć

Wyświetl plik

@ -34,6 +34,7 @@ openrtx_inc = ['openrtx/include',
'platform/drivers/tones',
'platform/drivers/baseband',
'platform/drivers/backlight',
'platform/drivers/chSelector',
'openrtx/include/fonts/adafruit']
# Add to sources either the main executable or a platform test
@ -218,6 +219,7 @@ mduv3x0_src = src + mdx_src + stm32f405_src + ['platform/drivers/NVM/nvmem_MDUV3
'platform/targets/MD-UV3x0/platform.c',
'platform/drivers/keyboard/keyboard_MD3x.c',
'platform/drivers/display/HX8353_MD3x.cpp',
'platform/drivers/chSelector/chSelector_UV3x0.c',
'platform/drivers/baseband/radio_UV3x0.c',
'platform/drivers/baseband/AT1846S_UV3x0.c',
'platform/drivers/baseband/HR_C6000_UV3x0.c',
@ -232,6 +234,7 @@ mduv3x0_def = def + stm32f405_def + {'PLATFORM_MDUV3x0': '', 'timegm': 'mktime'}
md9600_src = src + mdx_src + stm32f405_src + ['platform/targets/MD-9600/platform.c',
'platform/drivers/display/ST7567_MD9600.c',
'platform/drivers/keyboard/keyboard_MD9600.c',
'platform/drivers/chSelector/chSelector_MD9600.c',
'platform/drivers/baseband/radio_MD9600.c',
'platform/drivers/NVM/nvmem_MD9600.c',
'platform/drivers/NVM/spiFlash_MD9600.c']

Wyświetl plik

@ -0,0 +1,43 @@
/***************************************************************************
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Caleb Jamison *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#ifndef CH_SELECTOR_H
#define CH_SELECTOR_H
/**
* Low-level driver for correct handling of channel selector knobs connected to
* a quadrature encoder.
* This header file only provides the API for driver initialisation and shutdown,
* while the readout of current encoder position is provided by target-specific
* sources by implementating platform_getChSelector().
*/
/**
* Initialise channel selector driver.
*/
void chSelector_init();
/**
* Terminate channel selector driver.
*/
void chSelector_terminate();
#endif /* CH_SELECTOR_H */

Wyświetl plik

@ -0,0 +1,105 @@
/***************************************************************************
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <interfaces/platform.h>
#include <interfaces/gpio.h>
#include <hwconfig.h>
#include <qdec.h>
#include "chSelector.h"
static uint8_t last_state = 0; /* State storage */
static int8_t knob_pos = 0; /* Knob position */
/* Name of interrupt handler is mangled for C++ compatibility */
void _Z20EXTI15_10_IRQHandlerv()
{
if(EXTI->PR & (EXTI_PR_PR10 | EXTI_PR_PR11))
{
/* Clear interrupt flags */
EXTI->PR = EXTI_PR_PR10 | EXTI_PR_PR11;
/* Read curent pin state */
uint8_t pin_state = (gpio_readPin(CH_SELECTOR_1) << 1)
| gpio_readPin(CH_SELECTOR_0);
/* Look up next state */
uint8_t next_state = HALF_STEP_STATE_TRANSITIONS[last_state][pin_state];
/* update state for next call */
last_state = next_state & QDECODER_STATE_BITMASK;
/* Mask out events to switch on */
uint8_t event = next_state & QDECODER_EVENT_BITMASK;
/* Update knob_pos variable */
switch(event)
{
case QDECODER_EVENT_CW:
knob_pos++;
break;
case QDECODER_EVENT_CCW:
knob_pos--;
break;
default:
break;
}
}
}
void chSelector_init()
{
gpio_setMode(CH_SELECTOR_0, INPUT_PULL_UP);
gpio_setMode(CH_SELECTOR_1, INPUT_PULL_UP);
/*
* Configure GPIO interrupts: encoder signal is on PB10 and PB11
*/
EXTI->IMR |= EXTI_IMR_MR10 | EXTI_IMR_MR11;
EXTI->RTSR |= EXTI_RTSR_TR10 | EXTI_RTSR_TR11;
EXTI->FTSR |= EXTI_FTSR_TR10 | EXTI_FTSR_TR11;
SYSCFG->EXTICR[2] |= SYSCFG_EXTICR3_EXTI10_PB
| SYSCFG_EXTICR3_EXTI11_PB;
NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
NVIC_SetPriority(EXTI15_10_IRQn, 15);
NVIC_EnableIRQ(EXTI15_10_IRQn);
}
void chSelector_terminate()
{
EXTI->IMR &= ~(EXTI_IMR_MR10 | EXTI_IMR_MR11);
NVIC_DisableIRQ(EXTI15_10_IRQn);
}
/*
* This function is defined in platform.h
*/
int8_t platform_getChSelector()
{
/*
* The knob_pos variable is set in the EXTI15_10 interrupt handler
* this is safe because interrupt nesting is not allowed.
*/
return knob_pos;
}

Wyświetl plik

@ -0,0 +1,105 @@
/***************************************************************************
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <interfaces/platform.h>
#include <interfaces/gpio.h>
#include <hwconfig.h>
#include <qdec.h>
#include "chSelector.h"
static uint8_t last_state = 0; /* State storage */
static int8_t knob_pos = 0; /* Knob position */
/* Name of interrupt handler is mangled for C++ compatibility */
void _Z20EXTI15_10_IRQHandlerv()
{
if(EXTI->PR & (EXTI_PR_PR11 | EXTI_PR_PR14))
{
/* Clear interrupt flags */
EXTI->PR = EXTI_PR_PR11 | EXTI_PR_PR14;
/* Read curent pin state */
uint8_t pin_state = (gpio_readPin(CH_SELECTOR_1) << 1)
| gpio_readPin(CH_SELECTOR_0);
/* Look up next state */
uint8_t next_state = HALF_STEP_STATE_TRANSITIONS[last_state][pin_state];
/* update state for next call */
last_state = next_state & QDECODER_STATE_BITMASK;
/* Mask out events to switch on */
uint8_t event = next_state & QDECODER_EVENT_BITMASK;
/* Update knob_pos variable */
switch(event)
{
case QDECODER_EVENT_CW:
knob_pos++;
break;
case QDECODER_EVENT_CCW:
knob_pos--;
break;
default:
break;
}
}
}
void chSelector_init()
{
gpio_setMode(CH_SELECTOR_0, INPUT_PULL_UP);
gpio_setMode(CH_SELECTOR_1, INPUT_PULL_UP);
/*
* Configure GPIO interrupts: encoder signal is on PB11 and PE14
*/
EXTI->IMR |= EXTI_IMR_MR11 | EXTI_IMR_MR14;
EXTI->RTSR |= EXTI_RTSR_TR11 | EXTI_RTSR_TR14;
EXTI->FTSR |= EXTI_FTSR_TR11 | EXTI_FTSR_TR14;
SYSCFG->EXTICR[2] |= SYSCFG_EXTICR3_EXTI11_PB;
SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI14_PE;
NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
NVIC_SetPriority(EXTI15_10_IRQn, 15);
NVIC_EnableIRQ(EXTI15_10_IRQn);
}
void chSelector_terminate()
{
EXTI->IMR &= ~(EXTI_IMR_MR1 | EXTI_IMR_MR14);
NVIC_DisableIRQ(EXTI15_10_IRQn);
}
/*
* This function is defined in platform.h
*/
int8_t platform_getChSelector()
{
/*
* The knob_pos variable is set in the EXTI15_10 interrupt handler
* this is safe because interrupt nesting is not allowed.
*/
return knob_pos;
}

Wyświetl plik

@ -28,6 +28,7 @@
#include <toneGenerator_MDx.h>
#include <interfaces/rtc.h>
#include <SPI2.h>
#include <chSelector.h>
hwInfo_t hwInfo;
@ -76,6 +77,7 @@ void platform_init()
toneGen_init(); /* Initialise tone generator */
rtc_init(); /* Initialise RTC */
backlight_init(); /* Initialise backlight driver */
chSelector_init(); /* Initialise channel selector handler */
}
void platform_terminate()
@ -87,6 +89,7 @@ void platform_terminate()
adc1_terminate();
toneGen_terminate();
rtc_terminate();
chSelector_terminate();
/* Finally, remove power supply */
gpio_clearPin(PWR_SW);
@ -112,15 +115,6 @@ float platform_getVolumeLevel()
return 0.0f;
}
int8_t platform_getChSelector()
{
static const uint8_t rsPositions[] = { 1, 4, 2, 3};
int pos = gpio_readPin(CH_SELECTOR_0)
| (gpio_readPin(CH_SELECTOR_1) << 1);
return rsPositions[pos];
}
bool platform_getPttStatus()
{
/* PTT line has a pullup resistor with PTT switch closing to ground */
@ -160,6 +154,12 @@ const hwInfo_t *platform_getHwInfo()
return &hwInfo;
}
/*
* NOTE: implementation of this API function is provided in
* platform/drivers/chSelector/chSelector_MD9600.c
*/
// int8_t platform_getChSelector()
/*
* NOTE: implementation of this API function is provided in
* platform/drivers/backlight/backlight_MDx.c

Wyświetl plik

@ -25,7 +25,7 @@
#include <calibInfo_MDx.h>
#include <interfaces/nvmem.h>
#include <interfaces/rtc.h>
#include <qdec.h>
#include <chSelector.h>
#ifdef ENABLE_BKLIGHT_DIMMING
#include <backlight.h>
@ -33,43 +33,6 @@
mduv3x0Calib_t calibration;
hwInfo_t hwInfo;
static int8_t knob_pos = 0;
/*
* Note that this interrupt handler currently assumes only the encoder will
* ever cause this interrupt to fire
*/
void _Z20EXTI15_10_IRQHandlerv()
{
/* State storage */
static uint8_t last_state = 0;
/* Read curent pin state */
uint8_t pin_state = gpio_readPin(CH_SELECTOR_1)<<1 | gpio_readPin(CH_SELECTOR_0);
/* Look up next state */
uint8_t next_state = HALF_STEP_STATE_TRANSITIONS[last_state][pin_state];
/* update state for next call */
last_state = next_state & QDECODER_STATE_BITMASK;
/* Mask out events to switch on */
uint8_t event = next_state & QDECODER_EVENT_BITMASK;
/* Update file global knob_pos variable */
switch (event)
{
case QDECODER_EVENT_CW:
knob_pos++;
break;
case QDECODER_EVENT_CCW:
knob_pos--;
break;
default:
break;
}
/* Clear pin change flags */
EXTI->PR = EXTI_PR_PR11 | EXTI_PR_PR14;
}
void platform_init()
{
@ -77,20 +40,6 @@ void platform_init()
gpio_setMode(GREEN_LED, OUTPUT);
gpio_setMode(RED_LED, OUTPUT);
gpio_setMode(CH_SELECTOR_0, INPUT_PULL_UP);
gpio_setMode(CH_SELECTOR_1, INPUT_PULL_UP);
EXTI->IMR |= EXTI_IMR_MR11 | EXTI_IMR_MR14;
EXTI->RTSR |= EXTI_RTSR_TR11 | EXTI_RTSR_TR14;
EXTI->FTSR |= EXTI_FTSR_TR11 | EXTI_FTSR_TR14;
SYSCFG->EXTICR[2] |= SYSCFG_EXTICR3_EXTI11_PB;
SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI14_PE;
NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
NVIC_SetPriority(EXTI15_10_IRQn, 15);
NVIC_EnableIRQ(EXTI15_10_IRQn);
gpio_setMode(PTT_SW, INPUT_PULL_UP);
gpio_setMode(PWR_SW, OUTPUT);
@ -108,6 +57,7 @@ void platform_init()
nvm_readCalibData(&calibration); /* Load calibration data */
nvm_loadHwInfo(&hwInfo); /* Load hardware information data */
rtc_init(); /* Initialise RTC */
chSelector_init(); /* Initialise channel selector handler */
#ifdef ENABLE_BKLIGHT_DIMMING
backlight_init(); /* Initialise backlight driver */
@ -134,6 +84,7 @@ void platform_terminate()
adc1_terminate();
nvm_terminate();
rtc_terminate();
chSelector_terminate();
/* Finally, remove power supply */
gpio_clearPin(PWR_SW);
@ -159,15 +110,6 @@ float platform_getVolumeLevel()
return adc1_getMeasurement(ADC_VOL_CH);
}
int8_t platform_getChSelector()
{
/*
* The knob_pos variable is set in the EXTI15_10 interrupt handler
* this is safe because interrupt nesting is not allowed.
*/
return knob_pos;
}
bool platform_getPttStatus()
{
/* PTT line has a pullup resistor with PTT switch closing to ground */
@ -229,6 +171,12 @@ const hwInfo_t *platform_getHwInfo()
return &hwInfo;
}
/*
* NOTE: implementation of this API function is provided in
* platform/drivers/chSelector/chSelector_MDUV3x0.c
*/
// int8_t platform_getChSelector()
/*
* NOTE: when backligth dimming is enabled, the implementation of this API
* function is provided in platform/drivers/backlight/backlight_MDx.c to avoid