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!
This commit is contained in:
Michał Wróbel
2015-04-25 14:25:34 +02:00
parent 41f78440db
commit 485edb579d
11 changed files with 351 additions and 196 deletions
+20 -144
View File
@@ -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<ADC_READ_COUNT; adc_input++) {
s_anaFilt[adc_input] = read_adc10(adc_input);
}
}
#endif
#if !defined(CPUARM)
void getADC_bandgap()
{
#if defined(PCBGRUVIN9X)
static uint8_t s_bgCheck = 0;
static uint16_t s_bgSum = 0;
ADCSRA|=0x40; // request sample
s_bgCheck += 32;
while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; // wait for sample
if (s_bgCheck == 0) { // 8x over-sample (256/32=8)
BandGap = s_bgSum+ADC;
s_bgSum = 0;
}
else {
s_bgSum += ADC;
}
ADCSRB |= (1<<MUX5);
#elif defined(PCBMEGA2560)
BandGap = 2000;
#else
// TODO is the next line needed (because it has been called before perMain)?
ADMUX = 0x1E|ADC_VREF_TYPE; // Switch MUX to internal 1.22V reference
/*
MCUCR|=0x28; // enable Sleep (bit5) enable ADC Noise Reduction (bit2)
asm volatile(" sleep \n\t"); // if _SLEEP() is not defined use this
// ADCSRA|=0x40;
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10; // take sample clear flag?
BandGap=ADC;
MCUCR&=0x08; // disable sleep
*/
ADCSRA |= 0x40;
while (ADCSRA & 0x40);
BandGap = ADC;
#endif
}
#endif
#endif // SIMU
@@ -1619,12 +1497,10 @@ void doMixerCalculations()
Current_analogue = (Current_analogue*31 + s_anaFilt[8] ) >> 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<<MUX5);
ADMUX = 0x03|ADC_VREF_TYPE; // Switch MUX to internal reference
#elif defined(PCBSTD) && !defined(SIMU)
ADMUX = 0x1E|ADC_VREF_TYPE; // Switch MUX to internal reference
#endif
#if !defined(CPUARM)
adcPrepareBandgap();
#endif
evalMixes(tick10ms);
@@ -2176,14 +2052,14 @@ ISR(TIMER3_CAPT_vect) // G: High frequency noise can cause stack overflo with IS
#endif
#if defined(DSM2_SERIAL) && !defined(CPUARM)
FORCEINLINE void DSM2_USART0_vect()
FORCEINLINE void DSM2_USART_vect()
{
UDR0 = *((uint16_t*)pulses2MHzRPtr); // transmit next byte
pulses2MHzRPtr += sizeof(uint16_t);
if (pulses2MHzRPtr == pulses2MHzWPtr) { // if reached end of DSM2 data buffer ...
UCSR0B &= ~(1 << UDRIE0); // disable UDRE0 interrupt
UCSRB_N(TLM_USART) &= ~(1 << UDRIE_N(TLM_USART)); // disable UDRE interrupt
}
}
#endif
@@ -2192,30 +2068,30 @@ FORCEINLINE void DSM2_USART0_vect()
#if defined (FRSKY)
// USART0 Transmit Data Register Emtpy ISR
FORCEINLINE void FRSKY_USART0_vect()
FORCEINLINE void FRSKY_USART_vect()
{
if (frskyTxBufferCount > 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