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
|
||||
};
|
||||
|
||||
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};
|
||||
|
||||
@ -290,12 +290,15 @@ static int lw35ioc_chardev_open(struct inode *inodep, struct file *filep) {
|
||||
serdev_device_write(serdev, "XX", 2, 0);
|
||||
dev_info(&serdev->dev, "Put ioc into bypass mode.\n");
|
||||
break;
|
||||
case INIT:
|
||||
case PASSIVE:
|
||||
lw35ioc_reset_ioc_hw(serdev);
|
||||
usleep_range(2100000, 2210000);
|
||||
dev_info(&serdev->dev, "Put ioc into active mode.\n");
|
||||
if (priv->state == INIT) {
|
||||
serdev_device_write(serdev, "\xFF", 1, 0);
|
||||
priv->state = ACTIVE;
|
||||
}
|
||||
break;
|
||||
case ACTIVE:
|
||||
/* Don't do anything when active */
|
||||
@ -480,15 +483,12 @@ void pbuf_work_handler(struct work_struct *work)
|
||||
int i;
|
||||
int locked = 0;
|
||||
|
||||
dev_info(&serdev->dev,
|
||||
"pbuf_work_handler\n");
|
||||
|
||||
while (1) {
|
||||
// TODO: We are the only consumer, so we should be fine without a spinlock, right?
|
||||
head = smp_load_acquire(&priv->pbuf_head);
|
||||
tail = priv->pbuf_tail;
|
||||
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)
|
||||
break;
|
||||
|
||||
@ -519,11 +519,13 @@ void pbuf_work_handler(struct work_struct *work)
|
||||
serdev_device_write_buf(serdev,
|
||||
priv->pbuf + tail,
|
||||
bsize);
|
||||
#ifdef ENABLE_DEBUG
|
||||
for (i=0; i<bsize; ++i) {
|
||||
dev_info(&serdev->dev,
|
||||
"UART TX: %c\n",
|
||||
priv->pbuf[tail + i]);
|
||||
}
|
||||
#endif
|
||||
smp_store_release(&priv->pbuf_tail,
|
||||
(tail + bsize) & (PBUF_SIZE - 1));
|
||||
}
|
||||
@ -604,7 +606,7 @@ static int lw35ioc_probe(struct serdev_device *serdev)
|
||||
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_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, " input dev: %p\n", priv->input_dev);
|
||||
lw35ioc_set_hw_reset(serdev, 1);
|
||||
usleep_range(90000, 100000); // Make sure the reset actually happens
|
||||
gpiod_put(priv->gpio_rst);
|
||||
serdev_device_close(priv->serdev);
|
||||
input_unregister_device(priv->input_dev);
|
||||
|
@ -5,7 +5,7 @@
|
||||
#include <fcntl.h>
|
||||
|
||||
#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;
|
||||
|
||||
@ -37,6 +37,8 @@ static int set_mode(int argc, char *argv[])
|
||||
mode = BYPASS;
|
||||
else if (!strcmp(argv[2], "active"))
|
||||
mode = ACTIVE;
|
||||
else if (!strcmp(argv[2], "init"))
|
||||
mode = INIT;
|
||||
|
||||
if (mode == -1) {
|
||||
fprintf(stderr, "Error: Invalid mode.\n");
|
||||
|
@ -100,6 +100,7 @@ void hardfault() {
|
||||
uart_putc(0xFF);
|
||||
uart_putc(0xFF);
|
||||
uart_putc(0xFF);
|
||||
uart_putc(0xAA);
|
||||
uart_putc(0x00);
|
||||
uart_putc(0x00);
|
||||
uart_putc(0x00);
|
||||
@ -576,11 +577,14 @@ void arm_correction()
|
||||
#define DCMOTOR_ISACTIVE (!!(MOTLIM(PORT) & PIN_DCMOTOR))
|
||||
#define LIMITSWITCH (!(MOTLIM(PIN) & PIN_LIMITSWITCH))
|
||||
|
||||
#define BACKLIGHT_ON MISCIO(PORT) |= PIN_BACKLIGHT
|
||||
#define BACKLIGHT_OFF MISCIO(PORT) &= ~PIN_BACKLIGHT
|
||||
|
||||
/* 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[PRINT_BUFFER_SIZE];
|
||||
volatile uint8_t print_buffer_wr = 0;
|
||||
volatile uint8_t print_buffer_rd = 0;
|
||||
|
||||
@ -675,7 +679,7 @@ void move_carriage_to_far_left(uint8_t reset)
|
||||
if (LIMITSWITCH) {
|
||||
debug_write("[car] Clearing switch area...\r\n");
|
||||
cnt = 32;
|
||||
while (LIMITSWITCH && (cnt> 0)) {
|
||||
while (LIMITSWITCH && (cnt > 0)) {
|
||||
if (block_for(TIM_CARRIAGE, STEPPER_CFG_CARRIAGE.delay)) {
|
||||
STEPPER_NEXT(CARRIAGE, 1);
|
||||
cnt--;
|
||||
@ -840,7 +844,7 @@ void move_carriage_to_left_margin()
|
||||
/* 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 current_char;
|
||||
uint8_t index;
|
||||
uint16_t carriage_position;
|
||||
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()
|
||||
{
|
||||
static enum printer_state state = INIT;
|
||||
@ -916,21 +1014,17 @@ void printer_process()
|
||||
static uint8_t print_buffer_recovery = 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 end_of_next_line = 0;
|
||||
int8_t temp;
|
||||
static char debug_character = 0;
|
||||
static uint8_t debug_character = 0;
|
||||
|
||||
switch (state) {
|
||||
case IDLE:
|
||||
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 */
|
||||
if (!current_is_linebreak) {
|
||||
if (backward) {
|
||||
@ -997,10 +1091,22 @@ void printer_process()
|
||||
state = HAMMER;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// TODO: Handle special commands
|
||||
} else { /* TODO: 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 {
|
||||
DCMOTOR_STOP;
|
||||
}
|
||||
@ -1016,6 +1122,10 @@ void printer_process()
|
||||
}
|
||||
break;
|
||||
|
||||
case SPECIAL_COMMAND:
|
||||
state = process_special_command(special_command);
|
||||
break;
|
||||
|
||||
case INIT:
|
||||
move_carriage_to_left_margin();
|
||||
state = IDLE;
|
||||
@ -1291,7 +1401,7 @@ int main()
|
||||
|
||||
/* Set up miscellaneous I/O */
|
||||
MISCIO(DDR) |= PIN_BACKLIGHT;
|
||||
MISCIO(PORT) |= PIN_BACKLIGHT; /* Permanently enable backlight */
|
||||
BACKLIGHT_ON;
|
||||
|
||||
/* Set up SysTick Timer */
|
||||
TCCR1B = (1 << WGM12) | (1 << CS11); // f_tim = 8 MHz / 8
|
||||
@ -1303,7 +1413,10 @@ int main()
|
||||
update_status(0);
|
||||
debug_write("\n\n\r[sys] STARTING IO CONTROLLER...\r\n");
|
||||
#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);
|
||||
_delay_ms(250);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user