00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #include <dsensor.h>
00045
00046 #ifdef CONF_DSENSOR
00047
00048 #include <sys/h8.h>
00049 #include <sys/irq.h>
00050 #include <sys/bitops.h>
00051 #include <rom/registers.h>
00052 #include <unistd.h>
00053 #include <conio.h>
00054
00056
00057
00058
00060
00061 #define DS_ALL_ACTIVE 0x07
00062 #define DS_ALL_PASSIVE (~DS_ALL_ACTIVE)
00063
00064
00065
00066
00067
00069
00070 volatile unsigned char ds_channel;
00071
00072 unsigned char ds_activation;
00073
00074 #ifdef CONF_DSENSOR_ROTATION
00075 unsigned char ds_rotation;
00076
00077 volatile int ds_rotations[3];
00078
00079 static signed char rotation_state[3];
00080 static signed char rotation_new_state[3];
00081 static unsigned int state_duration[3];
00082
00083 #ifdef CONF_DSENSOR_VELOCITY
00084 volatile int ds_velocities[3];
00085 static unsigned int last_rotation[3];
00086 static unsigned int next_rotation[3];
00087 static signed char rotation_dir[3];
00088 #endif
00089
00090
00091
00093
00096 static const signed char ad2state[16]={
00097
00098 -1,-1,-1,-1,-1, 2, 2, 2, 3, 3, 3, 3, 1, 1, 1, 0
00099
00100
00101
00102
00103
00104 };
00105
00107
00112 static const signed char diff2change[7]={
00113
00114 1, 0,-1, 0, 1, 0,-1
00115 };
00116
00118
00119
00120
00122
00124
00129 void ds_rotation_set(volatile unsigned *sensor,int pos) {
00130 if(sensor>=&AD_A && sensor<=&AD_C) {
00131 unsigned channel=(unsigned) (sensor-&AD_A);
00132 signed char state=ad2state[(*sensor)>>12];
00133
00134 if(state<0)
00135 state=0;
00136
00137 rotation_state[channel]=state;
00138 rotation_new_state[channel] = -1;
00139 state_duration[channel]=0;
00140 ds_rotations[channel]=pos;
00141
00142 }
00143 }
00144
00146
00148 void ds_rotation_handler() {
00149 unsigned channel =ds_channel;
00150 unsigned raw =(*((&AD_A)+channel));
00151 signed char newstate=ad2state[raw>>12];
00152
00153 if (newstate < 0)
00154 return;
00155
00156 if (newstate == rotation_new_state[channel]) {
00157 if (++state_duration[channel] == 2) {
00158 signed char change = diff2change[newstate - rotation_state[channel] + 3];
00159
00160 ds_rotations[channel] += change;
00161
00162 #ifdef CONF_DSENSOR_VELOCITY
00163 {
00164
00165
00166
00167 unsigned int time = (unsigned int) sys_time;
00168 if (change != rotation_dir[channel]) {
00169 rotation_dir[channel] = change;
00170 ds_velocities[channel] = 0;
00171 last_rotation[channel] = time;
00172 next_rotation[channel] = time + 1000;
00173 } else {
00174 if (time == last_rotation[channel])
00175 ds_velocities[channel] = 1000 * change;
00176 else {
00177 unsigned int time_diff = (time - last_rotation[channel]);
00178 if (time_diff > 1000) {
00179 rotation_dir[channel] = 0;
00180 ds_velocities[channel] = 0;
00181 } else {
00182 int speed = 1000 / time_diff;
00183 ds_velocities[channel] = change > 0 ? speed : -speed;
00184 last_rotation[channel] = time;
00185 next_rotation[channel] = time + time_diff * 3 / 2;
00186 }
00187 }
00188 }
00189 }
00190 #endif
00191
00192 rotation_state[channel] = newstate;
00193 rotation_new_state[channel] = -1;
00194 }
00195 } else if (newstate != rotation_state[channel]) {
00196 rotation_new_state[channel] = newstate;
00197 state_duration[channel] = 1;
00198 #ifdef CONF_DSENSOR_VELOCITY
00199 } else {
00200
00201 unsigned int time = (unsigned int) sys_time;
00202 if (rotation_dir[channel] &&
00203 ((signed int) (time - next_rotation[channel])) >= 0) {
00204 unsigned int time_diff = (time - last_rotation[channel]);
00205 if (time_diff > 1000) {
00206 rotation_dir[channel] = 0;
00207 ds_velocities[channel] = 0;
00208 } else {
00209 int speed = 1000 / time_diff;
00210 ds_velocities[channel] = rotation_dir[channel] > 0 ? speed : -speed;
00211 next_rotation[channel] = time + time_diff / 2;
00212 }
00213 }
00214 #endif
00215 }
00216
00217 }
00218 #endif // CONF_DSENSOR_ROTATION
00219
00220 #ifdef CONF_DSENSOR_MUX
00221 unsigned char ds_mux;
00222
00223 volatile int ds_muxs[3][3];
00224
00225
00226
00227 #define DS_MUX_PULSE_TM_MS 10
00228
00229
00230
00231 typedef struct {
00232 unsigned long nextTm;
00233 char remainingEdges;
00234 char channel;
00235 unsigned int attached[3];
00236
00237
00238
00239 enum {ds_mux_prepRead,
00240 ds_mux_read,
00241 ds_mux_pulse_low,
00242 ds_mux_pulse_high} action;
00243 } ds_mux_data_t;
00244
00245 ds_mux_data_t ds_mux_data[3];
00246
00247 #endif //CONF_DSENSOR_MUX
00248
00249
00250
00251 static inline void ds_power_on(unsigned channel) {
00252 switch(channel) {
00253 case 0:
00254 bit_set(&PORT6,0);
00255 break;
00256 case 1:
00257 bit_set(&PORT6,1);
00258 break;
00259 case 2:
00260 bit_set(&PORT6,2);
00261 break;
00262 default:
00263
00264 break;
00265 }
00266 }
00267
00268 static inline void ds_power_off(unsigned channel) {
00269 switch(channel) {
00270 case 0:
00271 bit_clear(&PORT6,0);
00272 break;
00273 case 1:
00274 bit_clear(&PORT6,1);
00275 break;
00276 case 2:
00277 bit_clear(&PORT6,2);
00278 break;
00279 default:
00280
00281 break;
00282 }
00283 }
00284
00285 #ifdef CONF_DSENSOR_MUX
00286
00287
00289 void ds_mux_on(volatile unsigned *sensor,
00290 unsigned int ch1,
00291 unsigned int ch2,
00292 unsigned int ch3) {
00293 unsigned char i,j;
00294 ds_passive(sensor);
00295
00296
00297 if(ch1==0 &&
00298 ch2==0 &&
00299 ch3==0) {
00300
00301
00302 ds_mux_off(sensor);
00303 return;
00304 }
00305
00306 if (sensor == &SENSOR_3) {
00307 i=0;
00308 } else if (sensor == &SENSOR_2) {
00309 i=1;
00310 } else if (sensor == &SENSOR_1) {
00311 i=2;
00312 } else {
00313
00314 return;
00315 }
00316
00317
00318 ds_mux_data[i].attached[0]=ch1;
00319 ds_mux_data[i].attached[1]=ch2;
00320 ds_mux_data[i].attached[2]=ch3;
00321
00322
00323
00324
00325
00326
00327
00328
00329 if(ch1)
00330 ds_mux_data[i].attached[0]+=160;
00331 if(ch2)
00332 ds_mux_data[i].attached[1]+=135;
00333 if(ch3)
00334 ds_mux_data[i].attached[2]+=25;
00335
00336
00337
00338
00339
00340
00341 if(i==0 && ds_mux&1)
00342 return;
00343 if(i==1 && ds_mux&2)
00344 return;
00345 if(i==2 && ds_mux&4)
00346 return;
00347
00348
00349
00350
00351 ds_power_on(i);
00352
00353
00354
00355 for(j=0;j<3 && ds_mux_data[i].attached[j]==0;j++);
00356
00357 ds_mux_data[i].channel=j;
00358 ds_mux_data[i].remainingEdges=((j+1)*2);
00359 ds_mux_data[i].action=ds_mux_pulse_low;
00360 ds_mux_data[i].nextTm=sys_time+DS_MUX_PULSE_TM_MS;
00361
00362 if (sensor == &SENSOR_3) {
00363 bit_set(&ds_mux, 0);
00364 } else if (sensor == &SENSOR_2) {
00365 bit_set(&ds_mux, 1);
00366 } else if (sensor == &SENSOR_1) {
00367 bit_set(&ds_mux, 2);
00368 } else {
00369
00370 return;
00371 }
00372
00373 }
00374
00375
00376
00377 void ds_mux_handler() {
00378 unsigned sen=ds_channel;
00379
00380
00381 if(ds_mux_data[sen].nextTm <= sys_time) {
00382
00383
00384 switch(ds_mux_data[sen].action) {
00385 case ds_mux_prepRead:
00386 ds_power_off(sen);
00387 ds_mux_data[sen].action=ds_mux_read;
00388 ds_mux_data[sen].nextTm=sys_time;
00389 break;
00390 case ds_mux_read:
00391
00392 switch(sen) {
00393 case 0:
00394 ds_muxs[sen][(int)ds_mux_data[sen].channel]=SENSOR_3;
00395 break;
00396 case 1:
00397 ds_muxs[sen][(int)ds_mux_data[sen].channel]=SENSOR_2;
00398 break;
00399 case 2:
00400 ds_muxs[sen][(int)ds_mux_data[sen].channel]=SENSOR_1;
00401 break;
00402 default:
00403
00404 }
00405
00406
00407
00408 do {
00409 ds_mux_data[sen].channel++;
00410 if(ds_mux_data[sen].channel>2) {
00411 ds_mux_data[sen].channel=0;
00412 }
00413
00414
00415
00416 } while(
00417 (ds_mux_data[sen].attached
00418 [(int)ds_mux_data[sen].channel])==0);
00419
00420
00421
00422
00423 ds_mux_data[sen].remainingEdges=
00424 ((ds_mux_data[sen].channel+1)*2)-1;
00425
00426
00427 ds_mux_data[sen].action=ds_mux_pulse_high;
00428 ds_mux_data[sen].nextTm=sys_time+DS_MUX_PULSE_TM_MS;
00429 break;
00430 case ds_mux_pulse_low:
00431
00432 ds_power_off(sen);
00433
00434 ds_mux_data[sen].nextTm=sys_time+DS_MUX_PULSE_TM_MS;
00435 ds_mux_data[sen].remainingEdges--;
00436 ds_mux_data[sen].action=ds_mux_pulse_high;
00437 break;
00438 case ds_mux_pulse_high:
00439
00440 ds_power_on(sen);
00441 ds_mux_data[sen].remainingEdges--;
00442
00443 if(ds_mux_data[sen].remainingEdges==0) {
00444
00445
00446 ds_mux_data[sen].action=ds_mux_prepRead;
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 ds_mux_data[sen].nextTm=sys_time+
00457 ds_mux_data[sen].attached[(int)ds_mux_data[sen].channel];
00458
00459
00460 break;
00461 } else {
00462
00463 ds_mux_data[sen].action=ds_mux_pulse_low;
00464 ds_mux_data[sen].nextTm=sys_time+DS_MUX_PULSE_TM_MS;
00465 }
00466 break;
00467 default:
00468
00469 }
00470
00471 }
00472 }
00473
00474 #endif //CONF_DSENSOR_MUX
00475
00476
00477
00478
00480
00481 extern void ds_handler(void);
00482 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00483 __asm__("\n\
00484 .text\n\
00485 .align 1\n\
00486 _ds_handler:\n\
00487 ; r6 saved by ROM\n\
00488 \n\
00489 mov.b @_ds_channel,r6l ; r6l = current channel\n\
00490 \n\
00491 mov.b @_ds_activation,r6h ; r6h = activation bitmask\n\
00492 btst r6l,r6h ; activate output?\n\
00493 beq ds_noset\n\
00494 bset r6l,@_PORT6:8 ; activate output of last port scanned\n\
00495 ds_noset:\n\
00496 "
00497 #ifdef CONF_DSENSOR_ROTATION
00498 "\n\
00499 mov.b @_ds_rotation,r6h ; r6h = rotation bitmask\n\
00500 btst r6l,r6h ; process rotation sensor?\n\
00501 beq ds_norot\n\
00502 \n\
00503 push r0 ; save r0..r3\n\
00504 push r1\n\
00505 push r2\n\
00506 push r3 ; r4..r6 saved by gcc if necessary\n\
00507 \n\
00508 jsr _ds_rotation_handler ; process rotation sensor\n\
00509 \n\
00510 pop r3\n\
00511 pop r2\n\
00512 pop r1\n\
00513 pop r0\n\
00514 ds_norot:\n\
00515 "
00516 #endif
00517
00518 #ifdef CONF_DSENSOR_MUX
00519 "\n\
00520 mov.b @_ds_mux,r6h ; r6h = mux bitmask\n\
00521 btst r6l,r6h ; process mux sensor?\n\
00522 beq ds_nomux\n\
00523 \n\
00524 push r0 ; save r0..r3\n\
00525 push r1\n\
00526 push r2\n\
00527 push r3 ; r4..r6 saved by gcc if necessary\n\
00528 \n\
00529 jsr _ds_mux_handler ; process mux sensor\n\
00530 \n\
00531 pop r3\n\
00532 pop r2\n\
00533 pop r1\n\
00534 pop r0\n\
00535 ds_nomux:\n\
00536 "
00537 #endif
00538 "\n\
00539 inc r6l ; next channel\n\
00540 and #0x03,r6l ; limit to 0-3\n\
00541 \n\
00542 mov.b @_ds_activation,r6h ; r6h = activation bitmask\n\
00543 btst r6l,r6h ; activate output?\n\
00544 beq ds_nounset\n\
00545 bclr r6l,@_PORT6:8 ; set output inactive for reading\n\
00546 ds_nounset:\n\
00547 \n\
00548 ; The settle time for reading the value from active sensor start here\n\
00549 \n\
00550 ; moved here for helping timing problems\n\
00551 mov.b r6l,@_ds_channel ; store next channel\n\
00552 \n\
00553 ; Added a delay loop for sensor settle time\n\
00554 \n\
00555 mov.b #0x04, r6h ; delay loop\n\
00556 settle:\n\
00557 nop ; each nop is a 2 state clock delay\n\
00558 dec.b r6h ; 2 states ?\n\
00559 bne settle ; 4 states\n\
00560 \n\
00561 ; Total loop delay 32 states (?)\n\
00562 \n\
00563 mov.b @_AD_CSR:8,r6h ; r6h = A/D CSR\n\
00564 and.b #0x7c,r6h ; reset scanmode and channel num\n\
00565 or.b r6l,r6h ; scan next channel\n\
00566 mov.b r6h,@_AD_CSR:8 ; put r6h back on A/D CSR\n\
00567 \n\
00568 ; The settle time for reading the value from active sensor finish here\n\
00569 \n\
00570 bset #0x5,@_AD_CSR:8 ; go!\n\
00571 \n\
00572 rts\n\
00573 ");
00574 #endif // DOXYGEN_SHOULD_SKIP_THIS
00575
00576
00578
00581 void ds_init(void) {
00582 rom_port6_ddr|=DS_ALL_ACTIVE;
00583 PORT6_DDR =rom_port6_ddr;
00584
00585 ds_activation=0;
00586 ds_channel =0;
00587
00588 #ifdef CONF_DSENSOR_ROTATION
00589 ds_rotation =0;
00590 #endif
00591
00592 #ifdef CONF_DSENSOR_MUX
00593 ds_mux=0;
00594 #endif
00595
00596 ad_vector=&ds_handler;
00597 AD_CR &=~ADCR_EXTERN;
00598 AD_CSR =ADCSR_TIME_266 | ADCSR_GROUP_0 | ADCSR_AN_0 |
00599 ADCSR_ENABLE_IRQ | ADCSR_START;
00600
00601 #ifdef CONF_CONIO
00602 delay(10);
00603 #else
00604 # warning "Rotation initialization might fail."
00605 #endif
00606 }
00607
00608
00610
00612 void ds_shutdown(void) {
00613
00614 AD_CSR=0x00;
00615 PORT6 &=DS_ALL_PASSIVE;
00616 rom_port6_ddr&=DS_ALL_PASSIVE;
00617 PORT6_DDR =rom_port6_ddr;
00618 }
00619
00620 #endif // CONF_DSENSOR