From 485edb579d63f1f5025e397f0e407c04fd336ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Wr=C3=B3bel?= Date: Fri, 24 Apr 2015 00:36:15 +0200 Subject: [PATCH] TELEMETRY_MOD=14051_SWAPPED TELEMETRY_MOD=14051 (by gerardv @ forum.turnigy9xr.com) makes USART0 available by reallocating AIL and THR onto pins 14 and 15 of the 14051 multiplexer. TELEMETRY_MOD=14051_SWAPPED is based on TELEMETRY_MOD=14051, but uses USART1 instead of USART0, freeing USART0 for other purposes (debugging, interfacing via AVRISP port). USART1 is freed up by reallocating LVert Trim Dn/Up onto 14051's 12 and 1 pins respectively. Additionally, this commit cleans a few things up: * moves AVR ADC-related code to adc_driver.cpp, * provides #defines to have a convenient way to access either USART0 or USART1 registers depending on static (build-time) configuration * moves code related to this telemetry mod to board_stock * replaces a few magic numbers with enums. Thanks to Bernard Songis for review and suggestions! --- radio/src/Makefile | 18 +- radio/src/opentx.cpp | 164 +++--------------- radio/src/opentx.h | 15 +- radio/src/switches.cpp | 2 +- radio/src/targets/common_avr/adc_driver.cpp | 114 ++++++++++++ radio/src/targets/common_avr/board_avr.h | 73 ++++++++ .../targets/common_avr/telemetry_driver.cpp | 38 ++-- radio/src/targets/gruvin9x/board_gruvin9x.cpp | 4 +- radio/src/targets/mega2560/board_mega2560.cpp | 4 +- radio/src/targets/stock/board_stock.cpp | 88 ++++++++-- radio/src/targets/stock/board_stock.h | 27 +++ 11 files changed, 351 insertions(+), 196 deletions(-) create mode 100644 radio/src/targets/common_avr/adc_driver.cpp diff --git a/radio/src/Makefile b/radio/src/Makefile index 3e58daf97..947711b65 100644 --- a/radio/src/Makefile +++ b/radio/src/Makefile @@ -415,7 +415,7 @@ ifeq ($(PCB), $(filter $(PCB), STD 9X 9XR)) INCDIRS += targets/stock CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM64 -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc) BOARDSRC = main_avr.cpp targets/stock/board_stock.cpp - EXTRABOARDSRC = targets/common_avr/telemetry_driver.cpp + EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/common_avr/telemetry_driver.cpp ifeq ($(GUI), YES) EXTRABOARDSRC += targets/stock/lcd_driver.cpp endif @@ -437,6 +437,10 @@ ifeq ($(PCB), $(filter $(PCB), STD 9X 9XR)) CPPDEFS += -DTELEMETRY_MOD_14051 endif + ifeq ($(TELEMETRY_MOD), 14051_SWAPPED) + CPPDEFS += -DTELEMETRY_MOD_14051_SWAPPED + endif + ifeq ($(AUDIO), YES) CPPDEFS += -DAUDIO CPPSRC += audio_avr.cpp @@ -488,7 +492,7 @@ ifeq ($(PCB), $(filter $(PCB), STD128 9X128 9XR128)) CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM128 -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc) INCDIRS += targets/stock BOARDSRC = main_avr.cpp targets/stock/board_stock.cpp - EXTRABOARDSRC = targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp + EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp PULSESSRC = pulses/pulses_avr.cpp CPPSRC += debug.cpp @@ -507,6 +511,10 @@ ifeq ($(PCB), $(filter $(PCB), STD128 9X128 9XR128)) CPPDEFS += -DTELEMETRY_MOD_14051 endif + ifeq ($(TELEMETRY_MOD), 14051_SWAPPED) + CPPDEFS += -DTELEMETRY_MOD_14051_SWAPPED + endif + ifeq ($(AUDIO), YES) CPPDEFS += -DAUDIO CPPSRC += audio_avr.cpp @@ -554,7 +562,7 @@ ifeq ($(PCB), $(filter $(PCB), 9X2561)) CPPDEFS = -DF_CPU=$(F_CPU)UL -DPCBSTD -DCPUM2561 -DEEPROM_VARIANT=$(shell echo ${EEPROM_VARIANT} | bc) INCDIRS += targets/stock BOARDSRC = main_avr.cpp targets/stock/board_stock.cpp - EXTRABOARDSRC = targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp + EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp PULSESSRC = pulses/pulses_avr.cpp CPPSRC += debug.cpp @@ -622,7 +630,7 @@ ifeq ($(PCB), GRUVIN9X) THR_TRACE = YES INCDIRS += targets/gruvin9x targets/stock $(FATFSDIR) $(FATFSDIR)/option BOARDSRC = main_avr.cpp targets/gruvin9x/board_gruvin9x.cpp - EXTRABOARDSRC = targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp + EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp EEPROMSRC = eeprom_common.cpp eeprom_rlc.cpp PULSESSRC = pulses/pulses_avr.cpp CPPSRC += audio_avr.cpp haptic.cpp debug.cpp @@ -680,7 +688,7 @@ ifeq ($(PCB), MEGA2560) ifeq ($(LCD), ST7565R) CPPDEFS += -DLCD_ST7565R endif - EXTRABOARDSRC = targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp + EXTRABOARDSRC = targets/common_avr/adc_driver.cpp targets/stock/lcd_driver.cpp targets/common_avr/telemetry_driver.cpp ifeq ($(SDCARD), YES) EXTRABOARDSRC += $(FATFSDIR)/ff.c $(FATFSDIR)/fattime.c $(FATFSDIR)/option/ccsbcs.c targets/gruvin9x/diskio.cpp diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index 02152c56b..1d5787fc5 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -1301,7 +1301,7 @@ uint8_t checkTrim(uint8_t event) } #if !defined(SIMU) -static uint16_t s_anaFilt[NUMBER_ANALOG]; +uint16_t s_anaFilt[NUMBER_ANALOG]; #endif #if defined(SIMU) @@ -1328,8 +1328,12 @@ uint16_t anaIn(uint8_t chan) } volatile uint16_t *p = &s_anaFilt[pgm_read_byte(crossAna+chan)]; return *p; +#else +#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED) + static const pm_char crossAna[] PROGMEM = {3,1,2,0,4,5,6,0/* shouldn't be used */,TX_VOLTAGE}; #else static const pm_char crossAna[] PROGMEM = {3,1,2,0,4,5,6,7}; +#endif #if defined(FRSKY_STICKS) volatile uint16_t temp = s_anaFilt[pgm_read_byte(crossAna+chan)]; // volatile saves here 40 bytes; maybe removed for newer AVR when available if (chan < NUM_STICKS && (g_eeGeneral.stickReverse & (1 << chan))) { @@ -1378,132 +1382,6 @@ void getADC() s_anaFilt[x] = v; } } -#else - -/** - * Read ADC using 10 bits - */ -inline uint16_t read_adc10(uint8_t adc_input) -{ - uint16_t temp_ana; - ADMUX = adc_input|ADC_VREF_TYPE; -#if defined(TELEMETRY_MOD_14051) - ADCSRA &= 0x87; -#endif - ADCSRA |= 1 << ADSC; // Start the AD conversion - while (ADCSRA & (1 << ADSC)); // Wait for the AD conversion to complete - temp_ana = ADC; - ADCSRA |= 1 << ADSC; // Start the second AD conversion - while (ADCSRA & (1 << ADSC)); // Wait for the AD conversion to complete - temp_ana += ADC; - return temp_ana; -} - -#if defined(TELEMETRY_MOD_14051) -enum MuxInput { - MUX_BATT, - MUX_THR, - MUX_AIL, - MUX_MAX = MUX_AIL -}; - -uint8_t pf7_digital[2]; -/** - * Update ADC PF7 using 14051 multiplexer - * X0 : Battery voltage - * X1 : THR SW - * X2 : AIL SW - */ -void readMultiplexAna() -{ - static uint8_t muxNum = MUX_BATT; - uint16_t temp_ana; - uint8_t nextMuxNum = muxNum-1; - - DDRC |= 0xC1; - temp_ana = read_adc10(7); - - switch (muxNum) { - case MUX_BATT: - s_anaFilt[TX_VOLTAGE] = temp_ana; - nextMuxNum = MUX_MAX; - break; - case MUX_THR: - case MUX_AIL: - // Digital switch depend from input voltage - // take half voltage to determine digital state - pf7_digital[muxNum-1] = (temp_ana >= (s_anaFilt[TX_VOLTAGE] / 2)) ? 1 : 0; - break; - } - - // set the mux number for the next ADC convert, - // stabilize voltage before ADC read. - muxNum = nextMuxNum; - PORTC &= ~((1 << PC7) | (1 << PC6) | (1 << PC0)); // Clear CTRL ABC - switch (muxNum) { - case 1: - PORTC |= (1 << PC6); // Mux CTRL A : SW_THR - break; - case 2: - PORTC |= (1 << PC7); // Mux CTRL B : SW_AIL - break; - } -} -#endif - -void getADC() -{ -#if defined(TELEMETRY_MOD_14051) - readMultiplexAna(); - #define ADC_READ_COUNT 7 -#else - #define ADC_READ_COUNT 8 -#endif - - for (uint8_t adc_input=0; adc_input> 5 ; if (Current_analogue > Current_max) Current_max = Current_analogue ; -#elif defined(PCBGRUVIN9X) && !defined(SIMU) - // For PCB V4, use our own 1.2V, external reference (connected to ADC3) - ADCSRB &= ~(1< 0) { - UDR0 = frskyTxBuffer[--frskyTxBufferCount]; + UDR_N(TLM_USART) = frskyTxBuffer[--frskyTxBufferCount]; } else { - UCSR0B &= ~(1 << UDRIE0); // disable UDRE0 interrupt + UCSRB_N(TLM_USART) &= ~(1 << UDRIE_N(TLM_USART)); // disable UDRE interrupt } } -ISR(USART0_UDRE_vect) +// USART0/1 Transmit Data Register Emtpy ISR +ISR(USART_UDRE_vect_N(TLM_USART)) { #if defined(FRSKY) && defined(DSM2_SERIAL) if (IS_DSM2_PROTOCOL(g_model.protocol)) { // TODO not s_current_protocol? - DSM2_USART0_vect(); + DSM2_USART_vect(); } else { - FRSKY_USART0_vect(); + FRSKY_USART_vect(); } #elif defined(FRSKY) - FRSKY_USART0_vect(); + FRSKY_USART_vect(); #else - DSM2_USART0_vect(); + DSM2_USART_vect(); #endif } #endif diff --git a/radio/src/opentx.h b/radio/src/opentx.h index 8a7a14c2a..268c75e63 100644 --- a/radio/src/opentx.h +++ b/radio/src/opentx.h @@ -941,8 +941,6 @@ void checkSwitches(); void checkAlarm(); void checkAll(); -#define ADC_VREF_TYPE 0x40 // AVCC with external capacitor at AREF pin - #if !defined(SIMU) void getADC(); #endif @@ -979,6 +977,15 @@ enum Analogs { POT2, POT3, POT_LAST = POT3, +#endif +#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED) + // When the mod is applied, ADC7 is connected to 14051's X pin and TX_VOLTAGE + // is connected to 14051's X0 pin (one of the multiplexed inputs). TX_VOLTAGE + // value is filled in by processMultiplexAna(). + + // This shifts TX_VOLTAGE from 7 to 8 and makes X14051 take the 7th position + // corresponding to ADC7. + X14051, #endif TX_VOLTAGE, #if defined(PCBSKY9X) && !defined(REVA) @@ -1727,4 +1734,8 @@ struct Clipboard { extern Clipboard clipboard; #endif +#if !defined(SIMU) +extern uint16_t s_anaFilt[NUMBER_ANALOG]; +#endif + #endif diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp index c1fefe17d..e117941e2 100644 --- a/radio/src/switches.cpp +++ b/radio/src/switches.cpp @@ -604,7 +604,7 @@ void checkSwitches() #if !defined(MODULE_ALWAYS_SEND_PULSES) while (1) { -#if defined(TELEMETRY_MOD_14051) || defined(PCBTARANIS) +#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED) || defined(PCBTARANIS) getADC(); #endif #endif // !defined(MODULE_ALWAYS_SEND_PULSES) diff --git a/radio/src/targets/common_avr/adc_driver.cpp b/radio/src/targets/common_avr/adc_driver.cpp new file mode 100644 index 000000000..d92da7511 --- /dev/null +++ b/radio/src/targets/common_avr/adc_driver.cpp @@ -0,0 +1,114 @@ +/* + * Authors (alphabetical order) + * - Andre Bernet + * - Andreas Weitl + * - Bertrand Songis + * - Bryan J. Rentoul (Gruvin) + * - Cameron Weeks + * - Erez Raviv + * - Gabriel Birkus + * - Jean-Pierre Parisy + * - Karl Szmutny + * - Michael Blandford + * - Michal Hlavinka + * - Pat Mackenzie + * - Philip Moss + * - Rob Thomson + * - Romolo Manfredini + * - Thomas Husterer + * + * opentx is based on code named + * gruvin9x by Bryan J. Rentoul: http://code.google.com/p/gruvin9x/, + * er9x by Erez Raviv: http://code.google.com/p/er9x/, + * and the original (and ongoing) project by + * Thomas Husterer, th9x: http://code.google.com/p/th9x/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + * + */ + +#include "../../opentx.h" + +#define ADC_VREF_TYPE (1 << REFS0) // AVCC with external capacitor at AREF pin + +void adcInit() +{ + ADMUX = ADC_VREF_TYPE; + ADCSRA = 0x85; // ADC enabled, pre-scaler division=32 (no interrupt, no auto-triggering) +#if defined(CPUM2560) + ADCSRB = (1 << MUX5); +#endif +} + +void adcPrepareBandgap() +{ +#if defined(CPUM2560) + // For PCB V4, use our own 1.2V, external reference (connected to ADC3) + ADCSRB &= ~(1< - UBRR0H = UBRRH_VALUE; - UBRR0L = UBRRL_VALUE; - UCSR0A &= ~(1 << U2X0); // disable double speed operation. + UBRRH_N(TLM_USART) = UBRRH_VALUE; + UBRRL_N(TLM_USART) = UBRRL_VALUE; + UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation. // set 8N1 - UCSR0B = 0 | (0 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (0 << RXEN0) | (0 << TXEN0) | (0 << UCSZ02); - UCSR0C = 0 | (1 << UCSZ01) | (1 << UCSZ00); + UCSRB_N(TLM_USART) = 0 | (0 << RXCIE_N(TLM_USART)) | (0 << TXCIE_N(TLM_USART)) | (0 << UDRIE_N(TLM_USART)) | (0 << RXEN_N(TLM_USART)) | (0 << TXEN_N(TLM_USART)) | (0 << UCSZ2_N(TLM_USART)); + UCSRC_N(TLM_USART) = 0 | (1 << UCSZ1_N(TLM_USART)) | (1 << UCSZ0_N(TLM_USART)); - while (UCSR0A & (1 << RXC0)) UDR0; // flush receive buffer + while (UCSRA_N(TLM_USART) & (1 << RXC_N(TLM_USART))) UDR_N(TLM_USART); // flush receive buffer // These should be running right from power up on a FrSky enabled '9X. telemetryEnableTx(); // enable FrSky-Telemetry emission @@ -136,7 +136,7 @@ void telemetryPortInit() void telemetryTransmitBuffer() { - UCSR0B |= (1 << UDRIE0); // enable UDRE0 interrupt + UCSRB_N(TLM_USART) |= (1 << UDRIE_N(TLM_USART)); // enable UDRE1 interrupt } #endif diff --git a/radio/src/targets/gruvin9x/board_gruvin9x.cpp b/radio/src/targets/gruvin9x/board_gruvin9x.cpp index 460753309..d9ebe6047 100644 --- a/radio/src/targets/gruvin9x/board_gruvin9x.cpp +++ b/radio/src/targets/gruvin9x/board_gruvin9x.cpp @@ -65,9 +65,7 @@ inline void boardInit() DDRL = 0x80; PORTL = 0xff; // 7: Hold_PWR_On (1=On, default Off), 6:Jack_Presence_TTL, 5-0: User Button inputs #endif - ADMUX=ADC_VREF_TYPE; - ADCSRA=0x85; // ADC enabled, pre-scaler division=32 (no interrupt, no auto-triggering) - ADCSRB=(1<= (s_anaFilt[TX_VOLTAGE] / 2)) ? 1 : 0; + break; + } + + // set the mux number for the next ADC convert, + // stabilize voltage before ADC read. + muxNum = nextMuxNum; + PORTC &= ~((1 << PC7) | (1 << PC6) | (1 << PC0)); + if(muxNum & 1) PORTC |= (1 << PC7); // Mux CTRL A + if(muxNum & 2) PORTC |= (1 << PC6); // Mux CTRL B + if(muxNum & 4) PORTC |= (1 << PC0); // Mux CTRL C +} +#endif + +#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED) + #define THR_STATE() pf7_digital[PF7_THR] + #define AIL_STATE() pf7_digital[PF7_AIL] #elif defined(JETI) || defined(FRSKY) || defined(ARDUPILOT) || defined(NMEA) || defined(MAVLINK) #define THR_STATE() (PINC & (1<