11,6 → 11,13 |
unsigned int BeepMuster = 0xffff; |
int ServoValue = 0; |
|
volatile int16_t ServoNickValue = 0; |
volatile int16_t ServoRollValue = 0; |
|
#define HEF4017R_ON PORTC |= (1<<PORTC6) |
#define HEF4017R_OFF PORTC &= ~(1<<PORTC6) |
|
|
enum { |
STOP = 0, |
CK = 1, |
86,30 → 93,7 |
} |
} |
|
//---------------------------- |
void Timer_Init(void) |
{ |
tim_main = SetDelay(10); |
TCCR0B = CK8; |
TCCR0A = (1<<COM0A1)|(1<<COM0B1)|3;//fast PWM |
OCR0A = 0; |
OCR0B = 120; |
TCNT0 = (unsigned char)-TIMER_RELOAD_VALUE; // reload |
//OCR1 = 0x00; |
|
TCCR2A=(1<<COM2A1)|(1<<COM2A0)|3; |
// TCCR2B=(0<<CS20)|(1<<CS21)|(1<<CS22); // clk/256 |
TCCR2B=(0<<CS20)|(0<<CS21)|(1<<CS22); // clk/64 |
|
|
TIMSK2 |= _BV(OCIE2A); |
|
TIMSK0 |= _BV(TOIE0); |
OCR2A = 10; |
TCNT2 = 0; |
|
} |
|
// ----------------------------------------------------------------------- |
|
unsigned int SetDelay (unsigned int t) |
142,112 → 126,260 |
while (!CheckDelay(akt)) ANALOG_ON; |
} |
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
// Servo ansteuern |
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
SIGNAL(SIG_OVERFLOW2) |
/*****************************************************/ |
/* Initialize Timer 2 */ |
/*****************************************************/ |
// The timer 2 is used to generate the PWM at PD7 (J7) |
// to control a camera servo for nick compensation. |
void TIMER2_Init(void) |
{ |
if (ServoState > 0) PORTD |= 0x80; |
else PORTD &= ~0x80; |
TCCR2A =3; |
TIMSK2 &= ~_BV(TOIE2); |
uint8_t sreg = SREG; |
|
// disable all interrupts before reconfiguration |
cli(); |
|
// set PD7 as output of the PWM for nick servo |
DDRD |= (1<<DDD7); |
PORTD &= ~(1<<PORTD7); // set PD7 to low |
|
DDRC |= (1<<DDC6); // set PC6 as output (Reset for HEF4017) |
PORTC &= ~(1<<PORTC6); // set PC6 to low |
|
// Timer/Counter 2 Control Register A |
|
// Timer Mode is FastPWM with timer reload at OCR2A (Bits: WGM22 = 1, WGM21 = 1, WGM20 = 1) |
// PD7: Normal port operation, OC2A disconnected, (Bits: COM2A1 = 0, COM2A0 = 0) |
// PD6: Normal port operation, OC2B disconnected, (Bits: COM2B1 = 0, COM2B0 = 0) |
TCCR2A &= ~((1<<COM2A1)|(1<<COM2A0)|(1<<COM2B1)|(1<<COM2B0)); |
TCCR2A |= (1<<WGM21)|(1<<WGM20); |
|
// Timer/Counter 2 Control Register B |
|
// Set clock divider for timer 2 to SYSKLOCK/32 = 20MHz / 32 = 625 kHz |
// The timer increments from 0x00 to 0xFF with an update rate of 625 kHz or 1.6 us |
// hence the timer overflow interrupt frequency is 625 kHz / 256 = 2.44 kHz or 0.4096 ms |
|
// divider 32 (Bits: CS022 = 0, CS21 = 1, CS20 = 1) |
TCCR2B &= ~((1<<FOC2A)|(1<<FOC2B)|(1<<CS22)); |
TCCR2B |= (1<<CS21)|(1<<CS20)|(1<<WGM22); |
|
// Initialize the Timer/Counter 2 Register |
TCNT2 = 0; |
|
// Initialize the Output Compare Register A used for PWM generation on port PD7. |
OCR2A = 255; |
TCCR2A |= (1<<COM2A1); // set or clear at compare match depends on value of COM2A0 |
|
// Timer/Counter 2 Interrupt Mask Register |
// Enable timer output compare match A Interrupt only |
TIMSK2 &= ~((1<<OCIE2B)|(1<<TOIE2)); |
TIMSK2 |= (1<<OCIE2A); |
|
SREG = sreg; |
} |
|
SIGNAL(SIG_OUTPUT_COMPARE2A) |
//---------------------------- |
void Timer_Init(void) |
{ |
static unsigned char postPulse = 0x80; |
static int filterServo = 100; |
// static unsigned char restPulse = 50; |
#define MULTIPLIER 4 |
if(PlatinenVersion < 20) |
{ |
if(ServoState == 4) |
{ |
ServoValue = 0x0030; // Offset Part1 |
filterServo = (filterServo * 3 + (int) Parameter_ServoNickControl * 2)/4; |
ServoValue += filterServo; |
if(EE_Parameter.ServoNickCompInvert & 0x01) ServoValue += (int)( ( (long)EE_Parameter.ServoNickComp * (IntegralNick / 128L) ) / (512L/MULTIPLIER) ); |
else ServoValue -= (int)( ( (long)EE_Parameter.ServoNickComp * (IntegralNick / 128L) ) / (512L/MULTIPLIER) ); |
if((ServoValue) < ((int)EE_Parameter.ServoNickMin*3)) ServoValue = (int)EE_Parameter.ServoNickMin*3; |
else if((ServoValue) > ((int)EE_Parameter.ServoNickMax*3)) ServoValue = (int)EE_Parameter.ServoNickMax*3; |
tim_main = SetDelay(10); |
TCCR0B = CK8; |
TCCR0A = (1<<COM0A1)|(1<<COM0B1)|3;//fast PWM |
OCR0A = 0; |
OCR0B = 120; |
TCNT0 = (unsigned char)-TIMER_RELOAD_VALUE; // reload |
//OCR1 = 0x00; |
|
DebugOut.Analog[20] = ServoValue; |
if ((ServoValue % 255) < 45) { ServoValue+= 77; postPulse = 0x60 - 77; } else postPulse = 0x60; |
OCR2A = 255-(ServoValue % 256); |
TCCR2A=(1<<COM2A1)|(1<<COM2A0)|3; |
TIMSK0 |= _BV(TOIE0); |
} |
|
|
/*****************************************************/ |
/* Control Servo Position */ |
/*****************************************************/ |
|
ISR(TIMER2_COMPA_vect) |
{ |
|
// frame len 22.5 ms = 14063 * 1.6 us |
// stop pulse: 0.3 ms = 188 * 1.6 us |
// min servo pulse: 0.6 ms = 375 * 1.6 us |
// max servo pulse: 2.4 ms = 1500 * 1.6 us |
// resolution: 1500 - 375 = 1125 steps |
|
#define IRS_RUNTIME 127 |
#define PPM_STOPPULSE 188 |
// #define PPM_FRAMELEN (14063 |
#define PPM_FRAMELEN (1757 * EE_Parameter.ServoNickRefresh) |
#define MINSERVOPULSE 375 |
#define MAXSERVOPULSE 1500 |
#define SERVORANGE (MAXSERVOPULSE - MINSERVOPULSE) |
|
static uint8_t PulseOutput = 0; |
static uint16_t RemainingPulse = 0; |
static uint16_t ServoFrameTime = 0; |
static uint8_t ServoIndex = 0; |
|
#define MULTIPLYER 4 |
static int16_t ServoNickOffset = (255 / 2) * MULTIPLYER; // initial value near center positon |
|
|
if(PlatinenVersion < 20) |
{ |
//--------------------------- |
// Nick servo state machine |
//--------------------------- |
if(!PulseOutput) // pulse output complete |
{ |
if(TCCR2A & (1<<COM2A0)) // we had a low pulse |
{ |
TCCR2A &= ~(1<<COM2A0);// make a high pulse |
RemainingPulse = MINSERVOPULSE + SERVORANGE/2; // center position ~ 1.5ms |
|
ServoNickOffset = (ServoNickOffset * 3 + (int16_t)Parameter_ServoNickControl * MULTIPLYER) / 4; // lowpass offset |
ServoNickValue = ServoNickOffset; // offset (Range from 0 to 255 * 3 = 765) |
if(EE_Parameter.ServoNickCompInvert & 0x01) |
{ // inverting movement of servo |
ServoNickValue += (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) ); |
} |
else |
{ // non inverting movement of servo |
ServoNickValue -= (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) ); |
} |
// limit servo value to its parameter range definition |
if(ServoNickValue < ((int16_t)EE_Parameter.ServoNickMin * MULTIPLYER) ) |
{ |
ServoNickValue = (int16_t)EE_Parameter.ServoNickMin * MULTIPLYER; |
} |
else |
if(ServoNickValue > ((int16_t)EE_Parameter.ServoNickMax * MULTIPLYER) ) |
{ |
ServoNickValue = (int16_t)EE_Parameter.ServoNickMax * MULTIPLYER; |
} |
|
RemainingPulse += ServoNickValue - (256 / 2) * MULTIPLYER; // shift ServoNickValue to center position |
|
ServoNickValue /= MULTIPLYER; |
DebugOut.Analog[20] = ServoNickValue; |
|
// range servo pulse width |
if(RemainingPulse > MAXSERVOPULSE ) RemainingPulse = MAXSERVOPULSE; // upper servo pulse limit |
else if(RemainingPulse < MINSERVOPULSE ) RemainingPulse = MINSERVOPULSE; // lower servo pulse limit |
// accumulate time for correct update rate |
ServoFrameTime = RemainingPulse; |
} |
else // we had a high pulse |
{ |
TCCR2A |= (1<<COM2A0); // make a low pulse |
RemainingPulse = PPM_FRAMELEN - ServoFrameTime; |
} |
// set pulse output active |
PulseOutput = 1; |
} |
} // EOF Nick servo state machine |
else |
{ |
//----------------------------------------------------- |
// PPM state machine, onboard demultiplexed by HEF4017 |
//----------------------------------------------------- |
if(!PulseOutput) // pulse output complete |
{ |
if(TCCR2A & (1<<COM2A0)) // we had a low pulse |
{ |
TCCR2A &= ~(1<<COM2A0);// make a high pulse |
|
if(ServoIndex == 0) // if we are at the sync gap |
{ |
RemainingPulse = PPM_FRAMELEN - ServoFrameTime; // generate sync gap by filling time to full frame time |
ServoFrameTime = 0; // reset servo frame time |
HEF4017R_ON; // enable HEF4017 reset |
} |
else // servo channels |
{ |
RemainingPulse = MINSERVOPULSE + SERVORANGE/2; // center position ~ 1.5ms |
switch(ServoIndex) // map servo channels |
{ |
case 1: // Nick Compensation Servo |
ServoNickOffset = (ServoNickOffset * 3 + (int16_t)Parameter_ServoNickControl * MULTIPLYER) / 4; // lowpass offset |
ServoNickValue = ServoNickOffset; // offset (Range from 0 to 255 * 3 = 765) |
if(EE_Parameter.ServoNickCompInvert & 0x01) |
{ // inverting movement of servo |
ServoNickValue += (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) ); |
} |
else |
{ // non inverting movement of servo |
ServoNickValue -= (int16_t)( ( (int32_t)EE_Parameter.ServoNickComp * MULTIPLYER * (IntegralNick / 128L ) ) / (256L) ); |
} |
// limit servo value to its parameter range definition |
if(ServoNickValue < ((int16_t)EE_Parameter.ServoNickMin * MULTIPLYER) ) |
{ |
ServoNickValue = (int16_t)EE_Parameter.ServoNickMin * MULTIPLYER; |
} |
else |
if(ServoNickValue > ((int16_t)EE_Parameter.ServoNickMax * MULTIPLYER) ) |
{ |
ServoNickValue = (int16_t)EE_Parameter.ServoNickMax * MULTIPLYER; |
} |
RemainingPulse += ServoNickValue - (256 / 2) * MULTIPLYER; // shift ServoNickValue to center position |
ServoNickValue /= MULTIPLYER; |
DebugOut.Analog[20] = ServoNickValue; |
break; |
|
default: // other servo channels |
RemainingPulse += 2 * PPM_in[ServoIndex]; // add channel value, factor of 2 because timer 1 increments 3.2µs |
break; |
} |
// range servo pulse width |
if(RemainingPulse > MAXSERVOPULSE ) RemainingPulse = MAXSERVOPULSE; // upper servo pulse limit |
else if(RemainingPulse < MINSERVOPULSE ) RemainingPulse = MINSERVOPULSE; // lower servo pulse limit |
// substract stop pulse width |
RemainingPulse -= PPM_STOPPULSE; |
// accumulate time for correct sync gap |
ServoFrameTime += RemainingPulse; |
} |
} |
else // we had a high pulse |
{ |
TCCR2A |= (1<<COM2A0); // make a low pulse |
// set pulsewidth to stop pulse width |
RemainingPulse = PPM_STOPPULSE; |
// accumulate time for correct sync gap |
ServoFrameTime += RemainingPulse; |
HEF4017R_OFF; // disable HEF4017 reset |
ServoIndex++; // change to next servo channel |
if(ServoIndex > EE_Parameter.ServoNickRefresh) ServoIndex = 0; // reset to the sync gap |
} |
// set pulse output active |
PulseOutput = 1; |
} |
} // EOF PPM state machine |
|
// General pulse output generator |
if(RemainingPulse > (255 + IRS_RUNTIME)) |
{ |
OCR2A = 255; |
RemainingPulse -= 255; |
} |
else if ((ServoState > 0) && (ServoState < 4)) |
{ |
if(ServoValue > 255) |
{ PORTD |= 0x80; |
TCCR2A =3; |
ServoValue -= 255; |
} |
else |
{ |
TCCR2A=(1<<COM2A1)|(0<<COM2A0)|3; |
OCR2A = postPulse; // Offset Part2 |
ServoState = 1; |
} |
} |
else if (ServoState == 0) |
{ |
ServoState = (int) EE_Parameter.ServoNickRefresh * MULTIPLIER; |
PORTD&=~0x80; |
TCCR2A = 3; |
} |
} |
else |
{ |
if(ServoState == 4) |
{ |
PORTD &= ~0x80; |
PORTC |= _BV(PC6); |
ServoValue = 0x00030; // Offset Part1 |
filterServo = (filterServo * 3 + (int) Parameter_ServoNickControl * 2)/4; |
ServoValue += filterServo; |
if(EE_Parameter.ServoNickCompInvert & 0x01) ServoValue += (int)( ( (long)EE_Parameter.ServoNickComp * (IntegralNick / 128L) ) / (512L/MULTIPLIER) ); |
else ServoValue -= (int)( ( (long)EE_Parameter.ServoNickComp * (IntegralNick / 128L) ) / (512L/MULTIPLIER) ); |
if((ServoValue) < ((int)EE_Parameter.ServoNickMin*3)) ServoValue = (int)EE_Parameter.ServoNickMin*3; |
else if((ServoValue) > ((int)EE_Parameter.ServoNickMax*3)) ServoValue = (int)EE_Parameter.ServoNickMax*3; |
PORTD |= 0x80; // dummy clock to skip output Q0 |
if ((ServoValue % 256) < 1) ServoValue -=2; |
if ((ServoValue % 256) > 253) ServoValue +=2; |
DebugOut.Analog[20] = ServoValue; |
|
OCR2A = 254-(ServoValue % 255); |
PORTD &= ~0x80; |
|
TCCR2A=(1<<COM2A1)|(1<<COM2A0)|3; // set on match |
//ServoValue -= OCR2A; |
PORTC &= ~_BV(PC6); |
} |
else if ((ServoState > 0) && (ServoState < 4)) |
{ |
if(ServoValue > 255) |
{ |
PORTD &= ~0x80; |
TCCR2A =3; |
ServoValue -= 255; |
OCR2A = postPulse; // Offset Part2 |
//OCR2A = (ServoValue % 256); |
} |
else |
{ |
OCR2A = postPulse; // Offset Part2 |
//OCR2A = (ServoValue % 256); |
//TCCR2A=(1<<COM2A1)|(1<<COM2A0)|3; |
ServoState = 1; |
} |
} |
else if (ServoState == 0) |
{ |
PORTD &= ~0x80; |
TCCR2A=(1<<COM2A1)|(1<<COM2A0)|3; |
ServoState = (int) EE_Parameter.ServoNickRefresh * MULTIPLIER; |
TCCR2A =3; |
} |
} |
ServoState--; |
else |
{ |
if(RemainingPulse > 255) // this is the 2nd last part |
{ |
if((RemainingPulse - 255) < IRS_RUNTIME) |
{ |
OCR2A = 255 - IRS_RUNTIME; |
RemainingPulse -= 255 - IRS_RUNTIME; |
|
} |
else // last part > ISR_RUNTIME |
{ |
OCR2A = 255; |
RemainingPulse -= 255; |
} |
} |
else // this is the last part |
{ |
OCR2A = RemainingPulse; |
RemainingPulse = 0; |
PulseOutput = 0; // trigger to stop pulse |
} |
} // EOF general pulse output generator |
} |
|