00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <sys/dmotor.h>
00028 #include <dlcd.h>
00029
00030 #ifdef CONF_DMOTOR
00031
00032 #include <sys/h8.h>
00033 #include <sys/irq.h>
00034
00036
00037
00038
00040
00042
00045 #ifdef CONF_DMOTOR_HOLD
00046 const unsigned char dm_a_pattern[]={0xc0,0x40,0x80,0x00},
00047 dm_b_pattern[]={0x0c,0x04,0x08,0x00},
00048 dm_c_pattern[]={0x03,0x01,0x02,0x00};
00049 #else
00050 const unsigned char dm_a_pattern[]={0x00,0x80,0x40,0xc0},
00051 dm_b_pattern[]={0x00,0x08,0x04,0x0c},
00052 dm_c_pattern[]={0x00,0x02,0x01,0x03};
00053 #endif
00054
00055 MotorState dm_a,
00056 dm_b,
00057 dm_c;
00058
00059
00061
00062
00063
00065
00067
00069 extern void dm_handler(void);
00070 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00071 __asm__("\n\
00072 .section .text.hi\n\
00073 .align 1\n\
00074 .global _dm_handler\n\
00075 _dm_handler:\n\
00076 ; r6 saved by ROM\n\
00077 ; r0 saved by systime_handler\n\
00078 "
00079 #ifdef CONF_DMOTOR_HOLD
00080 " mov.b #0xcf,r6l ; r6l is output\n"
00081 #else
00082 " sub.w r6,r6 ; r6l is output\n"
00083 #endif
00084 " ; we simultaneously load delta (r0h) and sum (r0l)\n\
00085 ; this depends on byte order, but the H8 will stay MSB\n\
00086 ; and the resulting code is efficient and compact.\n\
00087 \n\
00088 ; motor A\n\
00089 \n\
00090 mov.w @_dm_a,r0\n\
00091 add.b #1,r0h ; maps 255 to 256\n\
00092 dec.b r0h\n\
00093 addx.b r0h,r0l ; add delta to sum\n\
00094 bcc dm0 ; sum overflow?\n\
00095 mov.b @_dm_a+2,r6h ; -> output drive pattern\n\
00096 xor.b r6h,r6l\n\
00097 dm0:mov.b r0l,@_dm_a+1 ; save sum\n\
00098 \n\
00099 ; motor B\n\
00100 \n\
00101 mov.w @_dm_b,r0\n\
00102 add.b #1,r0h ; maps 255 to 256\n\
00103 dec.b r0h\n\
00104 addx.b r0h,r0l ; add delta to sum\n\
00105 bcc dm1 ; sum overflow?\n\
00106 mov.b @_dm_b+2,r6h ; -> output drive pattern\n\
00107 xor.b r6h,r6l\n\
00108 dm1:mov.b r0l,@_dm_b+1 ; save sum\n\
00109 \n\
00110 ; motor C\n\
00111 \n\
00112 mov.w @_dm_c,r0\n\
00113 add.b #1,r0h ; maps 255 to 256\n\
00114 dec.b r0h\n\
00115 addx.b r0h,r0l ; add delta to sum\n\
00116 bcc dm2 ; sum overflow?\n\
00117 mov.b @_dm_c+2,r6h ; -> output drive pattern\n\
00118 xor.b r6h,r6l\n\
00119 dm2:mov.b r0l,@_dm_c+1 ; save sum\n\
00120 \n\
00121 ; driver chip\n\
00122 \n\
00123 mov.b r6l,@_motor_controller:8 ; output motor waveform\n\
00124 \n\
00125 rts \n\
00126 ");
00127 #endif // DOXYGEN_SHOULD_SKIP_THIS
00128
00129
00131
00132 void dm_init(void) {
00133 dm_shutdown();
00134 }
00135
00136
00138
00139 void dm_shutdown(void) {
00140 motor_a_dir(off);
00141 motor_b_dir(off);
00142 motor_c_dir(off);
00143
00144 motor_a_speed(MAX_SPEED);
00145 motor_b_speed(MAX_SPEED);
00146 motor_c_speed(MAX_SPEED);
00147
00148 motor_controller=0x00;
00149 }
00150
00151 #ifdef CONF_VIS
00152
00153
00154
00155
00156 void motor_a_dir(MotorDirection dir)
00157 {
00158 dm_a.dir = dm_a_pattern[dir];
00159 dlcd_hide(LCD_A_LEFT);
00160 dlcd_hide(LCD_A_RIGHT);
00161 if (dir == fwd || dir == brake)
00162 dlcd_show(LCD_A_RIGHT);
00163 if (dir == rev || dir == brake)
00164 dlcd_show(LCD_A_LEFT);
00165 }
00166
00167 void motor_b_dir(MotorDirection dir)
00168 {
00169 dm_b.dir = dm_b_pattern[dir];
00170 dlcd_hide(LCD_B_LEFT);
00171 dlcd_hide(LCD_B_RIGHT);
00172 if (dir == fwd || dir == brake)
00173 dlcd_show(LCD_B_RIGHT);
00174 if (dir == rev || dir == brake)
00175 dlcd_show(LCD_B_LEFT);
00176 }
00177
00178 void motor_c_dir(MotorDirection dir)
00179 {
00180 dm_c.dir = dm_c_pattern[dir];
00181 dlcd_hide(LCD_C_LEFT);
00182 dlcd_hide(LCD_C_RIGHT);
00183 if (dir == fwd || dir == brake)
00184 dlcd_show(LCD_C_RIGHT);
00185 if (dir == rev || dir == brake)
00186 dlcd_show(LCD_C_LEFT);
00187 }
00188
00189 #endif // ifdef CONF_VIS
00190
00191 #endif // CONF_DMOTOR