Port for DSM2 pulses,

Port for SOMO module,
ModelMatch function switch,
French translations.
This commit is contained in:
bsongis
2012-01-19 11:10:02 +00:00
parent ebff7a9d09
commit c67ba218fa
14 changed files with 745 additions and 192 deletions
+6 -2
View File
@@ -346,8 +346,12 @@ ifeq ($(PXX), YES)
CPPDEFS += -DPXX
endif
ifeq ($(DSM2), YES)
CPPDEFS += -DDSM2
ifeq ($(DSM2), SERIAL)
CPPDEFS += -DDSM2 -DDSM2_SERIAL
endif
ifeq ($(DSM2), PPM)
CPPDEFS += -DDSM2 -DDSM2_PPM
endif
ifeq ($(SILVER), YES)
-13
View File
@@ -339,19 +339,6 @@ ISR(USART0_RX_vect)
UCSR0B |= (1 << RXCIE0); // enable Interrupt
}
/*
USART0 Transmit Data Register Emtpy ISR
Used to transmit FrSky data packets
*/
ISR(USART0_UDRE_vect)
{
if (frskyTxBufferCount > 0) {
UDR0 = frskyTxBuffer[--frskyTxBufferCount];
}
else {
UCSR0B &= ~(1 << UDRIE0); // disable UDRE0 interrupt
}
}
#endif
/******************************************/
+2
View File
@@ -100,6 +100,8 @@ extern uint8_t FrskyAlarmSendState;
extern FrskyData frskyTelemetry[2];
extern FrskyData frskyRSSI[2];
extern uint8_t frskyTxBuffer[FRSKY_TX_PACKET_SIZE];
extern uint8_t frskyTxBufferCount;
void FRSKY_Init(void);
void FRSKY10mspoll(void);
+3
View File
@@ -171,6 +171,9 @@ enum Functions {
FUNC_TRAINER_AIL,
FUNC_INSTANT_TRIM,
FUNC_TRIMS_2_OFS,
#if defined(DSM2)
FUNC_MODELMATCH,
#endif
#ifdef LOGS
FUNC_LOGS,
#endif
-7
View File
@@ -1,12 +1,5 @@
#include "open9x.h"
#ifdef TRANSLATIONS_FR
#include "translations/fr.h"
#else
#endif
#include "translations/en.h"
// The non-0-terminated-strings
const prog_char APM STR_OPEN9X[] =
TR_OFFON
+4 -3
View File
@@ -1,12 +1,13 @@
#ifndef o9xstrings_h
#define o9xstrings_h
#ifdef TRANSLATIONS_FR
#if defined(TRANSLATIONS_FR)
#include "translations/fr.h"
#elif defined(TRANSLATIONS_IT)
#include "translations/it.h"
#else
#endif
#include "translations/en.h"
#endif
#define PSIZE(x) ( sizeof(x) - 1 )
+56 -26
View File
@@ -2026,6 +2026,54 @@ uint16_t DEBUG2 = 0;
#endif
/*
USART0 Transmit Data Register Emtpy ISR
Used to transmit FrSky data packets and DSM2 protocol
*/
#if defined (FRSKY)
FORCEINLINE void FRSKY_USART0_vect()
{
if (frskyTxBufferCount > 0) {
UDR0 = frskyTxBuffer[--frskyTxBufferCount];
}
else {
UCSR0B &= ~(1 << UDRIE0); // disable UDRE0 interrupt
}
}
#endif
#if defined (DSM2_SERIAL)
FORCEINLINE void DSM2_USART0_vect()
{
UDR0 = *pulses2MHzRPtr;
if (++pulses2MHzRPtr == pulses2MHzWPtr) {
UCSR0B &= ~(1 << UDRIE0); // disable UDRE0 interrupt
}
}
#endif
#ifndef SIMU
#if defined (FRSKY) or defined(DSM2_SERIAL)
ISR(USART0_UDRE_vect)
{
#if defined (FRSKY) and defined (DSM2_SERIAL)
if (g_model.protocol == PROTO_DSM2) {
DSM2_USART0_vect();
}
else {
FRSKY_USART0_vect();
}
#elif defined (FRSKY)
FRSKY_USART0_vect();
#else
DSM2_USART0_vect();
#endif
}
#endif
#endif
#if defined (PCBV3)
/*---------------------------------------------------------*/
/* User Provided Date/Time Function for FatFs module */
@@ -2159,10 +2207,10 @@ int main(void)
DDRE = 0b00001010; PORTE = 0b11110101; // 7:PPM_IN, 6: RENC1_B, 5:RENC1_A, 4:USB_DNEG, 3:BUZZER, 2:USB_DPOS, 1:TELEM_TX, 0:TELEM_RX
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
DDRH = 0x00; PORTH = 0xff; // 7:0 Spare port -- all inputs for now [Bit 2:VIB_OPTION -- setting to input for now]
DDRH = 0b00110000; PORTH = 0b11011111; // 7:0 Spare port [6:SOMO14D-BUSY 5:SOMO14D-DATA 4:SOMO14D-CLK] [2:VIB_OPTION -- setting to input for now]
DDRJ = 0x00; PORTJ = 0xff; // 7-0:Trim switch inputs
DDRK = 0x00; PORTK = 0x00; // anain. No pull-ups!
DDRL = 0x00; PORTL = 0xff; // 7-6:Spare6/5 (inputs), 5-0: User Button inputs
DDRL = 0x80; PORTL = 0x7f; // 7: Hold_PWR_On (1=On, default Off), 6:Jack_Presence_TTL, 5-0: User Button inputs
#else
# if defined (PCBV3)
DDRB = 0x97; PORTB = 0x1e; // 7:AUDIO, SD_CARD[6:SDA 5:SCL 4:CS 3:MISO 2:MOSI 1:SCK], 0:PPM_OUT
@@ -2265,10 +2313,14 @@ int main(void)
sei(); // interrupts needed for FRSKY_Init and eeReadAll.
#if defined (FRSKY)
#if defined (FRSKY) and !defined (DSM2_SERIAL)
FRSKY_Init();
#endif
#if defined (DSM2_SERIAL) and !defined (FRSKY)
DSM2_Init();
#endif
#ifdef JETI
JETI_Init();
#endif
@@ -2340,29 +2392,7 @@ int main(void)
/***************************************************/
#endif
/***********************************************************/
/*** Keep this code block directly before the main loop ****/
setupPulses();
#if defined (PCBV4)
OCR1B = 0xffff; /* Prevent any PPM_PUT pin toggle before the TCNT1 interrupt
fires for the first time and sets up the pulse period. */
// TCCR1A |= (1<<COM1B0); // (COM1B1=0 and COM1B0=1 in TCCR1A) toogle the state of PB6(OC1B) on each TCNT1==OCR1B
TCCR1A = (3<<COM1B0); // Connect OC1B to PPM_OUT pin (SET the state of PB6(OC1B) on next TCNT1==OCR1B)
#else
//addon Vinceofdrink@gmail (hardware ppm)
# if defined (DPPMPB7_HARDWARE)
OCR1C = 0xffff; // See comment for PCBV4, above
TCCR1A |= (1<<COM1C0); // (COM1C1=0 and COM1C0=1 in TCCR1A) toogle the state of PB7(OC1C) on each TCNT1==OCR1C
# endif
#endif
#if defined (PCBV3)
TIMSK1 |= (1<<OCIE1A); // Pulse generator enable immediately before mainloop
#else
TIMSK |= (1<<OCIE1A); // Pulse generator enable immediately before mainloop
#endif
startPulses();
wdt_enable(WDTO_500MS);
/*** Keep this code block directly before the main loop ****/
+35 -27
View File
@@ -69,6 +69,20 @@
#include "file.h"
#include "lcd.h"
#include "myeeprom.h"
#ifdef JETI
// Jeti-DUPLEX Telemetry
extern uint16_t jeti_keys;
#include "jeti.h"
#endif
#if defined (FRSKY)
// FrSky Telemetry
#include "frsky.h"
#endif
extern RlcFile theFile; //used for any file operation
// G: The following comments relate to the original stock PCB only
@@ -176,6 +190,11 @@ extern uint16_t DEBUG2;
# define INP_B_Trainer 5
# define INP_B_ID2 4
#ifdef SOMO
# define OUT_H_14DCLK 4
# define OUT_H_14DDATA 5
# define OUT_H_14DBUSY 6
#endif
#else // boards prior to v4 ...
@@ -343,22 +362,15 @@ enum EnumKeys {
#define NUM_PPM 8
#define CHOUT_BASE (PPM_BASE+NUM_PPM)
#if defined(FRSKY)
#if defined(FRSKY_HUB)
#define NUM_TELEMETRY 4
#define TELEMETRY_CHANNELS "AD1AD2ALTRPM"
#elif defined(WS_HOW_HIGH)
#define NUM_TELEMETRY 3
#define TELEMETRY_CHANNELS "AD1AD2ALT"
#else
#elif defined(FRSKY)
#define NUM_TELEMETRY 2
#define TELEMETRY_CHANNELS "AD1AD2"
#endif
#else
#define NUM_TELEMETRY 0
#define TELEMETRY_CHANNELS ""
#endif
#define TELEMETRY_STRLEN 3
#define DSW_THR 1
#define DSW_RUD 2
@@ -544,15 +556,14 @@ extern uint8_t s_eeDirtyMsk;
#define FORCEINLINE inline __attribute__ ((always_inline))
#endif
/// liefert Betrag des Arguments
template<class t> FORCEINLINE t abs(t a){ return a>0?a:-a; }
template<class t> FORCEINLINE t abs(t a) { return a>0?a:-a; }
/// liefert das Minimum der Argumente
template<class t> FORCEINLINE t min(t a, t b){ return a<b?a:b; }
template<class t> FORCEINLINE t min(t a, t b) { return a<b?a:b; }
/// liefert das Maximum der Argumente
template<class t> FORCEINLINE t max(t a, t b){ return a>b?a:b; }
template<class t> FORCEINLINE t sgn(t a){ return a>0 ? 1 : (a < 0 ? -1 : 0); }
template<class t> FORCEINLINE t limit(t mi, t x, t ma){ return min(max(mi,x),ma); }
template<class t> FORCEINLINE t max(t a, t b) { return a>b?a:b; }
template<class t> FORCEINLINE t sgn(t a) { return a>0 ? 1 : (a < 0 ? -1 : 0); }
template<class t> FORCEINLINE t limit(t mi, t x, t ma) { return min(max(mi,x),ma); }
/// Markiert einen EEPROM-Bereich als dirty. der Bereich wird dann in
/// eeCheck ins EEPROM zurueckgeschrieben.
@@ -600,31 +611,27 @@ extern inline uint16_t get_tmr10ms()
#define TMR_VAROFS 5
void startPulses();
void setupPulses();
void DSM2_Init();
void DSM2_Done();
void resetProto();
#ifdef LOGS
extern void startLogs();
extern void doLogs();
#endif
#include "lcd.h"
// TODO needed?
extern uint16_t *pulses2MHzRPtr;
extern uint16_t *pulses2MHzWPtr;
extern const char stamp1[];
extern const char stamp2[];
extern const char stamp3[];
extern const char stamp4[];
extern const char stamp5[];
#include "myeeprom.h"
#ifdef JETI
// Jeti-DUPLEX Telemetry
extern uint16_t jeti_keys;
#include "jeti.h"
#endif
#if defined (FRSKY)
// FrSky Telemetry
#include "frsky.h"
#endif
extern const char stamp6[];
#ifndef BATT_UNSTABLE_BANDGAP
extern uint16_t abRunningAvg;
@@ -636,6 +643,7 @@ extern volatile uint16_t g_tmr10ms;
extern volatile uint8_t g_blinkTmr10ms;
extern uint8_t g_beepCnt;
extern uint8_t g_beepVal[5];
// TODO needed?
extern const PROGMEM char modi12x3[];
#include "o9xstrings.h"
+29 -4
View File
@@ -123,16 +123,41 @@ void eeLoadModel(uint8_t id)
// TODO optim: resetAll()
resetTimer(0);
resetTimer(1);
#ifdef FRSKY
resetTelemetry();
FRSKY_setModelAlarms();
#endif
resetProto();
#ifdef LOGS
startLogs();
#endif
}
}
void resetProto() // TODO inline this if !DSM2_SERIAL
{
#if defined(DSM2_SERIAL)
if (g_model.protocol == PROTO_DSM2) {
cli();
#if defined(FRSKY)
DSM2_Init();
#endif
sei();
}
else {
cli();
#if defined(FRSKY)
FRSKY_Init();
#else
DSM2_Done();
#endif
sei();
#if defined(FRSKY)
FRSKY_setModelAlarms();
#endif
}
#elif defined(FRSKY)
resetTelemetry();
FRSKY_setModelAlarms();
#endif
}
int8_t eeFindEmptyModel(uint8_t id, bool down)
{
int8_t i = id;
+162 -109
View File
@@ -21,6 +21,48 @@
#include "open9x.h"
#ifdef DSM2_SERIAL
inline void DSM2_EnableTXD(void)
{
UCSR0B |= (1 << TXEN0); // enable TX
UCSR0B |= (1 << UDRIE0); // enable UDRE0 interrupt
}
#endif
void startPulses()
{
#ifndef SIMU
setupPulses();
#ifdef DSM2_SERIAL
if (g_model.protocol == PROTO_DSM2) {
DSM2_EnableTXD();
OCR1A = 40000;
}
else
#endif
{
#if defined (PCBV4)
OCR1B = 0xffff; /* Prevent any PPM_PUT pin toggle before the TCNT1 interrupt
fires for the first time and sets up the pulse period. */
// TCCR1A |= (1<<COM1B0); // (COM1B1=0 and COM1B0=1 in TCCR1A) toogle the state of PB6(OC1B) on each TCNT1==OCR1B
TCCR1A = (3<<COM1B0); // Connect OC1B to PPM_OUT pin (SET the state of PB6(OC1B) on next TCNT1==OCR1B)
#elif defined (DPPMPB7_HARDWARE) // addon Vinceofdrink@gmail (hardware ppm)
OCR1C = 0xffff; // See comment for PCBV4, above
TCCR1A |= (1<<COM1C0); // (COM1C1=0 and COM1C0=1 in TCCR1A) toogle the state of PB7(OC1C) on each TCNT1==OCR1C
#endif
}
#if defined (PCBV3)
TIMSK1 |= (1<<OCIE1A); // Pulse generator enable immediately before mainloop
#else
TIMSK |= (1<<OCIE1A); // Pulse generator enable immediately before mainloop
#endif
#endif // SIMU
}
#ifdef CTP1009
uint16_t pulses2MHz[50] = {0};
#else
@@ -39,83 +81,94 @@ uint16_t *pulses2MHzWPtr = pulses2MHz;
ISR(TIMER1_COMPA_vect) //2MHz pulse generation
{
static uint8_t pulsePol; // TODO strange, it's always 0 at first, shouldn't it be initialized properly in setupPulses?
static uint8_t pulsePol; // TODO strange, it's always 0 at first, shouldn't it be initialized properly in setupPulses?
// Latency -- how far further on from interrupt trigger has the timer counted?
// (or -- how long did it take to get to this function)
uint8_t dt = TCNT1L;
// vinceofdrink@gmail harwared ppm
// Orginal bitbang for PPM
#if !defined (DPPMPB7_HARDWARE) && !defined (PCBV4)
if (pulsePol) {
PORTB |= (1<<OUT_B_PPM); // GCC optimisation should result in a single SBI instruction
pulsePol = 0;
}
else {
PORTB &= ~(1<<OUT_B_PPM);
pulsePol = 1;
}
#endif
OCR1A = *pulses2MHzRPtr; // Schedule next interrupt vector (to this handler)
#if defined (PCBV4)
OCR1B = *pulses2MHzRPtr; /* G: Using timer in CTC mode, restricted to using OCR1A for interrupt triggering.
So we actually have to handle the OCR1B register separately in this way. */
// We cannot read the status of the PPM_OUT pin when OC1B is connected to it on the ATmega2560.
// So the only way to set polarity is to manually control set/reset mode in COM1B0/1
if (pulsePol) {
TCCR1A = (3<<COM1B0); // SET the state of PB6(OC1B) on next TCNT1==OCR1B
pulsePol = 0;
}
else {
TCCR1A = (2<<COM1B0); // CLEAR the state of PB6(OC1B) on next TCNT1==OCR1B
pulsePol = 1;
}
//vinceofdrink@gmail harwared ppm
#elif defined (DPPMPB7_HARDWARE)
OCR1C = *pulses2MHzRPtr; // just copy the value of the OCR1A to OCR1C to test PPM out without too
// much change in the code not optimum but will not alter ppm precision
#endif
if (dt > g_tmr1Latency_max) g_tmr1Latency_max = dt;
if (dt < g_tmr1Latency_min) g_tmr1Latency_min = dt;
++pulses2MHzRPtr;
if (pulses2MHzRPtr == pulses2MHzWPtr) {
//currpulse=0;
pulsePol = g_model.pulsePol;//0;
// channel = 0 ;
// PulseTotal = 0 ;
#if defined (PCBV3)
TIMSK1 &= ~(1<<OCIE1A); //stop reentrance
#else
TIMSK &= ~(1<<OCIE1A); //stop reentrance
#endif
#ifdef DSM2_SERIAL
if (g_model.protocol == PROTO_DSM2) {
OCR1A = 40000;
sei();
setupPulses();
cli();
UCSR0B |= (1 << UDRIE0); // enable UDRE0 interrupt
}
else
#endif
{
// vinceofdrink@gmail harwared ppm
// Orginal bitbang for PPM
#if !defined (DPPMPB7_HARDWARE) && !defined (PCBV4)
if (pulsePol) {
PORTB |= (1<<OUT_B_PPM); // GCC optimisation should result in a single SBI instruction
pulsePol = 0;
}
else {
PORTB &= ~(1<<OUT_B_PPM);
pulsePol = 1;
}
#endif
OCR1A = *pulses2MHzRPtr; // Schedule next interrupt vector (to this handler)
#if defined (PCBV4)
OCR1B = *pulses2MHzRPtr; /* G: Using timer in CTC mode, restricted to using OCR1A for interrupt triggering.
So we actually have to handle the OCR1B register separately in this way. */
// We cannot read the status of the PPM_OUT pin when OC1B is connected to it on the ATmega2560.
// So the only way to set polarity is to manually control set/reset mode in COM1B0/1
if (pulsePol) {
TCCR1A = (3<<COM1B0); // SET the state of PB6(OC1B) on next TCNT1==OCR1B
pulsePol = 0;
}
else {
TCCR1A = (2<<COM1B0); // CLEAR the state of PB6(OC1B) on next TCNT1==OCR1B
pulsePol = 1;
}
//vinceofdrink@gmail harwared ppm
#elif defined (DPPMPB7_HARDWARE)
OCR1C = *pulses2MHzRPtr; // just copy the value of the OCR1A to OCR1C to test PPM out without too
// much change in the code not optimum but will not alter ppm precision
#endif
if (++pulses2MHzRPtr == pulses2MHzWPtr) {
//currpulse=0;
pulsePol = g_model.pulsePol;//0;
// channel = 0 ;
// PulseTotal = 0 ;
#if defined (PCBV3)
TIMSK1 &= ~(1<<OCIE1A); //stop reentrance
#else
TIMSK &= ~(1<<OCIE1A); //stop reentrance
#endif
sei();
setupPulses();
#if !defined (PCBV3) && defined (DPPMPB7_HARDWARE)
// G: NOTE: This strategy does not work on the '2560 becasue you can't
// read the PPM out pin when connected to OC1B. Vincent says
// it works on the '64A. I haven't personally tested it.
if (PINB & (1<<OUT_B_PPM) && g_model.pulsePol)
TCCR1C=(1<<FOC1C);
// G: NOTE: This strategy does not work on the '2560 becasue you can't
// read the PPM out pin when connected to OC1B. Vincent says
// it works on the '64A. I haven't personally tested it.
if (PINB & (1<<OUT_B_PPM) && g_model.pulsePol)
TCCR1C=(1<<FOC1C);
#endif
cli();
cli();
#if defined (PCBV3)
TIMSK1 |= (1<<OCIE1A);
TIMSK1 |= (1<<OCIE1A);
#else
TIMSK |= (1<<OCIE1A);
TIMSK |= (1<<OCIE1A);
#endif
sei();
sei();
}
}
if (dt > g_tmr1Latency_max) g_tmr1Latency_max = dt;
if (dt < g_tmr1Latency_min) g_tmr1Latency_min = dt;
heartbeat |= HEART_TIMER2Mhz;
}
@@ -167,7 +220,7 @@ inline void __attribute__ ((always_inline)) setupPulsesPXX()
#endif
#ifdef DSM2
#ifdef DSM2_SERIAL
// DSM2 protocol pulled from th9x - Thanks thus!!!
@@ -199,55 +252,56 @@ normal:
*/
inline void __attribute__ ((always_inline)) _send_1(uint16_t v)
#define DSM2_CHANS 6
inline void __attribute__ ((always_inline)) setupPulsesDsm2()
{
*pulses2MHzWPtr++ = v;
if (isFunctionActive(FUNC_LOGS)) {*pulses2MHzWPtr++ = 0x80;}
//elseif (somerangetestvariable) {*pulses2MHzWPtr++ = 0x20;}
else *pulses2MHzWPtr++ = 0x00;
*pulses2MHzWPtr++ = g_eeGeneral.currModel;
for (uint8_t i=0; i<DSM2_CHANS; i++) {
uint16_t pulse = limit(0, (g_chans512[i]>>1)+512, 1023);
*pulses2MHzWPtr++ = (i<<2) | ((pulse>>8)&0x03);
*pulses2MHzWPtr++ = pulse & 0xff;
}
}
#define BITLEN_DSM2 (8*2) //125000 Baud
inline void __attribute__ ((always_inline)) sendByteDsm2(uint8_t b) //max 10changes 0 10 10 10 10 1
void DSM2_Done()
{
bool lev = 0;
uint8_t len = BITLEN_DSM2; //max val: 9*16 < 256
for( uint8_t i=0; i<=8; i++){ //8Bits + Stop=1
bool nlev = b & 1; //lsb first
if(lev == nlev){
len += BITLEN_DSM2;
}else{
_send_1(len-1);
len = BITLEN_DSM2;
lev = nlev;
}
b = (b>>1) | 0x80; //shift in stop bit
}
_send_1(len + 10*BITLEN_DSM2 -1); //some more space-time for security
UCSR0B &= ~((1 << TXEN0) | (1 << UDRIE0)); // disable TX pin and interrupt
}
inline void __attribute__ ((always_inline)) setupPulsesDsm2(uint8_t chns)
void DSM2_Init(void)
{
static uint8_t dsmDat[2+6*2]={0x80,0, 0x00,0xAA, 0x05,0xFF, 0x09,0xFF, 0x0D,0xFF, 0x13,0x54, 0x14,0xAA};
#ifndef SIMU
static uint8_t state = 0;
DDRE &= ~(1 << DDE0); // set RXD0 pin as input
PORTE &= ~(1 << PORTE0); // disable pullup on RXD0 pin
if(state==0){
#undef BAUD
#define BAUD 125000
if((dsmDat[0] == 0) || ! keyState(SW_Trainer) ){ //init - bind!
dsmDat[0]=0; dsmDat[1]=0; //DSM2_Header = 0,0;
for(uint8_t i=0; i<chns; i++){
uint16_t pulse = limit(0, g_chans512[i]+512,1023);
dsmDat[2+2*i] = (i<<2) | ((pulse>>8)&0x03);
dsmDat[3+2*i] = pulse & 0xff;
}
}
}
sendByteDsm2(dsmDat[state++]);
sendByteDsm2(dsmDat[state++]);
if(state >= 2+chns*2){
pulses2MHzWPtr--; //remove last stopbits and
_send_1(20000u*2 -1); //prolong them
state=0;
}
#include <util/setbaud.h>
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
UCSR0A &= ~(1 << U2X0); // disable double speed operation.
// set 8N1
UCSR0B = 0 | (0 << RXCIE0) | (0 << TXCIE0) | (0 << UDRIE0) | (0 << RXEN0) | (0 << TXEN0) | (0 << UCSZ02);
UCSR0C = 0 | (1 << UCSZ01) | (1 << UCSZ00);
while (UCSR0A & (1 << RXC0)) UDR0; // flush receive buffer
pulses2MHzWPtr = pulses2MHz;
pulses2MHzRPtr = pulses2MHz;
setupPulsesDsm2();
// These should be running right from power up on a FrSky enabled '9X.
DSM2_EnableTXD(); // enable FrSky-Telemetry reception
#endif // SIMU
}
#endif
@@ -416,9 +470,6 @@ void setupPulses()
pulses2MHzRPtr = pulses2MHz;
switch(g_model.protocol) {
case PROTO_PPM:
setupPulsesPPM();
break;
#ifdef SILVER
case PROTO_SILV_A:
case PROTO_SILV_B:
@@ -436,11 +487,13 @@ void setupPulses()
setupPulsesPXX();
break;
#endif
#ifdef DSM2
#ifdef DSM2_SERIAL
case PROTO_DSM2:
setupPulsesDsm2(6);
setupPulsesDsm2();
break;
#endif
default:
setupPulsesPPM();
break;
}
}
+142
View File
@@ -0,0 +1,142 @@
/*
* Authors (alphabetical order)
* - Cameron Weeks <th9xer@gmail.com>
*
* gruvin9x is based on code named er9x by
* Author - Erez Raviv <erezraviv@gmail.com>, which is in turn
* was based on the original (and ongoing) project by Thomas Husterer,
* th9x -- http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
/*
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 "open9x.h"
// Start and stop bits need to be 2ms in duration. Start bit is low, stop bit is high
#define SOMOSSBIT 4 //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
bool TIMER4_COMPA_vect()
#else
#define BUSY
ISR(TIMER4_COMPA_vect) //Every 0.5ms
#endif
{
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
OCR4A = 0x7d; //another 0.5ms
// 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;
}
else if (!SOMOBUSY) {
if (somo14RIdx == somo14WIdx) {
// TODO disable the interrupt (and re-enable when a new prompt is pushed)?
return BUSY;
}
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 BUSY;
}
// 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 BUSY;
}
}
// 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 BUSY;
}
// 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++;
// Strictly speaking there should be a data setup delay in here of 1us
// Be we don't like no stinking delays !
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 BUSY;
}
void somoPushPrompt(uint16_t prompt)
{
somo14playlist[somo14WIdx] = prompt;
somo14WIdx = (somo14WIdx + 1) % QUEUE_LENGTH;
}
+21
View File
@@ -0,0 +1,21 @@
/*
* Authors (alphabetical order)
* - Cameron Weeks <th9xer@gmail.com>
*
* gruvin9x is based on code named er9x by
* Author - Erez Raviv <erezraviv@gmail.com>, which is in turn
* was based on the original (and ongoing) project by Thomas Husterer,
* th9x -- http://code.google.com/p/th9x/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
extern void somoPushPrompt(uint16_t prompt);
+6 -1
View File
@@ -57,12 +57,17 @@
#define TR_VCSWFUNC "---- ""v>ofs ""v<ofs ""|v|>ofs""|v|<ofs""AND ""OR ""XOR ""v1==v2 ""v1!=v2 ""v1>v2 ""v1<v2 ""v1>=v2 ""v1<=v2 "
#define LEN_VFSWFUNC 14
#if defined(DSM2)
#define TR_MODELMATCH "ModelMatch "
#else
#define TR_MODELMATCH
#endif
#ifdef LOGS
#define TR_SDCLOGGS "SDCARD Logs "
#else
#define TR_SDCLOGGS
#endif
#define TR_VFSWFUNC "---- ""Trainer ""Trainer RUD ""Trainer ELE ""Trainer THR ""Trainer AIL ""Instant Trim ""Trims2Offsets "TR_SDCLOGGS
#define TR_VFSWFUNC "---- ""Trainer ""Trainer RUD ""Trainer ELE ""Trainer THR ""Trainer AIL ""Instant Trim ""Trims2Offsets "TR_MODELMATCH TR_SDCLOGGS
#define LEN_VTELEMUNIT 1
#define TR_VTELEMUNIT "v""-"
+279
View File
@@ -0,0 +1,279 @@
// NON ZERO TERMINATED STRINGS
#define LEN_OFFON 3
#define TR_OFFON "OFF""ON "
#define LEN_MMMINV 3
#define TR_MMMINV "---""INV"
#define LEN_NCHANNELS 4
#define TR_NCHANNELS "4CH 6CH 8CH 10CH12CH14CH16CH"
#define LEN_VBEEPER 5
#define TR_VBEEPER "Quiet""NoKey""Norm ""Long ""xLong"
#define LEN_ADCFILTER 4
#define TR_ADCFILTER "SING""OSMP""FILT"
#define LEN_WARNSW 4
#define TR_WARNSW "Bas ""OFF ""Haut"
#define LEN_TRNMODE 3
#define TR_TRNMODE "off"" +="" :="
#define LEN_TRNCHN 3
#define TR_TRNCHN "ch1ch2ch3ch4"
#define LEN_DATETIME 5
#define TR_DATETIME "DATE:""TIME:"
#define LEN_VTRIMINC 6
#define TR_VTRIMINC "Exp ""ExFine""Fine ""Medium""Coarse"
#define LEN_RETA123 1
#define TR_RETA123 "RETA123"
#define LEN_VPROTOS 6
#define TR_VPROTOS "PPM ""PXX ""DSM2 ""SILV_A""SILV_B""SILV_C""TRAC09"
#define LEN_POSNEG 3
#define TR_POSNEG "POS""NEG"
#define LEN_VCURVEFUNC 3
#define TR_VCURVEFUNC "---""x>0""x<0""|x|""f>0""f<0""|f|"
#define LEN_CURVMODES 5
#define TR_CURVMODES "EDIT ""PRSET""A.GAZ"
#define LEN_EXPLABELS 6
#define TR_EXPLABELS "Weight""Expo ""Phase ""Inter ""When ""Courbe"" "
#define LEN_VMLTPX 8
#define TR_VMLTPX "Add ""Multiply""Replace "
#define LEN_VMLTPX2 2
#define TR_VMLTPX2 "+=""*="":="
#define LEN_VCSWFUNC 7
#define TR_VCSWFUNC "---- ""v>ofs ""v<ofs ""|v|>ofs""|v|<ofs""ET ""OU ""XOU ""v1==v2 ""v1!=v2 ""v1>v2 ""v1<v2 ""v1>=v2 ""v1<=v2 "
#define LEN_VFSWFUNC 14
#if defined(DSM2)
#define TR_MODELMATCH "ModelMatch "
#else
#define TR_MODELMATCH
#endif
#ifdef LOGS
#define TR_SDCLOGGS "SDCARD Logs "
#else
#define TR_SDCLOGGS
#endif
#define TR_VFSWFUNC "---- ""Ecolage ""Ecolage DER ""Ecolage PRF ""Ecolage GAZ ""Ecolage AIL ""Instant Trim ""Trims2Offsets "TR_MODELMATCH TR_SDCLOGGS
#define LEN_VTELEMUNIT 1
#define TR_VTELEMUNIT "v""-"
#define LEN_VALARM 3
#define TR_VALARM "---""Yel""Org""Red"
#define LEN_VALARMFN 1
#define TR_VALARMFN "<>"
#define LEN_VTELPROTO 4
#if defined(WS_HOW_HIGH)
#define TR_VTELPROTO "NoneHub WSHH"
#elif defined(FRSKY_HUB)
#define TR_VTELPROTO "NoneHub "
#endif
#define LEN_VTEMPLATES 12
#define TR_VTEMPLATES "Simple 4-CH ""T-Cut ""V-Tail ""Elevon\\Delta""eCCPM ""Heli Setup ""Servo Test "
#define LEN_VSWASHTYPE 6
#define TR_VSWASHTYPE "--- ""120 ""120X ""140 ""90 "
#define LEN_VKEYS 5
#define TR_VKEYS " Menu"" Exit"" Down"" Up""Right"" Left"
#define LEN_RE1RE2 3
#define TR_RE1RE2 "RE1""RE2"
#define LEN_VSWITCHES 3
#define TR_VSWITCHES "GAZ""DER""PRF""ID0""ID1""ID2""AIL""GEA""TRN""SW1""SW2""SW3""SW4""SW5""SW6""SW7""SW8""SW9""SWA""SWB""SWC"
#define LEN_VSRCRAW 4
#define TR_VSRCRAW "DER ""PRF ""GAZ ""AIL ""P1 ""P2 ""P3 ""MAX ""FULL""CYC1""CYC2""CYC3"
#define LEN_VTMRMODES 3
#define TR_VTMRMODES "OFF""ABS""GZs""GZ%""GZt"
#define LEN_TELEMCHNS 3
#if defined(FRSKY_HUB)
#define TR_TELEMCHNS "AD1AD2ALTRPM"
#elif defined(WS_HOW_HIGH)
#define TR_TELEMCHNS "AD1AD2ALT"
#elif defined(FRSKY)
#define TR_TELEMCHNS "AD1AD2"
#endif
// ZERO TERMINATED STRINGS
#define TR_POPUPS "[MENU] [EXIT]"
#define TR_MENUWHENDONE " [MENU] WHEN DONE"
#define TR_FREE "libre"
#define TR_DELETEMODEL "SUPPRIMER MODELE"
#define TR_COPYINGMODEL "Copying model..."
#define TR_MOVINGMODEL "Moving model..."
#define TR_LOADINGMODEL " Chargement..."
#define TR_NAME "Nom"
#define TR_TIMER "Timer"
#define TR_ELIMITS "E.Limits"
#define TR_ETRIMS "E.Trims"
#define TR_TRIMINC "Trim Inc"
#define TR_TTRACE "T-Trace"
#define TR_TTRIM "T-Trim"
#define TR_BEEPCTR "Beep Ctr"
#define TR_PROTO "Proto"
#define TR_PPMFRAME "PPM frame"
#define TR_MS "ms"
#define TR_SWITCH "Inter"
#define TR_TRIMS "Trims"
#define TR_FADEIN "Fade In"
#define TR_FADEOUT "Fade Out"
#define TR_DEFAULT "(default)"
#define TR_CHECKTRIMS "Check Trims"
#define TR_SWASHTYPE "Swash Type"
#define TR_COLLECTIVE "Collective"
#define TR_SWASHRING "Swash Ring"
#define TR_ELEDIRECTION "PRF Direction"
#define TR_AILDIRECTION "AIL Direction"
#define TR_COLDIRECTION "COL Direction"
#define TR_MODE "MODE"
#define TR_NOFREEEXPO "No free expo!"
#define TR_NOFREEMIXER "No free mixer!"
#define TR_INSERTMIX "INSERT MIX "
#define TR_EDITMIX "EDIT MIX "
#define TR_SOURCE "Source"
#define TR_WEIGHT "Weight"
#define TR_OFFSET "Offset"
#define TR_TRIM "Trim"
#define TR_CURVES "Courbe"
#define TR_FPHASE "P.Vol"
#define TR_WARNING "Warning"
#define TR_OFF "OFF"
#define TR_MULTPX "Multpx"
#define TR_DELAYDOWN "Delay Down"
#define TR_DELAYUP "Delay Up"
#define TR_SLOWDOWN "Slow Down"
#define TR_SLOWUP "Slow Up"
#define TR_DREXPO "DR/EXPO"
#define TR_MIXER "MIXER"
#define TR_COPYTRIMMENU "COPY TRIM [MENU]"
#define TR_CV "CV"
#define TR_SW "SW"
#define TR_ACHANNEL "A channel"
#define TR_MAX "Max"
#define TR_CALIB "Calib"
#define TR_BAR "Bar"
#define TR_ALARM "Alarm"
#define TR_USRPROTO "UsrProto"
#define TR_CLEARMIXMENU "CLEAR MIXES [MENU]"
#define TR_BEEPER "Beeper"
#define TR_CONTRAST "Contrast"
#define TR_BATTERYWARNING "Battery warning"
#define TR_INACTIVITYALARM "Inactivity alarm"
#define TR_FILTERADC "Filter ADC"
#define TR_THROTTLEREVERSE "Throttle reverse"
#define TR_MINUTEBEEP "Minute beep"
#define TR_BEEPCOUNTDOWN "Beep countdown"
#define TR_FLASHONBEEP "Flash on beep"
#define TR_LIGHTSWITCH "Light switch"
#define TR_LIGHTOFFAFTER "Light off after"
#define TR_SPLASHSCREEN "Splash screen"
#define TR_THROTTLEWARNING "Throttle Warning"
#define TR_SWITCHWARNING "Switch Warning"
#define TR_MEMORYWARNING "Memory Warning"
#define TR_ALARMWARNING "Alarm Warning"
#define TR_NODATAALARM "NO DATA Alarm"
#define TR_RXCHANNELORD "Rx Channel Ord"
#define TR_MODE2 "Mode"
#define TR_SLAVE "Esclave"
#define TR_MODESRC "mode % src"
#define TR_MULTIPLIER "Multiplier"
#define TR_CAL "Cal"
#define TR_EEPROMV "EEPROM v"
#define TR_VTRIM "Trim- +"
#define TR_BG "BG"
#define TR_MENUTOSTART " [MENU] TO START "
#define TR_SETMIDPOINT " SET MIDPOINT "
#define TR_MOVESTICKSPOTS " MOVE STICKS/POTS "
#define TR_ALT "Alt:"
#define TR_RXBATT "Rx Batt:"
#define TR_RX "Rx:"
#define TR_TX "Tx:"
#define TR_HDG "Hdg:"
#define TR_SPD "Spd:"
#define TR_TEMP1 "Temp1:"
#define TR_TEMP2 "Temp2:"
#define TR_RPM "RPM:"
#define TR_FUEL "Fuel:"
#define TR_VOLTS "Volts:"
#define TR_ACCEL "Accel"
#define TR_TELE "Tele:"
#define TR_RSSI "RSSI:"
#define TR_NODATA "NO DATA"
#define TR_TM1 "TM1"
#define TR_TM2 "TM2"
#define TR_THR "GAZ"
#define TR_TH "TH%"
#define TR_TOT "TOT"
#define TR_TMR1LATMAXUS "tmr1Lat max us"
#define TR_TMR1LATMINUS "tmr1Lat min us"
#define TR_TMR1JITTERUS "tmr1 Jitter us"
#define TR_TMAINMAXMS "tmain max ms"
#define TR_T10MSUS "t10ms us"
#define TR_FREESTACKMINB "Free Stack min b"
#define TR_MENUTORESET "[MENU] to reset"
#define TR_PPM "PPM"
#define TR_CH "CH"
#define TR_TMR "TMR"
#define TR_MODEL "MODEL"
#define TR_FP "PV"
#define TR_EEPROMLOWMEM "EEPROM low mem"
#define TR_ALERT "ALERT"
#define TR_PRESSANYKEYTOSKIP "Appuyez sur une touche"
#define TR_THROTTLENOTIDLE "Throttle not idle"
#define TR_RESETTHROTTLE "Reset throttle"
#define TR_ALARMSDISABLED "Alarmes Desactivees"
#define TR_SWITCHESNOTOFF "Switches not off"
#define TR_PLEASERESETTHEM "Please reset them"
#define TR_MESSAGE "MESSAGE"
#define TR_PRESSANYKEY "press any Key"
#define TR_BADEEPROMDATA "Bad EEprom Data"
#define TR_EEPROMFORMATTING "EEPROM Formatting"
#define TR_EEPROMOVERFLOW "EEPROM overflow"
#define TR_PULSETABOVERFLOW "PULSES OVERFLOW"
#define TR_MENURADIOSETUP "RADIO SETUP"
#define TR_MENUDATEANDTIME "DATE ET HEURE"
#define TR_MENUTRAINER "ECOLAGE"
#define TR_MENUVERSION "VERSION"
#define TR_MENUDIAG "DIAG"
#define TR_MENUANA "ANA"
#define TR_MENUCALIBRATION "CALIBRATION"
#define TR_MENUSERROR "MENUS OVERFLOW"
#define TR_MENUMODELSEL "MODELSEL"
#define TR_MENUSETUP "SETUP"
#define TR_MENUFLIGHTPHASE "PHASE DE VOL"
#define TR_MENUFLIGHTPHASES "PHASES DE VOL"
#define TR_MENUHELISETUP "HELI SETUP"
#define TR_MENUDREXPO "DR/EXPO"
#define TR_MENULIMITS "LIMITES"
#define TR_MENUCURVES "COURBES"
#define TR_MENUCURVE "COURBE"
#define TR_MENUCUSTOMSWITCHES "INTERS PERS"
#define TR_MENUFUNCSWITCHES "FUNC SWITCHES"
#define TR_MENUSAFETYSWITCHES "INTERS SECURITE"
#define TR_MENUTELEMETRY "TELEMETRIE"
#define TR_MENUTEMPLATES "GABARITS"
#define TR_MENUSTAT "STAT"
#define TR_MENUDEBUG "DEBUG"