Implement special commands and fix some bugs
Note: Special commands are currently broken in backwards mode! Do not use them when the buffer is not empty!
This commit is contained in:
parent
446b6102ac
commit
5ebb104e19
@ -61,7 +61,7 @@ static int keycode_map[] = {
|
|||||||
KEY_SYSRQ
|
KEY_SYSRQ
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lw35ioc_state {PASSIVE = 0, PROG_KBD, PROG_PRI, BYPASS, ACTIVE, STATE_COUNT};
|
enum lw35ioc_state {PASSIVE = 0, INIT, PROG_KBD, PROG_PRI, BYPASS, ACTIVE, STATE_COUNT};
|
||||||
|
|
||||||
enum lw35ioc_packet_state {SYNC, TYPE, KEYBOARD, PRINTER};
|
enum lw35ioc_packet_state {SYNC, TYPE, KEYBOARD, PRINTER};
|
||||||
|
|
||||||
@ -290,12 +290,15 @@ static int lw35ioc_chardev_open(struct inode *inodep, struct file *filep) {
|
|||||||
serdev_device_write(serdev, "XX", 2, 0);
|
serdev_device_write(serdev, "XX", 2, 0);
|
||||||
dev_info(&serdev->dev, "Put ioc into bypass mode.\n");
|
dev_info(&serdev->dev, "Put ioc into bypass mode.\n");
|
||||||
break;
|
break;
|
||||||
|
case INIT:
|
||||||
case PASSIVE:
|
case PASSIVE:
|
||||||
lw35ioc_reset_ioc_hw(serdev);
|
lw35ioc_reset_ioc_hw(serdev);
|
||||||
usleep_range(2100000, 2210000);
|
usleep_range(2100000, 2210000);
|
||||||
dev_info(&serdev->dev, "Put ioc into active mode.\n");
|
dev_info(&serdev->dev, "Put ioc into active mode.\n");
|
||||||
serdev_device_write(serdev, "\xFF", 1, 0);
|
if (priv->state == INIT) {
|
||||||
priv->state = ACTIVE;
|
serdev_device_write(serdev, "\xFF", 1, 0);
|
||||||
|
priv->state = ACTIVE;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ACTIVE:
|
case ACTIVE:
|
||||||
/* Don't do anything when active */
|
/* Don't do anything when active */
|
||||||
@ -480,15 +483,12 @@ void pbuf_work_handler(struct work_struct *work)
|
|||||||
int i;
|
int i;
|
||||||
int locked = 0;
|
int locked = 0;
|
||||||
|
|
||||||
dev_info(&serdev->dev,
|
|
||||||
"pbuf_work_handler\n");
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// TODO: We are the only consumer, so we should be fine without a spinlock, right?
|
// TODO: We are the only consumer, so we should be fine without a spinlock, right?
|
||||||
head = smp_load_acquire(&priv->pbuf_head);
|
head = smp_load_acquire(&priv->pbuf_head);
|
||||||
tail = priv->pbuf_tail;
|
tail = priv->pbuf_tail;
|
||||||
bsize = CIRC_CNT(head, tail, PBUF_SIZE);
|
bsize = CIRC_CNT(head, tail, PBUF_SIZE);
|
||||||
dev_info(&serdev->dev, "CIRC CNT=%d\n", bsize);
|
//dev_info(&serdev->dev, "CIRC CNT=%d\n", bsize);
|
||||||
if (bsize == 0)
|
if (bsize == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -519,11 +519,13 @@ void pbuf_work_handler(struct work_struct *work)
|
|||||||
serdev_device_write_buf(serdev,
|
serdev_device_write_buf(serdev,
|
||||||
priv->pbuf + tail,
|
priv->pbuf + tail,
|
||||||
bsize);
|
bsize);
|
||||||
|
#ifdef ENABLE_DEBUG
|
||||||
for (i=0; i<bsize; ++i) {
|
for (i=0; i<bsize; ++i) {
|
||||||
dev_info(&serdev->dev,
|
dev_info(&serdev->dev,
|
||||||
"UART TX: %c\n",
|
"UART TX: %c\n",
|
||||||
priv->pbuf[tail + i]);
|
priv->pbuf[tail + i]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
smp_store_release(&priv->pbuf_tail,
|
smp_store_release(&priv->pbuf_tail,
|
||||||
(tail + bsize) & (PBUF_SIZE - 1));
|
(tail + bsize) & (PBUF_SIZE - 1));
|
||||||
}
|
}
|
||||||
@ -604,7 +606,7 @@ static int lw35ioc_probe(struct serdev_device *serdev)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->state = PASSIVE;
|
priv->state = ACTIVE; // TODO: This should be passive
|
||||||
priv->uart_buf_rx_rd = priv->uart_buf_rx;
|
priv->uart_buf_rx_rd = priv->uart_buf_rx;
|
||||||
priv->uart_buf_rx_wr = priv->uart_buf_rx;
|
priv->uart_buf_rx_wr = priv->uart_buf_rx;
|
||||||
|
|
||||||
@ -701,6 +703,7 @@ static void lw35ioc_remove(struct serdev_device *serdev)
|
|||||||
dev_info(&serdev->dev, " serdev: %p\n", priv->serdev);
|
dev_info(&serdev->dev, " serdev: %p\n", priv->serdev);
|
||||||
dev_info(&serdev->dev, " input dev: %p\n", priv->input_dev);
|
dev_info(&serdev->dev, " input dev: %p\n", priv->input_dev);
|
||||||
lw35ioc_set_hw_reset(serdev, 1);
|
lw35ioc_set_hw_reset(serdev, 1);
|
||||||
|
usleep_range(90000, 100000); // Make sure the reset actually happens
|
||||||
gpiod_put(priv->gpio_rst);
|
gpiod_put(priv->gpio_rst);
|
||||||
serdev_device_close(priv->serdev);
|
serdev_device_close(priv->serdev);
|
||||||
input_unregister_device(priv->input_dev);
|
input_unregister_device(priv->input_dev);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#define IOCTL_SET_MODE 42
|
#define IOCTL_SET_MODE 42
|
||||||
enum lw35ioc_state {PASSIVE = 0, PROG_KBD, PROG_PRI, BYPASS, ACTIVE, STATE_COUNT};
|
enum lw35ioc_state {PASSIVE = 0, INIT, PROG_KBD, PROG_PRI, BYPASS, ACTIVE, STATE_COUNT};
|
||||||
|
|
||||||
int f;
|
int f;
|
||||||
|
|
||||||
@ -37,6 +37,8 @@ static int set_mode(int argc, char *argv[])
|
|||||||
mode = BYPASS;
|
mode = BYPASS;
|
||||||
else if (!strcmp(argv[2], "active"))
|
else if (!strcmp(argv[2], "active"))
|
||||||
mode = ACTIVE;
|
mode = ACTIVE;
|
||||||
|
else if (!strcmp(argv[2], "init"))
|
||||||
|
mode = INIT;
|
||||||
|
|
||||||
if (mode == -1) {
|
if (mode == -1) {
|
||||||
fprintf(stderr, "Error: Invalid mode.\n");
|
fprintf(stderr, "Error: Invalid mode.\n");
|
||||||
|
@ -100,6 +100,7 @@ void hardfault() {
|
|||||||
uart_putc(0xFF);
|
uart_putc(0xFF);
|
||||||
uart_putc(0xFF);
|
uart_putc(0xFF);
|
||||||
uart_putc(0xFF);
|
uart_putc(0xFF);
|
||||||
|
uart_putc(0xAA);
|
||||||
uart_putc(0x00);
|
uart_putc(0x00);
|
||||||
uart_putc(0x00);
|
uart_putc(0x00);
|
||||||
uart_putc(0x00);
|
uart_putc(0x00);
|
||||||
@ -576,11 +577,14 @@ void arm_correction()
|
|||||||
#define DCMOTOR_ISACTIVE (!!(MOTLIM(PORT) & PIN_DCMOTOR))
|
#define DCMOTOR_ISACTIVE (!!(MOTLIM(PORT) & PIN_DCMOTOR))
|
||||||
#define LIMITSWITCH (!(MOTLIM(PIN) & PIN_LIMITSWITCH))
|
#define LIMITSWITCH (!(MOTLIM(PIN) & PIN_LIMITSWITCH))
|
||||||
|
|
||||||
|
#define BACKLIGHT_ON MISCIO(PORT) |= PIN_BACKLIGHT
|
||||||
|
#define BACKLIGHT_OFF MISCIO(PORT) &= ~PIN_BACKLIGHT
|
||||||
|
|
||||||
/* Communication Functions */
|
/* Communication Functions */
|
||||||
#define RINGBUF_CNT(wr,rd) ((wr) - (rd))
|
#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 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_*.
|
#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[PRINT_BUFFER_SIZE];
|
||||||
volatile uint8_t print_buffer_wr = 0;
|
volatile uint8_t print_buffer_wr = 0;
|
||||||
volatile uint8_t print_buffer_rd = 0;
|
volatile uint8_t print_buffer_rd = 0;
|
||||||
|
|
||||||
@ -675,7 +679,7 @@ void move_carriage_to_far_left(uint8_t reset)
|
|||||||
if (LIMITSWITCH) {
|
if (LIMITSWITCH) {
|
||||||
debug_write("[car] Clearing switch area...\r\n");
|
debug_write("[car] Clearing switch area...\r\n");
|
||||||
cnt = 32;
|
cnt = 32;
|
||||||
while (LIMITSWITCH && (cnt> 0)) {
|
while (LIMITSWITCH && (cnt > 0)) {
|
||||||
if (block_for(TIM_CARRIAGE, STEPPER_CFG_CARRIAGE.delay)) {
|
if (block_for(TIM_CARRIAGE, STEPPER_CFG_CARRIAGE.delay)) {
|
||||||
STEPPER_NEXT(CARRIAGE, 1);
|
STEPPER_NEXT(CARRIAGE, 1);
|
||||||
cnt--;
|
cnt--;
|
||||||
@ -840,7 +844,7 @@ void move_carriage_to_left_margin()
|
|||||||
/* It's only called once, so inline is good. */
|
/* It's only called once, so inline is good. */
|
||||||
inline int8_t simulate_print_run(uint8_t *start_end_index, uint8_t *recovery_index)
|
inline int8_t simulate_print_run(uint8_t *start_end_index, uint8_t *recovery_index)
|
||||||
{
|
{
|
||||||
char current_char;
|
uint8_t current_char;
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
uint16_t carriage_position;
|
uint16_t carriage_position;
|
||||||
uint8_t translated;
|
uint8_t translated;
|
||||||
@ -907,7 +911,101 @@ inline int8_t simulate_print_run(uint8_t *start_end_index, uint8_t *recovery_ind
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum printer_state {INIT, IDLE, HAMMER, PAUSED};
|
#define PRINT_COMMAND_RESET_ALL 0xFF
|
||||||
|
#define PRINT_COMMAND_HARDFAULLT 0xFE
|
||||||
|
#define PRINT_COMMAND_RESET_WHEEL 0xF0
|
||||||
|
#define PRINT_COMMAND_BACKLIGHT_ON 0xFD
|
||||||
|
#define PRINT_COMMAND_BACKLIGHT_OFF 0xFC
|
||||||
|
#define PRINT_COMMAND_SET_MARGIN_LEFT 0xE0
|
||||||
|
#define PRINT_COMMAND_SET_MARGIN_RIGHT 0xE1
|
||||||
|
#define PRINT_COMMAND_MOVE_CARRIAGE 0xE2
|
||||||
|
#define PRINT_COMMAND_MOVE_PAPERFEED 0xE3
|
||||||
|
|
||||||
|
enum printer_state {INIT, IDLE, HAMMER, PAUSED, SPECIAL_COMMAND};
|
||||||
|
|
||||||
|
// TODO: Special commands must currently not be used in reverse (auto) print mode
|
||||||
|
enum printer_state process_special_command(uint8_t command)
|
||||||
|
{
|
||||||
|
uint16_t temp;
|
||||||
|
uint8_t arg;
|
||||||
|
|
||||||
|
switch (command) {
|
||||||
|
case PRINT_COMMAND_RESET_ALL:
|
||||||
|
return INIT;
|
||||||
|
|
||||||
|
case PRINT_COMMAND_HARDFAULLT:
|
||||||
|
hardfault();
|
||||||
|
return INIT;
|
||||||
|
|
||||||
|
case PRINT_COMMAND_BACKLIGHT_ON:
|
||||||
|
BACKLIGHT_ON;
|
||||||
|
return IDLE;
|
||||||
|
|
||||||
|
case PRINT_COMMAND_BACKLIGHT_OFF:
|
||||||
|
BACKLIGHT_OFF;
|
||||||
|
return IDLE;
|
||||||
|
|
||||||
|
case PRINT_COMMAND_RESET_WHEEL:
|
||||||
|
stepper_status_CARRIAGE.target_pos = 0; // Go to far left to lock the daisy wheel
|
||||||
|
DCMOTOR_STOP; // TODO: We only need to issue this and the line before once
|
||||||
|
if (POSITION_REACHED(WHEEL) && POSITION_REACHED(CARRIAGE) && POSITION_REACHED(LINEFEED)) {
|
||||||
|
align_daisy_wheel();
|
||||||
|
return INIT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINT_COMMAND_SET_MARGIN_LEFT:
|
||||||
|
case PRINT_COMMAND_SET_MARGIN_RIGHT:
|
||||||
|
if (print_buffer_rd != print_buffer_wr) {
|
||||||
|
temp = (uint16_t) print_buffer[print_buffer_rd];
|
||||||
|
print_buffer_rd++;
|
||||||
|
temp *= PRINT_CHARACTER_WIDTH;
|
||||||
|
switch (command) {
|
||||||
|
case PRINT_COMMAND_SET_MARGIN_LEFT:
|
||||||
|
print_margin_left = temp;
|
||||||
|
break;
|
||||||
|
case PRINT_COMMAND_SET_MARGIN_RIGHT:
|
||||||
|
print_margin_right = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return INIT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINT_COMMAND_MOVE_CARRIAGE:
|
||||||
|
if (print_buffer_rd != print_buffer_wr) {
|
||||||
|
temp = (uint16_t) print_buffer[print_buffer_rd];
|
||||||
|
print_buffer_rd++;
|
||||||
|
temp *= PRINT_CHARACTER_WIDTH;
|
||||||
|
stepper_status_CARRIAGE.target_pos = temp;
|
||||||
|
return IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRINT_COMMAND_MOVE_PAPERFEED: // [line mult] [+/-] [6b abs amount]
|
||||||
|
if (print_buffer_rd != print_buffer_wr) {
|
||||||
|
arg = print_buffer[print_buffer_rd];
|
||||||
|
print_buffer_rd++;
|
||||||
|
temp = (uint16_t) (arg & 0x3F);
|
||||||
|
if (arg & 0x40) {
|
||||||
|
temp = -temp;
|
||||||
|
}
|
||||||
|
if (arg & 0x80) {
|
||||||
|
temp *= PRINT_LINE_HEIGHT;
|
||||||
|
}
|
||||||
|
stepper_status_LINEFEED.target_pos += temp;
|
||||||
|
return IDLE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SPECIAL_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void printer_process()
|
void printer_process()
|
||||||
{
|
{
|
||||||
static enum printer_state state = INIT;
|
static enum printer_state state = INIT;
|
||||||
@ -916,21 +1014,17 @@ void printer_process()
|
|||||||
static uint8_t print_buffer_recovery = 0;
|
static uint8_t print_buffer_recovery = 0;
|
||||||
|
|
||||||
static uint8_t current_is_linebreak = 0;
|
static uint8_t current_is_linebreak = 0;
|
||||||
char current_char;
|
uint8_t current_char;
|
||||||
|
static uint8_t special_command;
|
||||||
uint8_t translated;
|
uint8_t translated;
|
||||||
|
|
||||||
uint8_t end_of_next_line = 0;
|
uint8_t end_of_next_line = 0;
|
||||||
int8_t temp;
|
int8_t temp;
|
||||||
static char debug_character = 0;
|
static uint8_t debug_character = 0;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case IDLE:
|
case IDLE:
|
||||||
if (print_buffer_rd != print_buffer_wr) { // TODO: maybe add "|| current_is_linebreak"
|
if (print_buffer_rd != print_buffer_wr) { // TODO: maybe add "|| current_is_linebreak"
|
||||||
if (!DCMOTOR_ISACTIVE) {
|
|
||||||
DCMOTOR_EN;
|
|
||||||
_delay_ms(100); /* Let the motor get up to speed */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fetch new character from buffer */
|
/* Fetch new character from buffer */
|
||||||
if (!current_is_linebreak) {
|
if (!current_is_linebreak) {
|
||||||
if (backward) {
|
if (backward) {
|
||||||
@ -997,10 +1091,22 @@ void printer_process()
|
|||||||
state = HAMMER;
|
state = HAMMER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else { /* TODO: Special commands */
|
||||||
// TODO: Handle special commands
|
special_command = current_char;
|
||||||
|
state = SPECIAL_COMMAND;
|
||||||
|
|
||||||
|
/* TODO: below are just notes */
|
||||||
|
// process_command_forward(&modifier_state);
|
||||||
|
// After this call, wait until a "return to normal op command".
|
||||||
|
// I can also call this in simulate_print_run and return to end-of-line modifiers
|
||||||
|
// to allow BOLD en/dis using the toggle command if en/dis is split over multiple lines.
|
||||||
|
// TODO: But how do I handle margin changes etc?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!DCMOTOR_ISACTIVE && state != SPECIAL_COMMAND) {
|
||||||
|
DCMOTOR_EN;
|
||||||
|
_delay_ms(100); /* Let the motor get up to speed */
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DCMOTOR_STOP;
|
DCMOTOR_STOP;
|
||||||
}
|
}
|
||||||
@ -1016,6 +1122,10 @@ void printer_process()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SPECIAL_COMMAND:
|
||||||
|
state = process_special_command(special_command);
|
||||||
|
break;
|
||||||
|
|
||||||
case INIT:
|
case INIT:
|
||||||
move_carriage_to_left_margin();
|
move_carriage_to_left_margin();
|
||||||
state = IDLE;
|
state = IDLE;
|
||||||
@ -1291,7 +1401,7 @@ int main()
|
|||||||
|
|
||||||
/* Set up miscellaneous I/O */
|
/* Set up miscellaneous I/O */
|
||||||
MISCIO(DDR) |= PIN_BACKLIGHT;
|
MISCIO(DDR) |= PIN_BACKLIGHT;
|
||||||
MISCIO(PORT) |= PIN_BACKLIGHT; /* Permanently enable backlight */
|
BACKLIGHT_ON;
|
||||||
|
|
||||||
/* Set up SysTick Timer */
|
/* Set up SysTick Timer */
|
||||||
TCCR1B = (1 << WGM12) | (1 << CS11); // f_tim = 8 MHz / 8
|
TCCR1B = (1 << WGM12) | (1 << CS11); // f_tim = 8 MHz / 8
|
||||||
@ -1303,7 +1413,10 @@ int main()
|
|||||||
update_status(0);
|
update_status(0);
|
||||||
debug_write("\n\n\r[sys] STARTING IO CONTROLLER...\r\n");
|
debug_write("\n\n\r[sys] STARTING IO CONTROLLER...\r\n");
|
||||||
#ifndef DEBUG_BUILD
|
#ifndef DEBUG_BUILD
|
||||||
while (!((UCSRA & (1 << RXC)) && (UDR == 0xFF))); /* Wait for init command from driver */
|
while (!((UCSRA & (1 << RXC)))) {
|
||||||
|
if (process_special_command(UDR) == INIT)
|
||||||
|
break;
|
||||||
|
}
|
||||||
update_status(0);
|
update_status(0);
|
||||||
_delay_ms(250);
|
_delay_ms(250);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user