avr-remove remove files in main dir and targets

This commit is contained in:
3djc
2018-07-03 09:44:03 +02:00
parent ec0c82a4bf
commit c032b30247
36 changed files with 0 additions and 7803 deletions
-328
View File
@@ -1,328 +0,0 @@
/*
* 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"
audioQueue::audioQueue()
{
toneTimeLeft = 0;
tonePause = 0;
tone2TimeLeft = 0;
t_queueRidx = 0;
t_queueWidx = 0;
}
// heartbeat is responsibile for issueing the audio tones and general square waves
// it is essentially the life of the class.
// it is called every 10ms
void audioQueue::heartbeat()
{
#if defined(SIMU)
return;
#else
if (toneTimeLeft > 0) {
if (toneFreq == 0) { //pause only events
speakerOff();
}
else {
#if defined(CPUM2560)
if (toneFreq) {
OCR4A = (5000 / toneFreq); // sticking with old values approx 20(abs. min) to 90, 60 being the default tone(?).
speakerOn();
}
#endif
toneFreq += toneFreqIncr;
}
toneTimeLeft--; //time gets counted down
}
else {
if (tonePause > 0) {
speakerOff();
tonePause--; //time gets counted down
}
else if (t_queueRidx != t_queueWidx) {
toneFreq = queueToneFreq[t_queueRidx];
toneTimeLeft = queueToneLength[t_queueRidx];
toneFreqIncr = queueToneFreqIncr[t_queueRidx];
tonePause = queueTonePause[t_queueRidx];
if (!queueToneRepeat[t_queueRidx]--) {
t_queueRidx = (t_queueRidx + 1) & (AUDIO_QUEUE_LENGTH-1);
}
}
else {
if (tone2TimeLeft > 0) {
#if defined(CPUM2560)
if (tone2Freq) {
OCR4A = (5000 / tone2Freq); // sticking with old values approx 20(abs. min) to 90, 60 being the default tone(?).
speakerOn();
}
#else
toneFreq = tone2Freq;
#endif
tone2TimeLeft--; //time gets counted down
}
else {
speakerOff();
}
}
}
#endif // defined(SIMU)
}
inline uint8_t audioQueue::getToneLength(uint8_t tLen)
{
uint8_t result = tLen; // default
if (g_eeGeneral.beepLength < 0) {
result /= (1-g_eeGeneral.beepLength);
}
if (g_eeGeneral.beepLength > 0) {
result *= (1+g_eeGeneral.beepLength);
}
return result;
}
void audioQueue::pause(uint8_t tLen)
{
play(0, tLen, 5); // a pause
}
void audioQueue::play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlags)
{
if (tFlags & PLAY_BACKGROUND) {
tone2Freq = tFreq;
tone2TimeLeft = tLen;
}
else {
int8_t tFreqIncr = (tFlags >> 6);
if (tFreqIncr == 3) tFreqIncr = -1;
tFreq += g_eeGeneral.speakerPitch + BEEP_OFFSET; // add pitch compensator
tLen = getToneLength(tLen);
if ((tFlags & PLAY_NOW) || (!busy() && empty())) {
toneFreq = tFreq;
toneTimeLeft = tLen;
tonePause = tPause;
toneFreqIncr = tFreqIncr;
t_queueWidx = t_queueRidx;
}
else {
tFlags++;
}
tFlags &= 0x0f;
if (tFlags) {
uint8_t next_queueWidx = (t_queueWidx + 1) & (AUDIO_QUEUE_LENGTH-1);
if (next_queueWidx != t_queueRidx) {
queueToneFreq[t_queueWidx] = tFreq;
queueToneLength[t_queueWidx] = tLen;
queueTonePause[t_queueWidx] = tPause;
queueToneRepeat[t_queueWidx] = tFlags - 1;
queueToneFreqIncr[t_queueWidx] = tFreqIncr;
t_queueWidx = next_queueWidx;
}
}
}
}
void audioQueue::event(uint8_t e)
{
#if defined(HAPTIC)
haptic.event(e); //do this before audio to help sync timings
#endif
if (e <= AU_ERROR || (e >= AU_WARNING1 && e < AU_SPECIAL_SOUND_FIRST)) {
if (g_eeGeneral.alarmsFlash) {
flashCounter = FLASH_DURATION;
}
}
if (g_eeGeneral.beepMode >= e_mode_nokeys || (g_eeGeneral.beepMode >= e_mode_alarms && e <= AU_ERROR)) {
if (e < AU_SPECIAL_SOUND_FIRST || empty()) {
// TODO when VOICE enable some cases here are not needed!
switch (e) {
#if !defined(VOICE)
case AU_TX_BATTERY_LOW:
if (empty()) {
play(60, 20, 3, PLAY_REPEAT(2)|PLAY_INCREMENT(1));
play(80, 20, 3, PLAY_REPEAT(2)|PLAY_INCREMENT(-1));
}
break;
#endif
case AU_SPECIAL_SOUND_RING:
play(BEEP_DEFAULT_FREQ+25, 5, 2, PLAY_REPEAT(10));
play(BEEP_DEFAULT_FREQ+25, 5, 10, PLAY_REPEAT(1));
play(BEEP_DEFAULT_FREQ+25, 5, 2, PLAY_REPEAT(10));
break;
case AU_SPECIAL_SOUND_SCIFI:
play(80, 10, 3, PLAY_REPEAT(2)|PLAY_INCREMENT(-1));
play(60, 10, 3, PLAY_REPEAT(2)|PLAY_INCREMENT(1));
play(70, 10, 1);
break;
case AU_SPECIAL_SOUND_ROBOT:
play(70, 5, 1, PLAY_REPEAT(1));
play(50, 15, 2, PLAY_REPEAT(1));
play(80, 15, 2, PLAY_REPEAT(1));
break;
case AU_SPECIAL_SOUND_CHIRP:
play(BEEP_DEFAULT_FREQ+40, 5, 1, PLAY_REPEAT(2));
play(BEEP_DEFAULT_FREQ+54, 5, 1, PLAY_REPEAT(3));
break;
case AU_SPECIAL_SOUND_TADA:
play(50, 5, 5);
play(90, 5, 5);
play(110, 3, 4, PLAY_REPEAT(2));
break;
case AU_SPECIAL_SOUND_CRICKET:
play(80, 5, 10, PLAY_REPEAT(3));
play(80, 5, 20, PLAY_REPEAT(1));
play(80, 5, 10, PLAY_REPEAT(3));
break;
case AU_SPECIAL_SOUND_ALARMC:
play(50, 4, 10, PLAY_REPEAT(2));
play(70, 8, 20, PLAY_REPEAT(1));
play(50, 8, 10, PLAY_REPEAT(2));
play(70, 4, 20, PLAY_REPEAT(1));
break;
default:
{
static const pm_uint8_t singleSounds[] PROGMEM = {
70, 10, 2, PLAY_REPEAT(2)|PLAY_NOW, // INACTIVITY
BEEP_DEFAULT_FREQ, 40, 1, PLAY_NOW, // ERROR
BEEP_DEFAULT_FREQ, 10, 1, PLAY_NOW, // WARNING1
BEEP_DEFAULT_FREQ, 20, 1, PLAY_NOW, // WARNING2
BEEP_DEFAULT_FREQ, 30, 1, PLAY_NOW, // WARNING3
60, 10, 2, PLAY_NOW, // TRIM_MIDDLE
BEEP_DEFAULT_FREQ + 50, 10, 1, PLAY_NOW, // POT_STICK_MIDDLE
BEEP_DEFAULT_FREQ + 50, 6, 0, 0, // MIX_WARNING_1
BEEP_DEFAULT_FREQ + 52, 6, 3, PLAY_REPEAT(1), // MIX_WARNING_2
BEEP_DEFAULT_FREQ + 54, 6, 3, PLAY_REPEAT(2), // MIX_WARNING_3
BEEP_DEFAULT_FREQ, 10, 1, 0, // FRSKY_BEEP1
BEEP_DEFAULT_FREQ, 20, 1, 0, // FRSKY_BEEP2
BEEP_DEFAULT_FREQ, 30, 1, 0, // FRSKY_BEEP3
BEEP_DEFAULT_FREQ+20, 15, 5, PLAY_REPEAT(2), // FRSKY_WARN1
BEEP_DEFAULT_FREQ+30, 15, 5, PLAY_REPEAT(2), // FRSKY_WARN2
BEEP_DEFAULT_FREQ+30, 10, 2, PLAY_REPEAT(2)|PLAY_INCREMENT(2), // FRSKY_CHEEP
BEEP_DEFAULT_FREQ+50, 5, 10, PLAY_REPEAT(10), // FRSKY_RATATA
BEEP_DEFAULT_FREQ+50, 5, 50, PLAY_REPEAT(2), // FRSKY_TICK
10, 20, 5, PLAY_REPEAT(2)|PLAY_INCREMENT(1), // FRSKY_SIREN
};
const pm_uint8_t *ptr = &singleSounds[(e-AU_INACTIVITY)<<2];
uint8_t tFreq = pgm_read_byte(ptr++);
uint8_t tLen = pgm_read_byte(ptr++);
uint8_t tPause = pgm_read_byte(ptr++);
uint8_t tFlags = pgm_read_byte(ptr);
play(tFreq, tLen, tPause, tFlags);
break;
}
}
}
}
}
void audioDefevent(uint8_t e)
{
audio.event(e);
}
void audioKeyPress()
{
#if defined(AUDIO)
if (g_eeGeneral.beepMode == e_mode_all) {
audio.play(BEEP_DEFAULT_FREQ, 10, 1, PLAY_NOW);
}
#else
beep(0);
#endif
#if defined(HAPTIC)
if (g_eeGeneral.hapticMode == e_mode_all) {
haptic.play(5, 0, PLAY_NOW);
}
#endif
}
void audioTrimPress(int16_t value)
{
if (g_eeGeneral.beepMode >= e_mode_nokeys) {
#if defined(AUDIO)
value = limit<int16_t>(TRIM_MIN, value, TRIM_MAX);
value >>= 2;
value += 60;
audio.play(value, 6, 1, PLAY_NOW);
#else
warble = true;
beep(1);
#endif
}
}
void audioTimerCountdown(uint8_t timer, int value)
{
if (0) {
// pass
}
#if defined(CPUM2560) && (defined(VOICE_WTV20) || defined(VOICE_JQ6500))
else if (g_model.timers[timer].countdownBeep == COUNTDOWN_VOICE) {
if (value >= 0 && value <= TIMER_COUNTDOWN_START(timer)) {
playNumber(value, 0, 0);
}
else if (value == 30 || value == 20) {
playDuration(value);
}
}
#endif
#if defined(HAPTIC)
else if (g_model.timers[timer].countdownBeep == COUNTDOWN_HAPTIC) {
if (value == 0) {
haptic.play(15, 3, PLAY_NOW);
}
else if (value > 0 && value <= 10) {
haptic.play(5, 0, PLAY_NOW);
}
else if (value == 30) {
haptic.play(10, 3, PLAY_REPEAT(2) | PLAY_NOW);
}
else if (value == 20) {
haptic.play(10, 3, PLAY_REPEAT(1) | PLAY_NOW);
}
}
#endif
else {
if (value == 0) {
audio.play(BEEP_DEFAULT_FREQ + 50, 30, 3, PLAY_NOW);
}
else if (value > 0 && value <= 10) {
audio.play(BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_NOW);
}
else if (value == 30) {
audio.play(BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_REPEAT(2) | PLAY_NOW);
}
else if (value == 20) {
audio.play(BEEP_DEFAULT_FREQ + 50, 15, 3, PLAY_REPEAT(1) | PLAY_NOW);
}
}
}
-158
View File
@@ -1,158 +0,0 @@
/*
* 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.
*/
#ifndef _AUDIO_AVR_H_
#define _AUDIO_AVR_H_
#if defined(PCBSTD)
#define speakerOn() buzzerOn()
#define speakerOff() toneFreq=0; buzzerOff()
#endif
//audio
#define AUDIO_QUEUE_LENGTH (8) // 8 seems to suit most alerts
#define BEEP_DEFAULT_FREQ (70)
#define BEEP_OFFSET (10)
class audioQueue
{
public:
audioQueue();
void play(uint8_t tFreq, uint8_t tLen, uint8_t tPause, uint8_t tFlags=0);
void pause(uint8_t tLen);
inline bool busy() { return (toneTimeLeft > 0); }
void event(uint8_t e);
inline void driver() {
if (toneFreq) {
toneCounter += toneFreq;
if ((toneCounter & 0x80) == 0x80)
buzzerOn();
else
buzzerOff();
}
}
// heartbeat is responsibile for issueing the audio tones and general square waves
// it is essentially the life of the class.
void heartbeat();
inline bool empty() {
return (t_queueRidx == t_queueWidx);
}
protected:
inline uint8_t getToneLength(uint8_t tLen);
private:
uint8_t t_queueRidx;
uint8_t t_queueWidx;
uint8_t toneFreq;
int8_t toneFreqIncr;
uint8_t toneTimeLeft;
uint8_t tonePause;
// vario has less priority
uint8_t tone2Freq;
uint8_t tone2TimeLeft;
// queue arrays
uint8_t queueToneFreq[AUDIO_QUEUE_LENGTH];
int8_t queueToneFreqIncr[AUDIO_QUEUE_LENGTH];
uint8_t queueToneLength[AUDIO_QUEUE_LENGTH];
uint8_t queueTonePause[AUDIO_QUEUE_LENGTH];
uint8_t queueToneRepeat[AUDIO_QUEUE_LENGTH];
uint8_t toneCounter;
};
extern audioQueue audio;
void audioDefevent(uint8_t e);
#if defined(AUDIO) && defined(BUZZER)
#define AUDIO_BUZZER(a, b) do { a; b; } while(0)
#elif defined(AUDIO)
#define AUDIO_BUZZER(a, b) a
#else
#define AUDIO_BUZZER(a, b) b
#endif
#if defined(VOICE)
#define VOICE_AUDIO_BUZZER(v, a, b) v
#else
#define VOICE_AUDIO_BUZZER(v, a, b) AUDIO_BUZZER(a, b)
#endif
void audioKeyPress();
void audioKeyError();
void audioTrimPress(int16_t value);
void audioTimerCountdown(uint8_t timer, int value);
#define AUDIO_KEY_PRESS() audioKeyPress()
#define AUDIO_KEY_ERROR() AUDIO_WARNING2()
#define AUDIO_WARNING1() AUDIO_BUZZER(audioDefevent(AU_WARNING1), beep(3))
#define AUDIO_WARNING2() AUDIO_BUZZER(audioDefevent(AU_WARNING2), beep(2))
#define AUDIO_ERROR() AUDIO_BUZZER(audioDefevent(AU_ERROR), beep(4))
#define AUDIO_HELLO() VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AUDIO_HELLO),,)
#define AUDIO_BYE()
#define AUDIO_TX_BATTERY_LOW() VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_TX_BATTERY_LOW), audioDefevent(AU_TX_BATTERY_LOW), beep(4))
#define AUDIO_INACTIVITY() VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_INACTIVITY), audioDefevent(AU_INACTIVITY), beep(3))
#define AUDIO_ERROR_MESSAGE(e) VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT((e)), audioDefevent(AU_ERROR), beep(4))
#define AUDIO_TIMER_MINUTE(t) VOICE_AUDIO_BUZZER(playDuration(t), audioDefevent(AU_WARNING1), beep(2))
#define AUDIO_TIMER_COUNTDOWN(idx, val) audioTimerCountdown(idx, val)
#define AUDIO_TIMER_ELAPSED(idx) AUDIO_BUZZER(audioTimerCountdown(idx, 0), beep(3))
//#define AUDIO_TIMER_30() // VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_TIMER_30), audioDefevent(AU_TIMER_30), { beepAgain=2; beep(2); })
//#define AUDIO_TIMER_20() // VOICE_AUDIO_BUZZER(PUSH_SYSTEM_PROMPT(AU_TIMER_20), audioDefevent(AU_TIMER_20), { beepAgain=1; beep(2); })
//#define AUDIO_TIMER_LT10(m, x) // AUDIO_BUZZER(audioDefevent(AU_TIMER_LT10), beep(2))
//#define AUDIO_TIMER_00(m) // AUDIO_BUZZER(audioDefevent(AU_TIMER_00), beep(3))
#define AUDIO_MIX_WARNING(x) AUDIO_BUZZER(audioDefevent(AU_MIX_WARNING_1+x-1), beep(1))
#define AUDIO_POT_MIDDLE() AUDIO_BUZZER(audioDefevent(AU_POT_MIDDLE), beep(2))
#define AUDIO_VARIO_UP() // audioDefevent(AU_KEYPAD_UP)
#define AUDIO_VARIO_DOWN() // audioDefevent(AU_KEYPAD_DOWN)
#define AUDIO_TRIM_MIDDLE() // AUDIO_BUZZER(audio.event(AU_TRIM_MIDDLE, f), beep(2))
#define AUDIO_TRIM_MIN() // AUDIO_BUZZER(audioDefevent(f), beep(2))
#define AUDIO_TRIM_MAX() // AUDIO_BUZZER(audioDefevent(f), beep(2))
#define AUDIO_TRIM_PRESS(val) audioTrimPress(val)
#define AUDIO_PLAY(p) audio.event(p)
#define AUDIO_VARIO(f, t) audio.play(f, t, 0, PLAY_BACKGROUND)
#define AUDIO_DRIVER() audio.driver()
#define AUDIO_HEARTBEAT() audio.heartbeat()
#define IS_AUDIO_BUSY() audio.busy()
#define AUDIO_RESET()
#define AUDIO_FLUSH()
#define PLAY_PHASE_OFF(phase)
#define PLAY_PHASE_ON(phase)
#define PLAY_SWITCH_MOVED(sw)
#define PLAY_LOGICAL_SWITCH_OFF(sw)
#define PLAY_LOGICAL_SWITCH_ON(sw)
#define PLAY_MODEL_NAME()
#define START_SILENCE_PERIOD()
#endif // _AUDIO_AVR_H_
-162
View File
@@ -1,162 +0,0 @@
/*
* 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"
void checkBattery();
uint8_t checkTrim(event_t event);
void perMain()
{
#if defined(SIMU)
doMixerCalculations();
#endif
#if defined(LCD_ST7920)
uint8_t lcdstate=0;
#define IS_LCD_REFRESH_ALLOWED() (0==lcdstate)
#else
#define IS_LCD_REFRESH_ALLOWED() (1)
#endif
uint16_t t0 = getTmr16KHz();
int16_t delta = (nextMixerEndTime - lastMixerDuration) - t0;
if (delta > 0 && delta < MAX_MIXER_DELTA) {
#if defined(PCBSTD) && defined(ROTARY_ENCODER_NAVIGATION)
rotencPoll();
#endif
// @@@ open.20.fsguruh
// SLEEP(); // wouldn't that make sense? should save a lot of battery power!!!
/* for future use; currently very very beta... */
#if defined(POWER_SAVE)
ADCSRA&=0x7F; // disable ADC for power saving
ACSR&=0xF7; // disable ACIE Interrupts
ACSR|=0x80; // disable Analog Comparator
// maybe we disable here a lot more hardware components in future to save even more power
MCUCR|=0x20; // enable Sleep (bit5)
// MCUCR|=0x28; // enable Sleep (bit5) enable ADC Noise Reduction (bit3)
// first tests showed: simple sleep would reduce cpu current from 40.5mA to 32.0mA
// noise reduction sleep would reduce it down to 28.5mA; However this would break pulses in theory
// however with standard module, it will need about 95mA. Therefore the drop to 88mA is not much noticable
do {
asm volatile(" sleep \n\t"); // if _SLEEP() is not defined use this
t0=getTmr16KHz();
delta= (nextMixerEndTime - lastMixerDuration) - t0;
} while ((delta>0) && (delta<MAX_MIXER_DELTA));
// reenabling of the hardware components needed here
MCUCR&=0x00; // disable sleep
ADCSRA|=0x80; // enable ADC
#endif
return;
}
nextMixerEndTime = t0 + MAX_MIXER_DELTA;
// this is a very tricky implementation; lastMixerEndTime is just like a default value not to stop mixcalculations totally;
// the real value for lastMixerEndTime is calculated inside pulses_XXX.cpp which aligns the timestamp to the pulses generated
// nextMixerEndTime is actually defined inside pulses_XXX.h
doMixerCalculations();
t0 = getTmr16KHz() - t0;
lastMixerDuration = t0;
if (t0 > maxMixerDuration) maxMixerDuration = t0;
#if defined(MODULE_ALWAYS_SEND_PULSES)
if (startupWarningState < STARTUP_WARNING_DONE) {
// don't do menu's until throttle and switch warnings are handled
return;
}
#endif
if (eepromIsTransferComplete()) {
if (theFile.isWriting())
theFile.nextWriteStep();
else if (TIME_TO_WRITE())
storageCheck(false);
}
#if defined(SDCARD)
sdMountPoll();
logsWrite();
#endif
event_t evt = getEvent();
evt = checkTrim(evt);
if (evt && (g_eeGeneral.backlightMode & e_backlight_mode_keys)) backlightOn(); // on keypress turn the light on
doLoopCommonActions();
#if defined(TELEMETRY_FRSKY) || defined(TELEMETRY_MAVLINK)
telemetryWakeup();
#endif
#if defined(NAVIGATION_STICKS)
uint8_t sticks_evt = getSticksNavigationEvent();
if (sticks_evt) evt = sticks_evt;
#endif
#if defined(GUI)
const char * warn = warningText;
bool popupMenuActive = (popupMenuNoItems > 0);
if (IS_LCD_REFRESH_ALLOWED()) { // No need to redraw until lcdRefresh_ST7920(0) below completely refreshes the display.
lcdClear();
if (menuEvent) {
menuVerticalPosition = menuEvent == EVT_ENTRY_UP ? menuVerticalPositions[menuLevel] : 0;
menuHorizontalPosition = 0;
evt = menuEvent;
menuEvent = 0;
}
menuHandlers[menuLevel]((warn || popupMenuActive) ? 0 : evt);
if (warn) DISPLAY_WARNING(evt);
#if defined(NAVIGATION_MENUS)
if (popupMenuActive) {
const char * result = runPopupMenu(evt);
if (result) {
popupMenuHandler(result);
}
}
#endif
drawStatusLine();
}
#if defined(LCD_KS108)
lcdRefreshSide();
#elif defined(LCD_ST7920)
lcdstate = lcdRefresh_ST7920(0);
#else
lcdRefresh();
#endif
#endif // defined(GUI)
if (SLAVE_MODE()) {
JACK_PPM_OUT();
}
else {
JACK_PPM_IN();
}
checkBattery();
}
-31
View File
@@ -1,31 +0,0 @@
option(SP22 "SmartieParts 2.2 Backlight support" OFF)
option(PWM_BACKLIGHT "PWM Backlight" OFF)
set(ARCH AVR)
set(MCU atmega64)
set(AVRDUDE_MCU m64)
string(TOLOWER ${PCB} FLAVOUR)
set(EEPROM_VARIANT_NEEDED ON)
set(EEPROM EEPROM_RLC)
set(SDCARD NO)
set(GUI_DIR 128x64)
set(TARGET_DIR 9x)
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps)
add_definitions(-DPCBSTD -DPCB${PCB} -DCPUM64)
set(TARGET_SRC ${TARGET_SRC} board.cpp)
set(GUI_SRC
${GUI_SRC}
model_inputs_mixes.cpp
radio_diagkeys.cpp
radio_diaganas.cpp
)
if(SP22)
add_definitions(-DSP22)
endif()
if(PWM_BACKLIGHT)
add_definitions(-DPWM_BACKLIGHT)
endif()
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
lcd_driver.cpp
)
-364
View File
@@ -1,364 +0,0 @@
/*
* 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
-273
View File
@@ -1,273 +0,0 @@
/*
* 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.
*/
#ifndef _BOARD_STOCK_H_
#define _BOARD_STOCK_H_
#include "../common/avr/board_avr.h"
//
// elev thr
// LV RV
// 2 ^ 4 ^
// 1 2
// | rudd | aile
// <----X--3-> LH <----X--0-> RH
// 6 | 7 1 | 0
// | |
// 3 v 5 v
//
//PORTA 7 6 5 4 3 2 1 0
// O O O O O O O O
// ------------------------ LCD_DAT -----------------------
//
//PORTB 7 6 5 4 3 2 1 0
// O i i i i i i O
// light KEY_LFT KEY_RGT KEY_UP KEY_DWN KEY_EXT KEY_MEN PPM
//
//PORTC 7 6 5 4 3 2 1 0
// - - O O O O O -
// NC NC LCD_E LCD_RNW LCD_A0 LCD_RES LCD_CS1 NC
//
//PORTD 7 6 5 4 3 2 1 0
// i i i i i i i i
// TRM_D_DWN _UP TRM_C_DWN _UP TRM_B_DWN _UP TRM_A_DWN _UP
//
//PORTE 7 6 5 4 3 2 1 0
// i i i i O i i i
// PPM_IN ID2 Trainer Gear Buzzer ElevDR AileDR THRCT
//
//PORTF 7 6 5 4 3 2 1 0
// ai ai ai ai ai ai ai ai
// ANA_ BAT PITT_TRM HOV_THR HOV_PIT STCK_LH STCK_RV STCK_LV STCK_RH
// rud thro elev aile
//PORTG 7 6 5 4 3 2 1 0
// - - - O i i i
// SIM_CTL ID1 Haptic RF_POW RuddDR
// Board driver
void boardInit(void);
#define boardOff() pwrOff()
// Keys
#define KEYS_GPIO_REG_MENU pinb
#define KEYS_GPIO_PIN_MENU (1<<1)
#define KEYS_GPIO_REG_EXIT pinb
#define KEYS_GPIO_PIN_EXIT (1<<2)
#define KEYS_GPIO_REG_RIGHT pinb
#define KEYS_GPIO_PIN_RIGHT (1<<5)
#define KEYS_GPIO_REG_LEFT pinb
#define KEYS_GPIO_PIN_LEFT (1<<6)
#define KEYS_GPIO_REG_UP pinb
#define KEYS_GPIO_PIN_UP (1<<4)
#define KEYS_GPIO_REG_DOWN pinb
#define KEYS_GPIO_PIN_DOWN (1<<3)
#define IS_SHIFT_KEY(index) (false)
#define IS_SHIFT_PRESSED() (false)
// Trims
#define NUM_TRIMS 4
#define NUM_TRIMS_KEYS (NUM_TRIMS * 2)
#define TRIMS_GPIO_REG_LHL pind
#define TRIMS_GPIO_PIN_LHL (1<<6)
#define TRIMS_GPIO_REG_LVD pind
#define TRIMS_GPIO_PIN_LVD (1<<3)
#define TRIMS_GPIO_REG_RVU pind
#define TRIMS_GPIO_PIN_RVU (1<<4)
#define TRIMS_GPIO_REG_RHL pind
#define TRIMS_GPIO_PIN_RHL (1<<1)
#define TRIMS_GPIO_REG_LHR pind
#define TRIMS_GPIO_PIN_LHR (1<<7)
#define TRIMS_GPIO_REG_LVU pind
#define TRIMS_GPIO_PIN_LVU (1<<2)
#define TRIMS_GPIO_REG_RVD pind
#define TRIMS_GPIO_PIN_RVD (1<<5)
#define TRIMS_GPIO_REG_RHR pind
#define TRIMS_GPIO_PIN_RHR (1<<0)
#if defined(CPUM2561)
#define TIMER_16KHZ_VECT TIMER2_OVF_vect
#define COUNTER_16KHZ TCNT2
#define TIMER_10MS_VECT TIMER2_COMPA_vect
#define TIMER_10MS_COMPVAL OCR2A
#define PAUSE_10MS_INTERRUPT() TIMSK2 &= ~(1<<OCIE2A)
#define RESUME_10MS_INTERRUPT() TIMSK2 |= (1<<OCIE2A)
#define PAUSE_PPMIN_INTERRUPT() TIMSK3 &= ~(1<<ICIE3)
#define RESUME_PPMIN_INTERRUPT() TIMSK3 |= (1<<ICIE3)
#define TIMER_AUDIO_VECT TIMER4_COMPA_vect
#define SET_TIMER_AUDIO_CTRL() TCCR4B = (1 << WGM42) | (0b010 << CS40)
#define PAUSE_AUDIO_INTERRUPT() TIMSK4 &= ~(1<<OCIE4A)
#define RESUME_AUDIO_INTERRUPT() TIMSK4 |= (1<<OCIE4A)
#else
#define TIMER_16KHZ_VECT TIMER0_OVF_vect
#define COUNTER_16KHZ TCNT0
#define TIMER_10MS_VECT TIMER0_COMP_vect
#define TIMER_10MS_COMPVAL OCR0
#define PAUSE_10MS_INTERRUPT() TIMSK &= ~(1<<OCIE0)
#define RESUME_10MS_INTERRUPT() TIMSK |= (1<<OCIE0)
#define PAUSE_PPMIN_INTERRUPT() ETIMSK &= ~(1<<TICIE3)
#define RESUME_PPMIN_INTERRUPT() ETIMSK |= (1<<TICIE3)
#define TIMER_AUDIO_VECT TIMER2_OVF_vect
#define SET_TIMER_AUDIO_CTRL() TCCR2 = (0b010 << CS00) // Norm mode, clk/8
#define PAUSE_AUDIO_INTERRUPT() TIMSK &= ~(1<<TOIE2)
#define RESUME_AUDIO_INTERRUPT() TIMSK |= (1<<TOIE2)
#endif
// Power driver (none)
#define pwrCheck() (e_power_on)
#define pwrOff()
#define UNEXPECTED_SHUTDOWN() (mcusr & (1 << WDRF))
// Trainer driver
bool checkSlaveMode();
#define OUT_G_SIM_CTL 4 // 1 : phone-jack=ppm_in
#define SLAVE_MODE() checkSlaveMode()
#define JACK_PPM_OUT() PORTG &= ~(1<<OUT_G_SIM_CTL)
#define JACK_PPM_IN() PORTG |= (1<<OUT_G_SIM_CTL)
// Backlight driver
#define OUT_B_LIGHT 7
#if defined(PWM_BACKLIGHT)
void backlightEnable();
void backlightDisable();
bool isBacklightEnabled();
void backlightFade();
#elif defined(SP22)
#define backlightEnable() PORTB &= ~(1<<OUT_B_LIGHT)
#define backlightDisable() PORTB |= (1<<OUT_B_LIGHT)
#define isBacklightEnabled() (~PORTB & (1<<OUT_B_LIGHT))
#else
#define backlightEnable() PORTB |= (1<<OUT_B_LIGHT)
#define backlightDisable() PORTB &= ~(1<<OUT_B_LIGHT)
#define isBacklightEnabled() (PORTB & (1<<OUT_B_LIGHT))
#endif
#if defined(VOICE) && !defined(SIMU)
#define BACKLIGHT_ENABLE() Voice.Backlight = 1
#define BACKLIGHT_DISABLE() Voice.Backlight = 0
#else
#define BACKLIGHT_ENABLE() backlightEnable()
#define BACKLIGHT_DISABLE() backlightDisable()
#endif
#define OUT_B_PPM 0
#define INP_E_PPM_IN 7
#define INP_E_ID2 6
#define INP_E_Trainer 5
#define INP_E_Gear 4
#define OUT_E_BUZZER 3
#define INP_E_ElevDR 2
#if defined(TELEMETRY_JETI) || defined(TELEMETRY_FRSKY) || defined(TELEMETRY_ARDUPILOT) || defined(TELEMETRY_NMEA) || defined(TELEMETRY_MAVLINK)
#define INP_C_ThrCt 6
#define INP_C_AileDR 7
#else
#define INP_E_ThrCt 0
#define INP_E_AileDR 1
#endif
#define INP_G_ID1 3
#define OUT_G_HAPTIC 2
#define INP_G_RF_POW 1
#define INP_G_RuddDR 0
// Rotary Encoder driver
#if defined(ROTARY_ENCODER_NAVIGATION)
extern uint8_t RotEncoder;
#if defined(TELEMETREZ)
#define ROTENC_DOWN() (RotEncoder != 0)
#else
#define ROTENC_DOWN() (RotEncoder & 0x20)
#endif
#else
#define ROTENC_DOWN() (0)
#endif
// Keys driver
inline uint8_t keyDown()
{
return ((~PINB) & 0x7E) | ROTENC_DOWN();
}
#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED)
enum MuxInput {
MUX_BATT,
MUX_AIL,
MUX_PF7_DIGITAL_MIN = MUX_AIL,
MUX_THR,
MUX_TRM_LV_UP,
MUX_TRM_LV_DWN,
MUX_PF7_DIGITAL_MAX = MUX_TRM_LV_DWN,
MUX_MAX = MUX_PF7_DIGITAL_MAX
};
enum Pf7Digital {
PF7_AIL = MUX_AIL - MUX_PF7_DIGITAL_MIN,
PF7_THR = MUX_THR - MUX_PF7_DIGITAL_MIN,
PF7_TRM_LV_UP = MUX_TRM_LV_UP - MUX_PF7_DIGITAL_MIN,
PF7_TRM_LV_DWN = MUX_TRM_LV_DWN - MUX_PF7_DIGITAL_MIN,
};
extern uint8_t pf7_digital[MUX_PF7_DIGITAL_MAX - MUX_PF7_DIGITAL_MIN + 1];
void processMultiplexAna();
#endif
#if defined(TELEMETRY_MOD_14051_SWAPPED)
#define TRIMS_PRESSED() (~PIND & ~0x0c || pf7_digital[PF7_TRM_LV_UP] || pf7_digital[PF7_TRM_LV_DWN])
#else
#define TRIMS_PRESSED() (~PIND)
#endif
#define KEYS_PRESSED() (~PINB)
// LCD driver
#define PORTA_LCD_DAT PORTA
#define PORTC_LCD_CTRL PORTC
#define OUT_C_LCD_E 5
#define OUT_C_LCD_RnW 4
#define OUT_C_LCD_A0 3
#define OUT_C_LCD_RES 2
#define OUT_C_LCD_CS1 1
// Rotary encoder driver
#if defined(ROTARY_ENCODER_NAVIGATION)
extern uint8_t RotEncoder ;
void rotencPoll();
#endif
// Haptic
#define hapticOn() PORTG |= (1 << OUT_G_HAPTIC)
#define hapticOff() PORTG &= ~(1 << OUT_G_HAPTIC)
// USB fake driver
#define usbPlugged() false
// Buzzer driver
#define buzzerOn() PORTE |= (1 << OUT_E_BUZZER)
#define buzzerOff() PORTE &= ~(1 << OUT_E_BUZZER)
// Battery driver
#define BATTERY_MIN 90 // 9V
#define BATTERY_MAX 120 // 12V
#define BATTERY_WARN 90 // 9V
// Analogs
#define NUM_MOUSE_ANALOGS 0
#define NUM_DUMMY_ANAS 0
#endif // _BOARD_STOCK_H_
-138
View File
@@ -1,138 +0,0 @@
/*
* 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.
*/
void lcdSendCtl(uint8_t val)
{
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#if defined(LCD_MULTIPLEX)
DDRA = 0xFF; // Set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
PORTA_LCD_DAT = val;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
#if defined(LCD_MULTIPLEX)
DDRA = 0x00; // Set LCD_DAT pins to input
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
const static pm_uchar lcdInitSequence[] PROGMEM =
{
//ST7565 eq. : KS0713, SED1565, S6B1713, SPLC501C, NT7532 /34 /38, TL03245
#if defined(LCD_ST7565R)
0xE2, //Initialize the internal functions
0xAE, //DON = 0: display OFF
0xA0, //ADC = 0: normal direction (SEG132->SEG1)
0xA6, //REV = 0: non-reverse display
0xA4, //EON = 0: normal display. non-entire
0xA2, //Select LCD bias
0xC8, //SHL = 1: reverse direction (COM64->COM1)
0x2F, //Control power circuit operation VC=VR=VF=1
0x25, //Select int resistance ratio R2 R1 R0 =5
0x81, //Set reference voltage Mode
0x22, //24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
0xAF, //DON = 1: display ON
0x60 //Set the display start line to zero
#elif defined(LCD_ERC12864FSF)
0xE2, //Initialize the internal functions
0xAE, //DON = 0: display OFF
0xA1, //ADC = 1: reverse direction (SEG132->SEG1)
0xA6, //REV = 0: non-reverse display
0xA4, //EON = 0: normal display. non-entire
0xA3, //Select LCD bias
0xC0, //SHL = 0: normal direction (COM1->COM64)
0x2F, //Control power circuit operation VC=VR=VF=1
0x27, //Select int resistance ratio R2 R1 R0
0x81, //Set reference voltage Mode
0x2D, //24 SV5 SV4 SV3 SV2 SV1 SV0
0xAF //DON = 1: display ON
#else //ST7565P (default 9x LCD)
0xE2, //Initialize the internal functions
0xAE, //DON = 0: display OFF
0xA1, //ADC = 1: reverse direction(SEG132->SEG1)
0xA6, //REV = 0: non-reverse display
0xA4, //EON = 0: normal display. non-entire
0xA2, //Select LCD bias=0
0xC0, //SHL = 0: normal direction (COM1->COM64)
0x2F, //Control power circuit operation VC=VR=VF=1
0x25, //Select int resistance ratio R2 R1 R0 =5
0x81, //Set reference voltage Mode
0x22, //24 SV5 SV4 SV3 SV2 SV1 SV0 = 0x18
0xAF //DON = 1: display ON
#endif
};
void lcdInit()
{
LCD_LOCK();
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); // LCD reset
_delay_us(2);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); // LCD normal operation
_delay_us(1500);
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
}
#if defined(LCD_ERC12864FSF)
g_eeGeneral.contrast = 0x2D;
#else
g_eeGeneral.contrast = 0x22;
#endif
LCD_UNLOCK();
}
void lcdSetRefVolt(uint8_t val)
{
LCD_LOCK();
lcdSendCtl(0x81);
lcdSendCtl(val);
LCD_UNLOCK();
}
void lcdRefresh()
{
LCD_LOCK();
uint8_t * p = displayBuf;
for (uint8_t y=0; y < 8; y++) {
#if defined(LCD_ST7565R)
lcdSendCtl(0x01);
#else
lcdSendCtl(0x04);
#endif
lcdSendCtl(0x10); // Column addr 0
lcdSendCtl( y | 0xB0); //Page addr y
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
#if defined(LCD_MULTIPLEX)
DDRA = 0xFF; // Set LCD_DAT pins to output
#endif
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
for (coord_t x=LCD_W; x>0; --x) {
PORTA_LCD_DAT = *p++;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
}
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
LCD_UNLOCK();
}
-38
View File
@@ -1,38 +0,0 @@
/*
* 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(PCBSTD) && defined(VOICE)
volatile uint8_t LcdLock;
#define LCD_LOCK() LcdLock = 1
#define LCD_UNLOCK() LcdLock = 0
#else
#define LCD_LOCK()
#define LCD_UNLOCK()
#endif
#if defined(LCD_KS108)
#include "targets/9x/lcd_ks108_driver.cpp"
#elif defined(LCD_ST7920)
#include "targets/9x/lcd_st7920_driver.cpp"
#else
#include "targets/9x/lcd_default_driver.cpp"
#endif
-92
View File
@@ -1,92 +0,0 @@
/*
* 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.
*/
#define DISPLAY_SET_COLUMN 0x40
#define DISPLAY_SET_PAGE 0xB8
#define DISPLAY_SET_START 0XC0
#define DISPLAY_ON_CMD 0x3F
#define CS1_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1)
#define CS1_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1)
#define CS2_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS2)
#define CS2_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS2)
#define A0_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0)
#define A0_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0)
#define E_on PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E)
#define E_off PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E)
void lcdPulseEnable(void)
{
E_on;
_delay_us(4);
E_off;
}
void lcdSendCtl(uint8_t val)
{
PORTA_LCD_DAT = val;
A0_off;
lcdPulseEnable();
A0_on;
}
void lcdInit()
{
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD reset
_delay_us(20);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //LCD normal operation
CS1_on;
lcdSendCtl(DISPLAY_ON_CMD);
lcdSendCtl(DISPLAY_SET_START);
CS1_off;
CS2_on;
lcdSendCtl(DISPLAY_ON_CMD);
lcdSendCtl(DISPLAY_SET_START);
CS2_off;
}
void lcdSetRefVolt(uint8_t val)
{
}
void lcdRefreshSide()
{
static uint8_t change = 0; // toggle left or right lcd writing
uint8_t *p;
if (change == 0){ CS2_off; CS1_on; p = displayBuf; change = 1;} // Right
else{ CS1_off; CS2_on; p = displayBuf + 64; change = 0;} // Left
for (uint8_t page=0; page < 8; page++) {
lcdSendCtl(DISPLAY_SET_COLUMN); // Column addr 0
lcdSendCtl( page | DISPLAY_SET_PAGE); //Page addr
A0_on;
for (coord_t x=64; x>0; --x) {
PORTA_LCD_DAT = *p++;
lcdPulseEnable();
}
p += 64;
}
A0_off;
}
void lcdRefresh()
{
lcdRefreshSide();
lcdRefreshSide();
}
-137
View File
@@ -1,137 +0,0 @@
/*
* 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.
*/
void lcdSendCtl(uint8_t val)
{
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_CS1);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW);
PORTA_LCD_DAT = val;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_CS1);
}
const static pm_uchar lcdInitSequence[] PROGMEM =
{
0x30, // Set 8-bit interface
0x36, // Repeat with graphics bit set to ON
0x0C, // Display ON, cursor and blink OFF
0x01, // Clear display, reset address
0x06 // Display ON, no cursor
};
void lcdInit()
{
LCD_LOCK();
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RES); //LCD reset
_delay_us(2);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_RES); //LCD normal operation
_delay_ms(40);
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
_delay_us(80);
}
g_eeGeneral.contrast = 0x22;
LCD_UNLOCK();
}
void lcdSetRefVolt(uint8_t val)
{
}
uint8_t lcdRefresh_ST7920(uint8_t full)
{
LCD_LOCK();
static uint8_t state;
uint8_t yst;
uint8_t yend;
uint8_t y_table[6]={0,13,26,39,52,64};
uint8_t x_addr = 0;
uint8_t y_addr = 0;
uint16_t line_offset = 0;
uint8_t col_offset = 0;
uint8_t bit_count = 0;
uint8_t result;
uint8_t *p;
if(full!=0){
yst=0;
yend=64;
state=0;
}
else{ //Since writing to ST7920 is too slow we need to split it to five bands
yst=y_table[state];
yend=y_table[state+1];
if (state==4){
state=0;
}
else{
state++;
}
}
for (uint8_t y=yst; y<yend; y++) {
x_addr = 0;
//Convert coordinates to weirdly-arranged 128x64 screen (the ST7920 is mapped for 256x32 displays)
if (y > 31) {
y_addr = y - 32; //Because there are only 31 addressable lines in the ST7920
x_addr += 8; //so we overflow x (7 visible bytes per line) to reach the bottom half
}
else {
y_addr = y;
}
lcdSendCtl( 0x80 | y_addr ); //Set Vertical Address
_delay_us(49);
lcdSendCtl( 0x80 | x_addr ); //Set Horizontal Address
_delay_us(49);
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_A0); //HIGH RS and LOW RW will put the LCD to
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_RnW); //Write data register mode
bit_count = y & 0x07; //Count from 0 bis 7 -> 0=0, 1=1..7=7, 8=0, 9=1...
col_offset = 1 << bit_count; //Build a value for a AND operation with the vorrect bitposition
line_offset = ( y / 8 ) * 128; //On the ST7565 there are 8 lines with each 128 bytes width
for (coord_t x=0; x<16; x++) { //Walk through 16 bytes form left to right (128 Pixel)
p = displayBuf + line_offset + ( x * 8 ); //Calculate the position of the first byte im array
// adressing the bytes sequential and set the bits at the correct position merging them with an OR operation to get all bits in one byte
// the position of the LSB is the right-most position of the byte to the ST7920
result = ((*p++ & col_offset)!=0?0x80:0);
result |= ((*p++ & col_offset)!=0?0x40:0);
result |= ((*p++ & col_offset)!=0?0x20:0);
result |= ((*p++ & col_offset)!=0?0x10:0);
result |= ((*p++ & col_offset)!=0?0x08:0);
result |= ((*p++ & col_offset)!=0?0x04:0);
result |= ((*p++ & col_offset) !=0?0x02:0);
result |= ((*p++ & col_offset)!=0?0x01:0);
PORTA_LCD_DAT = result;
PORTC_LCD_CTRL |= (1<<OUT_C_LCD_E);
_delay_us(8);
PORTC_LCD_CTRL &= ~(1<<OUT_C_LCD_E);
_delay_us(49);
}
}
LCD_UNLOCK();
return state;
}
void lcdRefresh()
{
lcdRefresh_ST7920(1);
}
-139
View File
@@ -1,139 +0,0 @@
/*
* 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"
struct t_voice Voice ;
void pushPrompt(uint16_t value)
{
#ifdef SIMU
TRACE("playFile(\"%04d.ad4\")", value);
#endif
struct t_voice *vptr;
vptr = voiceaddress();
if (vptr->VoiceQueueCount < VOICE_Q_LENGTH) {
vptr->VoiceQueue[vptr->VoiceQueueInIndex++] = value;
vptr->VoiceQueueInIndex &= (VOICE_Q_LENGTH - 1);
vptr->VoiceQueueCount += 1;
}
}
void pushCustomPrompt(uint8_t value)
{
pushPrompt(PROMPT_CUSTOM_BASE + value);
}
void pushNumberPrompt(uint8_t value)
{
pushPrompt(PROMPT_I18N_BASE + value);
}
struct t_voice *voiceaddress()
{
return &Voice ;
}
void t_voice::voice_process(void)
{
if (Backlight)
VoiceLatch |= BACKLIGHT_BIT;
else
VoiceLatch &= ~BACKLIGHT_BIT;
if (VoiceState == V_IDLE) {
PORTB |= (1 << OUT_B_LIGHT); // Latch clock high
if (VoiceQueueCount) {
VoiceSerial = VoiceQueue[VoiceQueueOutIndex++];
VoiceQueueOutIndex &= (VOICE_Q_LENGTH - 1);
VoiceQueueCount -= 1;
VoiceTimer = 17;
if (VoiceSerial & 0x8000) { // Looking for sound volume 1F0-1F7
VoiceTimer = 40;
}
VoiceLatch &= ~VOICE_CLOCK_BIT & ~VOICE_DATA_BIT ;
if (VoiceSerial & 0x8000) {
VoiceLatch |= VOICE_DATA_BIT;
}
PORTA_LCD_DAT = VoiceLatch ; // Latch data set
PORTB &= ~(1<<OUT_B_LIGHT) ; // Latch clock low
VoiceCounter = 31;
VoiceState = V_CLOCKING;
}
else {
PORTA_LCD_DAT = VoiceLatch; // Latch data set
PORTB &= ~(1 << OUT_B_LIGHT); // Latch clock low
}
}
else if (VoiceState == V_STARTUP) {
PORTB |= (1<<OUT_B_LIGHT) ; // Latch clock high
VoiceLatch |= VOICE_CLOCK_BIT | VOICE_DATA_BIT ;
PORTA_LCD_DAT = VoiceLatch ; // Latch data set
if (g_blinkTmr10ms > 60) { // Give module 1.4 secs to initialise
VoiceState = V_WAIT_START_BUSY_OFF ;
}
PORTB &= ~(1<<OUT_B_LIGHT) ; // Latch clock low
}
else if (VoiceState != V_CLOCKING) {
uint8_t busy;
PORTA_LCD_DAT = VoiceLatch; // Latch data set
PORTB |= (1 << OUT_B_LIGHT); // Drive high,pullup enabled
DDRB &= ~(1 << OUT_B_LIGHT); // Change to input
// delay to allow input to settle
asm(" rjmp 1f");
asm("1:");
asm(" nop");
asm(" rjmp 1f");
asm("1:");
busy = PINB & 0x80;
DDRB |= (1 << OUT_B_LIGHT); // Change to output
// The next bit guarantees the backlight output gets clocked out
if (VoiceState == V_WAIT_BUSY_ON) { // check for busy processing here
if (busy == 0) { // Busy is active
VoiceState = V_WAIT_BUSY_OFF;
}
else {
if (--VoiceTimer == 0) {
VoiceState = V_WAIT_BUSY_OFF;
}
}
}
else if (VoiceState == V_WAIT_BUSY_OFF) { // check for busy processing here
if (busy) { // Busy is inactive
VoiceTimer = 3;
VoiceState = V_WAIT_BUSY_DELAY;
}
}
else if (VoiceState == V_WAIT_BUSY_DELAY) {
if (--VoiceTimer == 0) {
VoiceState = V_IDLE;
}
}
else if (VoiceState == V_WAIT_START_BUSY_OFF) { // check for busy processing here
if (busy) { // Busy is inactive
VoiceTimer = 20 ;
VoiceState = V_WAIT_BUSY_DELAY ;
}
}
PORTB &= ~(1 << OUT_B_LIGHT); // Latch clock low
}
}
-125
View File
@@ -1,125 +0,0 @@
/*
* 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.
*/
// Bits in VoiceLatch
#define VOICE_CLOCK_BIT 0x01
#define VOICE_DATA_BIT 0x02
#define BACKLIGHT_BIT 0x04
#define SPARE_BIT 0x08
#if defined(CPUM64)
#define VOICE_Q_LENGTH 8
#else
#define VOICE_Q_LENGTH 16
#endif
// Voice states
#define V_STARTUP 0
#define V_IDLE 1
#define V_CLOCKING 2
#define V_WAIT_BUSY_ON 3
#define V_WAIT_BUSY_OFF 4
#define V_WAIT_BUSY_DELAY 5
#define V_WAIT_START_BUSY_OFF 6
#define PROMPT_CUSTOM_BASE 0
#define PROMPT_I18N_BASE 256
#define PROMPT_SYSTEM_BASE 480
struct t_voice
{
uint16_t VoiceQueue[VOICE_Q_LENGTH] ;
uint8_t Backlight ;
uint8_t VoiceLatch ;
uint8_t VoiceCounter ;
uint8_t VoiceTimer ;
uint16_t VoiceSerial ;
uint8_t VoiceState ;
uint8_t VoiceQueueCount ;
uint8_t VoiceQueueInIndex ;
uint8_t VoiceQueueOutIndex ;
void voice_process( void ) ;
};
extern void pushPrompt(uint16_t value);
extern void pushCustomPrompt(uint8_t value);
extern void pushNumberPrompt(uint8_t value);
extern struct t_voice *voiceaddress( void ) ;
extern struct t_voice Voice ;
#define VOLUME_LEVEL_MAX 7
#define VOLUME_LEVEL_DEF 7
#define setScaledVolume(v) pushPrompt((v) | 0xFFF0)
inline bool isPlaying()
{
#if defined(SIMU)
return false;
#else
return Voice.VoiceState != V_IDLE;
#endif
}
/*
* Handle the Voice output
* Check for LcdLocked (in interrupt), and voice_enabled
*/
#define VOICE_DRIVER() \
if ( LcdLock == 0 ) { /* LCD not in use */ \
struct t_voice *vptr; \
vptr = voiceaddress(); \
if ( vptr->VoiceState == V_CLOCKING ) { \
if ( vptr->VoiceTimer ) { \
vptr->VoiceTimer -= 1; \
} \
else { \
PORTB |= (1<<OUT_B_LIGHT); /* Latch clock high */ \
if ((vptr->VoiceCounter & 1) == 0) { \
vptr->VoiceLatch &= ~VOICE_DATA_BIT; \
if ( vptr->VoiceSerial & 0x4000 ) { \
vptr->VoiceLatch |= VOICE_DATA_BIT; \
} \
vptr->VoiceSerial <<= 1; \
} \
vptr->VoiceLatch ^= VOICE_CLOCK_BIT; \
PORTA_LCD_DAT = vptr->VoiceLatch; /* Latch data set */ \
PORTB &= ~(1<<OUT_B_LIGHT); /* Latch clock low */ \
if ( --vptr->VoiceCounter == 0 ) { \
vptr->VoiceState = V_WAIT_BUSY_ON; \
vptr->VoiceTimer = 5; /* 50 mS */ \
} \
} \
} \
}
#define I18N_PLAY_FUNCTION(lng, x, ...) void x(__VA_ARGS__)
#define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__)
#define PUSH_CUSTOM_PROMPT(p, ...) pushCustomPrompt((p))
#define PUSH_NUMBER_PROMPT(p) pushNumberPrompt((p))
#define PUSH_SYSTEM_PROMPT(p) pushNumberPrompt(PROMPT_SYSTEM_BASE-PROMPT_I18N_BASE+(p))
#define PLAY_NUMBER(n, u, a) playNumber((n), (u), (a))
#define PLAY_DURATION(d, att) playDuration((d))
#define PLAY_DURATION_ATT
#define PLAY_TIME
#define IS_PLAY_TIME() (0)
#define IS_PLAYING(id) (0) /* isPlaying() */
#define PLAY_VALUE(v, id) playValue((v))
-144
View File
@@ -1,144 +0,0 @@
option(AUDIO "Audio support" OFF)
set(VOICE "OFF" CACHE STRING "Voice support (OFF/ON/WTV20/JQ6500)")
option(GRAPHICS "Additional graphics" ON)
option(BOLD "Bold font" ON)
option(BATTGRAPH "Battery graph" OFF)
option(HAPTIC "Haptic support" OFF)
set(TELEMETRY_TYPES NONE MAVLINK ARDUPILOT FRSKY FRSKY_SPORT TELEMETREZ NMEA)
set(TELEMETRY "NONE" CACHE STRING "Telemetry Type (${TELEMETRY_TYPES})")
set_property(CACHE TELEMETRY PROPERTY STRINGS ${TELEMETRY_TYPES})
set(TTS "EN" CACHE STRING "TTS language, one of: ${TTS_LANGUAGES}")
set_property(CACHE TTS PROPERTY STRINGS ${TTS_LANGUAGES})
set(LCD_TYPES DEFAULT ST7565P ST7565R ERC12864FSF ST7920 KS108)
set(LCD "DEFAULT" CACHE STRING "LCD type (${LCD_TYPES})")
set_property(CACHE LCD PROPERTY STRINGS ${LCD_TYPES})
set(DSM2 "NO" CACHE STRING "DSM2 support/interface (NO/PPM/SERIAL)")
set_property(CACHE DSM2 PROPERTY STRINGS NO PPM SERIAL)
set(LUA NO)
set(PULSES_SRC pulses_avr.cpp)
set(SRC ${SRC} main_avr.cpp)
set(FIRMWARE_SRC
${FIRMWARE_SRC}
targets/common/avr/adc_driver.cpp
targets/common/avr/eeprom_driver.cpp
)
add_definitions(-DLCD_${LCD})
if(DSM2)
add_definitions(-DDSM2 -DDSM2_${DSM2})
endif()
if(SDCARD)
set(FIRMWARE_SRC ${FIRMWARE_SRC} targets/gruvin9x/diskio.cpp)
endif()
if(AUDIO)
add_definitions(-DAUDIO)
set(SRC ${SRC} audio_avr.cpp)
set(BUZZER OFF)
else()
set(BUZZER ON)
endif()
if(BUZZER)
add_definitions(-DBUZZER)
set(SRC ${SRC} buzzer.cpp)
endif()
if((VOICE STREQUAL ON AND NOT PCB STREQUAL MEGA2560) OR ((VOICE STREQUAL WTV20 OR VOICE STREQUAL JQ6500) AND (PCB STREQUAL MEGA2560)))
add_definitions(-DVOICE)
if(PCB STREQUAL MEGA2560)
add_definitions(-DVOICE_${VOICE})
endif()
set(TARGET_SRC ${TARGET_SRC} voice.cpp)
foreach(LANGUAGE ${TTS_LANGUAGES})
string(TOUPPER ${LANGUAGE} LANGUAGE_CAPITALIZED)
if(TTS STREQUAL ${LANGUAGE_CAPITALIZED})
add_definitions(-DTTS_${LANGUAGE_CAPITALIZED})
set(SRC ${SRC} translations/tts_${LANGUAGE}.cpp)
endif()
endforeach()
endif()
if(GRAPHICS)
add_definitions(-DGRAPHICS)
endif()
if(BOLD)
add_definitions(-DBOLD_FONT)
endif()
if(BATTGRAPH)
add_definitions(-DBATTGRAPH)
endif()
if(HAPTIC)
add_definitions(-DHAPTIC)
set(SRC ${SRC} haptic.cpp)
endif()
if(${TELEMETRY} STREQUAL OFF)
add_definitions(-DTELEMETRY_NONE)
elseif(TELEMETRY STREQUAL ARDUPILOT)
add_definitions(-DTELEMETRY_ARDUPILOT)
set(SRC ${SRC} telemetry/ardupilot.cpp)
elseif(TELEMETRY STREQUAL NMEA)
add_definitions(-DTELEMETRY_NMEA)
set(SRC ${SRC} telemetry/nmea.cpp)
elseif(TELEMETRY STREQUAL JETI)
add_definitions(-DTELEMETRY_JETI)
set(SRC ${SRC} telemetry/jeti.cpp)
elseif(TELEMETRY STREQUAL MAVLINK)
add_definitions(-DTELEMETRY_MAVLINK)
include_directories(${THIRDPARTY_DIR} gui/${GUI_DIR} targets/common/avr)
if(NOT EXISTS ${THIRDPARTY_DIR}/GCS_MAVLink/include_v1.0/mavlink_types.h)
message(WARNING "Warning: ${THIRDPARTY_DIR}/GCS_MAVLink/include_v1.0 is empty, trying to clone submodules")
execute_process(COMMAND git submodule update --init
RESULT_VARIABLE GIT_SUBMODULE_RESULT
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
if(NOT ${GIT_SUBMODULE_RESULT} EQUAL 0)
message(FATAL_ERROR "Error: Cannot clone submodule at ${THIRDPARTY_DIR}/GCS_MAVLink/include_v1.0
If you downloaded this project as a ZIP file, please instead run
'git clone --recursive https://github.com/opentx/opentx.git'")
endif()
endif()
set(FIRMWARE_SRC
${FIRMWARE_SRC}
targets/common/avr/telemetry_driver.cpp
)
set(SRC ${SRC} telemetry/mavlink.cpp)
set(GUI_SRC ${GUI_SRC} view_mavlink.cpp)
math(EXPR EEPROM_VARIANT ${EEPROM_VARIANT}+${MAVLINK_VARIANT})
elseif(TELEMETRY STREQUAL TELEMETREZ)
add_definitions(-DTELEMETRY_TELEMETREZ)
elseif(TELEMETRY STREQUAL FRSKY_SPORT)
add_definitions(-DTELEMETRY_FRSKY_SPORT)
set(SRC ${SRC} crc16.cpp telemetry/frsky_sport.cpp)
endif()
if(TELEMETRY STREQUAL FRSKY OR TELEMETRY STREQUAL FRSKY_SPORT OR TELEMETRY STREQUAL TELEMETREZ)
option(FRSKY_HUB "FrSky Hub support" ON)
option(WS_HOW_HIGH "Winged Shadow sensors support" ON)
option(GAUGES "Telemetry gauges" OFF)
option(GPS "GPS support" ON)
option(VARIO "Vario support" ON)
add_definitions(-DTELEMETRY_FRSKY)
set(SRC ${SRC} telemetry/telemetry.cpp telemetry/telemetry_holders.cpp telemetry/frsky.cpp telemetry/frsky_d.cpp)
set(FIRMWARE_SRC
${FIRMWARE_SRC}
targets/common/avr/telemetry_driver.cpp
)
set(GUI_SRC ${GUI_SRC} view_telemetry.cpp)
if(FRSKY_HUB)
add_definitions(-DFRSKY_HUB)
endif()
if(WS_HOW_HIGH)
add_definitions(-DWS_HOW_HIGH)
endif()
if(GAUGES)
add_definitions(-DGAUGES)
endif()
if(GPS)
add_definitions(-DGPS)
endif()
if(VARIO)
add_definitions(-DVARIO)
set(SRC ${SRC} vario.cpp)
endif()
math(EXPR EEPROM_VARIANT ${EEPROM_VARIANT}+${FRSKY_VARIANT})
endif()
add_definitions(-DTIMERS=2)
-100
View File
@@ -1,100 +0,0 @@
/*
* 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"
#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 structure identical to the one in getADC_bandgap()
#if defined(PCBGRUVIN9X)
// 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(PCBMEGA2560)
#else
ADMUX = 0x1E|ADC_VREF_TYPE; // Switch MUX to internal reference
#endif
}
void getADC()
{
for (uint8_t adc_input=0; adc_input<8; adc_input++) {
uint16_t temp_ana;
ADMUX = adc_input|ADC_VREF_TYPE;
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;
s_anaFilt[adc_input] = temp_ana;
}
#if defined(TELEMETRY_MOD_14051) || defined(TELEMETRY_MOD_14051_SWAPPED)
processMultiplexAna();
#endif
}
void getADC_bandgap()
{
#if defined(PCBGRUVIN9X)
static uint8_t s_bgCheck = 0;
static uint16_t s_bgSum = 0;
ADCSRA |= (1 << ADSC); // request sample
s_bgCheck += 32;
while ((ADCSRA & (1 << ADIF))==0); // wait for sample
ADCSRA |= (1 << ADIF);
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
/*
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 |= (1 << ADSC);
while (ADCSRA & (1 << ADSC));
BandGap = ADC;
#endif
}
-249
View File
@@ -1,249 +0,0 @@
/*
* 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.
*/
#if defined(SIMU)
extern volatile unsigned char pina, pinb, pinc, pind, pine, pinf, ping, pinh, pinj, pinl;
#define PINA ~pina
#define PINB ~pinb
#define PINC ~pinc
#define PIND ~pind
#define PINE ~pine
#define PINF ~pinf
#define PING ~ping
#define PINH ~pinh
#define PINJ ~pinj
#define PINL ~pinl
#else
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "pgmtypes.h"
#include <avr/eeprom.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL // 16 MHz
#include <util/delay.h>
#define pgm_read_adr(address_short) pgm_read_word(address_short)
#include <avr/wdt.h>
#endif
// ADC driver
#define NUM_POTS 3
#define NUM_SLIDERS 0
#define NUM_XPOTS 0
enum Analogs {
STICK1,
STICK2,
STICK3,
STICK4,
POT_FIRST,
POT1 = POT_FIRST,
POT2,
POT3,
POT_LAST = POT3,
#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,
NUM_ANALOGS
};
enum CalibratedAnalogs {
CALIBRATED_STICK1,
CALIBRATED_STICK2,
CALIBRATED_STICK3,
CALIBRATED_STICK4,
CALIBRATED_POT_FIRST,
CALIBRATED_POT1 = CALIBRATED_POT_FIRST,
CALIBRATED_POT2,
CALIBRATED_POT3,
CALIBRATED_POT_LAST = CALIBRATED_POT3,
NUM_CALIBRATED_ANALOGS
};
void adcInit();
void adcPrepareBandgap();
void getADC();
void getADC_bandgap();
// Keys driver
#define NUM_SWITCHES 7
enum EnumKeys
{
KEY_MENU,
KEY_ENTER=KEY_MENU,
KEY_EXIT,
KEY_DOWN,
KEY_MINUS = KEY_DOWN,
KEY_UP,
KEY_PLUS = KEY_UP,
KEY_RIGHT,
KEY_LEFT,
TRM_BASE,
TRM_LH_DWN = TRM_BASE,
TRM_LH_UP,
TRM_LV_DWN,
TRM_LV_UP,
TRM_RV_DWN,
TRM_RV_UP,
TRM_RH_DWN,
TRM_RH_UP,
TRM_LAST = TRM_RH_UP,
#if ROTARY_ENCODERS > 0 || defined(ROTARY_ENCODER_NAVIGATION)
BTN_REa,
#endif
#if ROTARY_ENCODERS > 0
BTN_REb,
#endif
NUM_KEYS
};
enum EnumSwitches
{
SW_ID0,
SW_ID1,
SW_ID2,
SW_THR,
SW_RUD,
SW_ELE,
SW_AIL,
SW_GEA,
SW_TRN,
};
#define IS_3POS(sw) ((sw) == 0)
#define IS_TOGGLE(sw) ((sw) == SWSRC_TRN)
uint8_t keyState(uint8_t index);
uint8_t switchState(uint8_t index);
// LCD driver
#define LCD_W 128
#define LCD_H 64
#define LCD_DEPTH 1
#define LCD_CONTRAST_MIN 10
#define LCD_CONTRAST_MAX 45
#define LCD_CONTRAST_DEFAULT 25
void lcdRefresh(void);
#define lcdRefreshWait()
void lcdSetRefVolt(unsigned char val);
void lcdSetContrast(void);
void lcdInit(void);
#define lcdOff()
#if defined(LCD_KS108)
void lcdRefreshSide();
#endif
#if defined(LCD_ST7920)
uint8_t lcdRefresh_ST7920(uint8_t full);
#endif
// EEPROM driver
#if defined(CPUM2560) || defined(CPUM2561) || defined(CPUM128)
#define EEPROM_SIZE 4096
#else
#define EEPROM_SIZE 2048
#endif
#if defined(SIMU)
void eepromReadBlock(uint8_t * buffer, size_t address, size_t size);
#else
#define eepromReadBlock(buffer, address, size) eeprom_read_block(buffer, (const void *)address, size)
#endif
uint8_t eepromIsTransferComplete();
// USART driver (static register dispatcher)
#define RXD_DDR1 DDRD
#define RXD_DDR_PIN1 DDD2
#define RXD_PORT1 PORTD
#define RXD_PORT_PIN1 PORTD2
#define RXD_DDR0 DDRE
#define RXD_DDR_PIN0 DDE0
#define RXD_PORT0 PORTE
#define RXD_PORT_PIN0 PORTE0
#define _DOR_N(usart_no) DOR ## usart_no
#define _FE_N(usart_no) FE ## usart_no
#define _RXCIE_N(usart_no) RXCIE ## usart_no
#define _RXC_N(usart_no) RXC ## usart_no
#define _RXD_DDR_N(usart_no) RXD_DDR ## usart_no
#define _RXD_DDR_PIN_N(usart_no) RXD_DDR ## usart_no
#define _RXD_PORT_N(usart_no) RXD_DDR ## usart_no
#define _RXD_PORT_PIN_N(usart_no) RXD_DDR ## usart_no
#define _RXEN_N(usart_no) RXEN ## usart_no
#define _TXCIE_N(usart_no) TXCIE ## usart_no
#define _TXEN_N(usart_no) TXEN ## usart_no
#define _U2X_N(usart_no) U2X ## usart_no
#define _UBRRH_N(usart_no) UBRR ## usart_no ## H
#define _UBRRL_N(usart_no) UBRR ## usart_no ## L
#define _UCSRA_N(usart_no) UCSR ## usart_no ## A
#define _UCSRB_N(usart_no) UCSR ## usart_no ## B
#define _UCSRC_N(usart_no) UCSR ## usart_no ## C
#define _UCSZ0_N(usart_no) UCSZ ## usart_no ## 0
#define _UCSZ1_N(usart_no) UCSZ ## usart_no ## 1
#define _UCSZ2_N(usart_no) UCSZ ## usart_no ## 2
#define _UDRIE_N(usart_no) UDRIE ## usart_no
#define _UDR_N(usart_no) UDR ## usart_no
#define _UPE_N(usart_no) UPE ## usart_no
#define _USART_RX_vect_N(usart_no) USART ## usart_no ## _RX_vect
#define _USART_UDRE_vect_N(usart_no) USART ## usart_no ## _UDRE_vect
#define DOR_N(usart_no) _DOR_N(usart_no)
#define FE_N(usart_no) _FE_N(usart_no)
#define RXCIE_N(usart_no) _RXCIE_N(usart_no)
#define RXC_N(usart_no) _RXC_N(usart_no)
#define RXD_DDR_N(usart_no) _RXD_DDR_N(usart_no)
#define RXD_DDR_PIN_N(usart_no) _RXD_DDR_PIN_N(usart_no)
#define RXD_PORT_N(usart_no) _RXD_PORT_N(usart_no)
#define RXD_PORT_PIN_N(usart_no) _RXD_PORT_PIN_N(usart_no)
#define RXEN_N(usart_no) _RXEN_N(usart_no)
#define TXCIE_N(usart_no) _TXCIE_N(usart_no)
#define TXEN_N(usart_no) _TXEN_N(usart_no)
#define U2X_N(usart_no) _U2X_N(usart_no)
#define UBRRH_N(usart_no) _UBRRH_N(usart_no)
#define UBRRL_N(usart_no) _UBRRL_N(usart_no)
#define UCSRA_N(usart_no) _UCSRA_N(usart_no)
#define UCSRB_N(usart_no) _UCSRB_N(usart_no)
#define UCSRC_N(usart_no) _UCSRC_N(usart_no)
#define UCSZ0_N(usart_no) _UCSZ0_N(usart_no)
#define UCSZ1_N(usart_no) _UCSZ1_N(usart_no)
#define UCSZ2_N(usart_no) _UCSZ2_N(usart_no)
#define UDRIE_N(usart_no) _UDRIE_N(usart_no)
#define UDR_N(usart_no) _UDR_N(usart_no)
#define UPE_N(usart_no) _UPE_N(usart_no)
#define USART_RX_vect_N(usart_no) _USART_RX_vect_N(usart_no)
#define USART_UDRE_vect_N(usart_no) _USART_UDRE_vect_N(usart_no)
// Telemetry driver
#if defined(TELEMETRY_MOD_14051_SWAPPED)
#define TLM_USART 1
#else
#define TLM_USART 0
#endif
void telemetryPortInit();
void telemetryPortInit(uint8_t baudrate);
void telemetryTransmitBuffer();
@@ -1,86 +0,0 @@
/*
* 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"
uint16_t eeprom_pointer;
uint8_t * eeprom_buffer_data;
volatile int8_t eeprom_buffer_size = 0;
inline void eeprom_write_byte()
{
EEAR = eeprom_pointer;
EEDR = *eeprom_buffer_data;
// TODO add some define here
#if defined (CPUM2560) || defined(CPUM2561)
EECR |= 1<<EEMPE;
EECR |= 1<<EEPE;
#else
EECR |= 1<<EEMWE;
EECR |= 1<<EEWE;
#endif
eeprom_pointer++;
eeprom_buffer_data++;
}
ISR(EE_READY_vect)
{
if (--eeprom_buffer_size > 0) {
eeprom_write_byte();
}
else {
#if defined(CPUM2560) || defined(CPUM2561)
EECR &= ~(1<<EERIE);
#else
EECR &= ~(1<<EERIE);
#endif
}
}
void eepromStartWrite(uint8_t * buffer, size_t address, size_t size)
{
assert(eeprom_buffer_size == 0);
eeprom_pointer = address;
eeprom_buffer_data = buffer;
eeprom_buffer_size = size+1;
#if defined (CPUM2560) || defined(CPUM2561)
EECR |= (1<<EERIE);
#else
EECR |= (1<<EERIE);
#endif
}
uint8_t eepromIsTransferComplete()
{
return eeprom_buffer_size == 0;
}
void eepromWriteBlock(uint8_t * buffer, size_t address, size_t size)
{
eepromStartWrite(buffer, address, size);
if (s_sync_write) {
while (!eepromIsTransferComplete()) {
wdt_reset();
}
}
}
@@ -1,267 +0,0 @@
/*
* 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(TELEMETRY_FRSKY) || defined(TELEMETRY_MAVLINK)
// KEEP IN SYNC WITH GUI
enum SERIAL_BAUDS
{
BAUD_4800 = 0,
BAUD_9600,
BAUD_14400,
BAUD_19200,
BAUD_38400,
BAUD_57600,
BAUD_58798,
BAUD_76800
};
void telemetryEnableTx(void)
{
UCSRB_N(TLM_USART) |= (1 << TXEN_N(TLM_USART)); // enable TX
}
void telemetryEnableRx(void)
{
UCSRB_N(TLM_USART) |= (1 << RXEN_N(TLM_USART)); // enable RX
UCSRB_N(TLM_USART) |= (1 << RXCIE_N(TLM_USART)); // enable Interrupt
}
void processTelemetryData(uint8_t data);
extern uint8_t telemetryRxBufferCount;
ISR(USART_RX_vect_N(TLM_USART))
{
uint8_t stat;
uint8_t data;
UCSRB_N(TLM_USART) &= ~(1 << RXCIE_N(TLM_USART)); // disable Interrupt
sei();
stat = UCSRA_N(TLM_USART); // USART control and Status Register 0/1 A
/*
bit 7 6 5 4 3 2 1 0
RxC0 TxC0 UDRE0 FE0 DOR0 UPE0 U2X0 MPCM0
RxC0: Receive complete
TXC0: Transmit Complete
UDRE0: USART Data Register Empty
FE0: Frame Error
DOR0: Data OverRun
UPE0: USART Parity Error
U2X0: Double Tx Speed
PCM0: MultiProcessor Comms Mode
*/
// rh = UCSRB_N(TLM_USART); //USART control and Status Register 0/1 B
/*
bit 7 6 5 4 3 2 1 0
RXCIE0 TxCIE0 UDRIE0 RXEN0 TXEN0 UCSZ02 RXB80 TXB80
RxCIE0: Receive Complete int enable
TXCIE0: Transmit Complete int enable
UDRIE0: USART Data Register Empty int enable
RXEN0: Rx Enable
TXEN0: Tx Enable
UCSZ02: Character Size bit 2
RXB80: Rx data bit 8
TXB80: Tx data bit 8
*/
data = UDR_N(TLM_USART); // USART data register 0
if (stat & ((1 << FE_N(TLM_USART)) | (1 << DOR_N(TLM_USART)) | (1 << UPE_N(TLM_USART)))) {
// discard buffer and start fresh on any comms error
telemetryRxBufferCount = 0;
}
else {
processTelemetryData(data);
}
cli() ;
UCSRB_N(TLM_USART) |= (1 << RXCIE_N(TLM_USART)); // enable Interrupt
}
static void uart_4800(void)
{
#undef BAUD
#define BAUD 4800
#include <util/setbaud.h>
UBRRH_N(TLM_USART) = UBRRH_VALUE;
UBRRL_N(TLM_USART) = UBRRL_VALUE;
#if defined USE_2X
UCSRA_N(TLM_USART) |= (1 << U2X_N(TLM_USART)); // enable double speed operation.
#else
UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation.
#endif
}
FORCEINLINE void uart_9600(void)
{
#undef BAUD
#define BAUD 9600
#include <util/setbaud.h>
UBRRH_N(TLM_USART) = UBRRH_VALUE;
UBRRL_N(TLM_USART) = UBRRL_VALUE;
#if defined USE_2X
UCSRA_N(TLM_USART) |= (1 << U2X_N(TLM_USART)); // enable double speed operation.
#else
UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation.
#endif
}
static void uart_14400(void)
{
#undef BAUD
#define BAUD 14400
#include <util/setbaud.h>
UBRRH_N(TLM_USART) = UBRRH_VALUE;
UBRRL_N(TLM_USART) = UBRRL_VALUE;
#if defined USE_2X
UCSRA_N(TLM_USART) |= (1 << U2X_N(TLM_USART)); // enable double speed operation.
#else
UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation.
#endif
}
static void uart_19200(void)
{
#undef BAUD
#define BAUD 19200
#include <util/setbaud.h>
UBRRH_N(TLM_USART) = UBRRH_VALUE;
UBRRL_N(TLM_USART) = UBRRL_VALUE;
#if defined USE_2X
UCSRA_N(TLM_USART) |= (1 << U2X_N(TLM_USART)); // enable double speed operation.
#else
UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation.
#endif
}
static void uart_38400(void)
{
#undef BAUD
#define BAUD 38400
#include <util/setbaud.h>
UBRRH_N(TLM_USART) = UBRRH_VALUE;
UBRRL_N(TLM_USART) = UBRRL_VALUE;
#if defined USE_2X
UCSRA_N(TLM_USART) |= (1 << U2X_N(TLM_USART)); // enable double speed operation.
#else
UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation.
#endif
}
static void uart_57600(void)
{
#undef BAUD
#define BAUD 57600
#include <util/setbaud.h>
UBRRH_N(TLM_USART) = UBRRH_VALUE;
UBRRL_N(TLM_USART) = UBRRL_VALUE;
#if defined USE_2X
UCSRA_N(TLM_USART) |= (1 << U2X_N(TLM_USART)); // enable double speed operation.
#else
UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation.
#endif
}
static void uart_58798(void)
{
UBRRH_N(TLM_USART) = 0;
UBRRL_N(TLM_USART) = 0x010;
UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation.
}
static void uart_76800(void)
{
#undef BAUD
#define BAUD 76800
#include <util/setbaud.h>
UBRRH_N(TLM_USART) = UBRRH_VALUE;
UBRRL_N(TLM_USART) = UBRRL_VALUE;
#if defined USE_2X
UCSRA_N(TLM_USART) |= (1 << U2X_N(TLM_USART)); // enable double speed operation.
#else
UCSRA_N(TLM_USART) &= ~(1 << U2X_N(TLM_USART)); // disable double speed operation.
#endif
}
#if !defined(SIMU)
FORCEINLINE void telemetryPortInit(uint8_t baudrate)
{
RXD_DDR_N(TLM_USART) &= ~(1 << RXD_DDR_PIN_N(TLM_USART)); // set RXD pin as input
RXD_PORT_N(TLM_USART) &= ~(1 << RXD_PORT_PIN_N(TLM_USART)); // disable pullup on RXD pin
switch (baudrate) {
case BAUD_4800:
uart_4800();
break;
case BAUD_9600:
uart_9600();
break;
case BAUD_14400:
uart_14400();
break;
case BAUD_19200:
uart_19200();
break;
case BAUD_38400:
uart_38400();
break;
case BAUD_58798:
uart_58798();
break;
case BAUD_76800:
uart_76800();
break;
default:
uart_57600();
break;
}
// set 8N1
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 (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.
#if defined(TELEMETRY_FRSKY)
telemetryEnableTx(); // enable FrSky-Telemetry emission
#endif
telemetryEnableRx(); // enable FrSky-Telemetry reception
}
#endif
void telemetryTransmitBuffer()
{
UCSRB_N(TLM_USART) |= (1 << UDRIE_N(TLM_USART)); // enable UDRE1 interrupt
}
void telemetryPortInit()
{
telemetryPortInit(BAUD_9600);
}
#endif
-19
View File
@@ -1,19 +0,0 @@
set(ARCH AVR)
set(MCU atmega2560)
set(AVRDUDE_MCU m2560)
string(TOLOWER ${PCB} FLAVOUR)
set(EEPROM EEPROM_RLC)
add_definitions(-DEEPROM_VARIANT=0)
set(SDCARD NO)
set(GUI_DIR 128x64)
set(TARGET_DIR gruvin9x)
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps)
add_definitions(-DPCB${PCB} -DCPUM2560 -DROTARY_ENCODERS=2)
set(TARGET_SRC ${TARGET_SRC} board.cpp)
set(GUI_SRC
${GUI_SRC}
model_inputs_mixes.cpp
radio_diagkeys.cpp
radio_diaganas.cpp
)
set(FIRMWARE_SRC ${FIRMWARE_SRC} targets/9x/lcd_driver.cpp)
-294
View File
@@ -1,294 +0,0 @@
/*
* 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"
void boardInit()
{
#if !defined(SIMU)
// Set up I/O port data directions and initial states
DDRA = 0xff; PORTA = 0x00; // LCD data
DDRB = 0b11000111; PORTB = 0b00111111; // 7:SPKR, 6:PPM_OUT, 5:TrainSW, 4:IDL2_SW, SDCARD[3:MISO 2:MOSI 1:SCK 0:CS]
DDRC = 0x3f; PORTC = 0xc0; // 7:AilDR, 6:EleDR, LCD[5,4,3,2,1], 0:BackLight
DDRD = 0b11000000; PORTD = 0b11111100; // 7:VIB, 6:LED BL, 5:RENC2_PUSH, 4:RENC1_PUSH, 3:RENC2_B, 2:RENC2_A, 1:I2C_SDA, 0:I2C_SCL
DDRE = 0b00001010; PORTE = 0b11110100; // 7:PPM_IN, 6: RENC1_B, 5:RENC1_A, 4:USB_DNEG, 3:BUZZER, 2:USB_DPOS, 1:TELEM_TX, 0:TELEM_RX(pull-up off)
DDRF = 0x00; PORTF = 0x00; // 7-4:JTAG, 3:ADC_REF_1.2V input, 2-0:ADC_SPARE_2-0
DDRG = 0b00010000; PORTG = 0xff; // 7-6:N/A, 5:GearSW, 4: Sim_Ctrl[out], 3:IDL1_Sw, 2:TCut_Sw, 1:RF_Power[in], 0: RudDr_Sw
#if defined(DEBUG) && !defined(VOICE)
DDRH = 0b11111000; PORTH = 0b11010111; // PORTH:7-6 enabled for timing analysis output ... see below ...
#else
DDRH = 0b10111000; PORTH = 0b11010111; // [7:0 DSM/PPM TX-caddy control. 1=PPM, 0=DSM ]
// [6:SOMO14D-BUSY 5:SOMO14D-DATA 4:SOMO14D-CLK 3:SOMO14D-RESET]
// [2:VIB_OPTION -- setting to input for now]
// [1:TxD 0:RxD Spare serial port]
#endif
DDRJ = 0x00; PORTJ = 0xff; // 7-0:Trim switch inputs
DDRK = 0x00; PORTK = 0x00; // anain. No pull-ups!
#ifdef REV0
DDRL = 0x80; PORTL = 0x7f; // 7: Hold_PWR_On (1=On, default Off), 6:Jack_Presence_TTL, 5-0: User Button inputs
#else
DDRL = 0x80; PORTL = 0xff; // 7: Hold_PWR_On (1=On, default Off), 6:Jack_Presence_TTL, 5-0: User Button inputs
#endif
adcInit();
/**** Set up timer/counter 0 ****/
/** Move old 64A Timer0 functions to Timer2 and use WGM on OC0(A) (PB7) for spkear tone output **/
// TCNT0 10ms = 16MHz/1024/156(.25) periodic timer (100ms interval)
// cycles at 9.984ms but includes 1:4 duty cycle correction to /157 to average at 10.0ms
TCCR2B = (0b111 << CS20); // Norm mode, clk/1024 (differs from ATmega64 chip)
OCR2A = 156;
TIMSK2 |= (1<<OCIE2A) | (1<<TOIE2); // Enable Output-Compare and Overflow interrrupts
// Set up Phase correct Waveform Gen. mode, at clk/64 = 250,000 counts/second
// (Higher speed allows for finer control of frquencies in the audio range.)
// Used for audio tone generation
TCCR0B = (1<<WGM02) | (0b011 << CS00);
TCCR0A = (0b01<<WGM00);
/***************************************************/
/* Rotary encoder interrupt set-up (V4 board only) */
// All external interrupts initialise to disabled. But maybe not after
// a WDT or BOD event? So to be safe ...
EIMSK = 0; // disable ALL external interrupts.
// encoder 1
EICRB = (1<<ISC60) | (1<<ISC50); // 01 = interrupt on any edge
EIFR = (3<<INTF5); // clear the int. flag in case it got set when changing modes
// encoder 2
EICRA = (1<<ISC30) | (1<<ISC20); // do the same for encoder 1
EIFR = (3<<INTF2);
#if ROTARY_ENCODERS > 2
EIMSK = (3<<INT5); // enable the ONE rot. enc. ext. int. pairs.
#else
EIMSK = (3<<INT5) | (3<<INT2); // enable the two rot. enc. ext. int. pairs.
#endif
/***************************************************/
#if defined(VOICE)
/*
* SOMO set-up (V4 board only)
*/
OCR4A = 0x1F4; //2ms
TCCR4B = (1 << WGM42) | (0b011 << CS40); // CTC OCR1A, 16MHz / 64 (4us ticks)
TIMSK4 |= (1<<OCIE4A); // Start the interrupt so the unit reset can occur
#endif
#if ROTARY_ENCODERS > 2
//configure uart1 here
DDRD &= ~(1 << 2);
PORTD &= ~(1 << 2);
#define EXTRA_ROTARY_ENCODERS_USART_BAUD 9600UL
UBRR1 = F_CPU/(16*EXTRA_ROTARY_ENCODERS_USART_BAUD)-1;
//9 bit mode
UCSR1C = (1<<USBS1)|(3<<UCSZ10);
UCSR1B = (1<<RXEN1)|(0<<TXEN1)|(1<<UCSZ12);
UCSR1B |= 1 << RXCIE1; //enable interrupt on rx
#endif
#endif // !defined(SIMU)
}
#if ROTARY_ENCODERS > 2
uint8_t vpotToChange = 0;
uint8_t vpot_mod_state = 0;
ISR(USART1_RX_vect)
{
//receive data from extension board
//bit 9 = 1 mean encoder number, following byte with bit 9 = 0 is increment value
/* Get status and 9th bit, then data */
/* from buffer */
uint16_t resh = UCSR1B;
uint16_t resl = UDR1;
uint16_t res = 0;
/* Filter the 9th bit, then return */
resh = (resh >> 1) & 0x01;
res = ((resh << 8) | resl);
if((res == 0x180) | (res == 0x1C0)){ //button REb filter
keys[BTN_REa].input((res & 0x1C0) == 0x1C0);
} else if((res & 0x100) == 0x100){ //rotary filter
vpotToChange = res & 0xEF;
vpot_mod_state = 1;
}
else {
if(vpot_mod_state & (vpotToChange < NUM_ROTARY_ENCODERS))
{
int8_t vpot_inc = res & 0xFF;
if(vpot_inc){
incRotaryEncoder(vpotToChange, vpot_inc);
}
vpot_mod_state = 0;
}
}
}
#endif
uint8_t pwrCheck()
{
#if !defined(SIMU) && !defined(REV0)
if ((PING & 0b00000010) && (~PINL & 0b01000000))
return e_power_off;
#endif
return e_power_on;
}
void pwrOff()
{
#ifndef REV0
PORTL = 0x7f;
#endif
}
uint8_t keyDown()
{
return ((~PINL) & 0x3F) || ROTENC_DOWN();
}
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 = PINC & (1<<INP_C_ElevDR);
break;
case SW_AIL:
result = PINC & (1<<INP_C_AileDR);
break;
case SW_RUD:
result = PING & (1<<INP_G_RuddDR);
break;
// INP_G_ID1 INP_B_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))&& (PINB & (1<<INP_B_ID2));
break;
case SW_ID2:
result = !(PINB & (1<<INP_B_ID2));
break;
case SW_GEA:
result = PING & (1<<INP_G_Gear);
break;
case SW_THR:
result = PING & (1<<INP_G_ThrCt);
break;
case SW_TRN:
result = PINB & (1<<INP_B_Trainer);
break;
default:
break;
}
return result;
}
static const pm_uchar crossTrim[] PROGMEM = {
TRIMS_GPIO_PIN_LHL,
TRIMS_GPIO_PIN_LHR,
TRIMS_GPIO_PIN_LVD,
TRIMS_GPIO_PIN_LVU,
TRIMS_GPIO_PIN_RVD,
TRIMS_GPIO_PIN_RVU,
TRIMS_GPIO_PIN_RHL,
TRIMS_GPIO_PIN_RHR
};
uint8_t trimDown(uint8_t idx)
{
uint8_t in = ~PIND;
return (in & pgm_read_byte(crossTrim+idx));
}
void readKeysAndTrims()
{
uint8_t index = KEY_MENU;
// User buttons ...
uint8_t tin = ~PINL;
uint8_t in;
in = (tin & 0x0f) << 3;
in |= (tin & 0x30) >> 3;
for (int i=1; i<7; i++) {
keys[index].input(in & (1<<i));
++index;
}
// Trims ...
in = ~PINJ;
for (int i=0; i<8; i++) {
// INP_D_TRM_RH_UP 0 .. INP_D_TRM_LH_UP 7
keys[index].input(in & pgm_read_byte(crossTrim+i));
++index;
}
#if defined(ROTARY_ENCODERS)
keys[BTN_REa].input(REA_DOWN());
keys[BTN_REb].input(REB_DOWN());
#endif
}
ISR(INT2_vect)
{
uint8_t input = (PIND & 0x0C);
if (input == 0 || input == 0x0C) incRotaryEncoder(0, -1);
}
ISR(INT3_vect)
{
uint8_t input = (PIND & 0x0C);
if (input == 0 || input == 0x0C) incRotaryEncoder(0, +1);
}
ISR(INT5_vect)
{
uint8_t input = (PINE & 0x60);
if (input == 0 || input == 0x60) incRotaryEncoder(1, +1);
}
ISR(INT6_vect)
{
uint8_t input = (PINE & 0x60);
if (input == 0 || input == 0x60) incRotaryEncoder(1, -1);
}
-184
View File
@@ -1,184 +0,0 @@
/*
* 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.
*/
#ifndef _BOARD_GRUVIN9X_H_
#define _BOARD_GRUVIN9X_H_
#include "../common/avr/board_avr.h"
// Board driver
void boardInit(void);
#define boardOff() pwrOff()
// Keys
#define KEYS_GPIO_REG_MENU pinl
#define KEYS_GPIO_PIN_MENU (1<<4)
#define KEYS_GPIO_REG_EXIT pinl
#define KEYS_GPIO_PIN_EXIT (1<<5)
#define KEYS_GPIO_REG_RIGHT pinl
#define KEYS_GPIO_PIN_RIGHT (1<<2)
#define KEYS_GPIO_REG_LEFT pinl
#define KEYS_GPIO_PIN_LEFT (1<<3)
#define KEYS_GPIO_REG_UP pinl
#define KEYS_GPIO_PIN_UP (1<<1)
#define KEYS_GPIO_REG_DOWN pinl
#define KEYS_GPIO_PIN_DOWN (1<<0)
#define IS_SHIFT_KEY(index) (false)
#define IS_SHIFT_PRESSED() (false)
// Trims
#define NUM_TRIMS 4
#define NUM_TRIMS_KEYS (NUM_TRIMS * 2)
#define TRIMS_GPIO_REG_LHL pinj
#define TRIMS_GPIO_REG_LVD pinj
#define TRIMS_GPIO_REG_RVU pinj
#define TRIMS_GPIO_REG_RHL pinj
#define TRIMS_GPIO_REG_LHR pinj
#define TRIMS_GPIO_REG_LVU pinj
#define TRIMS_GPIO_REG_RVD pinj
#define TRIMS_GPIO_REG_RHR pinj
#define TRIMS_GPIO_PIN_LHL (1<<0)
#define TRIMS_GPIO_PIN_LVD (1<<2)
#define TRIMS_GPIO_PIN_RVU (1<<5)
#define TRIMS_GPIO_PIN_RHL (1<<6)
#define TRIMS_GPIO_PIN_LHR (1<<1)
#define TRIMS_GPIO_PIN_LVU (1<<3)
#define TRIMS_GPIO_PIN_RVD (1<<4)
#define TRIMS_GPIO_PIN_RHR (1<<7)
#define TIMER_16KHZ_VECT TIMER2_OVF_vect
#define COUNTER_16KHZ TCNT2
#define TIMER_10MS_VECT TIMER2_COMPA_vect
#define TIMER_10MS_COMPVAL OCR2A
#define PAUSE_10MS_INTERRUPT() TIMSK2 &= ~(1<<OCIE2A)
#define RESUME_10MS_INTERRUPT() TIMSK2 |= (1<<OCIE2A)
#define PAUSE_PPMIN_INTERRUPT() TIMSK3 &= ~(1<<ICIE3)
#define RESUME_PPMIN_INTERRUPT() TIMSK3 |= (1<<ICIE3)
#define SLAVE_MODE() (PING & (1<<INP_G_RF_POW))
#define JACK_PPM_OUT() PORTG |= (1<<OUT_G_SIM_CTL)
#define JACK_PPM_IN() PORTG &= ~(1<<OUT_G_SIM_CTL)
// SD driver
#define BLOCK_SIZE 512 /* Block Size in Bytes */
#define sdDone()
#define SD_IS_HC() (0)
#define SD_GET_SPEED() (0)
#if !defined(SIMU)
bool sdMounted();
void sdMountPoll();
void sdPoll10ms();
#endif
#define speakerOn() TCCR0A |= (1 << COM0A0)
#define speakerOff() TCCR0A &= ~(1 << COM0A0)
// Backlight driver
#define OUT_C_LIGHT 0
#define backlightEnable() PORTC |= (1<<OUT_C_LIGHT)
#define backlightDisable() PORTC &= ~(1<<OUT_C_LIGHT)
#define isBacklightEnabled() (PORTC & (1<<OUT_C_LIGHT))
#define BACKLIGHT_ENABLE() backlightEnable()
#define BACKLIGHT_DISABLE() backlightDisable()
#define INP_E_PPM_IN 7
#define INP_E_ROT_ENC_1_B 6
#define INP_E_ROT_ENC_1_A 5
#define INP_E_USB_D_PLS 4
#define OUT_E_BUZZER 3
#define INP_E_USB_D_NEG 2
#define INP_E_TELEM_RX 1
#define OUT_E_TELEM_TX 0
#define OUT_D_HAPTIC 7
#define INP_D_SPARE4 6
#define INP_D_ROT_ENC_2_PUSH 5
#define INP_D_ROT_ENC_1_PUSH 4
#define OUT_D_ROT_ENC_2_B 3
#define INP_D_ROT_ENC_2_A 2
#define INP_D_I2C_SCL 1
#define INP_D_I2C_SDA 0
#define INP_G_Gear 5
#define INP_G_ThrCt 2
#define OUT_G_SIM_CTL 4 //1 : phone-jack=ppm_in
#define INP_G_ID1 3
#define INP_G_RF_POW 1
#define INP_G_RuddDR 0
#define INP_C_AileDR 7
#define INP_C_ElevDR 6
#define OUT_B_Speaker 7
#define OUT_B_PPM 6 // will be switched by TCNT1==OCR1B in hardware
#define INP_B_Trainer 5
#define INP_B_ID2 4
#if defined(VOICE)
#define OUT_H_14DRESET 3
#define OUT_H_14DCLK 4
#define OUT_H_14DDATA 5
#define INP_H_14DBUSY 6
#endif
// Keys driver
#define TRIMS_PRESSED() (~PINJ)
#define KEYS_PRESSED() (~PINL) // used only for DBLKEYS code.
// LCD driver
#define PORTA_LCD_DAT PORTA
#define PORTC_LCD_CTRL PORTC
#define OUT_C_LCD_E 5
#define OUT_C_LCD_RnW 4
#define OUT_C_LCD_A0 3
#define OUT_C_LCD_RES 2
#define OUT_C_LCD_CS1 1
// Power driver
uint8_t pwrCheck();
void pwrOff();
#define UNEXPECTED_SHUTDOWN() ((mcusr & (1 << WDRF)) || g_eeGeneral.unexpectedShutdown)
// USB fake driver
#define usbPlugged() false
// Haptic driver
#define hapticOn() PORTD &= ~(1 << OUT_D_HAPTIC)
#define hapticOff() PORTD |= (1 << OUT_D_HAPTIC)
// Rotary encoder driver
#define REA_DOWN() (~PIND & 0x20)
#define REB_DOWN() (~PIND & 0x10)
#define ROTENC_DOWN() (REA_DOWN() || REB_DOWN())
// Buzzer driver
#define buzzerOn() PORTE |= (1 << OUT_E_BUZZER)
#define buzzerOff() PORTE &= ~(1 << OUT_E_BUZZER)
// Battery driver
#define BATTERY_MIN 90 // 9V
#define BATTERY_MAX 120 // 12V
#define BATTERY_WARN 90 // 9V
// Analogs driver
#define NUM_MOUSE_ANALOGS 0
#define NUM_DUMMY_ANAS 0
#endif // _BOARD_GRUVIN9X_H_
-676
View File
@@ -1,676 +0,0 @@
/*
* 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.
*/
/*-----------------------------------------------------------------------*/
/* MMCv3/SDv1/SDv2 (in SPI mode) control module (C)ChaN, 2010 */
/*-----------------------------------------------------------------------*/
/* Only rcvr_spi(), xmit_spi(), sdPoll10mS() and some macros */
/* are platform dependent. */
/*-----------------------------------------------------------------------*/
#include "opentx.h"
#include "diskio.h"
/* Definitions for MMC/SDC command */
#define CMD0 (0) /* GO_IDLE_STATE */
#define CMD1 (1) /* SEND_OP_COND (MMC) */
#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */
#define CMD8 (8) /* SEND_IF_COND */
#define CMD9 (9) /* SEND_CSD */
#define CMD10 (10) /* SEND_CID */
#define CMD12 (12) /* STOP_TRANSMISSION */
#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */
#define CMD16 (16) /* SET_BLOCKLEN */
#define CMD17 (17) /* READ_SINGLE_BLOCK */
#define CMD18 (18) /* READ_MULTIPLE_BLOCK */
#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */
#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
#define CMD24 (24) /* WRITE_BLOCK */
#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */
#define CMD55 (55) /* APP_CMD */
#define CMD58 (58) /* READ_OCR */
/* Card type flags (CardType) */
#define CT_MMC 0x01 /* MMC ver 3 */
#define CT_SD1 0x02 /* SD ver 1 */
#define CT_SD2 0x04 /* SD ver 2 */
#define CT_SDC (CT_SD1|CT_SD2) /* SD */
#define CT_BLOCK 0x08 /* Block addressing */
/* Port Controls (Platform dependent) */
// GCC optimisation should result in a single CBI/SBI instructions here
#if defined (CPUM2560)
# define CS_LOW() PORTB &= ~0x01 /* MMC CS = L */
# define CS_HIGH() PORTB |= 0x01 /* MMC CS = H */
#else
# define CS_LOW() PORTB &= ~0x10 /* MMC CS = L */
# define CS_HIGH() PORTB |= 0x10 /* MMC CS = H */
#endif
#define SOCKPORT PINB /* Socket contact port */
#define SOCKWP 0x00 // not implemented /* Write protect switch */
#define SOCKINS 0x00 // not implemented /* Card detect switch */
#define FCLK_SLOW() SPCR = 0x52 /* Set slow clock (100k-400k) */
#define FCLK_FAST() SPCR = 0x50 /* Set fast clock (depends on the CSD) */
/*--------------------------------------------------------------------------
Module Private Functions
---------------------------------------------------------------------------*/
static volatile
DSTATUS Stat = STA_NOINIT; /* Disk status */
volatile BYTE Timer1, Timer2; /* 100Hz decrement timer */
static
BYTE CardType; /* Card type flags */
#if defined(SIMU)
#define loop_mixer_until_bit_is_set loop_until_bit_is_set
#else
inline void checkMixer()
{
// TODO duplicated code ...
uint16_t t0 = getTmr16KHz();
int16_t delta = (nextMixerEndTime - lastMixerDuration) - t0;
if (delta > 0 && delta < MAX_MIXER_DELTA) return;
nextMixerEndTime = t0 + MAX_MIXER_DELTA;
doMixerCalculations();
t0 = getTmr16KHz() - t0;
lastMixerDuration = t0;
if (t0 > maxMixerDuration) maxMixerDuration = t0;
}
#define loop_mixer_until_bit_is_set(sfr, bit) do { checkMixer(); wdt_reset(); } while (bit_is_clear(sfr, bit))
#endif
/*-----------------------------------------------------------------------*/
/* Transmit a byte to MMC via SPI (Platform dependent) */
/*-----------------------------------------------------------------------*/
#define xmit_spi(dat) SPDR=(dat); loop_mixer_until_bit_is_set(SPSR,SPIF)
/*-----------------------------------------------------------------------*/
/* Receive a byte from MMC via SPI (Platform dependent) */
/*-----------------------------------------------------------------------*/
static
BYTE rcvr_spi (void)
{
SPDR = 0xFF;
loop_mixer_until_bit_is_set(SPSR, SPIF);
return SPDR;
}
/* Alternative macro to receive data fast */
#define rcvr_spi_m(dst) SPDR=0xFF; loop_mixer_until_bit_is_set(SPSR,SPIF); *(dst)=SPDR
/*-----------------------------------------------------------------------*/
/* Wait for card ready */
/*-----------------------------------------------------------------------*/
static
int wait_ready (void) /* 1:OK, 0:Timeout */
{
Timer2 = 50; /* Wait for ready in timeout of 500ms (G: now 50x16ms) */
rcvr_spi();
do
if (rcvr_spi() == 0xFF) return 1;
while (Timer2);
return 0;
}
/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus */
/*-----------------------------------------------------------------------*/
static
void deselect (void)
{
CS_HIGH();
rcvr_spi();
}
/*-----------------------------------------------------------------------*/
/* Select the card and wait for ready */
/*-----------------------------------------------------------------------*/
static
int select (void) /* 1:Successful, 0:Timeout */
{
CS_LOW();
if (!wait_ready()) {
deselect();
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------*/
/* Power Control (Platform dependent) */
/*-----------------------------------------------------------------------*/
/* When the target system does not support socket power control, there */
/* is nothing to do in these functions and chk_power always returns 1. */
static
int power_status(void) /* Socket power state: 0=off, 1=on */
{
return (PORTE & 0x80) ? 0 : 1;
}
static
void power_on (void)
{
// PORTE &= ~0x80; // Socket power on
#ifndef SIMU
for (Timer1 = 2; Timer1; ); // Wait for 20ms
#endif
//PORTB = 0b10110101; // Enable drivers
//DDRB = 0b11000111;
SPCR = 0x52; // Enable SPI function in mode 0
SPSR = 0x00; // G: was 0x01; // SPI 2x mode
}
static
void power_off (void)
{
SPCR = 0; /* Disable SPI function */
// DDRB = 0b11000000; /* Disable drivers */
// PORTB = 0b10110000;
// PORTE |= 0x80; /* Socket power off */
Stat |= STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Receive a data packet from MMC */
/*-----------------------------------------------------------------------*/
static
int rcvr_datablock (
BYTE *buff, /* Data buffer to store received data */
UINT btr /* Byte count (must be multiple of 4) */
)
{
BYTE token;
Timer1 = 20;
do { /* Wait for data packet in timeout of 200ms */
token = rcvr_spi();
} while ((token == 0xFF) && Timer1);
if(token != 0xFE) return 0; /* If not valid data token, retutn with error */
do { /* Receive the data block into buffer */
rcvr_spi_m(buff++);
rcvr_spi_m(buff++);
rcvr_spi_m(buff++);
rcvr_spi_m(buff++);
} while (btr -= 4);
rcvr_spi(); /* Discard CRC */
rcvr_spi();
return 1; /* Return with success */
}
/*-----------------------------------------------------------------------*/
/* Send a data packet to MMC */
/*-----------------------------------------------------------------------*/
static
int xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
BYTE token /* Data/Stop token */
)
{
BYTE resp, wc;
if (!wait_ready()) return 0;
xmit_spi(token); /* Xmit data token */
if (token != 0xFD) { /* Is data token */
wc = 0;
do { /* Xmit the 512 byte data block to MMC */
xmit_spi(*buff++);
xmit_spi(*buff++);
} while (--wc);
xmit_spi(0xFF); /* CRC (Dummy) */
xmit_spi(0xFF);
resp = rcvr_spi(); /* Reveive data response */
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
return 0;
}
return 1;
}
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
/*-----------------------------------------------------------------------*/
static
BYTE send_cmd ( /* Returns R1 resp (bit7==1:Send failed) */
BYTE cmd, /* Command index */
DWORD arg /* Argument */
)
{
BYTE n, res;
if (cmd & 0x80) { /* ACMD<n> is the command sequense of CMD55-CMD<n> */
cmd &= 0x7F;
res = send_cmd(CMD55, 0);
if (res > 1) return res;
}
/* Select the card and wait for ready */
deselect();
if (!select()) return 0xFF;
/* Send command packet */
xmit_spi(0x40 | cmd); /* Start + Command index */
xmit_spi((BYTE)(arg >> 24)); /* Argument[31..24] */
xmit_spi((BYTE)(arg >> 16)); /* Argument[23..16] */
xmit_spi((BYTE)(arg >> 8)); /* Argument[15..8] */
xmit_spi((BYTE)arg); /* Argument[7..0] */
n = 0x01; /* Dummy CRC + Stop */
if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */
if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */
xmit_spi(n);
/* Receive command response */
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
res = rcvr_spi();
while ((res & 0x80) && --n);
return res; /* Return with the response value */
}
/*--------------------------------------------------------------------------
Public Functions
---------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Initialize Disk Drive */
/*-----------------------------------------------------------------------*/
DSTATUS disk_initialize (
BYTE drv /* Physical drive nmuber (0) */
)
{
BYTE n, cmd, ty, ocr[4];
if (drv) return STA_NOINIT; /* Supports only single drive */
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
power_on(); /* Force socket power on */
FCLK_SLOW();
for (n = 10; n; n--) rcvr_spi(); /* 80 dummy clocks */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
Timer1 = 100; /* Initialization timeout of 1000 msec */
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDv2? */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); /* Get trailing return value of R7 resp */
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
while (Timer1 && send_cmd(ACMD41, 1UL << 30)); /* Wait for leaving idle state (ACMD41 with HCS bit) */
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
}
}
} else { /* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) {
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
}
while (Timer1 && send_cmd(cmd, 0)); /* Wait for leaving idle state */
if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Set R/W block length to 512 */
ty = 0;
}
}
CardType = ty;
deselect();
if (ty) { /* Initialization succeded */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
FCLK_FAST();
} else { /* Initialization failed */
power_off();
}
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Get Disk Status */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE drv /* Physical drive number (0) */
)
{
if (drv) return STA_NOINIT; /* Supports only single drive */
return Stat;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..255) */
)
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block read */
if ((send_cmd(CMD17, sector) == 0) /* READ_SINGLE_BLOCK */
&& rcvr_datablock(buff, 512))
count = 0;
}
else { /* Multiple block read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
}
deselect();
return count ? RES_ERROR : RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber (0) */
const BYTE *buff, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..255) */
)
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (Stat & STA_PROTECT) return RES_WRPRT;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block write */
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else { /* Multiple block write */
if (CardType & CT_SDC) send_cmd(ACMD23, count);
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
count = 1;
}
}
deselect();
return count ? RES_ERROR : RES_OK;
}
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl (
BYTE drv, /* Physical drive nmuber (0) */
BYTE ctrl, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
BYTE n, csd[16], *ptr = (BYTE*)buff;
WORD csize;
if (drv) return RES_PARERR;
res = RES_ERROR;
if (ctrl == CTRL_POWER) {
switch (ptr[0]) {
case 0: /* Sub control code (POWER_OFF) */
power_off(); /* Power off */
res = RES_OK;
break;
case 1: /* Sub control code (POWER_GET) */
ptr[1] = (BYTE)power_status();
res = RES_OK;
break;
default :
res = RES_PARERR;
}
}
else {
if (Stat & STA_NOINIT) return RES_NOTRDY;
switch (ctrl) {
case CTRL_SYNC : /* Make sure that no pending write process. Do not remove this or written sector might not left updated. */
if (select()) {
deselect();
res = RES_OK;
}
break;
case GET_SECTOR_COUNT : /* Get number of sectors on the disk (DWORD) */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
csize = csd[9] + ((WORD)csd[8] << 8) + 1;
*(DWORD*)buff = (DWORD)csize << 10;
} else { /* SDC ver 1.XX or MMC*/
n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
*(DWORD*)buff = (DWORD)csize << (n - 9);
}
res = RES_OK;
}
break;
case GET_SECTOR_SIZE : /* Get R/W sector size (WORD) */
*(WORD*)buff = 512;
res = RES_OK;
break;
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
if (CardType & CT_SD2) { /* SDv2? */
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
rcvr_spi();
if (rcvr_datablock(csd, 16)) { /* Read partial block */
for (n = 64 - 16; n; n--) rcvr_spi(); /* Purge trailing data */
*(DWORD*)buff = 16UL << (csd[10] >> 4);
res = RES_OK;
}
}
} else { /* SDv1 or MMCv3 */
if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */
if (CardType & CT_SD1) { /* SDv1 */
*(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
} else { /* MMCv3 */
*(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
}
res = RES_OK;
}
}
break;
case MMC_GET_TYPE : /* Get card type flags (1 byte) */
*ptr = CardType;
res = RES_OK;
break;
case MMC_GET_CSD : /* Receive CSD as a data block (16 bytes) */
if (send_cmd(CMD9, 0) == 0 /* READ_CSD */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_CID : /* Receive CID as a data block (16 bytes) */
if (send_cmd(CMD10, 0) == 0 /* READ_CID */
&& rcvr_datablock(ptr, 16))
res = RES_OK;
break;
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
for (n = 4; n; n--) *ptr++ = rcvr_spi();
res = RES_OK;
}
break;
case MMC_GET_SDSTAT : /* Receive SD statsu as a data block (64 bytes) */
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
rcvr_spi();
if (rcvr_datablock(ptr, 64))
res = RES_OK;
}
break;
default:
res = RES_PARERR;
}
deselect();
}
return res;
}
/*-----------------------------------------------------------------------*/
/* Device Timer Interrupt Procedure */
/*-----------------------------------------------------------------------*/
/* This function must be called in period of 10ms */
void sdPoll10ms()
{
BYTE s;
/*
n = Timer1; // 100Hz decrement timer
if (n) Timer1 = --n;
n = Timer2;
if (n) Timer2 = --n;
*/
if (Timer1) Timer1--;
if (Timer2) Timer2--;
s = Stat;
/* G: Not implemented
if (SOCKWP) // Write protected
s |= STA_PROTECT;
else // Write enabled
s &= ~STA_PROTECT;
if (SOCKINS) // Card inserted
s &= ~STA_NODISK;
else // Socket empty
s |= (STA_NODISK | STA_NOINIT);
*/
s &= ~STA_NODISK;
s &= ~STA_PROTECT;
Stat = s;
}
#if !defined(SIMU)
bool sdMounted()
{
return g_FATFS_Obj.fs_type != 0;
}
void sdMountPoll()
{
static uint8_t mountTimer;
if (mountTimer-- == 0) {
mountTimer = 100;
if (!sdMounted()) {
f_mount(&g_FATFS_Obj, "", 1);
f_chdir(ROOT_PATH);
}
}
}
#endif
FATFS g_FATFS_Obj;
-36
View File
@@ -1,36 +0,0 @@
The ATmega2561 uses quite different bit assignment for its option fuses
Fuse defaults for ATmega64A
Default values for ATmega64 are:
hfuse = 0b10011001 (0x99)
lfuse = 0b11100001 (0xE1)
efuse = 0b11111101 (0xFD)
Preferred values for ATmega64A are:
hfuse = 0x11
lfuse = 0x1F
efuse = 0xff
... which includes EESAVE feature, so that the EEPROM model data does NOT get
erased during chip erase prior to re-programming ... respectively.
- - - - - - - - - - - - - - - - - - - - - -
Fuse defaults for ATmega2560/1 are:
hfuse = 0b10011001 (0x99)
lfuse = 0b01100010 (0x62)
efuse = 0b11111111 (0xFF)
The bit assignments ae quite different from the AT'64A in all cases.
Preferred vale es for ATmega2560/1 are:
hfuse = 0b10011001 (0x11) [OCD enabled, JTAG enabled, WDT disabled :(,
EESAVE enabled, BOOT at 0x0000]
lfuse = 0b01101110 (0xd7) [CKDIV8 disabled, CKOUT disabled,
Full Swing Xtal Osc, 16K CK + 0ms reset,
BOD enabled]
efuse = 0b11111111 (0xfc) [ Brown out detector (BOD) = 4.3V ]
-304
View File
@@ -1,304 +0,0 @@
/*
* 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.
*/
/*--------------------------------------------------------------------------*/
/* RTC controls */
#include "opentx.h"
#include "FatFs/integer.h"
typedef struct {
WORD year; /* 2000..2099 */
BYTE month; /* 1..12 */
BYTE mday; /* 1.. 31 */
BYTE wday; /* 1..7 */
BYTE hour; /* 0..23 */
BYTE min; /* 0..59 */
BYTE sec; /* 0..59 */
} RTC;
#define SCL_LOW() DDRD |= 0x01 /* SCL = LOW */
#define SCL_HIGH() DDRD &= ~0x01 /* SCL = High-Z */
#define SCL_VAL ((PIND & 0x01) ? 1 : 0) /* SCL input level */
#define SDA_LOW() DDRD |= 0x02 /* SDA = LOW */
#define SDA_HIGH() DDRD &= ~0x02 /* SDA = High-Z */
#define SDA_VAL ((PIND & 0x02) ? 1 : 0) /* SDA input level */
/*-------------------------------------------------*/
/* I2C bus protocol */
static
void iic_delay (void)
{
#ifndef SIMU
for (int n = 4; n; n--) PINB;
#endif
}
/* Generate start condition on the IIC bus */
static
void iic_start (void)
{
SDA_HIGH();
iic_delay();
SCL_HIGH();
iic_delay();
SDA_LOW();
iic_delay();
SCL_LOW();
iic_delay();
}
/* Generate stop condition on the IIC bus */
static
void iic_stop (void)
{
SDA_LOW();
iic_delay();
SCL_HIGH();
iic_delay();
SDA_HIGH();
iic_delay();
}
/* Send a byte to the IIC bus */
static
int iic_send (BYTE dat)
{
BYTE b = 0x80;
int ack;
do {
if (dat & b) { /* SDA = Z/L */
SDA_HIGH();
} else {
SDA_LOW();
}
iic_delay();
SCL_HIGH();
iic_delay();
SCL_LOW();
iic_delay();
} while (b >>= 1);
SDA_HIGH();
iic_delay();
SCL_HIGH();
ack = SDA_VAL ? 0 : 1; /* Sample ACK */
iic_delay();
SCL_LOW();
iic_delay();
return ack;
}
/* Receive a byte from the IIC bus */
static
BYTE iic_rcvr (int ack)
{
UINT d = 1;
do {
d <<= 1;
SCL_HIGH();
if (SDA_VAL) d++;
iic_delay();
SCL_LOW();
iic_delay();
} while (d < 0x100);
if (ack) { /* SDA = ACK */
SDA_LOW();
} else {
SDA_HIGH();
}
iic_delay();
SCL_HIGH();
iic_delay();
SCL_LOW();
SDA_HIGH();
iic_delay();
return (BYTE)d;
}
/*-------------------------------------------------*/
/* I2C block read/write controls */
int iic_read (
BYTE dev, /* Device address */
UINT adr, /* Read start address */
UINT cnt, /* Read byte count */
BYTE *buff /* Read data buffer */
)
{
BYTE *rbuff = buff;
int n;
if (!cnt) return 0;
n = 10;
do { /* Select device */
iic_start();
} while (!iic_send(dev) && --n);
if (n) {
if (iic_send((BYTE)adr)) { /* Set start address */
iic_start(); /* Reselect device in read mode */
if (iic_send(dev | 1)) {
do { /* Receive data */
cnt--;
*rbuff++ = iic_rcvr(cnt ? 1 : 0);
} while (cnt);
}
}
}
iic_stop(); /* Deselect device */
return cnt ? 0 : 1;
}
int iic_write (
BYTE dev, /* Device address */
UINT adr, /* Write start address */
UINT cnt, /* Write byte count */
const BYTE *buff /* Data to be written */
)
{
const BYTE *wbuff = buff;
int n;
if (!cnt) return 0;
n = 10;
do { /* Select device */
iic_start();
} while (!iic_send(dev) && --n);
if (n) {
if (iic_send((BYTE)adr)) { /* Set start address */
do { /* Send data */
if (!iic_send(*wbuff++)) break;
} while (--cnt);
}
}
iic_stop(); /* Deselect device */
return cnt ? 0 : 1;
}
/*-------------------------------------------------*/
/* RTC functions */
int g9x_rtcGetTime (RTC *rtc)
{
BYTE buf[8];
if (!iic_read(0xD0, 0, 7, buf)) return 0;
rtc->sec = (buf[0] & 0x0F) + ((buf[0] >> 4) & 7) * 10;
rtc->min = (buf[1] & 0x0F) + (buf[1] >> 4) * 10;
rtc->hour = (buf[2] & 0x0F) + ((buf[2] >> 4) & 3) * 10;
rtc->wday = (buf[2] & 0x07);
rtc->mday = (buf[4] & 0x0F) + ((buf[4] >> 4) & 3) * 10;
rtc->month = (buf[5] & 0x0F) + ((buf[5] >> 4) & 1) * 10;
rtc->year = 2000 + (buf[6] & 0x0F) + (buf[6] >> 4) * 10;
return 1;
}
int g9x_rtcSetTime (const RTC *rtc)
{
BYTE buf[8];
buf[0] = rtc->sec / 10 * 16 + rtc->sec % 10;
buf[1] = rtc->min / 10 * 16 + rtc->min % 10;
buf[2] = rtc->hour / 10 * 16 + rtc->hour % 10;
buf[3] = rtc->wday & 7;
buf[4] = rtc->mday / 10 * 16 + rtc->mday % 10;
buf[5] = rtc->month / 10 * 16 + rtc->month % 10;
buf[6] = (rtc->year - 2000) / 10 * 16 + (rtc->year - 2000) % 10;
return iic_write(0xD0, 0, 7, buf);
}
void rtcGetTime(struct gtm * utm)
{
RTC rtc = {0,0,0,0,0,0,0};
g9x_rtcGetTime(&rtc);
utm->tm_year = rtc.year - TM_YEAR_BASE;
utm->tm_mon = rtc.month - 1;
utm->tm_mday = rtc.mday;
utm->tm_hour = rtc.hour;
utm->tm_min = rtc.min;
utm->tm_sec = rtc.sec;
utm->tm_wday = rtc.wday - 1;
}
void rtcSetTime(const struct gtm * t)
{
g_ms100 = 0; // start of next second begins now
RTC rtc;
rtc.year = t->tm_year + TM_YEAR_BASE;
rtc.month = t->tm_mon + 1;
rtc.mday = t->tm_mday;
rtc.hour = t->tm_hour;
rtc.min = t->tm_min;
rtc.sec = t->tm_sec;
rtc.wday = t->tm_wday + 1;
g9x_rtcSetTime(&rtc);
}
void rtcInit (void)
{
BYTE buf[8]; /* RTC R/W buffer */
UINT adr;
/* Read RTC registers */
if (!iic_read(0xD0, 0, 8, buf)) return; /* IIC error */
if (buf[7] & 0x20) { /* When data has been volatiled, set default time */
/* Clear nv-ram. Reg[8..63] */
memset(buf, 0, 8);
for (adr = 8; adr < 64; adr += 8)
iic_write(0x0D, adr, 8, buf);
/* Reset time to Jan 1, '08. Reg[0..7] */
buf[4] = 1; buf[5] = 1; buf[6] = 8;
iic_write(0x0D, 0, 8, buf);
}
struct gtm utm;
rtcGetTime(&utm);
g_rtcTime = gmktime(&utm);
}
-177
View File
@@ -1,177 +0,0 @@
/*
* 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.
*/
/*
Cam: I did think about implimenting this with an array for the timing durations
like the original bit bang DSM2 code was done but that meant another array
on top of the playlist one, therefore more memory waisted, and because
the playlist must be executed one after another it would mean putting
the code to fill the array in the interrupt (This would be unlike the
old DSM2 code) which seemed to much for the interrupt.
*/
#include "opentx.h"
// Start and stop bits need to be 2ms in duration. Start bit is low, stop bit is high
#define SOMOSSBIT 5 //The 2ms of a stop/start bit
#define SOMOSTOP 48 //This is the needed 2ms (4) + 20ms (40) to allow for the
//point at which the busy flag is checkable + 2ms for saftey (4)
#define SOMOSTART 60 //This is the needed 2ms (4) + 2ms (4) for safety + 26ms (52) for the
//undocumented delay that must exist between playbacks.
#define SOMOBUSY (PINH & 0x40) /* SOMO14D Busy flag */
#define SOMOCLK (PINH & 0x10) /* SOMO14D CLK */
#define QUEUE_LENGTH 10
uint16_t somo14playlist[QUEUE_LENGTH] = {0};
uint16_t somo14command = 0;
uint8_t somo14RIdx = 0;
volatile uint8_t somo14WIdx = 0;
#ifdef SIMU
#define BUSY busy
#else
#define BUSY
#endif
NOINLINE uint8_t SomoWakeup()
{
static uint16_t somo14_current;
static uint8_t i = 0;
static uint8_t busy = 0; // debugging make BOOL when done
static uint8_t startstop = SOMOSSBIT; // Only the first playback can have this short delay
// printf("startstop=%d i=%d\n", startstop, i); fflush(stdout);
// Send no data unless we are either not busy or it's a command
// Only when stop bit is sent do we increment read pointer
// This will happen before the SOMO14D busy flag gets set
// Busy flag happens 20ms after the last data is clocked in
if (i==0 && !busy) {
if (somo14command) { // Allow a command to be send even if the SOMO is busy, i.e. STOP or PAUSE
somo14_current = somo14command;
somo14command = 0;
busy = 1;
}
else if (!SOMOBUSY) {
if (somo14RIdx == somo14WIdx) {
return 1;
}
somo14_current = somo14playlist[somo14RIdx];
somo14RIdx = (somo14RIdx + 1) % QUEUE_LENGTH;
busy = 1;
}
}
// Start and stop bits
if (busy && startstop) {
// Start bit
if (i==0) {
if (startstop < SOMOSSBIT) { // This stretches the time before we start sending data to allow for the
// undocumented delay that must exist between playbacks. Unfortunately the
// device isn't ready even though the busy flag says it is.
PORTH &= ~(1<<OUT_H_14DCLK); // Start Bit, CLK low for 2ms
}
startstop--;
return 0;
}
// Stop bit
if (i==16) {
PORTH &= ~(1<<OUT_H_14DDATA); // Data low
PORTH |= (1<<OUT_H_14DCLK); // Stop Bit, CLK high for 2ms
startstop--;
return 0;
}
}
// After stop bit is sent
// we are done sending so prepair for next
if (i==16 && !startstop) {
// Cam, here I think there is a bug (if we send a "command") somo14RPtr++;
i=0;
busy=0;
startstop = SOMOSTART;
return 0;
}
// Send the data
if (i<16 && busy) {
if (!SOMOCLK) { // Only change data when the CLK is low
startstop =SOMOSTOP;
if (somo14_current & 0x8000) {
PORTH |= (1<<OUT_H_14DDATA); // Data high
}
somo14_current = (somo14_current<<1);
i++;
// Data setup delay
_delay_us(1);
PORTH |= (1<<OUT_H_14DCLK); // CLK high
}
else { // Don't alter after sending last bit in preparation for sending stop bit
PORTH &= ~(1<<OUT_H_14DCLK); // CLK low
PORTH &= ~(1<<OUT_H_14DDATA); // Data low
}
}
return 0;
}
#ifndef SIMU
ISR(TIMER4_COMPA_vect) //Every 0.5ms normally, every 2ms during startup reset
{
static uint8_t reset_dly=4;
static uint8_t reset_pause=150;
if (reset_dly)
{OCR4A=0x1f4; reset_dly--; PORTH &= ~(1<<OUT_H_14DRESET);} // CLK low
else if (reset_pause)
{OCR4A=0x1f4; reset_pause--; PORTH |= (1<<OUT_H_14DRESET);} // RESET high
else
{
OCR4A = 0x7d; // another 0.5ms
TIMSK4 &= ~(1<<OCIE4A); // stop reentrance
sei();
uint8_t finished = SomoWakeup();
cli();
if (!finished) TIMSK4 |= (1<<OCIE4A);
}
}
#endif
void pushPrompt(uint16_t prompt)
{
/* TODO id */
somo14playlist[somo14WIdx] = prompt;
somo14WIdx = (somo14WIdx + 1) % QUEUE_LENGTH;
cli();
TIMSK4 |= (1<<OCIE4A);
sei();
}
bool isPlaying()
{
/* TODO id */
#if defined(SIMU)
return false;
#else
return TIMSK4 & (1<<OCIE4A);
#endif
}
-43
View File
@@ -1,43 +0,0 @@
/*
* 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.
*/
#define PROMPT_CUSTOM_BASE 0
#define PROMPT_I18N_BASE 256
#define PROMPT_SYSTEM_BASE 480
extern void pushPrompt(uint16_t prompt);
extern bool isPlaying();
#define I18N_PLAY_FUNCTION(lng, x, ...) void x(__VA_ARGS__)
#define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__)
#define PUSH_CUSTOM_PROMPT(p, id) pushPrompt(PROMPT_CUSTOM_BASE+(p))
#define PUSH_NUMBER_PROMPT(p) pushPrompt(PROMPT_I18N_BASE+(p))
#define PUSH_SYSTEM_PROMPT(p) pushPrompt(PROMPT_SYSTEM_BASE+(p))
#define PLAY_NUMBER(n, u, a) playNumber((n), (u), (a))
#define PLAY_DURATION(d, att) playDuration((d))
#define PLAY_DURATION_ATT
#define PLAY_TIME
#define IS_PLAY_TIME() (0)
#define IS_PLAYING(id) isPlaying()
#define PLAY_VALUE(v, id) playValue((v))
#define VOLUME_LEVEL_MAX 7
#define VOLUME_LEVEL_DEF 7
#define setScaledVolume(v)
-8
View File
@@ -1,8 +0,0 @@
MEGA2560 board
======================= DESCRIPTION =======================
DIY radio wih :
- Arduino MEGA2560 or compatible
- Gruvin9x features (soft-off, SD-Card, RTC, haptic, voice, rotary encoders)
- LCD 128x64 8 bits parallel mode
- home made case
-23
View File
@@ -1,23 +0,0 @@
option(PWRMANAGE "Pwr Manage" OFF)
option(SDCARD "SD card support" OFF)
option(ROTENC_DIV2 "Rotary encoder resolution/2" OFF)
set(ARCH AVR)
set(MCU atmega2560)
string(TOLOWER ${PCB} FLAVOUR)
set(EEPROM EEPROM_RLC)
add_definitions(-DEEPROM_VARIANT=0)
set(GUI_DIR 128x64)
set(TARGET_DIR mega2560)
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps)
add_definitions(-DPCB${PCB} -DCPUM2560 -DROTARY_ENCODERS=2)
set(TARGET_SRC ${TARGET_SRC} board.cpp)
set(GUI_SRC
${GUI_SRC}
model_inputs_mixes.cpp
radio_diagkeys.cpp
radio_diaganas.cpp
)
set(FIRMWARE_SRC ${FIRMWARE_SRC} targets/9x/lcd_driver.cpp)
if(PWRMANAGE)
add_definitions(-DPWRMANAGE)
endif()
-257
View File
@@ -1,257 +0,0 @@
/*
* 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"
#include "i2c_driver.h"
void boardInit()
{
#if !defined(SIMU)
// Set up I/O port data directions and initial states (unused pin setting : input, pull-up on)
DDRA = 0b11111111; PORTA = 0b00000000; // LCD data
DDRB = 0b01100111; PORTB = 0b10111111; // 7:VoiceBusy, 6:PPM_OUT, 5:SimCTRL, 4:Unused, SDCARD[3:MISO 2:MOSI 1:SCK 0:CS]
DDRC = 0b11111100; PORTC = 0b00000011; // 7-3:LCD, 2:BackLight, 1:ID2_SW, 0:ID1_SW
DDRD = 0b00000000; PORTD = 0b11111111; // 7:AilDR_SW, 6:N/A, 5:N/A, 4:N/A, 3:RENC2_B, 2:RENC2_A, 1:I2C_SDA, 0:I2C_SCL
DDRE = 0b00001010; PORTE = 0b01110100; // 7:PPM_IN, 6:N/A, 5:RENC1_B, 4:RENC1_A, 3:VoiceData, 2:N/A, 1:TELEM_TX, 0:TELEM_RX
DDRF = 0b00000000; PORTF = 0b11111111; // 7-0:Trim switch inputs
DDRG = 0b00100000; PORTG = 0b11011111; // 7:N/A, 6:N/A, 5:VoiceClock, 4:N/A, 3:N/A, 2:TCut_SW, 1:Gear_SW, 0: RudDr_SW
#if defined(DEBUG)
DDRH = 0b01011011; PORTH = 0b11110100; // 7:N/A, 6:RF_Activated, 5:DSC_Activated, 4:Hold_Power, 3:Speaker, 2:N/A, 1:VoiceReset, 0:Haptic
#else
DDRH = 0b00011011; PORTH = 0b11110100; // 7:N/A, 6:RF_Activated, 5:DSC_Activated, 4:Hold_Power, 3:Speaker, 2:N/A, 1:VoiceReset, 0:Haptic
#endif
DDRJ = 0b00000000; PORTJ = 0b11111111; // 7:N/A, 6:N/A, 5:N/A, 4:N/A, 3:N/A, 2:N/A, 1:RENC2_push, 0:RENC1_push
DDRK = 0b00000000; PORTK = 0b00000000; // Analogic input (no pull-ups)
DDRL = 0b00000000; PORTL = 0b11111111; // 7:TRN_SW 6:EleDR_SW, 5:ESC, 4:MENU 3:Keyb_Left, 2:Keyb_Right, 1:Keyb_Up, 0:Keyb_Down
adcInit();
/**** Set up timer/counter 0 ****/
// TCNT0 10ms = 16MHz/1024/156(.25) periodic timer (100ms interval)
// cycles at 9.984ms but includes 1:4 duty cycle correction to /157 to average at 10.0ms
TCCR2B = (0b111 << CS20); // Norm mode, clk/1024 (differs from ATmega64 chip)
OCR2A = 156;
TIMSK2 |= (1<<OCIE2A) | (1<<TOIE2); // Enable Output-Compare and Overflow interrrupts
#if defined(AUDIO)
// TIMER4 set into CTC mode, prescaler 16MHz/64=250 kHz
// Used for audio tone generation
TCCR4B = (0b10<<WGM42) | (0b011 << CS40);
TCCR4A = 0x00;
#endif
#if defined(VOICE_WTV20)
// Voice set-up with TIMER5
OCR5A = 0x1F4; //2ms
TCCR5B = (1 << WGM52) | (0b011 << CS50); // CTC OCR5A
TIMSK5 |= (1<<OCIE5A); // Start the interrupt so the unit reset can occur
#endif
#if defined(VOICE_JQ6500)
// Voice set-up with TIMER5
JQ6500_Serial_on; // Idle state (1)
OCR5A = 0x19; // 0x1A=104µs needed for the 9600Bps serial command
TCCR5B = (1 << WGM52) | (0b011 << CS50); // CTC OCR5A
#endif
/* Rotary encoder interrupt set-up */
EIMSK = 0; // disable ALL external interrupts.
// encoder 1
EICRB = (1<<ISC50) | (1<<ISC40); // 01 = interrupt on any edge
EIFR = (3<<INTF4); // clear the int. flag in case it got set when changing modes
// encoder 2
EICRA = (1<<ISC30) | (1<<ISC20);
EIFR = (3<<INTF2);
EIMSK = (3<<INT4) | (3<<INT2); // enable the two rot. enc. ext. int. pairs.
#if defined(RTCLOCK)
i2c_init(); // hardware I2C init
#endif
#endif // !SIMU
}
uint8_t pwrCheck()
{
#if !defined(SIMU)
if ((~PINH & 0b00100000) && (~PINH & 0b01000000))
return e_power_off;
#endif
return e_power_on;
}
void pwrOff()
{
PORTH &= ~0x10; // PortH-4 set to 0
}
uint8_t keyDown()
{
return ((~PINL) & 0x3F) || ROTENC_DOWN();
}
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 = !(PINL & (1<<INP_L_ElevDR));
break;
case SW_AIL:
result = !(PIND & (1<<INP_D_AileDR));
break;
case SW_RUD:
result = !(PING & (1<<INP_G_RuddDR));
break;
// INP_C_ID1 INP_C_ID2
// ID0 0 1
// ID1 1 1
// ID2 1 0
case SW_ID0:
result = !(PINC & (1<<INP_C_ID1));
break;
case SW_ID1:
result = (PINC & (1<<INP_C_ID1))&& (PINC & (1<<INP_C_ID2));
break;
case SW_ID2:
result = !(PINC & (1<<INP_C_ID2));
break;
case SW_GEA:
result = !(PING & (1<<INP_G_Gear));
break;
case SW_THR:
result = !(PING & (1<<INP_G_ThrCt));
break;
case SW_TRN:
result = !(PINL & (1<<INP_L_Trainer));
break;
default:
break;
}
return result;
}
// Trim switches
static const pm_uchar crossTrim[] PROGMEM = {
TRIMS_GPIO_PIN_LHL,
TRIMS_GPIO_PIN_LHR,
TRIMS_GPIO_PIN_LVD,
TRIMS_GPIO_PIN_LVU,
TRIMS_GPIO_PIN_RVD,
TRIMS_GPIO_PIN_RVU,
TRIMS_GPIO_PIN_RHL,
TRIMS_GPIO_PIN_RHR
};
uint8_t trimDown(uint8_t idx)
{
uint8_t in = ~PINF; //was PIND
return (in & pgm_read_byte(crossTrim+idx));
}
void readKeysAndTrims()
{
uint8_t index = KEY_MENU;
keys[BTN_REa].input(~PINJ & 0x01);
keys[BTN_REb].input(~PINJ & 0x02);
uint8_t tin = ~PINL;
uint8_t in;
in = (tin & 0x0f) << 3;
in |= (tin & 0x30) >> 3;
for (int i=1; i<7; i++) {
keys[index].input(in & (1<<i));
++index;
}
// Trims
in = ~PINF;
for (int i=0; i<8; i++) {
// INP_D_TRM_RH_UP 0 .. INP_D_TRM_LH_UP 7
keys[index].input(in & pgm_read_byte(crossTrim+i));
++index;
}
}
// Rotary encoders increment/decrement (0 = rotary 1, 1 = rotary 2)
ISR(INT4_vect) // Arduino2560 IO02 (portE pin4)
{
uint8_t input = (PINE & 0x30);
#if defined (ROTENC_DIV2)// Rotenc resolution/2
if (input == 0) incRotaryEncoder(0, -1);
#else
if (input == 0 || input == 0x30) incRotaryEncoder(0, -1);
#endif
}
ISR(INT5_vect) // Arduino2560 IO03 (portE pin5)
{
uint8_t input = (PINE & 0x30);
#if defined (ROTENC_DIV2)// Rotenc resolution/2
if (input == 0) incRotaryEncoder(0, +1);
#else
if (input == 0 || input == 0x30) incRotaryEncoder(0, +1);
#endif
}
ISR(INT2_vect) // Arduino2560 IO19 (portD pin2)
{
uint8_t input = (PIND & 0x0C);
#if defined (ROTENC_DIV2)// Rotenc resolution/2
if (input == 0) incRotaryEncoder(1, -1);
#else
if (input == 0 || input == 0x0C) incRotaryEncoder(1, -1);
#endif
}
ISR(INT3_vect) // Arduino2560 IO18 (portD pin3)
{
uint8_t input = (PIND & 0x0C);
#if defined (ROTENC_DIV2)// Rotenc resolution/2
if (input == 0) incRotaryEncoder(1, +1);
#else
if (input == 0 || input == 0x0C) incRotaryEncoder(1, +1);
#endif
}
// RTC driver
void rtcSetTime(const struct gtm * tm)
{
}
-210
View File
@@ -1,210 +0,0 @@
/*
* 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.
*/
#ifndef _BOARD_MEGA2560_H_
#define _BOARD_MEGA2560_H_
#include "../common/avr/board_avr.h"
// Board driver
void boardInit(void);
#define boardOff() pwrOff()
// Keys
#define KEYS_GPIO_REG_MENU pinl
#define KEYS_GPIO_PIN_MENU (1<<4)
#define KEYS_GPIO_REG_EXIT pinl
#define KEYS_GPIO_PIN_EXIT (1<<5)
#define KEYS_GPIO_REG_RIGHT pinl
#define KEYS_GPIO_PIN_RIGHT (1<<2)
#define KEYS_GPIO_REG_LEFT pinl
#define KEYS_GPIO_PIN_LEFT (1<<3)
#define KEYS_GPIO_REG_UP pinl
#define KEYS_GPIO_PIN_UP (1<<1)
#define KEYS_GPIO_REG_DOWN pinl
#define KEYS_GPIO_PIN_DOWN (1<<0)
#define IS_SHIFT_KEY(index) (false)
#define IS_SHIFT_PRESSED() (false)
// Trims
#define NUM_TRIMS 4
#define NUM_TRIMS_KEYS (NUM_TRIMS * 2)
#define TRIMS_GPIO_REG_LHL pinf
#define TRIMS_GPIO_PIN_LHL (1<<7)
#define TRIMS_GPIO_REG_LVD pinf
#define TRIMS_GPIO_PIN_LVD (1<<5)
#define TRIMS_GPIO_REG_RVU pinf
#define TRIMS_GPIO_PIN_RVU (1<<2)
#define TRIMS_GPIO_REG_RHL pinf
#define TRIMS_GPIO_PIN_RHL (1<<1)
#define TRIMS_GPIO_REG_LHR pinf
#define TRIMS_GPIO_PIN_LHR (1<<6)
#define TRIMS_GPIO_REG_LVU pinf
#define TRIMS_GPIO_PIN_LVU (1<<4)
#define TRIMS_GPIO_REG_RVD pinf
#define TRIMS_GPIO_PIN_RVD (1<<3)
#define TRIMS_GPIO_REG_RHR pinf
#define TRIMS_GPIO_PIN_RHR (1<<0)
#define TIMER_16KHZ_VECT TIMER2_OVF_vect
#define COUNTER_16KHZ TCNT2
#define TIMER_10MS_VECT TIMER2_COMPA_vect
#define TIMER_10MS_COMPVAL OCR2A
#define PAUSE_10MS_INTERRUPT() TIMSK2 &= ~(1<<OCIE2A)
#define RESUME_10MS_INTERRUPT() TIMSK2 |= (1<<OCIE2A)
#define PAUSE_PPMIN_INTERRUPT() TIMSK3 &= ~(1<<ICIE3)
#define RESUME_PPMIN_INTERRUPT() TIMSK3 |= (1<<ICIE3)
#define SLAVE_MODE() ~PINH & (1<<INP_H_RF_Activated)
#define JACK_PPM_OUT() PORTB &= ~(1<<OUT_B_SIM_CTL)
#define JACK_PPM_IN() PORTB |= (1<<OUT_B_SIM_CTL)
// Backlight driver
#define backlightEnable() PORTC |= (1<<OUT_C_LIGHT)
#define backlightDisable() PORTC &= ~(1<<OUT_C_LIGHT)
#define isBacklightEnabled() (PORTC & (1<<OUT_C_LIGHT))
#define BACKLIGHT_ENABLE() backlightEnable()
#define BACKLIGHT_DISABLE() backlightDisable()
// SD driver
#define BLOCK_SIZE 512 /* Block Size in Bytes */
#define sdDone()
#define SD_IS_HC() (0)
#define SD_GET_SPEED() (0)
#if !defined(SIMU)
bool sdMounted(void);
void sdMountPoll(void);
void sdPoll10ms(void);
#endif
// Switchs driver
#define INP_C_ID2 1
#define INP_C_ID1 0
#define INP_D_AileDR 7
#define INP_G_ThrCt 2
#define INP_G_Gear 1
#define INP_G_RuddDR 0
#define INP_L_ElevDR 6
#define INP_L_Trainer 7
// Servitudes driver
#define INP_E_PPM_IN 7 //directly used
#define INP_B_VoiceBuzy 7 //directly used
#define OUT_B_PPM 6
#define OUT_B_SIM_CTL 5
#define I_O_B_UNUSED 4 //unused, was Buzzer
#define INP_D_I2C_SCL 1
#define INP_D_I2C_SDA 0
#define OUT_E_VoiceData 3
#define INP_E_TELEM_RX 1
#define OUT_E_TELEM_TX 0
#define OUT_G_VoiceClock 5
#define INP_H_RF_Activated 6
#define INP_H_DSC_Activated 5 //pwrCheck(), directly used
#define INP_H_Hold_Power 4 //pwrCheck(), directly used
#define OUT_H_SpeakerBuzzer 3
#define OUT_H_VoiceReset 1
#define OUT_H_HAPTIC 0
// Rotary encoders driver
#define INP_E_ROT_ENC_1_A 4
#define INP_E_ROT_ENC_1_B 5
#define INP_D_ROT_ENC_2_A 2
#define INP_D_ROT_ENC_2_B 3
#define INP_J_ROT_ENC_1_PUSH 0
#define INP_J_ROT_ENC_2_PUSH 1
#define REA_DOWN() (~PINJ & (1<<INP_J_ROT_ENC_1_PUSH))
#define REB_DOWN() (~PINJ & (1<<INP_J_ROT_ENC_2_PUSH))
#define ROTENC_DOWN() (REA_DOWN() || REB_DOWN())
#define ROTENC_DIV2 // rotary encoders resolution/2
// LCD driver
#define PORTA_LCD_DAT PORTA
#define PORTC_LCD_CTRL PORTC
#if defined(LCD_KS108) // (For KS108 LCD only) MEGA R/W pin always at 0 state in Opentx then
#define OUT_C_LCD_CS2 6 // use this pin to control second KS108 (CS2)
#else // and connect KS108 R/W pin to ground via a 1k resistor
#define OUT_C_LCD_RnW 6
#endif
#define OUT_C_LCD_E 7
#define OUT_C_LCD_A0 5
#define OUT_C_LCD_RES 4
#define OUT_C_LCD_CS1 3
#define OUT_C_LIGHT 2
// DBLKeys driver
#define KEYS_PRESSED() (~PINL)
// Power driver
uint8_t pwrCheck();
void pwrOff();
#if defined(PWRMANAGE)
#define UNEXPECTED_SHUTDOWN() ((mcusr & (1 << WDRF)) || g_eeGeneral.unexpectedShutdown)
#else
#define UNEXPECTED_SHUTDOWN() (mcusr & (1 << WDRF))
#endif
// USB fake driver
#define usbPlugged() false
// Haptic driver
#define hapticOn() PORTH |= (1 << OUT_H_HAPTIC)
#define hapticOff() PORTH &= ~(1 << OUT_H_HAPTIC)
// Buzzer driver
#define buzzerOn() PORTH |= (1 << OUT_H_SpeakerBuzzer)
#define buzzerOff() PORTH &= ~(1 << OUT_H_SpeakerBuzzer)
// Speaker driver
#if defined(AUDIO)
#define speakerOn() TCCR4A |= (1 << COM4A0)
#define speakerOff() TCCR4A &= ~(1 << COM4A0)
#endif
// Voice driver (WTV20)
#if defined(VOICE_WTV20)
#define WTV20_Data_on PORTE |= (1<<OUT_E_VoiceData)
#define WTV20_Data_off PORTE &= ~(1<<OUT_E_VoiceData)
#define WTV20_BUSY (PINB & (1<<INP_B_VoiceBuzy))
#define WTV20_Clock_on PORTG |= (1<<OUT_G_VoiceClock)
#define WTV20_Clock_off PORTG &= ~(1<<OUT_G_VoiceClock)
#define WTV20_CLK (PING & (1<<OUT_G_VoiceClock))
#define WTV20_Reset_on PORTH |= (1<<OUT_H_VoiceReset)
#define WTV20_Reset_off PORTH &= ~(1<<OUT_H_VoiceReset)
#endif
// Voice driver (JQ6500)
#if defined(VOICE_JQ6500)
#define JQ6500_Serial_on PORTE |= (1<<OUT_E_VoiceData)
#define JQ6500_Serial_off PORTE &= ~(1<<OUT_E_VoiceData)
#define JQ6500_BUSY (PINB & (1<<INP_B_VoiceBuzy))
#endif
// Battery driver
#define BATTERY_MIN 90 // 9V
#define BATTERY_MAX 120 // 12V
#define BATTERY_WARN 90 // 9V
// Analogs driver
#define NUM_MOUSE_ANALOGS 0
#define NUM_DUMMY_ANAS 0
#endif // _BOARD_MEGA2560_H_
File diff suppressed because it is too large Load Diff
-196
View File
@@ -1,196 +0,0 @@
/*
* 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.
*/
// From https://github.com/g4lvanix/I2C-master-lib
#include <avr/io.h>
#include <util/twi.h>
#include "i2c_driver.h"
//#define F_SCL 400000UL // SCL frequency
#define F_SCL 800000UL // SCL frequency
#define Prescaler 1
#define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2)
void wait()
{
while( !(TWCR & (1<<TWINT)) );
}
void i2c_init(void)
{
TWBR = (uint8_t)TWBR_val;
}
uint8_t i2c_start(uint8_t address)
{
// reset TWI control register
TWCR = 0;
// transmit START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait for end of transmission
wait();
// check if the start condition was successfully transmitted
if((TWSR & 0xF8) != TW_START){ return 1; }
// load slave address into data register
TWDR = address;
// start transmission of address
TWCR = (1<<TWINT) | (1<<TWEN);
// wait for end of transmission
wait();
// check if the device has acknowledged the READ / WRITE mode
uint8_t twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
return 0;
}
uint8_t i2c_write(uint8_t data)
{
// load data into data register
TWDR = data;
// start transmission of data
TWCR = (1<<TWINT) | (1<<TWEN);
// wait for end of transmission
wait();
if( (TWSR & 0xF8) != TW_MT_DATA_ACK ){ return 1; }
return 0;
}
uint8_t i2c_read_ack(void)
{
// start TWI module and acknowledge data after reception
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
// wait for end of transmission
wait();
// return received data from TWDR
return TWDR;
}
uint8_t i2c_read_nack(void)
{
// start receiving without acknowledging reception
TWCR = (1<<TWINT) | (1<<TWEN);
// wait for end of transmission
wait();
// return received data from TWDR
return TWDR;
}
uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length)
{
if (i2c_start(address | I2C_WRITE)) return 1;
for (uint16_t i = 0; i < length; i++)
{
if (i2c_write(data[i])) return 1;
}
i2c_stop();
return 0;
}
uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length)
{
if (i2c_start(address | I2C_READ)) return 1;
for (uint16_t i = 0; i < (length-1); i++)
{
data[i] = i2c_read_ack();
}
data[(length-1)] = i2c_read_nack();
i2c_stop();
return 0;
}
uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length)
{
if (i2c_start(devaddr | 0x00)) return 1;
i2c_write(regaddr);
for (uint16_t i = 0; i < length; i++)
{
if (i2c_write(data[i])) return 1;
}
i2c_stop();
return 0;
}
uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length)
{
if (i2c_start(devaddr)) return 1;
i2c_write(regaddr);
if (i2c_start(devaddr | 0x01)) return 1;
for (uint16_t i = 0; i < (length-1); i++)
{
data[i] = i2c_read_ack();
}
data[(length-1)] = i2c_read_nack();
i2c_stop();
return 0;
}
void i2c_stop(void)
{
// transmit STOP condition
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}
uint8_t iic_read (
uint8_t dev, /* Device address */
uint8_t adr, /* Read start address */
uint16_t cnt, /* Read uint8_t count */
uint8_t *buff /* Read data buffer */
)
{
uint8_t ret;
ret = i2c_readReg(dev, adr, buff, cnt);
return (!ret);
}
uint8_t iic_write (
uint8_t dev, /* Device address */
uint8_t adr, /* Write start address */
uint16_t cnt, /* Write uint8_t count */
const uint8_t *buff /* Data to be written */
)
{
uint8_t ret;
ret = i2c_writeReg(dev, adr, (uint8_t *)buff, cnt);
return (!ret);
}
-108
View File
@@ -1,108 +0,0 @@
/*
* 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.
*/
// From https://github.com/g4lvanix/I2C-master-lib
#ifndef I2C_DRIVER_H
#define I2C_DRIVER_H
#define I2C_READ 0x01
#define I2C_WRITE 0x00
void i2c_init(void);
uint8_t i2c_start(uint8_t address);
uint8_t i2c_write(uint8_t data);
uint8_t i2c_read_ack(void);
uint8_t i2c_read_nack(void);
uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length);
uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length);
uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length);
uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length);
void i2c_stop(void);
// M2560 functions
uint8_t iic_read (
uint8_t dev, /* Device address */
uint8_t adr, /* Read start address */
uint16_t cnt, /* Read uint8_t count */
uint8_t *buff /* Read data buffer */
);
uint8_t iic_write (
uint8_t dev, /* Device address */
uint8_t adr, /* Write start address */
uint16_t cnt, /* Write uint8_t count */
const uint8_t *buff /* Data to be written */
);
#endif // I2C_DRIVER_H
/*
##### void I2C_init(void)
This function needs to be called only once to set up the correct SCL frequency
for the bus
##### uint8_t I2C_start(uint8_t address)
This function needs to be called any time a connection to a new slave device should
be established. The function returns 1 if an error has occurred, otherwise it returns
0.
The syntax to start a operation write to a device is either:
`I2C_start(SLAVE_ADDRESS+I2C_WRITE);`
or
`I2C_start(SLAVE_WRITE_ADDRESS);`
The syntax to start a read operation from a device is either:
`I2C_start(SLAVE_ADDRESS+I2C_READ);`
or
`I2C_start(SLAVE_READ_ADDRESS);`
##### uint8_t I2C_write(uint8_t data)
This function is used to write data to the currently active device.
The only parameter this function takes is the 8 bit unsigned integer to be sent.
The function returns 1 if an error has occurred, otherwise it returns
0.
##### uint8_t I2C_read_ack(void)
This function is used to read one byte from a device and request another byte of data
after the transmission is complete by sending the acknowledge bit.
This function returns the received byte.
##### uint8_t I2C_read_nack(void)
This function is used to read one byte from a device an then not requesting another
byte and therefore stopping the current transmission.
This function returns the received byte.
##### uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length);
This function is used to transmit [length] number of bytes to an I2C device with the given
I2C address from [data].
The [address] passed to this function is the 7-bit slave address, left
shifted by one bit (i.e. 7-bit slave address is `0x2F` -> `(0x2F)<<1` = `0x5E`)
##### uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length);
This function is used to read [length] number of bytes from the I2C device with the given
I2C address into the [data].
The [address] passed to this function is the 7-bit slave address, left
shifted by one bit (i.e. 7-bit slave address is `0x2F` -> `(0x2F)<<1` = `0x5E`)
##### void I2C_stop(void)
This function disables the TWI peripheral completely
and therefore disconnects the device from the bus.
*/
-27
View File
@@ -1,27 +0,0 @@
/*
* 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(VOICE_WTV20)
#include "targets/mega2560/voice_wtv20.cpp"
#elif defined(VOICE_JQ6500)
#include "targets/mega2560/voice_jq6500.cpp"
#endif
-43
View File
@@ -1,43 +0,0 @@
/*
* 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.
*/
#define PROMPT_CUSTOM_BASE 0
#define PROMPT_I18N_BASE 256
#define PROMPT_SYSTEM_BASE 480
extern void pushPrompt(uint16_t prompt);
extern bool isPlaying();
#define I18N_PLAY_FUNCTION(lng, x, ...) void x(__VA_ARGS__)
#define PLAY_FUNCTION(x, ...) void x(__VA_ARGS__)
#define PUSH_CUSTOM_PROMPT(p, id) pushPrompt(PROMPT_CUSTOM_BASE+(p))
#define PUSH_NUMBER_PROMPT(p) pushPrompt(PROMPT_I18N_BASE+(p))
#define PUSH_SYSTEM_PROMPT(p) pushPrompt(PROMPT_SYSTEM_BASE+(p))
#define PLAY_NUMBER(n, u, a) playNumber((n), (u), (a))
#define PLAY_DURATION(d, att) playDuration((d))
#define PLAY_DURATION_ATT
#define PLAY_TIME
#define IS_PLAY_TIME() (0)
#define IS_PLAYING(id) isPlaying()
#define PLAY_VALUE(v, id) playValue((v))
#define VOLUME_LEVEL_MAX 7
#define VOLUME_LEVEL_DEF 7
#define setScaledVolume(v)
-109
View File
@@ -1,109 +0,0 @@
/*
* 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.
*/
// JQ6500 mp3 module driver
// 6 X 10 (bits) X 104µs = 6.24 mS to send a playfile command
#include "opentx.h"
#define QUEUE_LENGTH 16*2 //bytes
enum JQ6500_State
{
START = 0x7E, //Start
NUMBY = 0x04, //Num bytes follow
SELEC = 0X03, //Select file
FILEH = 0x00, //Dummy file
FILEL = 0x01, //Dummy file
TERMI = 0xEF //Termination
};
JQ6500_State state = START;
uint8_t JQ6500_playlist[QUEUE_LENGTH] = {0};
volatile uint8_t JQ6500_InputIndex = 0;
uint8_t JQ6500_PlayIndex = 0;
bool isPlaying()
{
/* interrupts active on Output Compare A Match ? */
#if defined(SIMU)
return false;
#else
return (TIMSK5 & (1<<OCIE5A));
#endif
}
void pushPrompt(uint16_t prompt)
{
// if mute active => no voice
if (g_eeGeneral.beepMode == e_mode_quiet) return;
++prompt; // With SDformatter, first FAT address = 1 ? Not all th time ??
/* Load playlist and activate interrupt */
JQ6500_playlist[JQ6500_InputIndex] = (uint8_t)(prompt >> 8); // MSB first
++JQ6500_InputIndex;
JQ6500_playlist[JQ6500_InputIndex] = (uint8_t)(prompt & 0xFF); // LSB after
++JQ6500_InputIndex;
if (JQ6500_InputIndex == QUEUE_LENGTH) JQ6500_InputIndex = 0;
if (!isPlaying()) {
TCNT5=0;
OCR5A = 0xFA;
TIMSK5 |= (1<<OCIE5A); // enable interrupts on Output Compare A Match
}
}
uint8_t JQ6500_sendbyte(uint8_t Data_byte)
{
static uint8_t i = 0;
if (!i) { JQ6500_Serial_off; ++i; return 0; } // serial start bit
if (i==9) { JQ6500_Serial_on; i = 0; return 1; } // serial stop bit
if ((Data_byte >> (i-1)) & 0x01) { JQ6500_Serial_on;} else { JQ6500_Serial_off;} // send data bits
++i;
return 0;
}
#if !defined(SIMU)
ISR(TIMER5_COMPA_vect) // every 104µS
{
sei();
if (state == START) { OCR5A = 0x19; if (JQ6500_BUSY) return; if (JQ6500_sendbyte(state)) { state = NUMBY; return; } }
if (state == NUMBY) { if (JQ6500_sendbyte(state)) { state = SELEC; return; } }
if (state == SELEC) { if (JQ6500_sendbyte(state)) { state = FILEH; return; } }
if (state == FILEH) { if (JQ6500_sendbyte(JQ6500_playlist[JQ6500_PlayIndex])) { ++JQ6500_PlayIndex; state = FILEL; return; } }
if (state == FILEL) { if (JQ6500_sendbyte(JQ6500_playlist[JQ6500_PlayIndex])) { ++JQ6500_PlayIndex; state = TERMI; return; } }
if (state == TERMI) {
if (JQ6500_sendbyte(state)) {
state = START;
if (JQ6500_PlayIndex == QUEUE_LENGTH) JQ6500_PlayIndex = 0;
if (JQ6500_PlayIndex == JQ6500_InputIndex) { OCR5A = 0x19; TIMSK5 &= ~(1<<OCIE5A); } // stop reentrance
return; }
}
cli();
}
#endif
-172
View File
@@ -1,172 +0,0 @@
/*
* 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.
*/
// WTV20SDMini module driver, adapted from somo14d driver (gruvin9x board)
#include "opentx.h"
// Start and stop bits need to be 2ms in duration. Start bit is low, stop bit is high
#define WTV20_STOP_TIME 84 // This is the needed 2ms (4) + 40ms (80) to allow for the
// point at which the busy flag is checkable + 2ms for saftey (4)
#define WTV20_START_TIME 5 // The 2ms of a stop/start bit
enum WTV20_State
{
RESET,
RESETPAUSE,
PAUSE,
SENDSTART,
SENDDATA,
SENDSTOP
};
#define QUEUE_LENGTH 10
uint16_t WTV20_playlist[QUEUE_LENGTH] = {0};
volatile uint8_t WTV20_InputIndex = 0;
uint8_t WTV20_PlayIndex = 4; // Also used for reset,(save 2 static uint8_t)
uint8_t Startstop = WTV20_START_TIME;
uint16_t WTV20_current = 0;
uint8_t state = RESET;
void WTV20_sendstart()
{
WTV20_Clock_off; // Start Bit, CLK low for 2ms
--Startstop;
if (!Startstop) state = SENDDATA;
}
void WTV20_senddata()
{
static uint8_t i = 0;
if (!WTV20_CLK) {
// Only change data when the CLK is low
if (WTV20_current & 0x8000) {
WTV20_Data_on; // Data high
}
WTV20_current = (WTV20_current << 1);
++i;
_delay_us(1); // Data setup delay
WTV20_Clock_on; // CLK high
}
else {
// Don't alter after sending last bit in preparation for sending stop bit
WTV20_Clock_off; // CLK low
WTV20_Data_off; // Data low
}
if (i == 16) { i = 0; Startstop = WTV20_STOP_TIME; state = SENDSTOP; }
}
void WTV20_sendstop()
{
WTV20_Data_off; // Data low
WTV20_Clock_on; // Stop Bit, CLK high for 2ms
--Startstop;
if (!Startstop && !WTV20_BUSY) state = PAUSE;
}
void pushPrompt(uint16_t prompt)
{
// if mute active => no voice
if (g_eeGeneral.beepMode == e_mode_quiet) return;
/* Load playlist and activate interrupt */
WTV20_playlist[WTV20_InputIndex] = prompt;
++WTV20_InputIndex;
if (WTV20_InputIndex == QUEUE_LENGTH) WTV20_InputIndex = 0;
if (!isPlaying()) {
TIMSK5 |= (1<<OCIE5A); // enable interrupts on Output Compare A Match
}
}
bool isPlaying()
{
/* interrupts active on Output Compare A Match ? */
#if defined(SIMU)
return false;
#else
return (TIMSK5 & (1<<OCIE5A));
#endif
}
#if !defined(SIMU)
ISR(TIMER5_COMPA_vect) // every 0.5ms normally, every 2ms during startup reset
{
sei();
if (state == PAUSE) {
if (WTV20_PlayIndex == WTV20_InputIndex) {
TIMSK5 &= ~(1<<OCIE5A); // stop reentrance
TCNT5=0; // reset timer
return; // nothing else to play
}
else {
WTV20_current = WTV20_playlist[WTV20_PlayIndex];
++WTV20_PlayIndex;
if (WTV20_PlayIndex == QUEUE_LENGTH) WTV20_PlayIndex = 0;
Startstop = WTV20_START_TIME;
state = SENDSTART;
}
} // end PAUSE
if (state == SENDSTART) {
WTV20_sendstart();
return;
}
if (state == SENDDATA) {
WTV20_senddata();
return;
}
if (state == SENDSTOP) {
WTV20_sendstop();
return;
}
if (state == RESET) {
if (WTV20_PlayIndex) { // WTV20_PlayIndex used as reset counter
// OCR5A=0x1f4; setted in board_mega2560.cpp
WTV20_Reset_off;
WTV20_Data_off;
WTV20_Clock_on;
--WTV20_PlayIndex;
return;
} // RESET low
else {
state = RESETPAUSE;
return;
}
}
if (state == RESETPAUSE) {
WTV20_Reset_on; // RESET high
if (!WTV20_BUSY) {
state = PAUSE;
OCR5A = 0x7d; // 0.5 ms after init
}
}
cli();
}
#endif