00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 #ifndef WIN32
00019     #include <avr/io.h>
00020 #endif
00021 
00022 #include "global.h"
00023 #include "servo.h"
00024 
00025 
00026 
00027 
00028 
00029 u16 ServoPosTics;
00030 u16 ServoPeriodTics;
00031 u08 ServoChannel;
00032 ServoChannelType ServoChannels[SERVO_NUM_CHANNELS];
00033 
00034 
00035 
00036 
00037 void servoInit(void)
00038 {
00039     u08 channel;
00040     
00041     cbi(TIMSK, OCIE1A);
00042     
00043     timer1SetPrescaler(TIMER_CLK_DIV256);
00044     
00045     timerAttach(TIMER1OUTCOMPAREA_INT, servoService);
00046     
00047     for(channel=0; channel<SERVO_NUM_CHANNELS; channel++)
00048     {
00049         
00050         ServoChannels[channel].duty = SERVO_MIN;
00051         
00052         ServoChannels[channel].port = _SFR_IO_ADDR(SERVO_DEFAULT_PORT);
00053         
00054         ServoChannels[channel].pin = (1<<channel);
00055         
00056         
00057         
00058     }
00059     
00060     ServoPosTics = 0;
00061     
00062     ServoPeriodTics = SERVO_MAX*9;
00063     
00064     u16 OCValue;
00065     
00066     OCValue =  inb(OCR1AL);     
00067     OCValue += inb(OCR1AH)<<8;  
00068     
00069     OCValue += ServoPeriodTics; 
00070     
00071     outb(OCR1AH, (OCValue>>8));         
00072     outb(OCR1AL, (OCValue & 0x00FF));   
00073     
00074     sbi(TIMSK, OCIE1A);
00075 }
00076 
00077 
00078 void servoOff(void)
00079 {
00080     
00081     cbi(TIMSK, OCIE1A);
00082     
00083     timerDetach(TIMER1OUTCOMPAREA_INT);
00084 }
00085 
00086 
00087 void servoSetChannelIO(u08 channel, u08 port, u08 pin)
00088 {
00089     ServoChannels[channel].port = port;
00090     ServoChannels[channel].pin = (1<<(pin&0x07));
00091 }
00092 
00093 
00094 void servoSetPosition(u08 channel, u08 position)
00095 {
00096     
00097     u16 pos_scaled;
00098     
00099     pos_scaled = ((u16)position*(SERVO_MAX-SERVO_MIN)/SERVO_POSITION_MAX)+SERVO_MIN;
00100     
00101     servoSetPositionRaw(channel, pos_scaled);
00102 }
00103 
00104 
00105 u08 servoGetPosition(u08 channel)
00106 {
00107     return (u08)( ((servoGetPositionRaw(channel)-SERVO_MIN)*SERVO_POSITION_MAX)/(SERVO_MAX-SERVO_MIN) );
00108 }
00109 
00110 
00111 void servoSetPositionRaw(u08 channel, u16 position)
00112 {
00113     
00114     position = MAX(position, SERVO_MIN);
00115     position = MIN(position, SERVO_MAX);
00116     
00117     ServoChannels[channel].duty = position;
00118 }
00119 
00120 
00121 u16 servoGetPositionRaw(u08 channel)
00122 {
00123     return ServoChannels[channel].duty;
00124 }
00125 
00126 void servoService(void)
00127 {
00128     u16 nextTics;
00129 
00130     if(ServoChannel < SERVO_NUM_CHANNELS)
00131     {
00132         
00133         outb(_SFR_IO8(ServoChannels[ServoChannel].port), inb(_SFR_IO8(ServoChannels[ServoChannel].port)) & ~(ServoChannels[ServoChannel].pin));
00134     }
00135     
00136     
00137     ServoChannel++;
00138 
00139     if(ServoChannel != SERVO_NUM_CHANNELS)
00140     {
00141         
00142         if(ServoChannel > SERVO_NUM_CHANNELS)   ServoChannel = 0;
00143         
00144         outb(_SFR_IO8(ServoChannels[ServoChannel].port), inb(_SFR_IO8(ServoChannels[ServoChannel].port)) | (ServoChannels[ServoChannel].pin));
00145         
00146         nextTics = ServoChannels[ServoChannel].duty;
00147     }
00148     else 
00149     {
00150         
00151         
00152         nextTics = ServoPeriodTics-ServoPosTics;
00153     }
00154 
00155     
00156     u16 OCValue;
00157     
00158     OCValue =  inb(OCR1AL);     
00159     OCValue += inb(OCR1AH)<<8;  
00160     
00161     OCValue += nextTics;
00162 
00163     
00164     outb(OCR1AH, (OCValue>>8));         
00165     outb(OCR1AL, (OCValue & 0x00FF));   
00166     
00167     ServoPosTics += nextTics;
00168     if(ServoPosTics >= ServoPeriodTics) ServoPosTics = 0;
00169 }