/*
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 3 of the License, or
(at your option) 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 should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Multi Interface
*
* (c) 2008 By DROID s.a.s.
* developed by Marco d'Ambrosio
*
* Compilare con C18 v3.0 o superiore
* il programma � compatibile con la versione student
*
* PIC18F2520 clock 40MHz (quarzo da 10MHz con PLL 4X attivo)
*
* Versione 1.6.0 build 14/02/2008
*
* Interfacce gestite:
*
* I2C, read e write operation
* ADC, cinque canali a dieci bit
* PWM, due canali con direzione
* GPIO, 0-4-8 bit sia In che OUT
* RC Servo, 0-4-8 servo RC da -90� a +90� risoluzione 1us
* Comunicazione wireless tramite modulo Xbee a 115200 bps
* Comunicazione seriale TTL tra 1200 e 115200 bps
*/
/*
EEPROM default
0x00 Carrier PWM
0x01 Duty PWM
0x02 Baud rate
0x03 GPIO/SERVO
0x04 PORTB dir
PWM carrier
2 = 2.44 kHz
1 = 9.76 kHz
0 = 39.44 kHz
PWM duty
0 = 0%
1 = 50%
2 = 100%
Baud rate
0 = 115200
1 = 57600
2 = 38400
3 = 19200
4 = 9600
5 = 4800
6 = 2400
7 = 1200
TRISB
0 = 8 GPIO
1 = 4 GPIO (RB4-RB7, 4 servo (RB0-RB3)
2 = 8 Servo
*/
// preinit EEPROM durante la programmazione
#pragma romdata eedata_scn=0xf00000
rom char eedata_values[5] = {0x01,0x01,0x00,0x01,0xF0};
#pragma romdata
//**** inizio header programma ****
// include
#include <p18cxxx.h> // General init
#include <delays.h>
#include <timers.h>
#include <stdlib.h>
#include <usart.h>
#include <adc.h>
#include <pwm.h>
#include <i2c.h>
#include "MultiFace.h"
// config fuse
#pragma config OSC = HSPLL // Usare con quarzo da 10MHz e PPL 4x
#pragma config WDT = OFF
#pragma config PWRT = ON
#pragma config LVP = OFF
#pragma config BOREN = ON
#pragma config BORV = 1
#pragma config XINST = OFF
#pragma config DEBUG = OFF
#define LC PORTAbits.RA4 // Led com
char Ssel,SGr1=0,SGr2=0,ParsFlag=0;
int PWM1,PWM2;
int S1,S2,S3,S4,S5,S6,S7,S8;
int ADC1,ADC2,ADC3,ADC4,ADC5,SRFdist,Compass;
char str[6],strcom[10],TXcount,AT_flag;
unsigned char lettura[2];
/**** fine header programma ****/
#pragma code high_vector=0x08 // vettore interrupt
void interrupt_at_high_vector(void)
{
_asm GOTO ISRgest _endasm // salta alla funzione per interrupt
}
#pragma code // ritorna al codice C
#pragma interrupt ISRgest
void main()
{
LATA = 0x00;
LATB = 0x00;
LATC = 0x00;
TRISA = 0b11101111; // input analogici, RA4 GPIO
TRISB = 0xFF; // Servi e GPIO
TRISC = 0b11011000; // I2C, Seriale, PWM
// interrupt
INTCON = 0; // disattiva tutti gli interrupt
INTCONbits.GIE = 1; // attiva interrupt UART e Timer
INTCONbits.PEIE = 1;
for (S1=0;S1<10;S1++) // fa lampeggiare il LED
{
LC=!LC;
Delay10KTCYx(80);
}
/* Init periferiche */
init_sys(); // legge parametri di default.
// Timer
OpenTimer0( TIMER_INT_OFF & T0_16BIT & T0_SOURCE_INT & T0_PS_1_1); // servo frame
OpenTimer1(TIMER_INT_ON & T1_PS_1_1 & T1_SOURCE_INT & T1_OSC1EN_OFF); // Servo pulse 1
OpenTimer3(TIMER_INT_ON & T3_PS_1_1 & T3_SOURCE_INT & T3_OSC1EN_OFF ); // Servo Pulse 2
// PWM
OpenPWM1(0xff);
OpenPWM2(0xff);
SetDCPWM1(PWM1);
SetDCPWM2(PWM2);
// ADC
ADCON1 = 0b00001010; // AN0, AN1, AN2, AN3,AN4 attivi
ADCON2 = 0b10110010; // 16 TAD, Fosc/32
ADCON0 = 0x01; // ADC ON
//I2C
OpenI2C(MASTER, SLEW_OFF); // Attiva bus I2C, Master mode 100 kbits
SSPADD =0x63; //400kHz clock(19H) @40MHz
//100kHz clock(63H) @40MHz (default)
// Azzeramento Timer
T1CONbits.TMR1ON = 0;
T3CONbits.TMR3ON = 0;
TMR3H=TMR3L=0;
TMR1H=TMR1L=0;
T0CONbits.TMR0ON = 1;
T1CONbits.TMR1ON = 1;
T2CONbits.TMR2ON = 1;
T3CONbits.TMR3ON = 1;
S1=S2=S3=S4=1500;
S5=S6=S7=S8=1500;
Ssel = 1;
LC = 1;
AT_flag = 1;
TXcount = 0;
while(1)
{
if (INTCONbits.TMR0IF)
{
ServoCiclo(); // gestione servi
LC=1;
}
ADCCiclo();
SetDCPWM1(PWM1); // PWM1 e PWM2
SetDCPWM2(PWM2);
if(ParsFlag) Parser(); // analisi comandi
}
}
/* ---------- fime main ---------- */
void ServoCiclo (void)
{
switch (Ssel)
{
case 1:
if(SGr1)
{
TMR1H = (65536 - S1*10) >> 8;
TMR1L = (65536 - S1*10);
LATBbits.LATB0 = 1;
TMR3H = (65536 - S2*10) >> 8;
TMR3L = (65536 - S2*10);
LATBbits.LATB1 = 1;
}
break;
case 2:
if(SGr1)
{
TMR1H = (65536 - S3*10) >> 8;
TMR1L = (65536 - S3*10);
LATBbits.LATB2 = 1;
TMR3H = (65536 - S4*10) >> 8;
TMR3L = (65536 - S4*10);
LATBbits.LATB3 = 1;
}
break;
case 3:
if(SGr2)
{
TMR1H = (65536 - S5*10) >> 8;
TMR1L = (65536 - S5*10);
LATBbits.LATB4 = 1;
TMR3H = (65536 - S6*10) >> 8;
TMR3L = (65536 - S6*10);
LATBbits.LATB5 = 1;
}
break;
case 4:
if(SGr2)
{
TMR1H = (65536 - S7*10) >> 8;
TMR1L = (65536 - S7*10);
LATBbits.LATB6 = 1;
TMR3H = (65536 - S8*10) >> 8;
TMR3L = (65536 - S8*10);
LATBbits.LATB7 = 1;
}
break;
}
if (Ssel < 4 ) Ssel++;
else Ssel = 1;
TMR0H = 0x3C; // 5 ms
TMR0L = 0xB0;
T1CONbits.TMR1ON = 1;
T3CONbits.TMR3ON = 1;
INTCONbits.TMR0IF = 0;
}
void ADCCiclo (void)
{
SetChanADC( ADC_CH0 ); // legge un canale dell'ADC
ConvertADC();
while (BusyADC());
ADC1 = ReadADC();
SetChanADC( ADC_CH1 );
ConvertADC();
while (BusyADC());
ADC2 = ReadADC();
SetChanADC( ADC_CH2 );
ConvertADC();
while (BusyADC());
ADC3 = ReadADC();
SetChanADC( ADC_CH3 );
ConvertADC();
while (BusyADC());
ADC4 = ReadADC();
SetChanADC( ADC_CH4 );
ConvertADC();
while (BusyADC());
ADC5 = ReadADC();
}
void ISRgest(void) // I.S.R.
{
char data; // buffer ricezione
if (PIR1bits.TMR1IF)
{
if (SGr1)
{
LATBbits.LATB0 = 0;
LATBbits.LATB2 = 0;
}
if (SGr2)
{
LATBbits.LATB4 = 0;
LATBbits.LATB6 = 0;
}
T1CONbits.TMR1ON = 0;
PIR1bits.TMR1IF = 0;
}
if (PIR2bits.TMR3IF)
{
if (SGr1)
{
LATBbits.LATB1 = 0;
LATBbits.LATB3 = 0;
}
if (SGr2)
{
LATBbits.LATB5 = 0;
LATBbits.LATB7 = 0;
}
T3CONbits.TMR3ON = 0;
PIR2bits.TMR3IF = 0;
}
if (PIR1bits.RCIF)
{
data = RCREG;
if (data == '@' & AT_flag) TXcount = 0, AT_flag = 0;
strcom[TXcount] = data;
TXcount++;
if (TXcount == 8 & data == '#')
{
TXcount = 0, ParsFlag = 1;
AT_flag = 1;
LC = 0;
}
if (TXcount > 7) AT_flag = 1;
}
}
void Parser(void)
{
char i;
if (strcom[0] = '@')
{
switch (strcom[1])
{
case 'P': // comando PWM
switch (strcom[2])
{
case '1':
PWM1 = ((int) strcom[3] << 8) + (unsigned char) strcom[4];
break;
case '2':
PWM2 = ((int) strcom[3] << 8) + (unsigned char) strcom[4];
break;
case 'R':
if (strcom[3] == '1')
{
if (strcom[4] == '1') LATCbits.LATC0 = 1;
else LATCbits.LATC0 = 0;
}
if (strcom[3] == '2')
{
if (strcom[4] == '1') LATCbits.LATC5 = 1;
else LATCbits.LATC5 = 0;
}
break;
}
break;
case 'G': /