Files
edgetx-gx12/radio/src/targets/9x/board.cpp
T
3djcandBertrand Songis fa951acf40 Review line ending handling (#4820)
* New line end handling rules

* Normalize all the line endings
2017-04-19 10:54:43 +02:00

365 lines
9.0 KiB
C++

/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* 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"
#if defined(ROTARY_ENCODER_NAVIGATION)
#if defined(TELEMETREZ)
uint8_t TrotCount; // TeZ version
uint8_t LastTrotCount; // TeZ version
uint8_t RotEncoder;
#else
uint8_t RotPosition;
int8_t LastRotaryValue;
int8_t Rotary_diff;
int8_t RotaryControl;
uint8_t RotEncoder;
#endif
void rotencPoll()
{
#if defined(TELEMETREZ)
if (TrotCount != LastTrotCount) {
rotencValue[0] = LastTrotCount = TrotCount;
}
#else
// Rotary Encoder polling
PORTA = 0; // No pullups
DDRA = 0x1F; // Top 3 bits input
asm(" rjmp 1f");
asm("1:");
uint8_t rotary;
rotary = PINA;
DDRA = 0xFF; // Back to all outputs
rotary &= 0xE0;
RotEncoder = rotary; // just read the lcd pin
rotary &= 0xDF;
if ( rotary != RotPosition ) {
uint8_t x;
x = RotPosition & 0x40;
x <<= 1;
x ^= rotary & 0x80;
if ( x ) {
rotencValue[0] -= 1;
}
else {
rotencValue[0] += 1;
}
RotPosition = rotary;
}
#endif // TELEMETREZ
}
#else
#define ROTENC_DOWN() (0)
#endif // ROTARY_ENCODER_NAVIGATION
void boardInit()
{
#if !defined(SIMU)
// Set up I/O port data directions and initial states
DDRA = 0xff; PORTA = 0x00; // LCD data
DDRB = 0x81; PORTB = 0x7e; //pullups keys+nc
#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED)
DDRC = 0xff; PORTC = 0x00;
#else
DDRC = 0x3e; PORTC = 0xc1; //pullups nc
#endif
DDRD = 0x00; PORTD = 0xff; //pullups keys
DDRE = (1<<OUT_E_BUZZER); PORTE = 0xff-(1<<OUT_E_BUZZER); //pullups + buzzer 0
DDRF = 0x00; PORTF = 0x00; //anain
DDRG = 0x14; PORTG = 0xfb; //pullups + SIM_CTL=1 = phonejack = ppm_in, Haptic output and off (0)
adcInit();
#if defined(CPUM2561)
TCCR2B = (0b111 << CS20); // Norm mode, clk/1024 (differs from ATmega64 chip)
OCR2A = 156;
TIMSK2 |= (1<<OCIE2A) | (1<<TOIE2); // Enable Output-Compare and Overflow interrrupts
#else
// TCNT0 10ms = 16MHz/1024/156 periodic timer (9.984ms)
// (with 1:4 duty at 157 to average 10.0ms)
// Timer overflows at about 61Hz or once every 16ms.
TCCR0 = (0b111 << CS00); // Norm mode, clk/1024
OCR0 = 156;
#endif
#if defined(AUDIO) || defined(VOICE)
SET_TIMER_AUDIO_CTRL();
#if defined(CPUM2561)
OCR4A = 0xFF;
RESUME_AUDIO_INTERRUPT();
#else
TIMSK |= (1<<OCIE0) | (1<<TOIE0) | (1<<TOIE2); // Enable Output-Compare and Overflow interrrupts
#endif
#elif defined(PWM_BACKLIGHT)
/** Smartieparts LED Backlight is connected to PORTB/pin7, which can be used as pwm output of timer2 **/
#if defined(CPUM2561)
#if defined(SP22)
TCCR0A = (1<<WGM00)|(1<<COM0A1)|(1<<COM0A0); // inv. pwm mode, clk/64
#else
TCCR0A = (1<<WGM00)|(1<<COM0A1); // pwm mode, clk/64
#endif
TCCR0B = (0b011<<CS00);
#else
#if defined(SP22)
TCCR2 = (0b011<<CS20)|(1<<WGM20)|(1<<COM21)|(1<<COM20); // inv. pwm mode, clk/64
#else
TCCR2 = (0b011<<CS20)|(1<<WGM20)|(1<<COM21); // pwm mode, clk/64
#endif
TIMSK |= (1<<OCIE0) | (1<<TOIE0); // Enable Output-Compare and Overflow interrrupts
#endif
#else
#if !defined(CPUM2561)
TIMSK |= (1<<OCIE0) | (1<<TOIE0); // Enable Output-Compare and Overflow interrrupts
#endif
#endif
#endif // !defined(SIMU)
}
#if !defined(SIMU) && (defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED))
uint8_t pf7_digital[MUX_PF7_DIGITAL_MAX - MUX_PF7_DIGITAL_MIN + 1];
/**
* Update ADC PF7 using 14051 multiplexer
* X0 : Battery voltage
* X1 : AIL SW
* X2 : THR SW
* X3 : TRIM LEFT VERTICAL UP
* X4 : TRIM LEFT VERTICAL DOWN
*/
void processMultiplexAna()
{
static uint8_t muxNum = MUX_BATT;
uint8_t nextMuxNum = muxNum-1;
switch (muxNum) {
case MUX_BATT:
s_anaFilt[TX_VOLTAGE] = s_anaFilt[X14051];
nextMuxNum = MUX_MAX;
break;
case MUX_AIL:
case MUX_THR:
case MUX_TRM_LV_UP:
case MUX_TRM_LV_DWN:
// Digital switch depend from input voltage
// take half voltage to determine digital state
pf7_digital[muxNum - MUX_PF7_DIGITAL_MIN] = (s_anaFilt[X14051] >= (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(SIMU) && (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(TELEMETRY_JETI) || defined(TELEMETRY_FRSKY) || defined(TELEMETRY_ARDUPILOT) || defined(TELEMETRY_NMEA) || defined(TELEMETRY_MAVLINK)
#define THR_STATE() (PINC & (1<<INP_C_ThrCt))
#define AIL_STATE() (PINC & (1<<INP_C_AileDR))
#else
#define THR_STATE() (PINE & (1<<INP_E_ThrCt))
#define AIL_STATE() (PINE & (1<<INP_E_AileDR))
#endif
uint8_t keyState(uint8_t index)
{
return keys[index].state();
}
uint8_t switchState(uint8_t index)
{
uint8_t result = 0;
switch (index) {
case SW_ELE:
result = PINE & (1<<INP_E_ElevDR);
break;
case SW_AIL:
result = AIL_STATE();
break;
case SW_RUD:
result = PING & (1<<INP_G_RuddDR);
break;
// INP_G_ID1 INP_E_ID2
// id0 0 1
// id1 1 1
// id2 1 0
case SW_ID0:
result = !(PING & (1<<INP_G_ID1));
break;
case SW_ID1:
result = (PING & (1<<INP_G_ID1)) && (PINE & (1<<INP_E_ID2));
break;
case SW_ID2:
result = !(PINE & (1<<INP_E_ID2));
break;
case SW_GEA:
result = PINE & (1<<INP_E_Gear);
break;
case SW_THR:
result = THR_STATE();
break;
case SW_TRN:
result = PINE & (1<<INP_E_Trainer);
break;
default:
break;
}
return result;
}
// Trim switches ...
uint8_t trimHelper(uint8_t negpin, uint8_t idx)
{
switch(idx){
case 0: return negpin & TRIMS_GPIO_PIN_LHL;
case 1: return negpin & TRIMS_GPIO_PIN_LHR;
#if !defined(SIMU) && defined(TELEMETRY_MOD_14051_SWAPPED)
case 2: return !pf7_digital[PF7_TRM_LV_DWN];
case 3: return !pf7_digital[PF7_TRM_LV_UP];
#else
case 2: return negpin & TRIMS_GPIO_PIN_LVD;
case 3: return negpin & TRIMS_GPIO_PIN_LVU;
#endif
case 4: return negpin & TRIMS_GPIO_PIN_RVD;
case 5: return negpin & TRIMS_GPIO_PIN_RVU;
case 6: return negpin & TRIMS_GPIO_PIN_RHL;
case 7: return negpin & TRIMS_GPIO_PIN_RHR;
default: return 0;
}
}
uint8_t trimDown(uint8_t idx)
{
return trimHelper(~PIND, idx);
}
void readKeysAndTrims()
{
uint8_t index = KEY_MENU;
// User buttons ...
uint8_t in = ~PINB;
for (int i=1; i<7; i++) {
keys[index].input(in & (1<<i));
++index;
}
// Trims ...
in = ~PIND;
for (int i=0; i<8; i++) {
// INP_D_TRM_RH_UP 0 .. INP_D_TRM_LH_UP 7
keys[index].input(trimHelper(in, i));
++index;
}
#if defined(ROTARY_ENCODER_NAVIGATION)
keys[index].input(ROTENC_DOWN()); // Rotary Enc. Switch
#endif
#if defined(NAVIGATION_STICKS)
if (~PINB & 0x7E) {
StickScrollTimer = STICK_SCROLL_TIMEOUT;
}
#endif
}
bool checkSlaveMode()
{
// no power -> only phone jack = slave mode
static bool lastSlaveMode = false;
static uint8_t checkDelay = 0;
if (IS_AUDIO_BUSY()) {
checkDelay = 20;
}
else if (checkDelay) {
--checkDelay;
}
else {
lastSlaveMode = (PING & (1<<INP_G_RF_POW));
}
return lastSlaveMode;
}
#if defined(PWM_BACKLIGHT)
// exponential PWM table for linear brightness
static const uint8_t pwmtable[16] PROGMEM =
{
0, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64, 90, 128, 181, 255
};
static uint8_t bl_target;
static uint8_t bl_current;
void backlightEnable()
{
bl_target = 15 - g_eeGeneral.blOnBright;
}
void backlightDisable()
{
bl_target = g_eeGeneral.blOffBright;
}
bool isBacklightEnabled()
{
return (bl_target==g_eeGeneral.blOnBright);
}
void backlightFade() // called from per10ms()
{
if (bl_target != bl_current) {
#if defined(CPUM2561)
if (bl_target > bl_current)
OCR0A = pgm_read_byte(&pwmtable[++bl_current]);
else
OCR0A = pgm_read_byte(&pwmtable[--bl_current]);
#else
if (bl_target > bl_current)
OCR2 = pgm_read_byte(&pwmtable[++bl_current]);
else
OCR2 = pgm_read_byte(&pwmtable[--bl_current]);
#endif
}
}
#endif