From 37cfd93bef7819f52387e860cec2225df6812a71 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Sat, 26 Oct 2019 17:11:07 +0200 Subject: [PATCH] printer: implement SPI based controller --- printer/avr/Makefile | 3 +- printer/avr/main.c | 774 +++++++++++++++++++++++++++++++--------- printer/avr/printer.pro | 2 + 3 files changed, 601 insertions(+), 178 deletions(-) diff --git a/printer/avr/Makefile b/printer/avr/Makefile index f88f849..4b5f434 100644 --- a/printer/avr/Makefile +++ b/printer/avr/Makefile @@ -1,5 +1,5 @@ MCU=atmega8 -CFLAGS=-g -Wall -mcall-prologues -mmcu=$(MCU) -Os -DF_CPU=8000000 +CFLAGS=-g -Wall -mcall-prologues -mmcu=$(MCU) -O2 -DF_CPU=8000000 LDFLAGS=-Wl,-gc-sections -Wl,-relax CC=avr-gcc TARGET=main @@ -15,6 +15,7 @@ clean: %.obj: $(OBJECT_FILES) $(CC) $(CFLAGS) $(OBJECT_FILES) $(LDFLAGS) -o $@ + avr-size -C --mcu=atmega8 main.obj program: $(TARGET).obj avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex diff --git a/printer/avr/main.c b/printer/avr/main.c index 0079e1c..de12264 100644 --- a/printer/avr/main.c +++ b/printer/avr/main.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -7,6 +7,8 @@ #define BAUDRATE 9600 #define UBRR 51 // (F_CPU / BAUDRATE) / 32 +inline void spi_process_data(); + /* System functions */ /* Timers */ enum TIMERS{TIM_CARRIAGE, @@ -28,6 +30,8 @@ uint8_t block_for(uint8_t channel, uint16_t time_systicks) return 0; } +uint8_t system_status; // CAUTION: Must not be updated from interrupts! + ISR (TIMER1_COMPA_vect) { uint8_t i; @@ -36,7 +40,8 @@ ISR (TIMER1_COMPA_vect) timer[i]--; } } - return; + if (SPSR & (1<lpstate = pstate; - //if (cfg->port == 'B') uart_printf("[%d] stop at: %x\r\n", stat->step, pstate & 0xF); + //if (cfg->port == 'B') debug_printf("[%d] stop at: %x\r\n", stat->step, pstate & 0xF); pstate &= ~(cfg->pin_a | cfg->pin_b | cfg->pin_c | cfg->pin_d); } else { if (stat->dir == 0) { /* If this is the first step */ pstate |= stat->lpstate & (cfg->pin_a | cfg->pin_b | cfg->pin_c | cfg->pin_d); - //if (cfg->port == 'B') uart_printf("[%d] restore to : %x\r\n", stat->step, pstate & 0xF); + //if (cfg->port == 'B') debug_printf("[%d] restore to : %x\r\n", stat->step, pstate & 0xF); } else { switch (stat->step) { case 0: @@ -385,7 +414,7 @@ void stepper_next_f(struct stepper_status *stat, default: break; } - //if (cfg->port == 'B') uart_printf("[%d] set to : %x\r\n", stat->step, pstate & 0xF); + //if (cfg->port == 'B') debug_printf("[%d] set to : %x\r\n", stat->step, pstate & 0xF); } } @@ -464,11 +493,11 @@ uint8_t stepper_perform_movement(struct stepper_status *stat, dir = stepper_required_direction(stat, cfg); if ((dir == -1) && (stat->dir == 1)) { /* Reversal */ dir = 0; - uart_write("[stp] Hard reversal detected. Pausing. -->|\r\n"); + //debug_write("[stp] Hard reversal detected. Pausing. -->|\r\n"); set_timer(cfg->timch, cfg->delay * REVERSAL_MULTIPLIER); } else if ((dir == 1) && (stat->dir == -1)) { /* Reversal */ dir = 0; - uart_write("[stp] Hard reversal detected. Pausing. |<--\r\n"); + //debug_write("[stp] Hard reversal detected. Pausing. |<--\r\n"); set_timer(cfg->timch, cfg->delay * REVERSAL_MULTIPLIER); } stepper_next_f(stat, cfg, dir); @@ -477,7 +506,7 @@ uint8_t stepper_perform_movement(struct stepper_status *stat, return 0; } -#define POSITION_REACHED(NAME) (stepper_status_##NAME.pos == stepper_status_##NAME.target_pos) +#define POSITION_REACHED(NAME) ((stepper_status_##NAME.dir == 0) && (stepper_status_##NAME.pos == stepper_status_##NAME.target_pos)) #define SET_TARGET(NAME, target) stepper_set_target(&stepper_status_##NAME, \ &STEPPER_CFG_##NAME,\ @@ -490,11 +519,11 @@ void stepper_set_target(struct stepper_status *stat, { if (cfg->wraparound) { while (target >= -cfg->wraparound) { - uart_printf("WRAP- %u\r\n", target); + debug_printf("WRAP- %u\r\n", target); target += cfg->wraparound; } while (target >= cfg->wraparound) { - uart_printf("WRAP+ %u\r\n", target); + debug_printf("WRAP+ %u\r\n", target); target -= cfg->wraparound; } } @@ -511,6 +540,7 @@ void arm_hammer() #define DCMOTOR_EN MOTLIM(PORT) |= PIN_DCMOTOR #define DCMOTOR_STOP MOTLIM(PORT) &= ~PIN_DCMOTOR +#define DCMOTOR_ISACTIVE (MOTLIM(PORT) & PIN_DCMOTOR) #define LIMITSWITCH (!(MOTLIM(PIN) & PIN_LIMITSWITCH)) @@ -526,7 +556,22 @@ void move_carriage_to_far_left(uint8_t reset) } stepper_status_CARRIAGE.dir = -1; - uart_write("[car] Moving carriage to far left...\r\n"); + if (LIMITSWITCH) { + debug_write("[car] Clearing switch area...\r\n"); + while (LIMITSWITCH) { + if (block_for(TIM_CARRIAGE, STEPPER_CFG_CARRIAGE.delay)) { + STEPPER_NEXT(CARRIAGE, 1); + } + } + for (cnt = 0; cnt < 16; cnt++) { + STEPPER_NEXT(CARRIAGE, 1); + } + STEPPER_STOP(CARRIAGE); + _delay_ms(100); + } + + debug_write("[car] Moving carriage to far left...\r\n"); + cnt = 0; while (!LIMITSWITCH) { if (block_for(TIM_CARRIAGE, STEPPER_CFG_CARRIAGE.delay)) { cnt++; @@ -539,14 +584,14 @@ void move_carriage_to_far_left(uint8_t reset) stepper_status_CARRIAGE.pos = 0; stepper_status_CARRIAGE.target_pos = 0; - uart_printf("[car] Carriage left after %u steps.\r\n", cnt); + debug_printf("[car] Carriage left after %u steps.\r\n", cnt); } void align_daisy_wheel() { int i; - uart_write("[whl] Aligning wheel...\r\n"); + debug_write("[whl] Aligning wheel...\r\n"); stepper_status_WHEEL.dir = 0; stepper_status_WHEEL.lpstate = 0; stepper_status_WHEEL.pos = 0; @@ -554,6 +599,15 @@ void align_daisy_wheel() stepper_status_WHEEL.target_pos = 0; stepper_status_WHEEL.ldir = 0; + /* Rotate right for one revolution -> lock daisy wheel to assembly */ + for (i = 0; i < (96 + 1) * 2; ) { + if (block_for(TIM_WHEEL, STEPPER_CFG_WHEEL.delay)) { + STEPPER_NEXT(WHEEL, 1); + i++; + } + } + + /* Rotate left for one revolution -> align daisy wheel assembly */ for (i = 0; i < (96 + 1) * 2; ) { if (block_for(TIM_WHEEL, STEPPER_CFG_WHEEL.delay)) { STEPPER_NEXT(WHEEL, -1); @@ -576,190 +630,548 @@ void align_daisy_wheel() stepper_status_WHEEL.target_pos = 0; stepper_status_WHEEL.pos = 4; - uart_write("[whl] Alignment completed.\r\n"); + debug_write("[whl] Alignment completed.\r\n"); } void reset_printhead() { - uart_write("[hmr] Resetting printhead...\r\n"); + debug_write("[hmr] Resetting printhead...\r\n"); DCMOTOR_EN; _delay_ms(200); DCMOTOR_STOP; - uart_write("[hmr] Printhead reset completed.\r\n"); + debug_write("[hmr] Printhead reset completed.\r\n"); } -int system_test_auto() +void initialize_paperfeed() { - char c; - int do_it = 0; - int print_stat = 0; + int i; - uart_write("[sys] Entering system test mode\r\n"); - uart_write(">"); + debug_write("[lfd] Initializing paperfeed...\r\n"); - while(1) { - if (UCSRA & (1 << RXC)) { - print_stat = 1; - c = UDR; + for (i = 0; i < 10;) { + if (block_for(TIM_LINEFEED, STEPPER_CFG_LINEFEED.delay)) { + STEPPER_NEXT(LINEFEED, 1); + i++; + } + } + STEPPER_STOP(LINEFEED); + + stepper_status_LINEFEED.dir = 0; + stepper_status_LINEFEED.lpstate = 0; + stepper_status_LINEFEED.pos = 32768; + stepper_status_LINEFEED.step = 0; + stepper_status_LINEFEED.target_pos = 32768; + stepper_status_LINEFEED.ldir = 0; + + debug_write("[lfd] Initialization completed.\r\n"); +} + +//int system_test_auto() +//{ +// char c; +// int do_it = 0; +// int print_stat = 0; + +// debug_write("[sys] Entering system test mode\r\n"); +// debug_write(">"); + +// while(1) { +// if (UCSRA & (1 << RXC)) { +// print_stat = 1; +// c = UDR; + +// if (c >= '0' && c <= '9') { +// stepper_status_CARRIAGE.target_pos = 100 * (c - '0'); +// } else { +// switch (c) { +// case ' ': +// stepper_status_CARRIAGE.target_pos += 10; +// break; +// case 'z': +// if (stepper_status_CARRIAGE.target_pos >= 10) +// stepper_status_CARRIAGE.target_pos -= 10; +// break; +// case 'r': +// move_carriage_to_far_left(0); +// break; +// case 'h': +// DCMOTOR_EN; +// arm_hammer(); +// _delay_ms(100); /* Note, this also locks the carriage movement -> important! */ +// DCMOTOR_STOP; +// break; +// default: +// break; +// } + +// switch (c) { +// case '\'': +// //if (stepper_status_WHEEL.target_pos >= 2) +// SET_TARGET_DELTA(WHEEL, -2); +// debug_printf("[whl] New wheel: %d\r\n", stepper_status_WHEEL.target_pos); +// break; +// case ',': +// SET_TARGET_DELTA(WHEEL, 2); +// debug_printf("[whl] New wheel: %d\r\n", stepper_status_WHEEL.target_pos); +// break; +// case 'w': +// align_daisy_wheel(); +// break; +// case 't': +// stepper_status_WHEEL.target_pos += 2; +// stepper_status_CARRIAGE.target_pos += 10; +// do_it = 1; +// break; +// default: +// break; +// } +// } +// } + +// stepper_perform_movement(&stepper_status_CARRIAGE, &STEPPER_CFG_CARRIAGE); +// stepper_perform_movement(&stepper_status_WHEEL, &STEPPER_CFG_WHEEL); + +// if (POSITION_REACHED(WHEEL) && POSITION_REACHED(CARRIAGE) && print_stat) { +// print_stat = 0; +// debug_printf("[pos] CAR: %u\r\n[pos] WHL: %u\r\n", +// stepper_status_CARRIAGE.pos, +// stepper_status_WHEEL.pos); +// } + +// if (do_it) { +// if (stepper_status_CARRIAGE.pos == stepper_status_CARRIAGE.target_pos) { +// do_it = 0; +// DCMOTOR_EN; +// arm_hammer(); +// _delay_ms(100); +// DCMOTOR_STOP; +// } +// } +// } +//} + +//void printer_test() +//{ +// uint8_t buf[80] = {0}; +// uint8_t *ptr = buf; +// uint8_t *rdptr = buf; +// uint8_t translated = 0; +// int state = 0; + +// debug_write("[sys] Entering printer test mode\r\n"); + +// while(1) { + +// switch (state) { +// case 0: +// _delay_ms(100); // Motor turnoff delay +// DCMOTOR_STOP; + +// stepper_status_CARRIAGE.target_pos = 80; +// stepper_status_WHEEL.target_pos = 0;stat->lpstate = pstate; +// ptr = buf; +// debug_write(">"); +// state++; +// break; +// case 1: +// if (UCSRA & (1 << RXC)) { +// //stepper_status_WHEEL.target_pos += 2; +// *ptr = UDR; +// uart_putc(*ptr); +// if (*ptr == '\r') { +// debug_write("\r\nOK.\r\n"); +// DCMOTOR_EN; +// _delay_ms(100); // Let motor get up to speed + +// state++; + +// stepper_status_CARRIAGE.target_pos = 80; +// rdptr = buf; +// } else { +// ptr++; +// } +// } +// break; +// case 2: +// stepper_status_CARRIAGE.target_pos += 10; +// translated = pgm_read_byte(&ascii_translation_table[*rdptr]); +// if (translated != PRINTER_NO_CHAR) { +// //debug_printf("Prepare: %x (%c) -> %d", *rdptr, *rdptr, translated); +// SET_TARGET(WHEEL, translated * 2); +// state++; +// } else { +// //debug_printf("Skip: %x (%c) -> %d\r\n", *rdptr, *rdptr, translated); +// rdptr++; +// if (rdptr == ptr) { +// state = 0; +// } +// } +// break; +// case 3: +// if (POSITION_REACHED(CARRIAGE) && POSITION_REACHED(WHEEL)) { +// //debug_write("!!!\r\n"); +// //DCMOTOR_EN; +// arm_hammer(); +// _delay_ms(50); +// //DCMOTOR_STOP; +// rdptr++; +// if (rdptr == ptr) { +// state = 0; +// } else { +// state--; +// } +// } +// break; +// default: +// break; +// } + +// stepper_perform_movement(&stepper_status_CARRIAGE, &STEPPER_CFG_CARRIAGE); +// stepper_perform_movement(&stepper_status_WHEEL, &STEPPER_CFG_WHEEL); +// } +//} + +//void systick_test() +//{ +// debug_write("[tmr] System timer test\r\n"); +// while (1) { +// if (block_for(0, 1000*4)) { +// debug_write("hello"); +// } +// } +//} + + +void hardfault() { + debug_write("HARDFAULT!\r\n"); + STEPPER_STOP(WHEEL); + STEPPER_STOP(CARRIAGE); + STEPPER_STOP(LINEFEED); + while(1); +} + +/* SPI */ +#define PRINT_BUFFER_SIZE 256 // Important: must be 256 atm, when changed, you need to change code handling print_buffer_*. +volatile char print_buffer[PRINT_BUFFER_SIZE]; +volatile uint8_t print_buffer_wr = 0; +volatile uint8_t print_buffer_rd = 0; + +#define SPI_COMMAND_NONE 0x00 + +#define SPI_COMMAND_PRINTER_WRITE 0x01 +#define SPI_COMMAND_PRINTER_RESET 0x02 +#define SPI_COMMAND_PRINTER_SETMODE 0x03 +#define SPI_COMMAND_PRINTER_MANUAL 0x04 +#define SPI_COMMAND_PRINTER_PAUSE 0x05 +#define SPI_COMMAND_PRINTER_RESUME 0x06 +#define SPI_COMMAND_PRINTER_CLEARBUF 0x07 + +#define SPI_COMMAND_KEYBOARD_GETKEY 0x20 +#define SPI_COMMAND_KEYBOARD_CLEARBUF 0x21 + +#define SPI_COMMAND_SYSTEM_BACKLIGHT 0x40 + +#define UART_CMD_ACK_KEYPRESS 'A' + +#define SPI_GET_CS (!(PINB & (1 << 2))) +#define UART_BYTE_READY (UCSRA & (1 << RXC)) + +volatile uint8_t spi_command = SPI_COMMAND_NONE; +volatile uint8_t keys_to_be_acked = 0; + +/* This function needs to be fast AF! */ +inline void spi_process_data() +{ + switch (spi_command) { + case SPI_COMMAND_KEYBOARD_GETKEY: /* Needs to be first, quick reply expected. */ + if (UART_BYTE_READY) { + SPDR = UDR; + keys_to_be_acked++; + } else { + SPDR = 0x00; + } + break; + + /* !!! Only no-reply commands below !!! */ + case SPI_COMMAND_NONE: /* This is the start of the transaction */ + spi_command = SPDR; + break; + + case SPI_COMMAND_PRINTER_WRITE: + print_buffer[print_buffer_wr++] = SPDR; // WARNING: No overflow protection + // Will auto wrap at 256; print_buffer_wr = print_buffer_wr % PRINT_BUFFER_SIZE; + break; + + default: + //SPDR = 0x0; + break; + + } +} + +ISR(SPI_STC_vect) +{ + spi_process_data(); +} + +void ioc_process() +{ + if (!SPI_GET_CS) { + /* Cancel the current command */ + spi_command = SPI_COMMAND_NONE; + SPDR = system_status; // TODO: status 1 + } + if (keys_to_be_acked && (UCSRA & (1 << UDRE))) { + UDR = UART_CMD_ACK_KEYPRESS; + keys_to_be_acked--; + } + +} + +#define PRINT_CHARACTER_WIDTH 10 +#define PRINT_LINE_HEIGHT 34 +#define PRINTER_STOP_RIGHT 1100 + +enum printer_mode_t {MANUAL, INTELLIGENT}; + +#define GET_PRINT_CODE(c) (pgm_read_byte(&ascii_translation_table[c])) + +uint16_t print_margin_left = 100; +uint16_t print_margin_right = PRINTER_STOP_RIGHT - 100; + +int8_t move_one_character(uint8_t backward) +{ + if (backward) { + if (stepper_status_CARRIAGE.target_pos < print_margin_left + PRINT_CHARACTER_WIDTH) { + return 1; + } + stepper_status_CARRIAGE.target_pos -= PRINT_CHARACTER_WIDTH; + } else { + if (stepper_status_CARRIAGE.target_pos >= print_margin_right - PRINT_CHARACTER_WIDTH) { + return 1; + } + stepper_status_CARRIAGE.target_pos += PRINT_CHARACTER_WIDTH; + } + return 0; +} + +void move_carriage_to_left_margin() +{ + stepper_status_CARRIAGE.target_pos = print_margin_left; + debug_putc('\r'); + debug_putc('{'); +} + +/* Simulates the print of one line and returns the end position of the printhead */ +/* It's only called once, so inline is good. */ +inline int8_t simulate_print_run(uint8_t *start_end_index, uint8_t *recovery_index) +{ + char current_char; + uint8_t index; + uint16_t carriage_position; + uint8_t translated; + uint8_t status = 0; + uint8_t line_matters = 0; + + index = *start_end_index; + carriage_position = print_margin_left; + + while (!status) { + current_char = print_buffer[index]; + + if (index == print_buffer_wr) { /* END OF BUFFER - Can't determine length */ + status = 3; + line_matters = 1; + carriage_position = print_margin_right; + break; + } + + if (current_char == '\n') { + index--; + status = 1; + break; + + } else if (current_char < ASCII_TRANSLATION_TABLE_SIZE) { + translated = GET_PRINT_CODE(current_char); + + if (translated == PRINTER_CONTROL_CHAR) { + // ignore - if (c >= '0' && c <= '9') { - stepper_status_CARRIAGE.target_pos = 100 * (c - '0'); } else { - switch (c) { - case ' ': - stepper_status_CARRIAGE.target_pos += 10; - break; - case 'z': - if (stepper_status_CARRIAGE.target_pos >= 10) - stepper_status_CARRIAGE.target_pos -= 10; - break; - case 'r': - move_carriage_to_far_left(0); - break; - case 'h': - DCMOTOR_EN; - arm_hammer(); - _delay_ms(100); /* Note, this also locks the carriage movement -> important! */ - DCMOTOR_STOP; - break; - default: - break; - } - - switch (c) { - case '\'': - //if (stepper_status_WHEEL.target_pos >= 2) - SET_TARGET_DELTA(WHEEL, -2); - uart_printf("[whl] New wheel: %d\r\n", stepper_status_WHEEL.target_pos); - break; - case ',': - SET_TARGET_DELTA(WHEEL, 2); - uart_printf("[whl] New wheel: %d\r\n", stepper_status_WHEEL.target_pos); - break; - case 'w': - align_daisy_wheel(); - break; - case 't': - stepper_status_WHEEL.target_pos += 2; - stepper_status_CARRIAGE.target_pos += 10; - do_it = 1; - break; - default: - break; + if (carriage_position >= print_margin_right - PRINT_CHARACTER_WIDTH) { + status = 2; + carriage_position += PRINT_CHARACTER_WIDTH; + //(*recovery_index) = index + 1; + break; /* Don't consume character */ + } else { + carriage_position += PRINT_CHARACTER_WIDTH; + if (translated != PRINTER_NO_CHAR) { + line_matters = 1; + } } } } - stepper_perform_movement(&stepper_status_CARRIAGE, &STEPPER_CFG_CARRIAGE); - stepper_perform_movement(&stepper_status_WHEEL, &STEPPER_CFG_WHEEL); + index++; /* Consume character */ + (*recovery_index) = index + 1; + } - if (POSITION_REACHED(WHEEL) && POSITION_REACHED(CARRIAGE) && print_stat) { - print_stat = 0; - uart_printf("[pos] CAR: %u\r\n[pos] WHL: %u\r\n", - stepper_status_CARRIAGE.pos, - stepper_status_WHEEL.pos); - } + carriage_position -= PRINT_CHARACTER_WIDTH; + *start_end_index = index; - if (do_it) { - if (stepper_status_CARRIAGE.pos == stepper_status_CARRIAGE.target_pos) { - do_it = 0; + //debug_printf("$ restore to: %d M=%d S=%d\n", print_buffer[*recovery_index], line_matters, status); + //debug_printf("CMP %d <= %d\n", ((carriage_position - print_margin_left) / 2) , (stepper_status_CARRIAGE.target_pos - print_margin_left)); + if (!line_matters) { + return 0; + } else if (((carriage_position - print_margin_left) / 2) < (stepper_status_CARRIAGE.target_pos - print_margin_left)) { + //debug_printf("next char: %c\n", print_buffer[index]); + //_delay_ms(5000); + stepper_status_CARRIAGE.target_pos = carriage_position; + return -1; + } else { + return 1; + } +} + +enum printer_state {INIT, IDLE, HAMMER, PAUSED}; +void printer_process() +{ + static enum printer_state state = INIT; + static uint8_t backward = 0; + static uint8_t print_buffer_backward = 0; + static uint8_t print_buffer_recovery = 0; + + static uint8_t current_is_linebreak = 0; + char current_char; + uint8_t translated; + + uint8_t end_of_next_line = 0; + int8_t temp; + static char debug_character = 0; + + switch (state) { + case IDLE: + if (print_buffer_rd != print_buffer_wr) { // maybe add "|| current_is_linebreak" + if (!DCMOTOR_ISACTIVE) { DCMOTOR_EN; - arm_hammer(); - _delay_ms(100); - DCMOTOR_STOP; + _delay_ms(100); /* Let the motor get up to speed */ } - } - } -} -void printer_test() -{ - uint8_t buf[80] = {0}; - uint8_t *ptr = buf; - uint8_t *rdptr = buf; - uint8_t translated = 0; - int state = 0; - - uart_write("[sys] Entering printer test mode\r\n"); - - while(1) { - - switch (state) { - case 0: - _delay_ms(100); // Motor turnoff delay - DCMOTOR_STOP; - - stepper_status_CARRIAGE.target_pos = 80; - stepper_status_WHEEL.target_pos = 0; - ptr = buf; - uart_write(">"); - state++; - break; - case 1: - if (UCSRA & (1 << RXC)) { - //stepper_status_WHEEL.target_pos += 2; - *ptr = UDR; - uart_tx(*ptr); - if (*ptr == '\r') { - uart_write("\r\nOK.\r\n"); - DCMOTOR_EN; - _delay_ms(100); // Let motor get up to speed - - state++; - - stepper_status_CARRIAGE.target_pos = 80; - rdptr = buf; + /* Fetch new character from buffer */ + if (!current_is_linebreak) { + if (backward) { + current_char = print_buffer[print_buffer_backward]; + print_buffer_backward--; } else { - ptr++; + current_char = print_buffer[print_buffer_rd]; + print_buffer_rd++; } - } - break; - case 2: - stepper_status_CARRIAGE.target_pos += 10; - translated = pgm_read_byte(&ascii_translation_table[*rdptr]); - if (translated != PRINTER_NO_CHAR) { - //uart_printf("Prepare: %x (%c) -> %d", *rdptr, *rdptr, translated); - SET_TARGET(WHEEL, translated * 2); - state++; } else { - //uart_printf("Skip: %x (%c) -> %d\r\n", *rdptr, *rdptr, translated); - rdptr++; - if (rdptr == ptr) { - state = 0; - } + current_char = '\0'; } - break; - case 3: - if (POSITION_REACHED(CARRIAGE) && POSITION_REACHED(WHEEL)) { - //uart_write("!!!\r\n"); - //DCMOTOR_EN; - arm_hammer(); - _delay_ms(50); - //DCMOTOR_STOP; - rdptr++; - if (rdptr == ptr) { - state = 0; - } else { - state--; - } - } - break; - default: - break; - } - stepper_perform_movement(&stepper_status_CARRIAGE, &STEPPER_CFG_CARRIAGE); - stepper_perform_movement(&stepper_status_WHEEL, &STEPPER_CFG_WHEEL); + /* Check whether the current character is a command or something to print */ + current_is_linebreak += (current_char == '\n'); + if (current_is_linebreak) { + if (backward) { + uart_putc('='); + print_buffer_rd = print_buffer_recovery; + } + backward = 0; // Re-evaluate backward. Default is forward. + + stepper_status_LINEFEED.target_pos -= PRINT_LINE_HEIGHT; + uart_putc('\n'); + current_is_linebreak--; + //_delay_ms(1000); + + /* Decide whether we move the carriage back to the left, or + * whether print the new line in reverse. */ + + end_of_next_line = print_buffer_rd; + temp = simulate_print_run(&end_of_next_line, &print_buffer_recovery); + + if (temp == -1) { + //uart_putc('\r'); + uart_putc('['); + backward = 1; + print_buffer_backward = end_of_next_line; + + } else if (temp == 0) { + // do nothing + uart_putc('#'); + + } else { + move_carriage_to_left_margin(); + } + + } else if (current_char < ASCII_TRANSLATION_TABLE_SIZE) { + translated = GET_PRINT_CODE(current_char); + debug_character = current_char; + + switch (translated) { + case PRINTER_CONTROL_CHAR: + break; + + case PRINTER_NO_CHAR: + current_is_linebreak += move_one_character(backward); + if (!current_is_linebreak) + uart_putc(' '); + break; + + default: /* It's a printable character */ + SET_TARGET(WHEEL, translated * 2); + state = HAMMER; + break; + } + } else { + // TODO: Handle special commands + } + + } else { + DCMOTOR_STOP; + } + break; + + case HAMMER: + if (POSITION_REACHED(WHEEL) && POSITION_REACHED(CARRIAGE) && POSITION_REACHED(LINEFEED)) { + arm_hammer(); + _delay_ms(50); // TODO: replace with timer + uart_putc(debug_character); + current_is_linebreak += move_one_character(backward); + state = IDLE; + } + break; + + case INIT: + move_carriage_to_left_margin(); + state = IDLE; } + + + // if (print_buffer_rd != print_buffer_wr) { + // if (UCSRA & (1 << UDRE)) { + // UDR = print_buffer[print_buffer_rd++]; + // } + // } + // // debug only: load the CPU with some stepper movements + // pgm_read_byte(&ascii_translation_table[123]); + // stepper_status_CARRIAGE.target_pos += 10; + // stepper_status_WHEEL.target_pos += 10; + // // ----------- + + if (stepper_status_CARRIAGE.target_pos > PRINTER_STOP_RIGHT) { // Right margin safety + hardfault(); + } + stepper_perform_movement(&stepper_status_LINEFEED, &STEPPER_CFG_LINEFEED); + stepper_perform_movement(&stepper_status_CARRIAGE, &STEPPER_CFG_CARRIAGE); + stepper_perform_movement(&stepper_status_WHEEL, &STEPPER_CFG_WHEEL); } -void systick_test() +void mainloop() { - uart_write("[tmr] System timer test\r\n"); while (1) { - if (block_for(0, 1000*4)) { - uart_write("hello"); - } + printer_process(); + ioc_process(); } } @@ -778,6 +1190,10 @@ int main() UBRRH = (UBRR >> 8) & 0xFF; UBRRL = UBRR & 0xFF; + /* Set up SPI */ + DDRB |= (1 << PB4); + SPCR = (1 << SPE) | (1 << CPOL) | (1 << CPHA) | (1 << SPIE); + /* Set up DC components */ MOTLIM(DDR) |= PIN_DCMOTOR; MOTLIM(DDR) &= ~(PIN_LIMITSWITCH); @@ -788,6 +1204,7 @@ int main() /* Set up steppers */ STEPPER_SET_IO(CARRIAGE); STEPPER_SET_IO(WHEEL); + STEPPER_SET_IO(LINEFEED); /* Set up SysTick Timer */ TCCR1B = (1 << WGM12) | (1 << CS11); // f_tim = 8 MHz / 8 @@ -795,22 +1212,25 @@ int main() TIMSK = (1 << OCIE1A); /* Init system */ - uart_write("\n\n\r[sys] STARTING IO CONTROLLER...\r\n"); - uart_write("[sys] Enabling interrupts.\r\n"); + system_status = 0; + debug_write("\n\n\r[sys] STARTING IO CONTROLLER...\r\n"); + debug_write("[sys] Enabling interrupts.\r\n"); sei(); /* Align printer */ + initialize_paperfeed(); move_carriage_to_far_left(1); align_daisy_wheel(); reset_printhead(); - uart_write("[sys] Startup completed.\r\n"); + debug_write("[sys] Startup completed.\r\n"); /* Run system */ - printer_test(); - system_test_auto(); - systick_test(); + mainloop(); + // printer_test(); + // system_test_auto(); + // systick_test(); - uart_write("[sys] REACHED END OF MAIN. HALTING.\r\n"); + debug_write("[sys] REACHED END OF MAIN. HALTING.\r\n"); while (1); } diff --git a/printer/avr/printer.pro b/printer/avr/printer.pro index 4e0df99..d48b1f0 100644 --- a/printer/avr/printer.pro +++ b/printer/avr/printer.pro @@ -7,3 +7,5 @@ INCLUDEPATH += /usr/avr/include SOURCES += \ main.c + +DEFINES += __AVR_ATmega8__