00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string.h>
00023
00024 #include <aversive.h>
00025 #include <aversive/error.h>
00026 #include <multiservo.h>
00027 #include <multiservo_archs.h>
00028
00029 struct multiservo g_multiservo;
00030
00031
00032
00033 #ifdef MULTISERVO_ENABLE_DEBUG
00034 #define MULTISERVO_DEBUG(args...) DEBUG(args)
00035 #else
00036 #define MULTISERVO_DEBUG(args...) do { } while(0)
00037 #endif
00038
00039
00040 #define TIME_1MS (CONFIG_QUARTZ/((1000UL)*MULTISERVO_TIMER_PRESCALER))
00041 #define TIME_1_5MS ((TIME_1MS*3)/2)
00042
00043
00044 #if (MULTISERVO_TIMER == 0 || MULTISERVO_TIMER == 2) && ((TIME_1MS*2) >= 256L)
00045 #error "Bad PRESCALER, you should increase it in multiservo_config.h"
00046 #endif
00047
00048
00049 #if (MULTISERVO_TIMER == 1 || MULTISERVO_TIMER == 3) && ((TIME_1MS*2) >= 65536L)
00050 #error "Bad PRESCALER, you should increase it in multiservo_config.h"
00051 #endif
00052
00053
00054
00055 SIGNAL(MULTISERVO_SIG_OUTPUT_COMPARE)
00056 {
00057 volatile uint8_t * port ;
00058
00059 if (g_multiservo.time_sum > TIME_1MS * 20) {
00060 MULTISERVO_DEBUG(E_MULTISERVO, "end, restart");
00061 g_multiservo.time_sum = 0;
00062 g_multiservo.current_multiservo = 0;
00063 }
00064
00065
00066 if (g_multiservo.id_prev != -1) {
00067 port = g_multiservo.elts[g_multiservo.id_prev].port;
00068 if(port) {
00069 MULTISERVO_DEBUG(E_MULTISERVO, "reset %d",g_multiservo.id_prev);
00070 cbi(*port, g_multiservo.elts[g_multiservo.id_prev].bitnum);
00071 }
00072 }
00073
00074
00075 while (g_multiservo.current_multiservo < MULTISERVO_NB_MAX) {
00076 port = g_multiservo.elts[g_multiservo.current_multiservo].port;
00077 if(port) {
00078 MULTISERVO_DEBUG(E_MULTISERVO, "set %d %d",
00079 g_multiservo.current_multiservo,
00080 g_multiservo.elts[g_multiservo.current_multiservo].value);
00081 sbi(*port, g_multiservo.elts[g_multiservo.current_multiservo].bitnum);
00082 g_multiservo.id_prev = g_multiservo.current_multiservo;
00083 MULTISERVO_OCR = g_multiservo.elts[g_multiservo.current_multiservo].value;
00084 g_multiservo.time_sum += g_multiservo.elts[g_multiservo.current_multiservo].value;
00085 break;
00086 }
00087 g_multiservo.current_multiservo ++;
00088 }
00089
00090
00091 if (g_multiservo.current_multiservo >= MULTISERVO_NB_MAX) {
00092 g_multiservo.id_prev = -1;
00093 MULTISERVO_DEBUG(E_MULTISERVO, "wait 1ms %d (%ld)", g_multiservo.current_multiservo, TIME_1MS);
00094 MULTISERVO_OCR = TIME_1MS;
00095 g_multiservo.time_sum += TIME_1MS;
00096 }
00097 else {
00098 g_multiservo.current_multiservo ++;
00099 }
00100 }
00101
00102
00103
00104 void multiservo_init(void)
00105 {
00106 uint8_t flags;
00107
00108 IRQ_LOCK(flags);
00109
00110 cbi(MULTISERVO_TIMSK, MULTISERVO_OCIE);
00111
00112 memset(&g_multiservo, 0, sizeof(g_multiservo));
00113 g_multiservo.id_prev = -1;
00114
00115
00116 MULTISERVO_TCCRnA = MULTISERVO_TCCRnA_VALUE;
00117 #ifdef MULTISERVO_TCCRnB
00118 MULTISERVO_TCCRnB = MULTISERVO_TCCRnB_VALUE;
00119 #endif
00120
00121 MULTISERVO_OCR = TIME_1MS;
00122 sbi(MULTISERVO_TIMSK, MULTISERVO_OCIE);
00123 IRQ_UNLOCK(flags);
00124 }
00125
00126
00127 int8_t multiservo_add(volatile uint8_t * port, uint8_t bitnum)
00128 {
00129 uint8_t i;
00130 uint8_t flags;
00131
00132 IRQ_LOCK(flags);
00133
00134 for ( i=0 ; i< MULTISERVO_NB_MAX ; i++ ) {
00135 if(! g_multiservo.elts[i].port) {
00136 g_multiservo.elts[i].port = port;
00137 g_multiservo.elts[i].bitnum = bitnum;
00138 g_multiservo.elts[i].value = TIME_1_5MS;
00139 sbi(DDR(*port), bitnum);
00140 break;
00141 }
00142 }
00143 IRQ_UNLOCK(flags);
00144
00145
00146 if(i == MULTISERVO_NB_MAX)
00147 return -1;
00148
00149 return i;
00150 }
00151
00152
00153
00154
00155 void multiservo_del(int8_t id)
00156 {
00157 uint8_t flags;
00158
00159 IRQ_LOCK(flags);
00160 cbi(DDR(*g_multiservo.elts[id].port), g_multiservo.elts[id].bitnum);
00161 memset(&g_multiservo.elts[id], 0, sizeof(struct multiservo_element));
00162 IRQ_UNLOCK(flags);
00163 }
00164
00165
00170 void multiservo_set(int8_t id, uint16_t val_us)
00171 {
00172 uint16_t val_timer;
00173 uint8_t flags;
00174
00175 val_timer = (((uint32_t)val_us)*TIME_1MS)/1000;
00176 IRQ_LOCK(flags);
00177
00178 g_multiservo.elts[id].value = val_timer;
00179 IRQ_UNLOCK(flags);
00180 }
00181