diff --git a/avr/Makefile b/avr/Makefile index fd4725f..f85ac71 100644 --- a/avr/Makefile +++ b/avr/Makefile @@ -7,8 +7,9 @@ HEADER_SUBDIR = tabby CROSS = avr- CC = $(CROSS)gcc -CFLAGS = $(CGFLAGS) -Wall -Os -mmcu=atmega328p -I$(INCLUDE_PATH) \ - -DF_CPU=$(CLOCK_SPEED) -DUSE_2X +CFLAGS = $(CGFLAGS) -Wall -Os -mmcu=atmega2560 \ + -fdata-sections -ffunction-sections -Wl,--gc-sections \ + -I$(INCLUDE_PATH) -DF_CPU=$(CLOCK_SPEED) -DUSE_2X LDFLAGS = OBJCOPY = $(CROSS)objcopy @@ -16,24 +17,24 @@ OBJCOPY_FLAGS = -S AVRDUDE = avrdude AVRDUDE_DEVICE = /dev/cu.usbmodem1411 -AVRDUDE_FLAGS = -c arduino -p atmega328p -b 115200 -D -P $(AVRDUDE_DEVICE) +AVRDUDE_FLAGS = -c wiring -p atmega2560 -b 115200 -D -P $(AVRDUDE_DEVICE) HEADERS_LOCAL = HEADERS_BUILD = $(HEADERS_LOCAL) \ $(addprefix $(INCLUDE_PATH)/$(HEADER_SUBDIR)/,$(HEADERS)) -HEADERS = avr.h avr/uart.h link.h -OBJS = send.o recv.o uart.o +HEADERS = avr.h avr/uart.h avr/link.h avr/printer.h link.h printer.h +OBJS = send.o recv.o printer.o link.o uart.o RECV_NAME = recv RECV_BIN = $(RECV_NAME).bin RECV_ELF = $(RECV_NAME).elf -RECV_OBJS = recv.o uart.o +RECV_OBJS = recv.o printer.o link.o uart.o SEND_NAME = send SEND_BIN = $(SEND_NAME).bin SEND_ELF = $(SEND_NAME).elf -SEND_OBJS = send.o uart.o +SEND_OBJS = send.o printer.o link.o uart.o IMAGES_BIN = $(RECV_BIN) $(SEND_BIN) IMAGES_ELF = $(RECV_ELF) $(SEND_ELF) diff --git a/avr/link.c b/avr/link.c new file mode 100644 index 0000000..6d61d9a --- /dev/null +++ b/avr/link.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +#include +#include +#include + +void tabby_avr_link_init_master() { + SC_OUTPUT(); + SO_OUTPUT(); + + SI_INPUT(); + SI_PULLUP(); + + SC_HIGH(); + SO_LOW(); +} + +void tabby_avr_link_init_slave() { + SS_INPUT(); + SC_INPUT(); + SI_INPUT(); + SO_OUTPUT(); + + /* + * Set SPI slave mode, and shift in/out most significant bit first + */ + SPCR &= ~((1 << MSTR) | (1 << DORD)); + + /* + * Enable SPI in Mode 3 with interrupts, clock nominally high, output on + * falling edge, input on rising edge + */ + SPCR |= (1 << CPOL) | (1 << CPHA) | (1 << SPIE) | (1 << SPE); + + /* + * Initialize the SPI Data Register and serial buffer + */ + SPDR = 0; +} + +uint8_t tabby_avr_link_send_byte(uint8_t value) { + uint8_t i, ret = 0; + + for (i=0; i<8; i++) { + SC_LOW(); + + if (value & 0x80) { + SO_HIGH(); + } else { + SO_LOW(); + } + + _delay_us(SPI_PULSE_USEC); + + value <<= 1; + ret <<= 1; + + if (SI_IS_HIGH()) { + ret |= 1; + } + + SC_HIGH(); + + _delay_us(SPI_PULSE_USEC); + } + + return ret; +} diff --git a/avr/printer.c b/avr/printer.c new file mode 100644 index 0000000..17000d6 --- /dev/null +++ b/avr/printer.c @@ -0,0 +1,116 @@ +#include + +#include +#include + +int tabby_avr_printer_packet_toolarge(uint8_t type, uint16_t size) { + switch (type) { + case TABBY_PRINTER_PACKET_JOB: { + if (size > sizeof(tabby_printer_job)) { + return 1; + } + } + + case TABBY_PRINTER_PACKET_DATA: { + if (size > TABBY_PRINTER_PACKET_MAX_SIZE) { + return 1; + } + } + } + + return 0; +} + +static uint16_t checksum(tabby_printer_packet *header, uint8_t *body) { + uint16_t sum = 0; + + int i; + + for (i=2; idata[i]; + } + + for (i=0; isize; i++) { + sum += body[i]; + } + + return sum; +} + +void tabby_avr_printer_send_packet(uint8_t type, + uint8_t *body, + uint16_t size, + tabby_printer_response *response) { + tabby_printer_packet header = { + .preamble = { TABBY_PRINTER_SYNC_1, TABBY_PRINTER_SYNC_2 }, + .type = type, + .compression = TABBY_PRINTER_COMPRESSION_NONE, + .size = size + }; + + uint16_t sum = checksum(&header, body); + + int i; + + for (i=0; i> 8); + + response->device = tabby_avr_link_send_byte(0); + response->status = tabby_avr_link_send_byte(0); +} + +void tabby_avr_printer_init(tabby_printer_response *response) { + tabby_avr_printer_send_packet(TABBY_PRINTER_PACKET_INIT, + NULL, + 0, + response); +} + +void tabby_avr_printer_send_inquiry(tabby_printer_response *response) { + tabby_avr_printer_send_packet(TABBY_PRINTER_PACKET_INQUIRY, + NULL, + 0, + response); +} + +void tabby_avr_printer_job_start(tabby_printer_job *job, + tabby_printer_response *response) { + tabby_avr_printer_send_packet(TABBY_PRINTER_PACKET_JOB, + job->data, + sizeof(*job), + response); +} + +void tabby_avr_printer_send_data(uint8_t *data, + uint16_t size, + tabby_printer_response *response) { + tabby_avr_printer_send_packet(TABBY_PRINTER_PACKET_DATA, + data, + size, + response); +} + +void tabby_avr_printer_send_sheet(uint8_t *sheet, + uint16_t size, + tabby_printer_response *response) { + int i; + + tabby_avr_printer_init(response); + + for (i=0; i #include -#include +#include #include +#include #include -static volatile tabby_printer_packet header; +static volatile uint16_t offset_header = 0, + offset_body = 0, + size_body = 0, + sum_calc = 0, + sum_footer = 0; -static volatile uint16_t i, b; +static volatile tabby_printer_response response = { + .device = TABBY_PRINTER_DEVICE_ID, + .status = TABBY_PRINTER_OK +}; /* * SPI byte receipt interrupt vector @@ -19,13 +27,14 @@ ISR(SPI_STC_vect) { uart_putchar(in, NULL); - switch (i) { + switch (offset_header) { case 0: { if (in == TABBY_PRINTER_SYNC_1) { - header.data[0] = in; - i++; + offset_header++; + offset_body = 0; + sum_calc = 0; - b = 0; + response.status = TABBY_PRINTER_OK; } break; @@ -33,54 +42,68 @@ ISR(SPI_STC_vect) { case 1: { if (in == TABBY_PRINTER_SYNC_2) { - header.data[1] = in; - i++; + offset_header++; } else { - i = 0; + offset_header = 0; } break; } - case 2: { - header.type = in; - i++; - - break; - } - + case 2: case 3: { - header.compression = in; - i++; + offset_header++; + sum_calc += in; break; } case 4: { - header.size = in; - i++; + size_body = in; + + sum_calc += in; + offset_header++; break; } case 5: { - header.size |= in << 8; - i++; + size_body |= in << 8; + + if (size_body > TABBY_PRINTER_PACKET_MAX_SIZE) { + offset_header = 0; + } else { + offset_header++; + } + + sum_calc += in; break; } default: { - if (b <= header.size) { - b++; - } else if (b == header.size + 1) { - b++; + if (offset_body < size_body) { + offset_body++; + sum_calc += in; + } else if (offset_body == size_body) { + offset_body++; + sum_footer = in; + } else if (offset_body == size_body + 1) { + offset_body++; - out = TABBY_PRINTER_DEVICE_ID; - } else if (b == header.size + 2) { - b++; - } else if (b == header.size + 3) { - i = 0; + sum_footer |= in << 8; + + if (sum_footer != sum_calc) { + response.status |= TABBY_PRINTER_SUM; + } + + out = response.device; + } else if (offset_body == size_body + 2) { + offset_body++; + + out = response.status; + } else if (offset_body == size_body + 3) { + offset_header = 0; } } } @@ -88,32 +111,10 @@ ISR(SPI_STC_vect) { SPDR = out; } -static void spi_init() { - SS_INPUT(); - SC_INPUT(); - SI_INPUT(); - SO_OUTPUT(); - - /* - * Set SPI slave mode, and shift in/out most significant bit first - */ - SPCR &= ~((1 << MSTR) | (1 << DORD)); - - /* - * Enable SPI in Mode 3 with interrupts, clock nominally high, output on - * falling edge, input on rising edge - */ - SPCR |= (1 << CPOL) | (1 << CPHA) | (1 << SPIE) | (1 << SPE); - - /* - * Initialize the SPI Data Register and serial buffer - */ - SPDR = 0; -} - int main() { uart_init(); - spi_init(); + + tabby_avr_link_init_slave(); sei(); diff --git a/avr/send.c b/avr/send.c index d0e1970..aef40d9 100644 --- a/avr/send.c +++ b/avr/send.c @@ -5,104 +5,46 @@ #include #include +#include +#include #include -static tabby_printer_packet header; -static tabby_printer_response response; - -static uint8_t body[TABBY_PRINTER_PACKET_MAX_SIZE]; - -static uint16_t sum; - -static void spi_init() { - SC_OUTPUT(); - SO_OUTPUT(); - - SI_INPUT(); - SI_PULLUP(); - - SC_HIGH(); - SO_LOW(); -} - -static uint8_t spi_send_byte(uint8_t value) { - uint8_t i, ret = 0; - - for (i=0; i<8; i++) { - SC_LOW(); - - if (value & 0x80) { - SO_HIGH(); - } else { - SO_LOW(); - } - - _delay_us(SPI_PULSE_USEC); - - ret <<= 1; - value <<= 1; - - if (SI_IS_HIGH()) { - ret |= 1; - } - - SC_HIGH(); - - _delay_us(SPI_PULSE_USEC); - } - - return ret; -} - -static void spi_send_packet() { - int i; - - for (i=0; i> 8); - - response.device = spi_send_byte(0); - response.status = spi_send_byte(0); -} - int main() { - uint16_t i = 0, - b = 0; + tabby_printer_packet header = { + .size = 0 + }; - uint8_t c; + tabby_printer_response response = { + .device = TABBY_PRINTER_DEVICE_ID, + .status = TABBY_PRINTER_OK + }; + + tabby_printer_job job; + + uint8_t sheet[TABBY_PRINTER_SHEET_SIZE]; + + uint16_t offset_header = 0, + offset_body = 0, + offset_sheet = 0; + + uint16_t sum_calc = 0, + sum_footer = 0; uart_init(); - spi_init(); - sei(); + tabby_avr_link_init_master(); while (1) { - uart_putchar('O', NULL); + uint8_t c = uart_getchar(NULL); - c = uart_getchar(NULL); - - if (c == 'K') { - break; - } - } - - while (1) { - c = uart_getchar(NULL); - - switch (i) { + switch (offset_header) { case 0: { if (c == TABBY_PRINTER_SYNC_1) { header.data[0] = c; - i++; + offset_header++; - b = 0; + offset_body = 0; + sum_calc = 0; } break; @@ -111,9 +53,9 @@ int main() { case 1: { if (c == TABBY_PRINTER_SYNC_2) { header.data[1] = c; - i++; + offset_header++; } else { - i = 0; + offset_header = 0; } break; @@ -122,61 +64,104 @@ int main() { case 2: { switch (c) { case TABBY_PRINTER_PACKET_INIT: + case TABBY_PRINTER_PACKET_CANCEL: { + response.status = TABBY_PRINTER_OK; + offset_sheet = 0; + } + case TABBY_PRINTER_PACKET_JOB: case TABBY_PRINTER_PACKET_DATA: - case TABBY_PRINTER_PACKET_CANCEL: case TABBY_PRINTER_PACKET_INQUIRY: { header.type = c; - i++; + offset_header++; break; } default: { - i = 0; + offset_header = 0; break; } } + sum_calc += c; + break; } case 3: { header.compression = c; - i++; + offset_header++; + + sum_calc += c; break; } case 4: { header.size = c; - i++; + offset_header++; + + sum_calc += c; break; } case 5: { header.size |= c << 8; - i++; + + if (tabby_avr_printer_packet_toolarge(header.type, + header.size)) { + offset_header = 0; + + response.status |= TABBY_PRINTER_FULL; + + goto respond; + } else { + offset_header++; + } + + sum_calc += c; break; } default: { - if (b < header.size) { - body[b++] = c; - } else if (b == header.size) { - sum = c; - b++; - } else if (b == header.size + 1) { - sum |= c << 8; + if (offset_body < header.size) { + if (header.type == TABBY_PRINTER_PACKET_JOB) { + job.data[offset_body] = c; + } else if (header.type == TABBY_PRINTER_PACKET_DATA) { + sheet[offset_sheet++] = c; + } - i = 0; - b = 0; + offset_body++; - spi_send_packet(); + sum_calc += c; + } else if (offset_body == header.size) { + sum_footer = c; + offset_body++; + } else if (offset_body == header.size + 1) { + sum_footer |= c << 8; + + offset_header = 0; + + if (sum_footer != sum_calc) { + response.status |= TABBY_PRINTER_SUM; + } else if (header.type == TABBY_PRINTER_PACKET_JOB) { + tabby_avr_printer_send_sheet(sheet, + offset_sheet, + &response); + + tabby_avr_printer_job_start(&job, &response); + + offset_sheet = 0; + } else if (header.type == TABBY_PRINTER_PACKET_INQUIRY) { + tabby_avr_printer_send_inquiry(&response); + } + +respond: uart_putchar(response.device, NULL); uart_putchar(response.status, NULL); } diff --git a/bin/Makefile b/bin/Makefile index a27d05a..f27db7b 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -8,9 +8,9 @@ CFLAGS += -I$(INCLUDE_PATH) LDFLAGS = TABBY = tabby -TABBY_OBJS = main.o +TABBY_OBJS = main.o grab.o print.o TABBY_STATIC = ../src/lib$(LIBNAME).a -TABBY_HEADERS = +TABBY_HEADERS = commands.h TABBY_LDFLAGS = LIBNAME = tabby diff --git a/bin/commands.h b/bin/commands.h new file mode 100644 index 0000000..aae6d7f --- /dev/null +++ b/bin/commands.h @@ -0,0 +1,7 @@ +#ifndef _COMMANDS_H +#define _COMMANDS_H + +int tabby_command_grab(int argc, char **argv); +int tabby_command_print(int argc, char **argv); + +#endif /* _COMMANDS_H */ diff --git a/bin/grab.c b/bin/grab.c new file mode 100644 index 0000000..fd6149f --- /dev/null +++ b/bin/grab.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void usage(int argc, char **argv, char *message, ...) { + if (message) { + va_list args; + + va_start(args, message); + vfprintf(stderr, message, args); + fprintf(stderr, "\n"); + va_end(args); + } + + fprintf(stderr, "usage: %s grab device\n", argv[0]); + + exit(1); +} + +int tabby_command_grab(int argc, char **argv) { + tabby_printer *printer; + tabby_printer_packet header; + + uint8_t body[TABBY_PRINTER_PACKET_MAX_SIZE]; + + if (argc != 3) { + usage(argc, argv, "No device specified"); + } + + if ((printer = tabby_printer_open(argv[1])) == NULL) { + fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "tabby_printer_open()", + argv[2], strerror(errno)); + + goto error_printer_open; + } + + while (1) { + if (tabby_printer_packet_recv(printer, &header, &body) < 0) { + fprintf(stderr, "%s: %s: %s\n", + argv[0], "tabby_printer_packet_recv()", strerror(errno)); + + continue; + } + + if (header.type == 0x04) { + write(1, &body, header.size); + } + } + + tabby_printer_close(printer); + + return 0; + +error_printer_open: + return 1; +} diff --git a/bin/main.c b/bin/main.c index f2db050..f38c587 100644 --- a/bin/main.c +++ b/bin/main.c @@ -4,12 +4,13 @@ #include #include #include -#include #include #include #include +#include "commands.h" + static void usage(int argc, char **argv, char *message, ...) { if (message) { va_list args; @@ -20,77 +21,36 @@ static void usage(int argc, char **argv, char *message, ...) { va_end(args); } - fprintf(stderr, "usage: %s device sheet.tile\n", argv[0]); + fprintf(stderr, "usage: %1$s print ...\n" + " %1$s grab ...\n", + argv[0]); exit(1); } +static struct { + char *name; + int (*fun)(int, char **); +} commands[] = { + { "print", tabby_command_print }, + { "grab", tabby_command_grab }, + { NULL, NULL } +}; + int main(int argc, char **argv) { - int fd, tile_fd; + int i; - tabby_printer_response response; - void *tile; - - if (argc != 3) { - usage(argc, argv, "Must specify device and tile"); + if (argc < 2) { + usage(argc, argv, "No command specified"); } - if ((tile = malloc(TABBY_PRINTER_SHEET_SIZE)) == NULL) { - goto error_malloc_tile; + for (i=0; commands[i].name; i++) { + if (strcmp(argv[1], commands[i].name) == 0) { + return commands[i].fun(argc, argv); + } } - if ((tile_fd = open(argv[2], O_RDONLY)) < 0) { - fprintf(stderr, "%s: %s: %s: %s\n", - argv[0], "open()", argv[2], strerror(errno)); - - goto error_open_tile; - } - - if (read(tile_fd, tile, TABBY_PRINTER_SHEET_SIZE) < 0) { - goto error_read_tile; - } - - if ((fd = tabby_link_open(argv[1])) < 0) { - fprintf(stderr, "%s: %s: %s: %s\n", argv[0], "tabby_link_open()", - argv[1], strerror(errno)); - - goto error_link_open; - } - - printf("Waiting for AVR to reboot after CTS\n"); - - sleep(1); - - tabby_printer_link_init(fd); - - do { - tabby_printer_init(fd, &response); - - usleep(100000); - } while (response.device != TABBY_PRINTER_DEVICE_ID); - - tabby_printer_send_sheet(fd, tile, &response); - - printf("Sent sheet, got response %02x%02x\n", - response.device, response.status); - - while (response.status & TABBY_PRINTER_UNTRAN) { - tabby_printer_send_inquiry(fd, &response); - - usleep(100000); - } - - tabby_link_close(fd); + usage(argc, argv, "Unknown command '%s'", argv[1]); return 0; - -error_link_open: -error_read_tile: - close(tile_fd); - -error_open_tile: - free(tile); - -error_malloc_tile: - return 1; } diff --git a/bin/print.c b/bin/print.c new file mode 100644 index 0000000..529c709 --- /dev/null +++ b/bin/print.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void usage(int argc, char **argv, char *message, ...) { + if (message) { + va_list args; + + va_start(args, message); + vfprintf(stderr, message, args); + fprintf(stderr, "\n"); + va_end(args); + } + + fprintf(stderr, "usage: %s print device sheet.tile\n", argv[0]); + + exit(1); +} + +int tabby_command_print(int argc, char **argv) { + int fd; + + ssize_t readlen; + size_t offset = 0; + + tabby_printer *printer; + + uint8_t band[TABBY_PRINTER_BAND_SIZE]; + + if (argc != 4) { + usage(argc, argv, "Must specify device and tile"); + } + + if ((fd = open(argv[3], O_RDONLY)) < 0) { + fprintf(stderr, "%s: %s: %s: %s\n", + argv[0], "open()", argv[3], strerror(errno)); + + goto error_open_tile; + } + + if ((printer = tabby_printer_open(argv[2])) == NULL) { + fprintf(stderr, "%s: %s: %s: %s\n", + argv[0], "tabby_printer_open()", argv[2], strerror(errno)); + + goto error_printer_open; + } + + do { + sleep(1); + + tabby_printer_init(printer); + } while (printer->device != TABBY_PRINTER_DEVICE_ID); + + while ((readlen = read(fd, band, sizeof(band))) > 0) { + offset += readlen; + + tabby_printer_band_send(printer, band); + + if (offset % TABBY_PRINTER_SHEET_SIZE == 0) { + tabby_printer_band_finish(printer); + + tabby_printer_wait(printer); + + tabby_printer_job_start(printer, 1, 0x00, 0x00, 0x40); + + tabby_printer_wait(printer); + } + } + + if (offset % TABBY_PRINTER_SHEET_SIZE) { + tabby_printer_band_finish(printer); + + tabby_printer_wait(printer); + + tabby_printer_job_start(printer, 1, 0x00, 0x00, 0x40); + + tabby_printer_wait(printer); + } + + tabby_printer_close(printer); + + return 0; + +error_printer_open: + close(fd); + +error_open_tile: + return 1; +} diff --git a/include/tabby/avr.h b/include/tabby/avr.h index 733d3eb..5e5e7dd 100644 --- a/include/tabby/avr.h +++ b/include/tabby/avr.h @@ -20,9 +20,9 @@ * SC -- Serial Clock */ #define SC_DDR DDRB -#define SC_DDB DDB5 +#define SC_DDB DDB1 #define SC_PORT PORTB -#define SC_PORT_PIN PORTB5 +#define SC_PORT_PIN PORTB1 #define SC_INPUT() \ (SC_DDR |= ~(1 << SC_DDB)) @@ -40,11 +40,11 @@ * SI -- Serial In */ #define SI_DDR DDRB -#define SI_DDB DDB3 +#define SI_DDB DDB2 #define SI_PIN_REG PINB -#define SI_PIN PINB3 +#define SI_PIN PINB2 #define SI_PORT PORTB -#define SI_PORT_PIN PORTB3 +#define SI_PORT_PIN PORTB2 #define SI_INPUT() \ (SI_DDR &= ~(1 << SI_DDB)) @@ -59,9 +59,9 @@ * SO -- Serial Out */ #define SO_DDR DDRB -#define SO_DDB DDB4 +#define SO_DDB DDB3 #define SO_PORT PORTB -#define SO_PORT_PIN PORTB4 +#define SO_PORT_PIN PORTB3 #define SO_OUTPUT() \ (SO_DDR |= (1 << SO_DDB)) @@ -73,7 +73,7 @@ (SO_PORT &= ~(1 << SO_PORT_PIN)) #define SS_DDR DDRB -#define SS_DDB DDB2 +#define SS_DDB DDB0 #define SS_INPUT() \ (SS_DDR &= ~(1 << SS_DDB)) diff --git a/include/tabby/avr/link.h b/include/tabby/avr/link.h new file mode 100644 index 0000000..7817d65 --- /dev/null +++ b/include/tabby/avr/link.h @@ -0,0 +1,12 @@ +#ifndef _TABBY_AVR_LINK_H +#define _TABBY_AVR_LINK_H + +#include + +void tabby_avr_link_init_master(); + +void tabby_avr_link_init_slave(); + +uint8_t tabby_avr_link_send_byte(uint8_t value); + +#endif /* _TABBY_AVR_LINK_H */ diff --git a/include/tabby/avr/printer.h b/include/tabby/avr/printer.h new file mode 100644 index 0000000..390423e --- /dev/null +++ b/include/tabby/avr/printer.h @@ -0,0 +1,30 @@ +#ifndef _TABBY_AVR_PRINTER_H +#define _TABBY_AVR_PRINTER_H + +#include + +#include + +int tabby_avr_printer_packet_toolarge(uint8_t type, uint16_t size); + +void tabby_avr_printer_send_packet(uint8_t type, + uint8_t *body, + uint16_t size, + tabby_printer_response *response); + +void tabby_avr_printer_init(tabby_printer_response *response); + +void tabby_avr_printer_send_inquiry(tabby_printer_response *response); + +void tabby_avr_printer_job_start(tabby_printer_job *job, + tabby_printer_response *response); + +void tabby_avr_printer_send_data(uint8_t *data, + uint16_t size, + tabby_printer_response *response); + +void tabby_avr_printer_send_sheet(uint8_t *sheet, + uint16_t size, + tabby_printer_response *response); + +#endif /* _TABBY_AVR_PRINTER_H */ diff --git a/include/tabby/printer.h b/include/tabby/printer.h index dd55225..6400b75 100644 --- a/include/tabby/printer.h +++ b/include/tabby/printer.h @@ -5,7 +5,6 @@ #define TABBY_PRINTER_SYNC_2 0x33 #define TABBY_PRINTER_DEVICE_ID 0x81 -#define TABBY_PRINTER_RETRY_COUNT 5 #define TABBY_PRINTER_PACKET_MAX_SIZE 640 @@ -23,9 +22,13 @@ typedef enum { TABBY_PRINTER_UNTRAN = (1 << 3), TABBY_PRINTER_FULL = (1 << 2), TABBY_PRINTER_BUSY = (1 << 1), - TABBY_PRINTER_SUM = (1 << 0) + TABBY_PRINTER_SUM = (1 << 0), + TABBY_PRINTER_OK = 0 } tabby_printer_status; +#define TABBY_PRINTER_WAIT 0x0e +#define TABBY_PRINTER_ERROR 0xf0 + typedef enum { TABBY_PRINTER_PACKET_INIT = 0x01, TABBY_PRINTER_PACKET_JOB = 0x02, @@ -39,6 +42,24 @@ typedef enum { TABBY_PRINTER_COMPRESSION_RLE = 0x01 } tabby_printer_compression; +typedef struct _tabby_printer_response { + uint8_t device; + uint8_t status; +} tabby_printer_response; + +typedef struct _tabby_printer { + int fd; + + union { + tabby_printer_response response; + + struct { + uint8_t device, + status; + }; + }; +} tabby_printer; + /* * Data definitions for packets sent from Game Boy to printer */ @@ -56,50 +77,61 @@ typedef struct _tabby_printer_packet { }; } tabby_printer_packet; +typedef struct _tabby_printer_job { + union { + struct { + uint8_t sheets, + linefeeds, + palette, + density; + }; + + uint8_t data[4]; + }; +} tabby_printer_job; + typedef struct _tabby_printer_buffer { tabby_printer_packet header; uint8_t body[TABBY_PRINTER_PACKET_MAX_SIZE]; uint16_t sum; } tabby_printer_buffer; -typedef struct _tabby_printer_response { - uint8_t device; - uint8_t status; -} tabby_printer_response; +tabby_printer *tabby_printer_open(const char *device); -int tabby_printer_link_init(int fd); +void tabby_printer_close(tabby_printer *printer); /* * For receiving printer data packets from a Game Boy Camera */ -int tabby_printer_packet_recv(int fd, +int tabby_printer_packet_recv(tabby_printer *printer, tabby_printer_packet *header, void *body); /* * For sending printer data packets to a Game Boy Printer */ -int tabby_printer_packet_send(int fd, +int tabby_printer_packet_send(tabby_printer *printer, tabby_printer_packet *header, - void *body, - tabby_printer_response *response); + void *body); -int tabby_printer_init(int fd, - tabby_printer_response *response); +int tabby_printer_init(tabby_printer *printer); -int tabby_printer_send_inquiry(int fd, - tabby_printer_response *response); +int tabby_printer_inquiry_send(tabby_printer *printer); -int tabby_printer_job_start(int fd, uint8_t sheets, - uint8_t linefeeds, - uint8_t palette, - uint8_t density, - tabby_printer_response *response); +int tabby_printer_job_start(tabby_printer *printer, uint8_t sheets, + uint8_t linefeeds, + uint8_t palette, + uint8_t density); -int tabby_printer_job_cancel(int fd, - tabby_printer_response *response); +int tabby_printer_job_cancel(tabby_printer *printer); -int tabby_printer_send_sheet(int fd, void *data, - tabby_printer_response *response); +int tabby_printer_wait(tabby_printer *printer); + +int tabby_printer_band_send(tabby_printer *printer, uint8_t *band); + +int tabby_printer_band_finish(tabby_printer *printer); + +int tabby_printer_sheet_send(tabby_printer *printer, void *data, + uint16_t size); #endif /* _TABBY_PRINTER_H */ diff --git a/src/link.c b/src/link.c index 7f52ac6..359f097 100644 --- a/src/link.c +++ b/src/link.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -15,17 +14,12 @@ int tabby_link_open(const char *dev) { goto error_open; } - attr.c_cflag = CS8 | CREAD | HUPCL; - attr.c_ispeed = TABBY_LINK_BAUD; - attr.c_ospeed = TABBY_LINK_BAUD; - attr.c_iflag = IGNPAR; - attr.c_oflag = 0; - attr.c_lflag = 0; + cfmakeraw(&attr); + cfsetspeed(&attr, TABBY_LINK_BAUD); - attr.c_cc[VTIME] = 0; - attr.c_cc[VMIN] = 1; + sleep(1); - if (tcsetattr(fd, TCSANOW, &attr) < 0) { + if (tcsetattr(fd, TCSAFLUSH, &attr) < 0) { goto error_io; } diff --git a/src/printer.c b/src/printer.c index 79dd00f..3c85a59 100644 --- a/src/printer.c +++ b/src/printer.c @@ -1,5 +1,6 @@ -#include +#include #include +#include #include #include #include @@ -9,21 +10,32 @@ #define PACKET_RECV_ERROR_THRESHOLD 30 -int tabby_printer_link_init(int fd) { - uint8_t out = 'K', - in; +tabby_printer *tabby_printer_open(const char *device) { + tabby_printer *printer; - while (1) { - read(fd, &in, 1); - - if (in == 'O') { - write(fd, &out, 1); - - break; - } + if ((printer = malloc(sizeof(*printer))) == NULL) { + goto error_malloc_printer; } - return 0; + if ((printer->fd = tabby_link_open(device)) < 0) { + goto error_link_open; + } + + printer->device = TABBY_PRINTER_DEVICE_ID; + printer->status = TABBY_PRINTER_OK; + + return printer; + +error_link_open: + free(printer); + +error_malloc_printer: + return NULL; +} + +void tabby_printer_close(tabby_printer *printer) { + tabby_link_close(printer->fd); + free(printer); } static uint16_t checksum(tabby_printer_packet *header, void *body) { @@ -41,7 +53,7 @@ static uint16_t checksum(tabby_printer_packet *header, void *body) { return checksum; } -int tabby_printer_packet_recv(int fd, +int tabby_printer_packet_recv(tabby_printer *printer, tabby_printer_packet *header, void *body) { ssize_t len; @@ -55,7 +67,7 @@ int tabby_printer_packet_recv(int fd, memset(header, '\0', sizeof(*header)); - while ((len = read(fd, &value, 1)) >= 0) { + while ((len = read(printer->fd, &value, 1)) >= 0) { if (i == 0) { if (value == TABBY_PRINTER_SYNC_1) { header->preamble[0] = value; @@ -107,50 +119,28 @@ error_io: return -errno; } -static inline int resend(tabby_printer_response *response) { - if (response->device != TABBY_PRINTER_DEVICE_ID) { - return 1; - } - - if (response->status & (TABBY_PRINTER_ER0 | TABBY_PRINTER_SUM)) { - return 1; - } - - return 0; -} - -int tabby_printer_packet_send(int fd, +int tabby_printer_packet_send(tabby_printer *printer, tabby_printer_packet *header, - void *body, - tabby_printer_response *response) { + void *body) { uint16_t sum = checksum(header, body); - int tries = TABBY_PRINTER_RETRY_COUNT; - do { - if (tries-- == 0) { - errno = EIO; + if (write(printer->fd, header, sizeof(*header)) < 0) { + goto error_io; + } + if (header->size) { + if (write(printer->fd, body, header->size) < 0) { goto error_io; } + } - if (write(fd, header, sizeof(*header)) < 0) { - goto error_io; - } + if (write(printer->fd, &sum, sizeof(sum)) < 0) { + goto error_io; + } - if (header->size) { - if (write(fd, body, header->size) < 0) { - goto error_io; - } - } - - if (write(fd, &sum, sizeof(sum)) < 0) { - goto error_io; - } - - if (read(fd, response, sizeof(*response)) < 0) { - goto error_io; - } - } while (resend(response)); + if (read(printer->fd, &printer->response, sizeof(printer->response)) < 0) { + goto error_io; + } return 0; @@ -167,29 +157,26 @@ static void init_header(tabby_printer_packet *header, header->size = (uint16_t)size; } -int tabby_printer_init(int fd, - tabby_printer_response *response) { +int tabby_printer_init(tabby_printer *printer) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_INIT, 0); - return tabby_printer_packet_send(fd, &header, NULL, response); + return tabby_printer_packet_send(printer, &header, NULL); } -int tabby_printer_send_inquiry(int fd, - tabby_printer_response *response) { +int tabby_printer_inquiry_send(tabby_printer *printer) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_INQUIRY, 0); - return tabby_printer_packet_send(fd, &header, NULL, response); + return tabby_printer_packet_send(printer, &header, NULL); } -int tabby_printer_job_start(int fd, uint8_t sheets, - uint8_t linefeeds, - uint8_t palette, - uint8_t density, - tabby_printer_response *response) { +int tabby_printer_job_start(tabby_printer *printer, uint8_t sheets, + uint8_t linefeeds, + uint8_t palette, + uint8_t density) { tabby_printer_packet header; uint8_t body[4] = { @@ -198,60 +185,89 @@ int tabby_printer_job_start(int fd, uint8_t sheets, init_header(&header, TABBY_PRINTER_PACKET_JOB, sizeof(body)); - return tabby_printer_packet_send(fd, &header, &body, response); + return tabby_printer_packet_send(printer, &header, &body); } -int tabby_printer_job_cancel(int fd, - tabby_printer_response *response) { +int tabby_printer_job_cancel(tabby_printer *printer) { tabby_printer_packet header; init_header(&header, TABBY_PRINTER_PACKET_CANCEL, 0); - return tabby_printer_packet_send(fd, &header, NULL, response); + return tabby_printer_packet_send(printer, &header, NULL); } -int tabby_printer_send_sheet(int fd, void *data, - tabby_printer_response *response) { - int i; - size_t offset = 0; +int tabby_printer_wait(tabby_printer *printer) { + while (1) { + sleep(1); - tabby_printer_packet header; - - for (i=0; istatus & (TABBY_PRINTER_WAIT | TABBY_PRINTER_SUM)) { + continue; + } else if (printer->status & TABBY_PRINTER_ERROR) { + goto error_printer; + } else { + break; } } return 0; +error_printer: +error_inquiry_send: + return -1; +} + +int tabby_printer_band_send(tabby_printer *printer, uint8_t *band) { + tabby_printer_packet header; + + init_header(&header, TABBY_PRINTER_PACKET_DATA, TABBY_PRINTER_BAND_SIZE); + + return tabby_printer_packet_send(printer, &header, band); +} + +int tabby_printer_band_finish(tabby_printer *printer) { + tabby_printer_packet header; + + init_header(&header, TABBY_PRINTER_PACKET_DATA, 0); + + return tabby_printer_packet_send(printer, &header, NULL); +} + +int tabby_printer_sheet_send(tabby_printer *printer, void *data, + uint16_t size) { + uint16_t offset = 0; + + tabby_printer_packet header; + + while (offset < size) { + init_header(&header, + TABBY_PRINTER_PACKET_DATA, + TABBY_PRINTER_BAND_SIZE); + + if (tabby_printer_packet_send(printer, + &header, + ((uint8_t *)data) + offset) < 0) { + goto error_packet_send; + } + + if (printer->status & TABBY_PRINTER_SUM) { + tabby_printer_init(printer); + + offset = 0; + + continue; + } + + offset += TABBY_PRINTER_BAND_SIZE; + } + + init_header(&header, TABBY_PRINTER_PACKET_DATA, 0); + + return tabby_printer_packet_send(printer, &header, NULL); + error_packet_send: return -1; }