Merge branch 'mega'

Conflicts:
	avr/send.c
This commit is contained in:
XANTRONIX Development 2016-06-10 22:13:28 +00:00
commit 19ad83a02d
16 changed files with 756 additions and 371 deletions

View file

@ -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)

71
avr/link.c Normal file
View file

@ -0,0 +1,71 @@
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <tabby/printer.h>
#include <tabby/avr/uart.h>
#include <tabby/avr.h>
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;
}

116
avr/printer.c Normal file
View file

@ -0,0 +1,116 @@
#include <stdlib.h>
#include <tabby/avr/link.h>
#include <tabby/avr/printer.h>
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; i<sizeof(*header); i++) {
sum += header->data[i];
}
for (i=0; i<header->size; 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<sizeof(header); i++) {
(void)tabby_avr_link_send_byte(header.data[i]);
}
for (i=0; i<size; i++) {
(void)tabby_avr_link_send_byte(body[i]);
}
(void)tabby_avr_link_send_byte( sum & 0x00ff);
(void)tabby_avr_link_send_byte((sum & 0xff00) >> 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<size; i+=TABBY_PRINTER_BAND_SIZE) {
tabby_avr_printer_send_data(sheet + i,
TABBY_PRINTER_BAND_SIZE,
response);
}
tabby_avr_printer_send_data(NULL, 0, response);
}

View file

@ -2,13 +2,21 @@
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <tabby/printer.h>
#include <tabby/avr/printer.h>
#include <tabby/avr/uart.h>
#include <tabby/avr/link.h>
#include <tabby/avr.h>
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();

View file

@ -5,104 +5,46 @@
#include <tabby/printer.h>
#include <tabby/avr/uart.h>
#include <tabby/avr/link.h>
#include <tabby/avr/printer.h>
#include <tabby/avr.h>
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<sizeof(header); i++) {
(void)spi_send_byte(header.data[i]);
}
for (i=0; i<header.size; i++) {
(void)spi_send_byte(body[i]);
}
(void)spi_send_byte( sum & 0x00ff);
(void)spi_send_byte((sum & 0xff00) >> 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);
}

View file

@ -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

7
bin/commands.h Normal file
View file

@ -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 */

63
bin/grab.c Normal file
View file

@ -0,0 +1,63 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <tabby/link.h>
#include <tabby/printer.h>
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;
}

View file

@ -4,12 +4,13 @@
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <tabby/link.h>
#include <tabby/printer.h>
#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;
}

97
bin/print.c Normal file
View file

@ -0,0 +1,97 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <tabby/link.h>
#include <tabby/printer.h>
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;
}

View file

@ -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))

12
include/tabby/avr/link.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef _TABBY_AVR_LINK_H
#define _TABBY_AVR_LINK_H
#include <stdint.h>
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 */

View file

@ -0,0 +1,30 @@
#ifndef _TABBY_AVR_PRINTER_H
#define _TABBY_AVR_PRINTER_H
#include <stdint.h>
#include <tabby/printer.h>
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 */

View file

@ -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 */

View file

@ -1,4 +1,3 @@
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -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;
}

View file

@ -1,5 +1,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
@ -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; i<TABBY_PRINTER_SHEET_BANDS; i++) {
tabby_printer_response current;
init_header(&header,
TABBY_PRINTER_PACKET_DATA,
TABBY_PRINTER_BAND_SIZE);
if (tabby_printer_packet_send(fd, &header,
((uint8_t *)data) + offset,
&current) < 0) {
goto error_packet_send;
if (tabby_printer_inquiry_send(printer) < 0) {
goto error_inquiry_send;
}
init_header(&header, TABBY_PRINTER_PACKET_DATA, 0);
tabby_printer_packet_send(fd, &header, NULL, response);
if (i == 0) {
tabby_printer_job_start(fd, 1, 0x10, 0x00, 0x40, &current);
} else if (i < TABBY_PRINTER_SHEET_BANDS - 1) {
tabby_printer_job_start(fd, 1, 0x00, 0x00, 0x40, &current);
} else if (i == TABBY_PRINTER_SHEET_BANDS - 1) {
tabby_printer_job_start(fd, 1, 0x03, 0x00, 0x40, &current);
}
offset += TABBY_PRINTER_BAND_SIZE;
while (current.status) {
tabby_printer_send_inquiry(fd, &current);
usleep(1000000);
if (printer->status & (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;
}