Some RAM saved in getADC functions (port from er9x). Reverse throttle issue 14 solved. Bug in mixer delays. PPM frame length configurable.

This commit is contained in:
bsongis
2011-11-18 18:45:12 +00:00
parent a9a8947744
commit afe2e339b3
6 changed files with 129 additions and 82 deletions
+41 -35
View File
@@ -757,51 +757,46 @@ uint16_t anaIn(uint8_t chan)
#define ADC_VREF_TYPE 0x40 // AVCC with external capacitor at AREF pin
void getADC_filt()
{
static uint16_t t_ana[3][8];
for (uint8_t adc_input=0;adc_input<8;adc_input++)
{
static uint16_t t_ana[2][8];
for (uint8_t adc_input=0; adc_input<8; adc_input++) {
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Do this while waiting
s_anaFilt[adc_input] = (s_anaFilt[adc_input]/2 + t_ana[1][adc_input]) & 0xFFFE; //gain of 2 on last conversion - clear last bit
t_ana[1][adc_input] = (t_ana[1][adc_input] + t_ana[0][adc_input]) >> 1;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
s_anaFilt[adc_input] = (s_anaFilt[adc_input]/2 + t_ana[1][adc_input]) & 0xFFFE; //gain of 2 on last conversion - clear last bit
//t_ana[2][adc_input] = (t_ana[2][adc_input] + t_ana[1][adc_input]) >> 1;
t_ana[1][adc_input] = (t_ana[1][adc_input] + t_ana[0][adc_input]) >> 1;
t_ana[0][adc_input] = (t_ana[0][adc_input] + ADCW ) >> 1;
}
}
/*
s_anaFilt[chan] = (s_anaFilt[chan] + sss_ana[chan]) >> 1;
sss_ana[chan] = (sss_ana[chan] + ss_ana[chan]) >> 1;
ss_ana[chan] = (ss_ana[chan] + s_ana[chan]) >> 1;
s_ana[chan] = (ADC + s_ana[chan]) >> 1;
*/
void getADC_osmp()
{
uint16_t temp_ana[8] = {0};
for (uint8_t adc_input=0;adc_input<8;adc_input++)
{
ADMUX=adc_input|ADC_VREF_TYPE; // TODO now it is done only one time before the loop, is it good?
uint16_t temp_ana;
for (uint8_t adc_input=0; adc_input<8; adc_input++) {
temp_ana = 0;
ADMUX = adc_input|ADC_VREF_TYPE;
for (uint8_t i=0; i<4;i++) { // Going from 10bits to 11 bits. Addition = n. Loop 4^n times
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
temp_ana[adc_input] += ADCW;
temp_ana += ADCW;
}
s_anaFilt[adc_input] = temp_ana[adc_input] / 2; // divide by 2^n to normalize result.
s_anaFilt[adc_input] = temp_ana / 2; // divide by 2^n to normalize result.
}
}
void getADC_single()
{
for (uint8_t adc_input=0;adc_input<8;adc_input++)
{
for (uint8_t adc_input=0; adc_input<8; adc_input++) {
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
@@ -812,13 +807,20 @@ void getADC_single()
}
}
getADCp getADC[3] = {
getADC_single,
getADC_osmp,
getADC_filt
};
void getADC_bandgap()
{
#if defined(PCBSTD)
ADMUX=0x1E|ADC_VREF_TYPE; // Switch MUX to internal 1.22V reference
_delay_us(10); // short delay to stablise reference voltage
ADCSRA|=0x40; while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; // grab a sample
ADCSRA|=0x40; while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; // grab a sample
_delay_us(5); // short delay to stablise reference voltage
ADCSRA|=0x40;
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10; // grab a sample
BandGap=ADCW;
#elif defined (PCBV4)
// For PCB V4, use our own 1.2V, external reference (connected to ADC3)
@@ -846,11 +848,6 @@ void getADC_bandgap()
#endif
}
getADCp getADC[3] = {
getADC_single,
getADC_osmp,
getADC_filt
};
#else
uint16_t BandGap = 225;
#endif
@@ -1104,9 +1101,9 @@ inline void evalTrims()
int32_t vv = 2*RESX;
int16_t trim = getTrimValue(getTrimFlightPhase(i), i);
if (IS_THROTTLE(i) && g_model.thrTrim) {
vv = (g_eeGeneral.throttleReversed) ?
((int32_t)trim+TRIM_MIN)*(RESX+v)/(2*RESX) :
((int32_t)trim-TRIM_MIN)*(RESX-v)/(2*RESX);
if (g_eeGeneral.throttleReversed)
trim = -trim;
vv = ((int32_t)trim-TRIM_MIN)*(RESX-v)/(2*RESX);
}
else if (trimsCheckTimer > 0) {
trim = 0;
@@ -1147,6 +1144,10 @@ uint8_t evalSticks()
if(v <= -RESX) v = -RESX;
if(v >= RESX) v = RESX;
if (g_eeGeneral.throttleReversed && i==THR_STICK)
v = -v;
calibratedStick[i] = v; //for show in expo
if(!(v/16)) anaCenter |= 1<<(CONVERT_MODE((i+1))-1);
@@ -1367,13 +1368,15 @@ void perOut(int16_t *chanOut)
if(diff) sDelay[i] = (diff<0 ? md->delayUp : md->delayDown) * 100;
}
if(sDelay[i]){ // perform delay
if(tick10ms) sDelay[i]--;
v = act[i]/DEL_MULT;
if (sDelay[i]) { // perform delay
if(tick10ms) sDelay[i]--;
if (sDelay[i] != 0) {
v = act[i]/DEL_MULT; // Stay in old position until delay over
diff = 0;
}
}
if(diff && (md->speedUp || md->speedDown)){
if (diff && (md->speedUp || md->speedDown)) {
//rate = steps/sec => 32*1024/100*md->speedUp/Down
//act[i] += diff>0 ? (32768)/((int16_t)100*md->speedUp) : -(32768)/((int16_t)100*md->speedDown);
//-100..100 => 32768 -> 100*83886/256 = 32768, For MAX we divide by 2 sincde it's asymmetrical
@@ -1387,6 +1390,9 @@ void perOut(int16_t *chanOut)
if(((diff>0) && (v<(act[i]/DEL_MULT))) || ((diff<0) && (v>(act[i]/DEL_MULT)))) act[i]=(int32_t)v*DEL_MULT; //deal with overflow
v = act[i]/DEL_MULT;
}
else if (diff) {
act[i]=(int32_t)v*DEL_MULT;
}
}
//========== CURVES ===============
+36 -13
View File
@@ -373,10 +373,10 @@ void EditName(uint8_t x, uint8_t y, char *name, uint8_t size, uint8_t event, boo
}
}
#define PARAM_OFS (9*FW)
#define PARAM_OFS (9*FW+2)
void menuProcModel(uint8_t event)
{
MENU("SETUP", menuTabModel, e_Model, 10, {0,sizeof(g_model.name)-1,3,3,0,0,0,1,6,3});
MENU("SETUP", menuTabModel, e_Model, (g_model.protocol ? 10 : 11), {0,sizeof(g_model.name)-1,3,3,0,0,0,1,6,2,1});
uint8_t sub = m_posVert;
uint8_t y = 1*FH;
@@ -468,7 +468,7 @@ void menuProcModel(uint8_t event)
if(s_pgOfs<subN) {
lcd_puts_P( 0, y, PSTR("Beep Ctr"));
for(uint8_t i=0;i<7;i++) lcd_putsnAtt((9+i)*FW, y, PSTR("RETA123")+i,1, ((m_posHorz==i) && (sub==subN)) ? BLINK : ((g_model.beepANACenter & (1<<i)) ? INVERS : 0 ) );
for(uint8_t i=0;i<7;i++) lcd_putsnAtt(PARAM_OFS+i*FW, y, PSTR("RETA123")+i,1, ((m_posHorz==i) && (sub==subN)) ? BLINK : ((g_model.beepANACenter & (1<<i)) ? INVERS : 0 ) );
if(sub==subN){
if((event==EVT_KEY_FIRST(KEY_MENU)) || p1valdiff) {
killEvents(event);
@@ -481,17 +481,20 @@ void menuProcModel(uint8_t event)
}subN++;
if(s_pgOfs<subN) {
lcd_puts_P( 0, y, PSTR("Proto"));
lcd_putsnAtt( 6*FW, y, PSTR(PROT_STR)+PROT_STR_LEN*g_model.protocol,PROT_STR_LEN,
lcd_puts_P(0, y, PSTR("Proto"));
lcd_putsnAtt(PARAM_OFS, y, PSTR(PROT_STR)+PROT_STR_LEN*g_model.protocol,PROT_STR_LEN,
(sub==subN && m_posHorz==0 ? (s_editMode ? BLINK : INVERS):0));
if(!g_model.protocol) {
lcd_putsnAtt(10*FW-2, y, PSTR("4CH 6CH 8CH 10CH12CH14CH16CH")+4*(g_model.ppmNCH+2),4,(sub==subN && m_posHorz==1 ? (s_editMode ? BLINK : INVERS):0));
lcd_putsAtt(17*FW-2, y, PSTR("u"),0);
lcd_outdezAtt(17*FW-2, y, (g_model.ppmDelay*50)+300, (sub==subN && m_posHorz==2 ? (s_editMode ? BLINK : INVERS):0));
lcd_putsnAtt(19*FW-4, y, PSTR("POSNEG")+3*g_model.pulsePol,3,(sub==subN && m_posHorz==3 ? (s_editMode ? BLINK : INVERS):0));
lcd_putsnAtt(PARAM_OFS+4*FW, y, PSTR("4CH 6CH 8CH 10CH12CH14CH16CH")+4*(g_model.ppmNCH+2),4,(sub==subN && m_posHorz==1 ? (s_editMode ? BLINK : INVERS):0));
lcd_putsAtt(PARAM_OFS+11*FW, y, PSTR("u"),0);
lcd_outdezAtt(PARAM_OFS+11*FW, y, (g_model.ppmDelay*50)+300, (sub==subN && m_posHorz==2 ? (s_editMode ? BLINK : INVERS):0));
}
if(sub==subN && (s_editMode || p1valdiff))
switch (m_posHorz){
else if (sub==subN) {
m_posHorz = 0;
CHECK_INCDEC_MODELVAR(event,g_model.protocol,0,PROT_MAX);
}
if(sub==subN && (s_editMode || p1valdiff)) {
switch (m_posHorz) {
case 0:
CHECK_INCDEC_MODELVAR(event,g_model.protocol,0,PROT_MAX);
break;
@@ -501,11 +504,31 @@ void menuProcModel(uint8_t event)
case 2:
CHECK_INCDEC_MODELVAR(event,g_model.ppmDelay,-4,10);
break;
case 3:
}
}
if((y+=FH)>7*FH) return;
}subN++;
if(s_pgOfs<subN) {
if (!g_model.protocol) {
lcd_puts_P(0, y, PSTR("PPM frame"));
lcd_puts_P(PARAM_OFS+3*FW, y, PSTR("ms"));
lcd_outdezAtt(PARAM_OFS, y, (int16_t)g_model.ppmFrameLength*5 + 225, ((sub==subN && m_posHorz==0) ? INVERS:0) | PREC1|LEFT);
lcd_putsnAtt(PARAM_OFS+6*FW, y, PSTR("POSNEG")+3*g_model.pulsePol,3,(sub==subN && m_posHorz==1 ? (s_editMode ? BLINK : INVERS):0));
if(sub==subN && (s_editMode || p1valdiff)) {
switch (m_posHorz) {
case 0:
CHECK_INCDEC_MODELVAR(event, g_model.ppmFrameLength, -20, 20);
break;
case 1:
CHECK_INCDEC_MODELVAR(event,g_model.pulsePol,0,1);
break;
}
}
if((y+=FH)>7*FH) return;
}
else {
}
}
}
+2 -1
View File
@@ -253,7 +253,8 @@ typedef struct t_ModelData {
FuncSwData funcSw[NUM_FSW];
SwashRingData swashR;
PhaseData phaseData[MAX_PHASES];
FrSkyData frsky;
FrSkyData frsky;
int8_t ppmFrameLength; // 0=22.5ms (10ms-30ms) 0.5msec increments
} __attribute__((packed)) ModelData;
extern EEGeneral g_eeGeneral;
+1
View File
@@ -204,6 +204,7 @@ uint8_t Translate()
}
for (uint8_t i=0; i<NUM_STICKS; i++)
setTrimValue(0, i, trims[i]);
g_model.ppmFrameLength = 0;
theFile.writeRlc(FILE_MODEL(id), FILE_TYP_MODEL, (uint8_t*)&g_model, sizeof(g_model), 200);
}
}
+2 -2
View File
@@ -139,11 +139,11 @@ inline void __attribute__ ((always_inline)) setupPulsesPPM() // changed 10/05/20
// G: Found the following reference at th9x. The below code does not seem
// to produce quite exactly this, to my eye. *shrug*
// http://www.aerodesign.de/peter/2000/PCM/frame_ppm.gif
uint16_t *ptr = pulses2MHz ; // TODO check this saves flash
uint16_t *ptr = pulses2MHzWPtr;
uint8_t p = 8+(g_model.ppmNCH*2); // channels count
uint16_t q = (g_model.ppmDelay*50+300)*2; //Stoplen *2
uint16_t rest = 22500u*2-q; //Minimum Framelen=22.5 ms
// TODO in er9x this line replaces the next one: rest += (int16_t(g_model.ppmFrameLength))*1000;
rest += (int16_t(g_model.ppmFrameLength))*1000;
if(p>9) rest=p*(1720u*2 + q) + 4000u*2; //for more than 9 channels, frame must be longer
for (uint8_t i=0; i<p; i++) {
int16_t v = max(min(g_chans512[i], PPM_range), -PPM_range) + PPM_CENTER;
+47 -31
View File
@@ -49,6 +49,24 @@
#include "gruvin9x.h"
#include "templates.h"
const char stn1[] APM = "Simple 4-CH";
const char stn2[] APM = "T-Cut";
const char stn3[] APM = "V-Tail";
const char stn4[] APM = "Elevon\\Delta";
const char stn5[] APM = "eCCPM";
const char stn6[] APM = "Heli Setup";
const char stn7[] APM = "Servo Test";
const prog_char* n_Templates[] =
{
stn1,
stn2,
stn3,
stn4,
stn5,
stn6,
stn7
};
MixData* setDest(uint8_t dch)
{
uint8_t i = 0;
@@ -74,12 +92,12 @@ void clearCurves()
memset(g_model.curves9,0,sizeof(g_model.curves9)); //clear all curves
}
void setCurve(uint8_t c, int8_t ar[])
void setCurve(uint8_t c, const prog_int8_t ar[])
{
if(c<MAX_CURVE5) //5 pt curve
for(uint8_t i=0; i<5; i++) g_model.curves5[c][i] = ar[i];
for(uint8_t i=0; i<5; i++) g_model.curves5[c][i] = pgm_read_byte(&ar[i]);
else //9 pt curve
for(uint8_t i=0; i<9; i++) g_model.curves9[c-MAX_CURVE5][i] = ar[i];
for(uint8_t i=0; i<9; i++) g_model.curves9[c-MAX_CURVE5][i] = pgm_read_byte(&ar[i]);
}
void setSwitch(uint8_t idx, uint8_t func, int8_t v1, int8_t v2)
@@ -89,15 +107,13 @@ void setSwitch(uint8_t idx, uint8_t func, int8_t v1, int8_t v2)
g_model.customSw[idx-1].v2 = v2;
}
const prog_int8_t APM heli_ar1[] = {-100, 20, 50, 70, 90};
const prog_int8_t APM heli_ar2[] = {90, 70, 50, 70, 90};
const prog_int8_t APM heli_ar3[] = {-20, -20, 0, 60, 100};
const prog_int8_t APM heli_ar4[] = {-100, -60, 0, 60, 100};
const prog_int8_t APM heli_ar5[] = {-100, 0, 0, 0, 100};
void applyTemplate(uint8_t idx)
{
int8_t heli_ar1[] = {-100, 20, 50, 70, 90};
int8_t heli_ar2[] = {90, 70, 50, 70, 90};
int8_t heli_ar3[] = {-20, -20, 0, 60, 100};
int8_t heli_ar4[] = {-100, -60, 0, 60, 100};
int8_t heli_ar5[] = {-100, 0, 0, 0, 100};
MixData *md = &g_model.mixData[0];
//CC(STK) -> vSTK
@@ -107,39 +123,39 @@ void applyTemplate(uint8_t idx)
for(uint8_t i=1; i<=4; i++) //generate inverse array
for(uint8_t j=1; j<=4; j++) if(CC(i)==j) icc[j-1]=i;
switch (idx){
//Simple 4-Ch
case (0):
// Simple 4-Ch
case (0):
clearMixes();
md=setDest(ICC(STK_RUD)); md->srcRaw=CM(STK_RUD); md->weight=100;
md=setDest(ICC(STK_ELE)); md->srcRaw=CM(STK_ELE); md->weight=100;
md=setDest(ICC(STK_THR)); md->srcRaw=CM(STK_THR); md->weight=100;
md=setDest(ICC(STK_AIL)); md->srcRaw=CM(STK_AIL); md->weight=100;
break;
//T-Cut
case (1):
// T-Cut
case (1):
md=setDest(ICC(STK_THR)); md->srcRaw=MIX_MAX; md->weight=-100; md->swtch=DSW_THR; md->mltpx=MLTPX_REP;
break;
//V-Tail
case (2):
// V-Tail
case (2):
md=setDest(ICC(STK_RUD)); md->srcRaw=CM(STK_RUD); md->weight= 100;
md=setDest(ICC(STK_RUD)); md->srcRaw=CM(STK_ELE); md->weight=-100;
md=setDest(ICC(STK_ELE)); md->srcRaw=CM(STK_RUD); md->weight= 100;
md=setDest(ICC(STK_ELE)); md->srcRaw=CM(STK_ELE); md->weight= 100;
break;
//Elevon\\Delta
case (3):
// Elevon\\Delta
case (3):
md=setDest(ICC(STK_ELE)); md->srcRaw=CM(STK_ELE); md->weight= 100;
md=setDest(ICC(STK_ELE)); md->srcRaw=CM(STK_AIL); md->weight= 100;
md=setDest(ICC(STK_AIL)); md->srcRaw=CM(STK_ELE); md->weight= 100;
md=setDest(ICC(STK_AIL)); md->srcRaw=CM(STK_AIL); md->weight=-100;
break;
//eCCPM
case (4):
// eCCPM
case (4):
md=setDest(ICC(STK_ELE)); md->srcRaw=CM(STK_ELE); md->weight= 72;
md=setDest(ICC(STK_ELE)); md->srcRaw=CM(STK_THR); md->weight= 55;
md=setDest(ICC(STK_AIL)); md->srcRaw=CM(STK_ELE); md->weight=-36;
@@ -150,8 +166,8 @@ void applyTemplate(uint8_t idx)
md=setDest(6); md->srcRaw=CM(STK_THR); md->weight= 55;
break;
//Heli Setup
case (5):
// Heli Setup
case (5):
clearMixes(); //This time we want a clean slate
clearCurves();
@@ -186,15 +202,15 @@ void applyTemplate(uint8_t idx)
md=setDest(11); md->srcRaw=CM(STK_THR); md->weight=100; md->swtch=DSW_THR; md->curve=CV(5); md->carryTrim=TRIM_OFF; md->mltpx=MLTPX_REP;
//Set up Curves
setCurve(CURVE5(1),heli_ar1);
setCurve(CURVE5(2),heli_ar2);
setCurve(CURVE5(3),heli_ar3);
setCurve(CURVE5(4),heli_ar4);
setCurve(CURVE5(5),heli_ar5);
setCurve(CURVE5(1), heli_ar1);
setCurve(CURVE5(2), heli_ar2);
setCurve(CURVE5(3), heli_ar3);
setCurve(CURVE5(4), heli_ar4);
setCurve(CURVE5(5), heli_ar5);
break;
//Servo Test
case (6):
// Servo Test
case (6):
md=setDest(15); md->srcRaw=CH(16); md->weight= 100; md->speedUp = 8; md->speedDown = 8;
md=setDest(16); md->srcRaw=MIX_FULL; md->weight= 110; md->swtch=DSW_SW1;
md=setDest(16); md->srcRaw=MIX_MAX; md->weight=-110; md->swtch=DSW_SW2; md->mltpx=MLTPX_REP;
@@ -210,6 +226,6 @@ void applyTemplate(uint8_t idx)
break;
}
STORE_MODELVARS;
STORE_MODELVARS;
}