mirror of
https://github.com/opentx/opentx.git
synced 2025-07-23 08:15:17 +03:00
[MEGA2560] Add KS108 lcd + voice + "far" splash for firmware > 64Kb (#3515)
This commit is contained in:
parent
907b6337fc
commit
5f65217124
25 changed files with 1250 additions and 726 deletions
|
@ -17,3 +17,4 @@ Karl Szmutny
|
|||
Michal Hlavinka
|
||||
Pat Mackenzie
|
||||
Michael Byrne
|
||||
Christophe Brision (Ingwie)
|
||||
|
|
|
@ -1160,6 +1160,7 @@ void addOpenTxLcdOptions(OpenTxFirmware * firmware)
|
|||
{ "ST7565R", QObject::tr("ST7565R LCD or compatible") },
|
||||
{ "ERC12864FSF", QObject::tr("ERC12864FSF LCD") },
|
||||
{ "ST7920", QObject::tr("ST7920 LCD") },
|
||||
{ "KS108", QObject::tr("KS108 LCD") },
|
||||
{ NULL }
|
||||
};
|
||||
firmware->addOptions(lcd_options);
|
||||
|
@ -1433,7 +1434,7 @@ void registerOpenTxFirmwares()
|
|||
firmware->addOption("nocurves", QObject::tr("Disable curves menus"));
|
||||
firmware->addOption("sdcard", QObject::tr("Support for SD memory card"));
|
||||
firmware->addOption("audio", QObject::tr("Support for radio modified with regular speaker"));
|
||||
//firmware->addOption("voice", QObject::tr("Used if you have modified your radio with voice mode"));
|
||||
firmware->addOption("voice", QObject::tr("Used if you have modified your radio with voice mode"));
|
||||
firmware->addOption("haptic", QObject::tr("Used if you have modified your radio with haptic mode"));
|
||||
firmware->addOption("ppmca", QObject::tr("PPM center adjustment in limits"));
|
||||
firmware->addOption("gvars", QObject::tr("Global variables"), GVARS_VARIANT);
|
||||
|
|
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -633,7 +633,7 @@ else()
|
|||
option(BATTGRAPH "Battery graph" OFF)
|
||||
option(HAPTIC "Haptic support" OFF)
|
||||
set(TTS "EN" CACHE STRING "TTS language")
|
||||
set(LCD "DEFAULT" CACHE STRING "LCD type (DEFAULT/ST7565P/ST7565R/ERC12864FSF/ST7920)")
|
||||
set(LCD "DEFAULT" CACHE STRING "LCD type (DEFAULT/ST7565P/ST7565R/ERC12864FSF/ST7920/KS108)")
|
||||
set(LUA NO)
|
||||
set(PULSES_SRC pulses_avr.cpp)
|
||||
set(SRC ${SRC} main_avr.cpp)
|
||||
|
|
|
@ -266,7 +266,7 @@ void audioTrimPress(int16_t value)
|
|||
{
|
||||
if (g_eeGeneral.beepMode >= e_mode_nokeys) {
|
||||
#if defined(AUDIO)
|
||||
value = limit(TRIM_MIN, value, TRIM_MAX);
|
||||
value = limit<int16_t>(TRIM_MIN, value, TRIM_MAX);
|
||||
value >>= 2;
|
||||
value += 60;
|
||||
audio.play(value, 6, 1, PLAY_NOW);
|
||||
|
@ -284,12 +284,12 @@ void audioTimerCountdown(uint8_t timer, int value)
|
|||
}
|
||||
|
||||
#if defined(CPUM2560)
|
||||
if (g_model.timers[timer].countdownBeep == COUNTDOWN_VOICE) {
|
||||
if (value >= 0 && value <= g_model.timers[timer].countdownStart) {
|
||||
playNumber(value, 0, 0, 0);
|
||||
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, 0, 0);
|
||||
playDuration(value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -107,6 +107,11 @@ void audioDefevent(uint8_t e);
|
|||
#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))
|
||||
|
|
|
@ -452,7 +452,7 @@ PACK(struct TimerData {
|
|||
uint8_t countdownBeep:2;
|
||||
uint8_t minuteBeep:1;
|
||||
uint8_t persistent:2;
|
||||
uint8_t spare:3;
|
||||
uint8_t countdownStart:3;
|
||||
uint16_t value;
|
||||
});
|
||||
#else
|
||||
|
|
|
@ -1371,24 +1371,29 @@ void lcdInvertLine(int8_t y)
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOT)
|
||||
void lcd_img(coord_t x, coord_t y, const pm_uchar * img, uint8_t idx, LcdFlags att)
|
||||
{
|
||||
const pm_uchar *q = img;
|
||||
uint8_t w = pgm_read_byte(q++);
|
||||
uint8_t hb = (pgm_read_byte(q++)+7)/8;
|
||||
bool inv = (att & INVERS) ? true : (att & BLINK ? BLINK_ON_PHASE : false);
|
||||
q += idx*w*hb;
|
||||
for (uint8_t yb = 0; yb < hb; yb++) {
|
||||
uint8_t *p = &displayBuf[ (y / 8 + yb) * LCD_W + x ];
|
||||
for (coord_t i=0; i<w; i++){
|
||||
uint8_t b = pgm_read_byte(q);
|
||||
q++;
|
||||
ASSERT_IN_DISPLAY(p);
|
||||
*p++ = inv ? ~b : b;
|
||||
}
|
||||
}
|
||||
#define LCD_IMG_FUNCTION(NAME, TYPE, READ_BYTE) \
|
||||
void NAME(coord_t x, coord_t y, TYPE img, uint8_t idx, LcdFlags att) \
|
||||
{ \
|
||||
TYPE q = img; \
|
||||
uint8_t w = READ_BYTE(q++); \
|
||||
uint8_t hb = (READ_BYTE(q++)+7)/8; \
|
||||
bool inv = (att & INVERS) ? true : (att & BLINK ? BLINK_ON_PHASE : false); \
|
||||
q += idx*w*hb; \
|
||||
for (uint8_t yb = 0; yb < hb; yb++) { \
|
||||
uint8_t *p = &displayBuf[ (y / 8 + yb) * LCD_W + x ]; \
|
||||
for (coord_t i=0; i<w; i++){ \
|
||||
uint8_t b = READ_BYTE(q); \
|
||||
q++; \
|
||||
ASSERT_IN_DISPLAY(p); \
|
||||
*p++ = inv ? ~b : b; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#if defined(PCBMEGA2560) && !defined(SIMU)
|
||||
LCD_IMG_FUNCTION(lcd_imgfar, uint_farptr_t, pgm_read_byte_far)
|
||||
#endif
|
||||
|
||||
LCD_IMG_FUNCTION(lcd_img, const pm_uchar *, pgm_read_byte)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -237,6 +237,10 @@ void lcdDrawTelemetryTopBar();
|
|||
lcdDrawSolidVerticalLine(xx ,yy-ll,ll); \
|
||||
lcdDrawSolidVerticalLine(xx+1,yy-ll,ll)
|
||||
|
||||
#if defined(PCBMEGA2560) && !defined(SIMU)
|
||||
void lcd_imgfar(coord_t x, coord_t y, const uint_farptr_t img, uint8_t idx, LcdFlags att); // progmem "far"
|
||||
#endif
|
||||
|
||||
void lcd_img(coord_t x, coord_t y, const pm_uchar * img, uint8_t idx, LcdFlags att=0);
|
||||
|
||||
void lcdSetRefVolt(unsigned char val);
|
||||
|
|
|
@ -293,10 +293,12 @@ void menuModelSetup(uint8_t event)
|
|||
break;
|
||||
case 2:
|
||||
qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62) - 2;
|
||||
if (timer->start >= qr.rem) {
|
||||
if ((int16_t)timer->start >= qr.rem) {
|
||||
timer->start -= qr.rem ;
|
||||
}
|
||||
if ((int32_t)timer->start > 3599) timer->start=3599; // 59:59
|
||||
if ((int16_t)timer->start > 3599) {
|
||||
timer->start = 3599; // 59:59
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,19 +18,44 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../../opentx.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#if !defined GET_FAR_ADDRESS
|
||||
#define GET_FAR_ADDRESS(var) \
|
||||
({ \
|
||||
uint32_t tmp; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
\
|
||||
"ldi %A0, lo8(%1)" "\n\t" \
|
||||
"ldi %B0, hi8(%1)" "\n\t" \
|
||||
"ldi %C0, hh8(%1)" "\n\t" \
|
||||
"clr %D0" "\n\t" \
|
||||
: \
|
||||
"=d" (tmp) \
|
||||
: \
|
||||
"p" (&(var)) \
|
||||
); \
|
||||
tmp; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#if defined(SPLASH)
|
||||
const pm_uchar splashdata[] PROGMEM = {
|
||||
'S','P','S',0,
|
||||
#include "bitmaps/9x/splash.lbm"
|
||||
'S','P','E',0 };
|
||||
|
||||
const pm_uchar * const splash_lbm = splashdata+4;
|
||||
|
||||
void drawSplash()
|
||||
{
|
||||
lcdClear();
|
||||
#if defined(PCBMEGA2560) && !defined(SIMU)
|
||||
lcd_imgfar(0, 0, pgm_get_far_address(splash_lbm), 0, 0); // use progmem "far" for splash working with all other options enabled
|
||||
#else
|
||||
lcd_img(0, 0, splash_lbm, 0, 0);
|
||||
#endif
|
||||
|
||||
#if MENUS_LOCK == 1
|
||||
if (readonly == false) {
|
||||
|
|
|
@ -1426,7 +1426,11 @@ enum AUDIO_SOUNDS {
|
|||
#endif
|
||||
|
||||
#if defined(PCBGRUVIN9X) && defined(VOICE)
|
||||
#include "targets/gruvin9x/somo14d.h"
|
||||
#include "targets/gruvin9x/voice.h"
|
||||
#endif
|
||||
|
||||
#if defined(PCBMEGA2560) && defined(VOICE)
|
||||
#include "targets/mega2560/voice.h"
|
||||
#endif
|
||||
|
||||
#include "translations.h"
|
||||
|
|
139
radio/src/targets/9x/lcd_default_driver.cpp
Normal file
139
radio/src/targets/9x/lcd_default_driver.cpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
|
@ -20,24 +20,6 @@
|
|||
|
||||
#include "opentx.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#if defined(PCBSTD) && defined(VOICE)
|
||||
volatile uint8_t LcdLock;
|
||||
#define LCD_LOCK() LcdLock = 1
|
||||
|
@ -47,217 +29,10 @@ void lcdSendCtl(uint8_t val)
|
|||
#define LCD_UNLOCK()
|
||||
#endif
|
||||
|
||||
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
|
||||
#if defined(LCD_KS108)
|
||||
#include "targets/9x/lcd_ks108_driver.cpp"
|
||||
#elif defined(LCD_ST7920)
|
||||
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
|
||||
#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
|
||||
#if defined(LCD_ST7920)
|
||||
_delay_ms(40);
|
||||
#include "targets/9x/lcd_st7920_driver.cpp"
|
||||
#else
|
||||
_delay_us(1500);
|
||||
#include "targets/9x/lcd_default_driver.cpp"
|
||||
#endif
|
||||
for (uint8_t i=0; i<DIM(lcdInitSequence); i++) {
|
||||
lcdSendCtl(pgm_read_byte(&lcdInitSequence[i])) ;
|
||||
#if defined(LCD_ST7920)
|
||||
_delay_us(80);
|
||||
#endif
|
||||
}
|
||||
#if defined(LCD_ERC12864FSF)
|
||||
g_eeGeneral.contrast = 0x2D;
|
||||
#else
|
||||
g_eeGeneral.contrast = 0x22;
|
||||
#endif
|
||||
LCD_UNLOCK();
|
||||
}
|
||||
|
||||
void lcdSetRefVolt(uint8_t val)
|
||||
{
|
||||
#if !defined(LCD_ST7920) // No contrast setting for ST7920
|
||||
LCD_LOCK();
|
||||
lcdSendCtl(0x81);
|
||||
lcdSendCtl(val);
|
||||
LCD_UNLOCK();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(LCD_ST7920)
|
||||
void lcdRefresh(){
|
||||
lcdRefresh_ST7920(1);
|
||||
}
|
||||
|
||||
uint8_t lcdRefresh_ST7920(uint8_t full)
|
||||
{
|
||||
#else
|
||||
void lcdRefresh()
|
||||
{
|
||||
#endif
|
||||
LCD_LOCK();
|
||||
#if defined(LCD_ST7920)
|
||||
static uint8_t state;
|
||||
uint8_t yst,yend;
|
||||
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{
|
||||
switch (state){//Since writing to ST7920 is too slow we need to split it to five bands.
|
||||
default:
|
||||
case 0:
|
||||
yst=0;
|
||||
yend=13;
|
||||
state=1;
|
||||
break;
|
||||
case 1:
|
||||
yst=13;
|
||||
yend=26;
|
||||
state=2;
|
||||
break;
|
||||
case 2:
|
||||
yst=26;
|
||||
yend=39;
|
||||
state=3;
|
||||
break;
|
||||
case 3:
|
||||
yst=39;
|
||||
yend=52;
|
||||
state=4;
|
||||
break;
|
||||
case 4:
|
||||
yst=52;
|
||||
yend=64;
|
||||
state=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
#else //All other LCD
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
LCD_UNLOCK();
|
||||
#if defined(LCD_ST7920)
|
||||
return state;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
94
radio/src/targets/9x/lcd_ks108_driver.cpp
Normal file
94
radio/src/targets/9x/lcd_ks108_driver.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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(display_t * p)
|
||||
{
|
||||
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()
|
||||
{
|
||||
// Right
|
||||
CS1_on;
|
||||
lcdRefreshSide(displayBuf);
|
||||
CS1_off;
|
||||
|
||||
// Left
|
||||
CS2_on;
|
||||
lcdRefreshSide(displayBuf + 64);
|
||||
CS2_off;
|
||||
}
|
154
radio/src/targets/9x/lcd_st7920_driver.cpp
Normal file
154
radio/src/targets/9x/lcd_st7920_driver.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* 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,yend;
|
||||
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 {
|
||||
switch (state) { // Since writing to ST7920 is too slow we need to split it to five bands.
|
||||
default:
|
||||
case 0:
|
||||
yst=0;
|
||||
yend=13;
|
||||
state=1;
|
||||
break;
|
||||
case 1:
|
||||
yst=13;
|
||||
yend=26;
|
||||
state=2;
|
||||
break;
|
||||
case 2:
|
||||
yst=26;
|
||||
yend=39;
|
||||
state=3;
|
||||
break;
|
||||
case 3:
|
||||
yst=39;
|
||||
yend=52;
|
||||
state=4;
|
||||
break;
|
||||
case 4:
|
||||
yst=52;
|
||||
yend=64;
|
||||
state=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
|
@ -25,16 +25,16 @@ inline void boardInit()
|
|||
{
|
||||
// Set up I/O port data directions and initial states (unused pin setting : input, pull-up on)
|
||||
DDRA = 0b11111111; PORTA = 0b00000000; // LCD data
|
||||
DDRB = 0b01110111; PORTB = 0b10101111; // 7:N/A 6:PPM_OUT, 5:SimCTRL, 4:Buzzer, SDCARD[3:MISO 2:MOSI 1:SCK 0:CS]
|
||||
DDRB = 0b01110111; PORTB = 0b00101111; // 7:SOMOBusy, 6:PPM_OUT, 5:SimCTRL, 4:Buzzer, 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 = 0b11111100; // 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 = 0b00000010; PORTE = 0b01111100; // 7:PPM_IN, 6:N/A, 5:RENC1_B, 4:RENC1_A, 3:N/A, 2:N/A, 1:TELEM_TX, 0:TELEM_RX
|
||||
DDRE = 0b00001010; PORTE = 0b01110100; // 7:PPM_IN, 6:N/A, 5:RENC1_B, 4:RENC1_A, 3:SOMOData, 2:N/A, 1:TELEM_TX, 0:TELEM_RX
|
||||
DDRF = 0b00000000; PORTF = 0b11111111; // 7-0:Trim switch inputs
|
||||
DDRG = 0b00000000; PORTG = 0b11111111; // 7:N/A, 6:N/A, 5:N/A, 4:N/A, 3:N/A, 2:TCut_SW, 1:Gear_SW, 0: RudDr_SW
|
||||
#if defined(PCBMEGA2560) && defined(DEBUG)
|
||||
DDRH = 0b01011000; PORTH = 0b11110110; // 7:N/A, 6:RF_Activated, 5:DSC_Activated, 4:Hold_Power, 3:Speaker, 2:N/A, 1:N/A, 0:Haptic
|
||||
DDRG = 0b00100000; PORTG = 0b11011111; // 7:N/A, 6:N/A, 5:SOMOClock, 4:N/A, 3:N/A, 2:TCut_SW, 1:Gear_SW, 0: RudDr_SW
|
||||
#if defined(DEBUG)
|
||||
DDRH = 0b01011010; PORTH = 0b11110100; // 7:N/A, 6:RF_Activated, 5:DSC_Activated, 4:Hold_Power, 3:Speaker, 2:N/A, 1:SOMOReset, 0:Haptic
|
||||
#else
|
||||
DDRH = 0b00011000; PORTH = 0b11110110; // 7:N/A, 6:RF_Activated, 5:DSC_Activated, 4:Hold_Power, 3:Speaker, 2:N/A, 1:N/A, 0:Haptic
|
||||
DDRH = 0b00011010; PORTH = 0b11110100; // 7:N/A, 6:RF_Activated, 5:DSC_Activated, 4:Hold_Power, 3:Speaker, 2:N/A, 1:SOMOReset, 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)
|
||||
|
@ -49,16 +49,18 @@ inline void boardInit()
|
|||
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 = (1<<WGM42) | (0b011 << CS00);
|
||||
TCCR4B = (1<<WGM42) | (0b011 << CS40);
|
||||
TCCR4A = 0x00;
|
||||
#endif
|
||||
|
||||
#if defined (VOICE) // OLD FROM GRUVIN9X, TO REWRITE
|
||||
// SOMO set-up
|
||||
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
|
||||
#if defined(VOICE)
|
||||
// SOMO 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
|
||||
|
||||
/* Rotary encoder interrupt set-up */
|
||||
|
|
|
@ -94,18 +94,22 @@ void sdPoll10ms(void);
|
|||
#define INP_L_Trainer 7
|
||||
|
||||
// Servitudes driver
|
||||
//#define INP_E_PPM_IN 7 //reserved PPM_IN
|
||||
#define INP_E_PPM_IN 7 //not used (reserved)
|
||||
#define INP_B_14DBUSY 7 //somo14d, not used (reserved)
|
||||
#define OUT_B_PPM 6
|
||||
#define OUT_B_SIM_CTL 5
|
||||
#define OUT_B_BUZZER 4
|
||||
#define INP_D_I2C_SCL 1
|
||||
#define INP_D_I2C_SDA 0
|
||||
#define OUT_E_14DDATA 3 //somo14d
|
||||
#define INP_E_TELEM_RX 1
|
||||
#define OUT_E_TELEM_TX 0
|
||||
#define OUT_G_14DCLK 5 //somo14d
|
||||
#define INP_H_RF_Activated 6
|
||||
//#define INP_H_ 5 //reserved DSC_Activated, for pwrCheck()
|
||||
//#define INP_H_ 4 //reserved Hold_Power, for pwrCheck()
|
||||
#define INP_H_DSC_Activated 5 //not used, reserved for pwrCheck()
|
||||
#define INP_H_Hold_Power 4 //not used, reserved for pwrCheck()
|
||||
#define OUT_H_Speaker 3
|
||||
#define OUT_H_14DRESET 1 //somo14d
|
||||
#define OUT_H_HAPTIC 0
|
||||
|
||||
// Rotary encoders driver
|
||||
|
@ -122,8 +126,12 @@ void sdPoll10ms(void);
|
|||
// LCD driver
|
||||
#define PORTA_LCD_DAT PORTA
|
||||
#define PORTC_LCD_CTRL PORTC
|
||||
#define OUT_C_LCD_E 7
|
||||
#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
|
||||
#else // And connect LCD 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
|
||||
|
@ -153,8 +161,22 @@ void pwrOff();
|
|||
#define buzzerOff() PORTB &= ~(1 << OUT_B_BUZZER)
|
||||
|
||||
// Speaker driver
|
||||
#if defined(AUDIO)
|
||||
#define speakerOn() TCCR4A |= (1 << COM4A0)
|
||||
#define speakerOff() TCCR4A &= ~(1 << COM4A0)
|
||||
#endif
|
||||
|
||||
// Voice driver
|
||||
#if defined(VOICE)
|
||||
#define WTV20SD_Clock_on PORTG |= (1<<OUT_G_14DCLK)
|
||||
#define WTV20SD_Clock_off PORTG &= ~(1<<OUT_G_14DCLK)
|
||||
#define WTV20SD_Data_on PORTE |= (1<<OUT_E_14DDATA)
|
||||
#define WTV20SD_Data_off PORTE &= ~(1<<OUT_E_14DDATA)
|
||||
#define WTV20SD_Reset_on PORTH |= (1<<OUT_H_14DRESET)
|
||||
#define WTV20SD_Reset_off PORTH &= ~(1<<OUT_H_14DRESET)
|
||||
#define WTV20SD_BUSY (PINB & 0x80)
|
||||
#define WTV20SD_CLK (PING & 0x20)
|
||||
#endif
|
||||
|
||||
// EEPROM driver
|
||||
#if !defined(SIMU)
|
||||
|
|
164
radio/src/targets/mega2560/voice.cpp
Normal file
164
radio/src/targets/mega2560/voice.cpp
Normal file
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// driver adapted from somo14d driver for gruvin9x board for driving WTV20SDMini module
|
||||
|
||||
#include "../../opentx.h"
|
||||
|
||||
// Start and stop bits need to be 2ms in duration. Start bit is low, stop bit is high
|
||||
#define WTV20SD_STOP_TIME 68 // This is the needed 2ms (4) + 30ms (60) to allow for the
|
||||
// point at which the busy flag is checkable + 2ms for saftey (4)
|
||||
#define WTV20SD_START_TIME 5 // The 2ms of a stop/start bit
|
||||
|
||||
enum WTV20SD_State
|
||||
{
|
||||
PAUSE,
|
||||
SENDSTART,
|
||||
SENDDATA,
|
||||
SENDSTOP
|
||||
};
|
||||
|
||||
#define QUEUE_LENGTH 10
|
||||
uint16_t WTV20SD_playlist[QUEUE_LENGTH] = {0};
|
||||
volatile uint8_t WTV20SD_InputIndex = 0;
|
||||
uint8_t WTV20SD_PlayIndex = 0;
|
||||
uint8_t Startstop = WTV20SD_START_TIME;
|
||||
uint16_t WTV20SD_current = 0;
|
||||
uint8_t state = PAUSE;
|
||||
|
||||
void WTV20SD_sendstart()
|
||||
{
|
||||
WTV20SD_Clock_off; // Start Bit, CLK low for 2ms
|
||||
|
||||
--Startstop;
|
||||
|
||||
if (!Startstop) state = SENDDATA;
|
||||
}
|
||||
|
||||
void WTV20SD_senddata()
|
||||
{
|
||||
static uint8_t i = 0;
|
||||
|
||||
if (!WTV20SD_CLK) {
|
||||
// Only change data when the CLK is low
|
||||
if (WTV20SD_current & 0x8000) {
|
||||
WTV20SD_Data_on; // Data high
|
||||
}
|
||||
WTV20SD_current = (WTV20SD_current<<1);
|
||||
++i;
|
||||
_delay_us(1); // Data setup delay
|
||||
WTV20SD_Clock_on; // CLK high
|
||||
}
|
||||
else {
|
||||
// Don't alter after sending last bit in preparation for sending stop bit
|
||||
WTV20SD_Clock_off; // CLK low
|
||||
WTV20SD_Data_off; // Data low
|
||||
}
|
||||
|
||||
if (i == 16) { i = 0; Startstop = WTV20SD_STOP_TIME; state = SENDSTOP; }
|
||||
}
|
||||
|
||||
void WTV20SD_sendstop()
|
||||
{
|
||||
WTV20SD_Data_off; // Data low
|
||||
WTV20SD_Clock_on; // Stop Bit, CLK high for 2ms
|
||||
--Startstop;
|
||||
|
||||
if (!Startstop && !WTV20SD_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 */
|
||||
WTV20SD_playlist[WTV20SD_InputIndex] = prompt;
|
||||
++WTV20SD_InputIndex;
|
||||
WTV20SD_InputIndex %= QUEUE_LENGTH;
|
||||
|
||||
if (!isPlaying()) {
|
||||
TIMSK5 |= (1<<OCIE5A); // enable interrupts on Output Compare A Match
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t 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
|
||||
{
|
||||
static uint8_t reset_dly=4;
|
||||
static uint8_t reset_pause=150;
|
||||
|
||||
if (reset_dly) {
|
||||
OCR5A=0x1f4;
|
||||
reset_dly--;
|
||||
WTV20SD_Reset_off;
|
||||
WTV20SD_Data_off;
|
||||
WTV20SD_Clock_on;
|
||||
} // RESET low
|
||||
else if (reset_pause) {
|
||||
OCR5A=0x1f4;
|
||||
reset_pause--;
|
||||
WTV20SD_Reset_on;
|
||||
} // RESET high
|
||||
else {
|
||||
OCR5A = 0x7d; // another 0.5ms
|
||||
|
||||
if (state == PAUSE) {
|
||||
if (WTV20SD_PlayIndex == WTV20SD_InputIndex) {
|
||||
TIMSK5 &= ~(1<<OCIE5A); // stop reentrance
|
||||
TCNT5=0; // reset timer
|
||||
return; // nothing else to play
|
||||
}
|
||||
else {
|
||||
WTV20SD_current = WTV20SD_playlist[WTV20SD_PlayIndex];
|
||||
++WTV20SD_PlayIndex;
|
||||
WTV20SD_PlayIndex %= QUEUE_LENGTH;
|
||||
Startstop = WTV20SD_START_TIME;
|
||||
state = SENDSTART;
|
||||
}
|
||||
} // end PAUSE
|
||||
|
||||
if (state == SENDSTART) {
|
||||
WTV20SD_sendstart();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == SENDDATA) {
|
||||
WTV20SD_senddata();
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == SENDSTOP) {
|
||||
WTV20SD_sendstop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
43
radio/src/targets/mega2560/voice.h
Normal file
43
radio/src/targets/mega2560/voice.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 uint8_t 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)
|
|
@ -39,14 +39,14 @@ make -j2 gtests ; ./gtests
|
|||
|
||||
# OpenTX on Mega2560 with Mavlink telemetry
|
||||
rm -rf *
|
||||
cmake ${COMMON_OPTIONS} -DPCB=MEGA2560 -DEXT=MAVLINK -DHELI=YES ${SRCDIR}
|
||||
cmake ${COMMON_OPTIONS} -DPCB=MEGA2560 -DEXT=MAVLINK -DHELI=YES -DAUDIO=YES -DVOICE=YES ${SRCDIR}
|
||||
make -j2 firmware
|
||||
make -j2 simu
|
||||
make -j2 gtests ; ./gtests
|
||||
|
||||
# OpenTX on gruvin9x board
|
||||
rm -rf *
|
||||
cmake ${COMMON_OPTIONS} -DPCB=GRUVIN9X -DHELI=YES ${SRCDIR}
|
||||
cmake ${COMMON_OPTIONS} -DPCB=GRUVIN9X -DHELI=YES -DAUDIO=YES -DVOICE=YES ${SRCDIR}
|
||||
make -j2 firmware
|
||||
make -j2 simu
|
||||
make -j2 gtests ; ./gtests
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue