diff --git a/printer/avr/main.c b/printer/avr/main.c index ea0627f..0876c20 100644 --- a/printer/avr/main.c +++ b/printer/avr/main.c @@ -5,6 +5,7 @@ #include #define BAUDRATE 19200 +//#define DEBUG_BUILD DEBUG_BUILD /* System functions */ /* Timers */ @@ -53,8 +54,7 @@ void uart_putc(char c) UDR = c; } -#define ENABLE_SERIAL_DEBUG -#ifdef ENABLE_SERIAL_DEBUG +#ifdef DEBUG_BUILD void debug_putc(char c) { uart_putc(c); }; @@ -90,10 +90,20 @@ unsigned int debug_printf(char *format,...) {return 0;}; void hardfault() { cli(); - debug_write("HARDFAULT!\r\n"); PORTB = 0; PORTC = 0; PORTD = 0; + uart_putc(0xFF); + uart_putc(0xFF); + uart_putc(0xFF); + uart_putc(0xFF); + uart_putc(0xFF); + uart_putc(0xFF); + uart_putc(0xFF); + uart_putc(0x00); + uart_putc(0x00); + uart_putc(0x00); + debug_write("HARDFAULT!\r\n"); while(1); } @@ -560,16 +570,99 @@ void arm_correction() #define DCMOTOR_EN MOTLIM(PORT) |= PIN_DCMOTOR #define DCMOTOR_STOP MOTLIM(PORT) &= ~PIN_DCMOTOR -#define DCMOTOR_ISACTIVE (MOTLIM(PORT) & PIN_DCMOTOR) +#define DCMOTOR_ISACTIVE (!!(MOTLIM(PORT) & PIN_DCMOTOR)) #define LIMITSWITCH (!(MOTLIM(PIN) & PIN_LIMITSWITCH)) +/* Communication Functions */ +#define RINGBUF_CNT(wr,rd) ((wr) - (rd)) +#define RINGBUF_FREE(wr,rd,sz) ((RINGBUF_CNT(rd,wr+1))) // TODO: 255 is actually not correct... +#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 UART_BYTE_READY (UCSRA & (1 << RXC)) + +ISR(USART_RXC_vect) +{ + if (UCSRA & (1 << RXC)) { + print_buffer[print_buffer_wr++] = UDR;// WARNING: No overflow protection + // Will auto wrap at 256; print_buffer_wr = print_buffer_wr % PRINT_BUFFER_SIZE; + } +} + +#define TX_BUFFER_SIZE 256 // Important: must be 256 atm, when changed, you need to change code handling print_buffer_*. +char tx_buffer[TX_BUFFER_SIZE]; +uint8_t tx_buffer_wr = 0; +uint8_t tx_buffer_rd = 0; +uint8_t tx_buffer_async = 0; + +uint8_t global_status; +#define STATUS_PAPERFEED (1 << 0) +#define STATUS_CARRIAGE (1 << 1) +#define STATUS_DAISY (1 << 2) +#define STATUS_PRINTHEAD (1 << 3) +#define STATUS_READY (1 << 4) +#define STATUSBIT_ACTIVE 5 + +void tx_buffer_putc(char c) +{ + if (tx_buffer_async) { + if (tx_buffer_rd == tx_buffer_wr + 1) // implicit % 256 + hardfault(); + tx_buffer[tx_buffer_wr++] = c; // implicit % 256 + } else { + uart_putc(c); + } +} + +void tx_status() +{ + unsigned char local_status = 0; + local_status |= (DCMOTOR_ISACTIVE << STATUSBIT_ACTIVE); + + tx_buffer_putc(0xFF); /* Header[0] */ + tx_buffer_putc(0xAA); /* Header[1] */ + tx_buffer_putc((char) (global_status | local_status)); + tx_buffer_putc(RINGBUF_FREE(print_buffer_wr, print_buffer_rd, PRINT_BUFFER_SIZE)); + tx_buffer_putc(0); /* RESERVED */ + tx_buffer_putc(0); /* RESERVED */ +} + +void update_status(uint8_t status) +{ + global_status = status; + + tx_status(); +} + +void set_status(uint8_t bit) +{ + update_status(global_status | bit); +} + +void clear_status(uint8_t bit) +{ + update_status(global_status & ~bit); +} + +void tx_buffer_process() +{ + if (tx_buffer_rd != tx_buffer_wr) { + if (UCSRA & (1 << UDRE)) { + UDR = tx_buffer[tx_buffer_rd]; + tx_buffer_rd++; // implicit % 256 + } + } +} /* Initialization Functions */ - void move_carriage_to_far_left(uint8_t reset) { uint16_t cnt = 0; + clear_status(STATUS_CARRIAGE); + /* Init stepper controller */ if (reset) { stepper_status_CARRIAGE.step = 0; @@ -605,6 +698,7 @@ void move_carriage_to_far_left(uint8_t reset) stepper_status_CARRIAGE.target_pos = 0; debug_printf("[car] Carriage left after %u steps.\r\n", cnt); + set_status(STATUS_CARRIAGE); } void align_daisy_wheel() @@ -612,6 +706,8 @@ void align_daisy_wheel() int i; debug_write("[whl] Aligning wheel...\r\n"); + clear_status(STATUS_DAISY); + stepper_status_WHEEL.dir = 0; stepper_status_WHEEL.lpstate = 0; stepper_status_WHEEL.pos = 0; @@ -651,15 +747,18 @@ void align_daisy_wheel() stepper_status_WHEEL.pos = 0; debug_write("[whl] Alignment completed.\r\n"); + set_status(STATUS_DAISY); } void reset_printhead() { debug_write("[hmr] Resetting printhead...\r\n"); + clear_status(STATUS_PRINTHEAD); DCMOTOR_EN; _delay_ms(200); DCMOTOR_STOP; debug_write("[hmr] Printhead reset completed.\r\n"); + set_status(STATUS_PRINTHEAD); } void initialize_paperfeed() @@ -667,6 +766,7 @@ void initialize_paperfeed() int i; debug_write("[lfd] Initializing paperfeed...\r\n"); + clear_status(STATUS_PAPERFEED); for (i = 0; i < 10;) { if (block_for(TIM_LINEFEED, STEPPER_CFG_LINEFEED.delay)) { @@ -684,26 +784,10 @@ void initialize_paperfeed() stepper_status_LINEFEED.ldir = 0; debug_write("[lfd] Initialization completed.\r\n"); + set_status(STATUS_PAPERFEED); } /* Printer Functions */ - -#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 UART_BYTE_READY (UCSRA & (1 << RXC)) - -ISR(USART_RXC_vect) -{ - if (UCSRA & (1 << RXC)) { - print_buffer[print_buffer_wr++] = UDR;// WARNING: No overflow protection - // Will auto wrap at 256; print_buffer_wr = print_buffer_wr % PRINT_BUFFER_SIZE; - } -} - - #define PRINT_CHARACTER_WIDTH 10 #define PRINT_LINE_HEIGHT 34 #define PRINTER_STOP_RIGHT 1100 @@ -841,6 +925,7 @@ void printer_process() } else { current_char = print_buffer[print_buffer_rd]; print_buffer_rd++; + tx_status(); // Tell SoC when bytes are consumed from the buffer. TODO: Too often? } } else { current_char = '\0'; @@ -850,31 +935,30 @@ void printer_process() current_is_linebreak += (current_char == '\n'); if (current_is_linebreak) { if (backward) { - uart_putc('='); + debug_putc('='); print_buffer_rd = print_buffer_recovery; + tx_status(); } backward = 0; // Re-evaluate backward. Default is forward. stepper_status_LINEFEED.target_pos += PRINT_LINE_HEIGHT; - uart_putc('\n'); + debug_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. */ + * whether to 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('['); + debug_putc('['); backward = 1; print_buffer_backward = end_of_next_line; } else if (temp == 0) { // do nothing - uart_putc('#'); + debug_putc('#'); } else { move_carriage_to_left_margin(); @@ -891,7 +975,7 @@ void printer_process() case PRINTER_NO_CHAR: current_is_linebreak += move_one_character(backward); if (!current_is_linebreak) - uart_putc(' '); + debug_putc(' '); break; default: /* It's a printable character */ @@ -912,7 +996,7 @@ void printer_process() if (POSITION_REACHED(WHEEL) && POSITION_REACHED(CARRIAGE) && POSITION_REACHED(LINEFEED)) { arm_hammer(); _delay_ms(50); // TODO: replace with timer - uart_putc(debug_character); + debug_putc(debug_character); current_is_linebreak += move_one_character(backward); state = IDLE; } @@ -943,7 +1027,16 @@ void printer_process() stepper_perform_movement(&stepper_status_WHEEL, &STEPPER_CFG_WHEEL); } +void sync_uart() +{ + int i; + for (i = 0; i < 10; ++i) { + tx_buffer_putc(0xFF); + } +} + /* Test Functions */ +#ifdef DEBUG_BUILD void systick_test() { debug_write("[tmr] System timer test\r\n"); @@ -1135,11 +1228,17 @@ static void system_test_auto() } } } +#endif void mainloop() { + tx_buffer_async = 1; + uart_irq_enable(); /* rx buffer process */ + set_status(STATUS_READY); + while (1) { printer_process(); + tx_buffer_process(); } } @@ -1181,24 +1280,26 @@ int main() TIMSK = (1 << OCIE1A); /* Init system */ + sync_uart(); + update_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(); + initialize_paperfeed(); + move_carriage_to_far_left(1); + align_daisy_wheel(); + reset_printhead(); debug_write("[sys] Startup completed.\r\n"); /* Run system */ +#ifdef DEBUG_BUILD system_test_auto(); - // mainloop(); - // printer_test(); - // system_test_auto(); - // systick_test(); +#else + mainloop(); +#endif debug_write("[sys] REACHED END OF MAIN. HALTING.\r\n"); while (1);