/************************************************************************ Radio switch servo decoder Copyright (c) 2002 Andy Birkett This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. 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. You may view the GNU General Public License at http://www.gnu.org/copyleft/gpl.html or write to: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. mailto:AndyBirkett.Planes@gaspode.co.uk http://www.gaspode.co.uk ************************************************************************/ /* 16f84: ; --------- ; <->RA2 |1 18| RA1<-> ; <->RA3 |2 17| RA0<-> ; <->RA4 |3 16| osc -xtal---||--0V ; -->CLR |4 15| osc -xtal---||--0V ; 0V |5 14| 5V ; int <->RB0 |6 13| RB7<-> int ; <->RB1 |7 12| RB6<-> int ; <->RB2 |8 11| RB5<-> int ; <->RB3 |9 10| RB4<-> int ; --------- 12C508a: ; --------- ; 5V |1 18| 0V ; elevatorB <->GP5 |2 17| GP0<-> Throttle ; elevatorA <->GP4 |3 16| GP1<-> RudderA ; rx i/p -->GP3 |4 15| GP2<-> RudderB ; --------- */ /* What a servo o/p look like: <-------------- 21 ms --------------------------> <- 1 to 2.5ms -> ----------------- ---- channel x -- ------------------------------- typical values Mine, Colins worst case Used ( 1 lot of 35 towards centre) full trim 990 (est) 1010 n/a left / up 1120 1090 1120 1155 centre 1520 1500 1500 1500 right / down 1980 1950 1950 1915 full trim 2110 (est) 2070 n/a for simple switch operation if < 1300 => left if > 1700 => right otherwise centre */ // 16F84A can be used for testing the code #define PIC84 // Skip settle time for simulation //#define SIMULATE #ifdef PIC84 #include "..\compiler\cc5xfree\16f84a.h" #define CP_off |= 0x3FF8 #pragma config PWRTE=on, WDTE=off, FOSC=HS, CP_off #else #include "..\compiler\cc5xfree\12C508a.h" /* bit 0 0} bit 1 1}=> Internal RC bit 2 0=>Watchdog disabled bit 3 1=>No code protecr bit 4 0=>mclr pin NOT used */ #define NO_MCLR &= ~0x80 #define CP_off |= 0xFFE8 #define INTERNAL_RX |= 2 #pragma config INTERNAL_RX, CP_off, WDTE=off #endif /***********/ /* DEFINES */ /***********/ #define LEFT 0 #define CENTRE 1 #define RIGHT 2 #define PRESCALER_VALUE 3 //A value of 3 gives a pre-scaler of 16, this meas the counter will count to 4096µS #define MICRO_SECONDS_AT_FULL_COUNT 4096 #define MICRO_SECONDS_PER_COUNT (4096/256) #define STICK_LEFT_TIME 1300 #define STICK_RIGHT_TIME 1700 #define STICK_LEFT_COUNT (STICK_LEFT_TIME / MICRO_SECONDS_PER_COUNT) // 81 #define STICK_RIGHT_COUNT (STICK_RIGHT_TIME / MICRO_SECONDS_PER_COUNT) // 106 #define FALSE 0 #define TRUE 1 /************/ /* VARIABLES */ /************/ #ifdef PIC84 /* Outputs */ // Assignment for PIC84 #pragma bit OP_LEFT @ PORTB.0 #pragma bit OP_RIGHT @ PORTB.1 #pragma bit OP_LEFT_TOGGLE @ PORTB.2 #pragma bit OP_RIGHT_TOGGLE @ PORTB.3 #pragma bit OP_CENTRE @ PORTA.0 /* Input */ #pragma bit ip_rx @ PORTB.6 // bit stream from receiver #else /* Outputs */ // Assignment for PIC12508 #pragma bit OP_LEFT @ GPIO.0 #pragma bit OP_RIGHT @ GPIO.1 #pragma bit OP_LEFT_TOGGLE @ GPIO.2 // Note a gap since we can't use bit 3 of gpio as o/p #pragma bit OP_RIGHT_TOGGLE @ GPIO.4 #pragma bit OP_CENTRE @ GPIO.5 /* Input */ // NB bit 3 must be an input #pragma bit ip_rx @ GPIO.3 // bit stream from receiver #endif // General counter unsigned char nTimer; unsigned char nLastPosition; /************************************************************/ // Routine to read the input and measure how long it is high /************************************************************/ static void ReadInput() { // Initally look a low while (ip_rx) { } // Now wait for it to go high while (!ip_rx) { } // measure how long it is high TMR0 = 0; while (ip_rx) { } // and return the value nTimer = TMR0; } // static char ReadInput() void waitHalfSecond() { unsigned long nDelay; // each loop takes 10µS for (nDelay=0;nDelay < (500000/10);nDelay++); } /***************************************************************/ /* MAIN */ /***************************************************************/ void main( void) { #ifdef PIC84 // switch banks during inittialisation #pragma update_RP 1 PORTA = 0; TRISA = 0xF0; /* bit 0..3 outputs */ TRISB = 0xF0; /* bit 0..3 outputs */ #else OSCCAL = W; GPIO = 0; TRIS = 0x08; /* bit 3 i/p bits 0,1,2,4,5 o/p */ #endif #ifdef PIC84 // OPTION = 0x0; /* prescaler divide by 2 */ // PSA = 1; /* prescale WDT */ OPTION = PRESCALER_VALUE; /* prescale timer by 16 */ // RBPU_ = 1; #else // OPTION = 0x8; /* prescaler divide by 2 - prescale WDT */ OPTION = PRESCALER_VALUE; /* prescale timer by 16 */ #endif TMR0 = 0; #ifdef PIC84 // don't switch banks again #pragma update_RP 0 #endif nTimer = 0; nLastPosition = CENTRE; #ifndef SIMULATE // wait for everything to settle!!! waitHalfSecond(); waitHalfSecond(); #endif // Main loop while (1) { // Read current value of servo input ReadInput(); if (nTimer < STICK_LEFT_COUNT) { // stick is left OP_LEFT = TRUE; OP_RIGHT = FALSE; OP_CENTRE = FALSE; if (nLastPosition != LEFT) OP_LEFT_TOGGLE = !OP_LEFT_TOGGLE; nLastPosition = LEFT; } else if (nTimer > STICK_RIGHT_COUNT) { // stick is right OP_LEFT = FALSE; OP_RIGHT = TRUE; OP_CENTRE = FALSE; if (nLastPosition != RIGHT) OP_RIGHT_TOGGLE = !OP_RIGHT_TOGGLE; nLastPosition = RIGHT; } else { // stick is in the middle OP_LEFT = FALSE; OP_RIGHT = FALSE; OP_CENTRE = TRUE; nLastPosition = CENTRE; } } // while (1) } // main