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 = 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 = (pin & 0x0F);
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)/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)*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)) & ~(1<<ServoChannels[ServoChannel].pin));
00134
00135
00136 }
00137
00138
00139 ServoChannel++;
00140
00141 if(ServoChannel != SERVO_NUM_CHANNELS)
00142 {
00143
00144 if(ServoChannel > SERVO_NUM_CHANNELS) ServoChannel = 0;
00145
00146 outb(_SFR_IO8(ServoChannels[ServoChannel].port), inb(_SFR_IO8(ServoChannels[ServoChannel].port)) | (1<<ServoChannels[ServoChannel].pin));
00147
00148
00149
00150 nextTics = ServoChannels[ServoChannel].duty;
00151 }
00152 else
00153 {
00154
00155
00156 nextTics = ServoPeriodTics-ServoPosTics;
00157 }
00158
00159
00160 u16 OCValue;
00161
00162 OCValue = inb(OCR1AL);
00163 OCValue += inb(OCR1AH)<<8;
00164
00165 OCValue += nextTics;
00166
00167
00168 outb(OCR1AH, (OCValue>>8));
00169 outb(OCR1AL, (OCValue & 0x00FF));
00170
00171 ServoPosTics += nextTics;
00172 if(ServoPosTics >= ServoPeriodTics) ServoPosTics = 0;
00173 }