00001
00002
00003
00004
00005
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 #include "configs.h"
00044
00045 #include <inttypes.h>
00046 #include <avr/io.h>
00047 #include <avr/delay.h>
00048 #include <avr/interrupt.h>
00049 #include <avr/sleep.h>
00050 #include <avr/pgmspace.h>
00051 #include <stdio.h>
00052 #include <stdlib.h>
00053 #include <math.h>
00054
00055 #include "usrat.h"
00056 #include "shvars.h"
00057 #include "line.h"
00058 #include "arc.h"
00059 #include "htext.h"
00060 #include "scale.h"
00061 #include "hpgl.h"
00062 #include "motori.h"
00063
00064
00065 #define MRESET 2
00066 #define MSLEEP 1
00067 #define MENABLE 0
00068
00069 #define DIR 0
00070 #define STEP 1
00071 #define MS1 2
00072 #define MS2 3
00073
00074 #define PENPCM 6
00075
00077 #define XSUP 0
00078 #define XINF 1
00079 #define YSUP 2
00080 #define YINF 3
00081 #define ZSUP 4
00082 #define ZINF 5
00083
00084
00085 volatile int16_t motor_pace = MOTOR_PACE_SLOW;
00086 volatile int16_t motor_pace_goal;
00087 volatile uint8_t motor_accel_ctr = 0;
00088 volatile int8_t motor_accel = 0;
00089
00090 volatile int16_t accel_strokesteps;
00091 volatile int16_t accel_decelthresh;
00092
00093 #define sgn(x) ((x)==0?0:((x)<1)?-1:1)
00094
00095 volatile uint8_t pen_status = 255;
00096 volatile uint8_t pen_relax = 255;
00097
00098 volatile uint8_t pen_pulse_counter = 0;
00099
00100 double alpha, last_alpha, alpha_delta;
00101
00102 #define SEEK0_NULL 0
00103 #define SEEK0_SEEK 1
00104 #define SEEK0_DONE 0x80
00105 volatile uint8_t seeking0;
00106
00108 void init_io() {
00109 DDRC=0xff;
00110 DDRD=0xff;
00111 DDRB=0xff;
00112 DDRA=0xff & (~_BV(XSUP) | _BV(YSUP));
00113 PORTA = _BV(XSUP)|_BV(YSUP);
00114 PORTB = 0x00;
00115 PORTC = 0x00;
00116 PORTD = 0x00;
00117 }
00118
00122 void timer0_init() {
00123 TCCR0A = 2;
00124 TCCR0B = 4;
00125 TIMSK0 = _BV(OCIE0A);
00126 OCR0A = 0xff;
00127 }
00128
00132 void timer2_init() {
00133 TCCR2A = 0x00;
00134 TCCR2B = 0x02;
00135 TIMSK2 = _BV(TOIE2);
00136 }
00137
00139 void motori_init() {
00140 PORTB |= _BV(MSLEEP);
00141 PORTB &= ~(_BV(MENABLE) | _BV(MRESET));
00142 _delay_ms(20);
00143 PORTB |= _BV(MRESET);
00144 _delay_ms(100);
00145 }
00146
00149 void motori_enable(uint8_t enable) {
00150 if (enable) {
00151 PORTB &= ~(_BV(MENABLE) | _BV(MRESET));
00152 PORTB |= _BV(MRESET);
00153 } else {
00154 PORTB |= _BV(MENABLE);
00155 }
00156 }
00157
00158
00159
00160 void step(int8_t xdir, int8_t ydir) {
00161
00162 PORTC = 0xcc;
00163 PORTC |= (ydir < 0 ? 0 : _BV(DIR+4)) | (xdir < 0 ? 0 : _BV(DIR));
00164
00165
00166 PORTC |= (ydir ? _BV(STEP+4) : 0) | (xdir ? _BV(STEP) : 0);
00167 }
00168
00169 void set_acceleration(ACCEL_MODE accel_mode, uint8_t steep) {
00170 switch (accel_mode) {
00171 case ACCEL_FIXSLOW:
00172 motor_accel = 0;
00173 motor_pace = MOTOR_PACE_SLOW;
00174 break;
00175 case ACCEL_FIXFAST:
00176 motor_accel = 0;
00177 motor_pace = steep ? MOTOR_PACE_FASTY : MOTOR_PACE_FASTX;
00178 break;
00179 case ACCEL_FIXMEDIUM:
00180 motor_accel = 0;
00181 motor_pace = (MOTOR_PACE_SLOW-MOTOR_PACE_FASTX)/2;
00182 break;
00183 case ACCEL_ACCEL:
00184 motor_pace_goal = steep ? MOTOR_PACE_FASTY : MOTOR_PACE_FASTX;
00185 if (pen_status == 0) motor_pace_goal /= steep ? 2 : 4;
00186 motor_accel_ctr = ACCEL_STEPS_PER_INCREMENT;
00187 if (motor_pace != motor_pace_goal) motor_accel = -1;
00188 break;
00189 case ACCEL_DECEL:
00190 motor_pace_goal = MOTOR_PACE_SLOW;
00191 motor_accel_ctr = ACCEL_STEPS_PER_INCREMENT;
00192 if (motor_pace != motor_pace_goal) motor_accel = 1;
00193 break;
00194 }
00195 }
00196
00197 double calc_angle(int16_t x2, int16_t y2) {
00198 alpha = atan2(y2-stepper_loc.y, x2-stepper_loc.x)*180/M_PI;
00199 double dA = fabs(last_alpha-alpha);
00200
00201
00202
00203 return dA;
00204 }
00205
00206
00207 void pen_control(uint8_t down) {
00208 if (pen_status != down) {
00209 while(!motors_ready());
00210 if (down) {
00211 _delay_ms(25);
00212 pen_relax = 255;
00213 pen_status = 1;
00214 } else {
00215 pen_relax = 255;
00216 pen_status = 0;
00217 }
00218
00219 PORTD = (PORTD & ~_BV(7)) | (pen_status ? 0: _BV(7));
00220
00221 _delay_ms(100);
00222 }
00223 }
00224
00225 void plotter_init() {
00226 timer0_init();
00227 timer2_init();
00228 set_acceleration(ACCEL_FIXSLOW, 0);
00229
00230 stepper_loc.x = stepper_loc.y = 0;
00231 user_loc.x = user_loc.y = 0.0;
00232 alpha = 0;
00233 last_alpha = 0;
00234
00235 text_init();
00236 translate_init();
00237 pen_control(0);
00238
00239 seeking0 = SEEK0_NULL;
00240 }
00241
00250 void do_stuff() {
00251 STEPPER_COORD dstx, dsty;
00252 char c;
00253 uint8_t labelchar;
00254 uint8_t penny;
00255 static uint8_t arc_active = 0, initializing = 0, char_active = 0;
00256 int16_t runway_length;
00257
00258 dstx = dsty = -1;
00259 if (seeking0 != SEEK0_NULL) {
00260 while (seeking0 != SEEK0_DONE);
00261 seeking0 = SEEK0_NULL;
00262 plotter_init();
00263 printf_P(PSTR("\nHOME\n"));
00264 } else if (initializing) {
00265 while(!motors_ready());
00266 initializing = 0;
00267 plotter_init();
00268 } else if (arc_active) {
00269 arc_active = arc_next(&dstx,&dsty);
00270 } else if (char_active) {
00271 char_active = text_char(0, &dstx, &dsty, &penny);
00272 pen_control(penny);
00273 } else {
00274 if (uart_available()) {
00275 uart_putchar(c = uart_getc());
00276
00277 switch(hpgl_char(c, &dstx, &dsty, &labelchar)) {
00278 case CMD_PU:
00279 pen_control(0);
00280 break;
00281 case CMD_PD:
00282 pen_control(1);
00283 break;
00284 case CMD_PA:
00285 break;
00286 case CMD_ARCABS:
00287 arc_active = arc_init();
00288 break;
00289 case CMD_INIT:
00290
00291
00292 dstx = dsty = 0;
00293 initializing = 1;
00294 break;
00295 case CMD_SEEK0:
00296 seeking0 = SEEK0_SEEK;
00297 break;
00298 case CMD_LB0:
00299 text_beginlabel();
00300 break;
00301 case CMD_LB:
00302 if (labelchar != 0) {
00303 printf_P(PSTR("[%c]"), labelchar);
00304 char_active = text_char(labelchar, &dstx, &dsty, &penny);
00305 }
00306
00307 break;
00308 case CMD_SI:
00309 text_scale_cm(numpad[0], numpad[1]);
00310 break;
00311 case CMD_SR:
00312 text_scale_rel(numpad[0], numpad[1]);
00313 break;
00314 case CMD_DI:
00315 text_direction(numpad[0], numpad[1]);
00316 break;
00317 default:
00318 break;
00319 }
00320 }
00321 }
00322
00323
00324 if (dstx >= 0 && dsty >= 0) {
00325 #ifdef SLOW_QUALITY
00326 last_alpha = alpha;
00327 alpha_delta = calc_angle(dstx,dsty);
00328 #endif
00329
00330 while(!motors_ready());
00331
00332 #ifdef SLOW_QUALITY
00333
00334 if (alpha_delta > 60) {
00335 _delay_ms(50);
00336 }
00337 #endif
00338 printf_P(PSTR("PRE-PACE: %d; "), motor_pace);
00339 accel_strokesteps = movestep(dstx, dsty);
00340 set_acceleration(ACCEL_FIXSLOW, 0);
00341 set_acceleration(ACCEL_ACCEL, move_is_steep());
00342
00343 runway_length = (motor_pace-motor_pace_goal)*ACCEL_STEPS_PER_INCREMENT/2;
00344 if (2*runway_length < accel_strokesteps) {
00345 accel_decelthresh = accel_strokesteps - runway_length;
00346 } else {
00347 accel_decelthresh = accel_strokesteps/2;
00348 }
00349
00350
00351 printf_P(PSTR("User: (%5.2f,%5.2f)\n"), user_loc.x, user_loc.y);
00352 }
00353 }
00354
00355 int main() {
00356 init_io();
00357
00358 set_sleep_mode(SLEEP_MODE_IDLE);
00359
00360 usart_init((F_CPU/(16*115200))-1);
00361
00362 printf_P(PSTR("HEART OF THE INTERSTELLAR LINER\n"));
00363
00364 motori_init();
00365
00366 plotter_init();
00367
00368 hpgl_init();
00369
00370 sei();
00371
00372 set_acceleration(ACCEL_FIXFAST, 0);
00373 seeking0 = SEEK0_SEEK;
00374
00375 for (;;) {
00376 do_stuff();
00377 }
00378
00379 return 0;
00380 }
00381
00382
00389 void SIG_OUTPUT_COMPARE0A( void ) __attribute__ ( ( signal ) );
00390 void SIG_OUTPUT_COMPARE0A( void ) {
00391 int16_t stepnumber;
00392
00393 OCR0A = motor_pace;
00394
00395 borderflags = ~PINA & 0x3f;
00396
00397 if (seeking0 == SEEK0_SEEK) {
00398 if ((borderflags & (_BV(XSUP)|_BV(YSUP))) == (_BV(XSUP)|_BV(YSUP))) {
00399 seeking0 = SEEK0_DONE;
00400 }
00401 step(borderflags & _BV(XSUP) ? 0 : -1, borderflags & _BV(YSUP) ? 0 : -1);
00402
00403 return;
00404 }
00405
00406 stepnumber = movestep(-1,-1);
00407
00408 if (stepnumber == accel_decelthresh) {
00409 if (accel_decelthresh != 0) {
00410 set_acceleration(ACCEL_DECEL, move_is_steep());
00411 }
00412 }
00413
00414 if (stepnumber != -1 && motor_accel) {
00415 if (--motor_accel_ctr == 0) {
00416 motor_accel_ctr = ACCEL_STEPS_PER_INCREMENT;
00417 motor_pace += motor_accel;
00418 if (motor_pace == motor_pace_goal) {
00419 motor_accel = 0;
00420 }
00421 }
00422 }
00423 }
00424
00426 void SIG_OVERFLOW2( void ) __attribute__ ( ( signal ) );
00427 void SIG_OVERFLOW2( void ) {
00428 if (pen_relax != 0) {
00429 if (pen_pulse_counter == 0) {
00430 pen_relax--;
00431 PORTD |= _BV(PENPCM);
00432 } else if (pen_pulse_counter == 15 && pen_status == 0) {
00433 PORTD &= ~_BV(PENPCM);
00434 } else if (pen_pulse_counter == 17) {
00435 PORTD &= ~_BV(PENPCM);
00436 }
00437 }
00438 pen_pulse_counter = (pen_pulse_counter + 1) & 0x7f;
00439 }
00440
00441