Files
edgetx-gx12/radio/util/hw_defs/hal_adc.py
T

287 lines
8.1 KiB
Python

from pot_config import pot_cfg_by_target
MAX_POTS = 4
MAX_SLIDERS = 4
MAX_EXTS = 4
MAX_RAWS = 4
def eprint(*args, **kwargs):
from sys import stderr
print(*args, file=stderr, **kwargs)
class ADCInput:
TYPE_STICK = 'STICK'
TYPE_FLEX = 'FLEX'
TYPE_SWITCH = 'SWITCH'
TYPE_RAW = 'RAW'
# TYPE_BATT = 'BATT'
def __init__(self, name, adc_input_type, adc, gpio, pin, channel):
self.name = name
self.type = adc_input_type
self.adc = adc
self.gpio = gpio
self.pin = pin
self.channel = channel
class SPI_ADCInput:
def __init__(self, name, adc_input_type, channel):
self.name = name
self.type = adc_input_type
self.adc = 'SPI'
self.channel = channel
class ADC:
def __init__(self, name, adc):
self.name = name
self.adc = adc
class MouseName:
AXIS = ['x','y']
def format(self, idx):
axis = self.AXIS[idx - 1]
return f'JS{axis}'
def AZ_seq():
return [chr(i) for i in range(ord('A'), ord('Z') + 1)]
class ADCInputParser:
ADC_MAIN = 'MAIN'
ADC_EXT = 'EXT'
ADC_INPUTS = [
{
'range': ['LH','LV','RV','RH','ST','TH'],
'type': ADCInput.TYPE_STICK,
'suffix': 'STICK_{}',
'name': '{}',
},
{
'range': range(1, MAX_POTS + 1),
'type': ADCInput.TYPE_FLEX,
'suffix': 'POT{}',
'name': 'P{}',
},
{
'range': range(1, MAX_SLIDERS + 1),
'type': ADCInput.TYPE_FLEX,
'suffix': 'SLIDER{}',
'name': 'SL{}',
},
{
'range': range(1, MAX_EXTS + 1),
'type': ADCInput.TYPE_FLEX,
'suffix': 'EXT{}',
'name': 'EXT{}',
},
{
'range': range(1, MAX_RAWS + 1),
'type': ADCInput.TYPE_RAW,
'suffix': 'RAW{}',
'name': 'RAW{}',
},
{
'range': range(1, 2 + 1),
'type': ADCInput.TYPE_FLEX,
'suffix': 'MOUSE{}',
'name': MouseName(),
},
{
'type': 'VBAT',
'name': 'VBAT',
'suffix': 'BATT',
},
{
'type': 'RTC_BAT',
'name': 'RTC_BAT',
'suffix': 'RTC_BAT',
},
{
'range': AZ_seq(),
'type': ADCInput.TYPE_SWITCH,
'suffix': 'SW{}',
'name': 'SW{}',
},
]
def __init__(self, target, hw_defs, labels):
self.target = target
self.hw_defs = hw_defs
self.labels = labels
self.regs = self._parse_regs()
self.dirs = self._parse_dirs()
self.adcs = []
def _parse_regs(self):
regs = {}
for reg in AZ_seq():
reg = f'GPIO{reg}'
pins_def = f'ADC_{reg}_PINS'
if pins_def in self.hw_defs:
regs[reg] = self.hw_defs[pins_def]
return regs
def _parse_dirs(self):
ret = []
dirs = self.hw_defs.get('ADC_DIRECTION') or ''
if dirs:
dirs = dirs.strip('{} ').split(',')
# eprint(dirs)
for i in dirs:
ret.append(int(i))
return ret
def _find_adc(self, channel_def):
if (self.ext_list is None) or (channel_def not in self.ext_list):
return self.ADC_MAIN
else:
return self.ADC_EXT
def _find_gpio(self, pin):
gpio = None
for reg, pins_def in self.regs.items():
if pins_def and (pin in pins_def):
gpio = reg
return gpio
def _parse_adc(self, name, periph, prefix):
adc_periph = self.hw_defs.get(periph)
if not adc_periph:
return None
adc = ADC(name, adc_periph)
adc.dma = self.hw_defs.get(f'{prefix}_DMA')
if adc.dma:
adc.dma_channel = self.hw_defs[f'{prefix}_DMA_CHANNEL']
adc.dma_stream = self.hw_defs[f'{prefix}_DMA_STREAM']
adc.dma_stream_irq = self.hw_defs[f'{prefix}_DMA_STREAM_IRQ']
adc.dma_stream_irq_handler = self.hw_defs[f'{prefix}_DMA_STREAM_IRQHandler']
adc.sample_time = self.hw_defs[f'{prefix}_SAMPTIME']
return adc
def _parse_adcs(self):
adcs = []
adc_spi = self.hw_defs.get('ADC_SPI')
if adc_spi:
#eprint('## Found SPI ADC')
adc = ADC('SPI', adc_spi)
adc.gpio_pin_miso = self.hw_defs['ADC_SPI_GPIO_PIN_MISO']
adc.gpio_pin_mosi = self.hw_defs['ADC_SPI_GPIO_PIN_MOSI']
adc.gpio_pin_sck = self.hw_defs['ADC_SPI_GPIO_PIN_SCK']
adc.gpio_pin_cs = self.hw_defs['ADC_SPI_GPIO_PIN_CS']
adcs.append(adc)
adc_main = self._parse_adc('MAIN', 'ADC_MAIN', 'ADC')
if adc_main:
adcs.append(adc_main)
self.ext_list = None
adc_ext = self._parse_adc('EXT', 'ADC_EXT', 'ADC_EXT')
if adc_ext:
self.ext_list = self.hw_defs['ADC_EXT_CHANNELS']
adcs.append(adc_ext)
return adcs
def _parse_input_type(self, input_type, name, suffix):
gpio = None
pin = None
d = 1 # non-inverted
# search for SPI input first
spi_def = f'ADC_SPI_{suffix}'
if spi_def in self.hw_defs:
#eprint('## Found SPI ADC Input:', spi_def)
channel = self.hw_defs[spi_def]
return SPI_ADCInput(name, input_type, channel)
if name != 'RTC_BAT':
pin_def = f'ADC_GPIO_PIN_{suffix}'
pin = self.hw_defs[pin_def]
gpio = self._find_gpio(pin_def)
# check if 'pin' is maybe an alias
alias = self.hw_defs.get(pin)
if alias is not None:
alias_gpio = self._find_gpio(pin)
gpio = alias_gpio if alias_gpio else gpio
pin = alias
channel_def = f'ADC_CHANNEL_{suffix}'
channel = self.hw_defs[channel_def]
adc = self._find_adc(channel_def)
return ADCInput(name, input_type, adc, gpio, pin, channel)
def _add_input(self, adc_input):
if adc_input is not None:
idx = len(self.inputs)
if adc_input.type == 'STICK':
if 'PWM_STICKS' in self.hw_defs:
ch = self.hw_defs.get(f'STICK_PWM_CHANNEL_{adc_input.name}')
adc_input.pwm_channel = idx if ch is None else ch
if adc_input.type != 'VBAT' and adc_input.type != 'RTC_BAT':
d = self.dirs[idx]
if d < 0:
adc_input.inverted = True
if adc_input.type == 'FLEX':
input_labels = self.labels[adc_input.name]
adc_input.label = input_labels.get('label')
adc_input.short_label = input_labels.get('short_label')
cfg = pot_cfg_by_target(self.target,adc_input.name)
if cfg:
adc_input.default = cfg.get('default')
self.inputs.append(adc_input)
def parse_inputs(self):
self.adcs = self._parse_adcs()
self.inputs = []
for adc_input in self.ADC_INPUTS:
input_type = adc_input['type']
input_range = adc_input.get('range')
if input_range is not None:
for i in input_range:
name = adc_input['name'].format(i)
suffix = adc_input['suffix'].format(i)
try:
self._add_input(self._parse_input_type(input_type, name, suffix))
except KeyError:
pass
else:
# type, name, suffix
name = adc_input['name']
suffix = adc_input['suffix']
try:
self._add_input(self._parse_input_type(input_type, name, suffix))
except KeyError:
pass
return { 'adcs': self.adcs, 'inputs': self.inputs }
def find_input(self, name):
for adc_input in self.inputs:
if adc_input.name == name:
return adc_input
return None