printer: Add preliminary printer controller
This commit is contained in:
parent
f2e24dc5b1
commit
ffb91b51c3
5
printer/avr/.gitignore
vendored
Normal file
5
printer/avr/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*.hex
|
||||
*.o
|
||||
*.pro.user
|
||||
*.autosave
|
||||
*.old*
|
26
printer/avr/Makefile
Normal file
26
printer/avr/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
MCU=atmega8
|
||||
CFLAGS=-g -Wall -mcall-prologues -mmcu=$(MCU) -Os -DF_CPU=8000000
|
||||
LDFLAGS=-Wl,-gc-sections -Wl,-relax
|
||||
CC=avr-gcc
|
||||
TARGET=main
|
||||
OBJECT_FILES=main.o
|
||||
|
||||
all: $(TARGET).hex
|
||||
|
||||
clean:
|
||||
rm -f *.o *.hex *.obj *.hex
|
||||
|
||||
%.hex: %.obj
|
||||
avr-objcopy -R .eeprom -O ihex $< $@
|
||||
|
||||
%.obj: $(OBJECT_FILES)
|
||||
$(CC) $(CFLAGS) $(OBJECT_FILES) $(LDFLAGS) -o $@
|
||||
|
||||
program: $(TARGET).obj
|
||||
avrdude -p $(MCU) -c usbasp -U flash:w:$(TARGET).hex
|
||||
#avrdude -p $(MCU) -P /dev/ttyUSB1 -c arduino -b 57600 -U flash:w:$(TARGET).hex
|
||||
|
||||
fuse:
|
||||
avrdude -p m8 -c usbasp -U lfuse:w:0xe4:m -U hfuse:w:0xd9:m
|
||||
|
||||
.phony: program fuse
|
816
printer/avr/main.c
Normal file
816
printer/avr/main.c
Normal file
@ -0,0 +1,816 @@
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include <stdio.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define BAUDRATE 9600
|
||||
#define UBRR 51 // (F_CPU / BAUDRATE) / 32
|
||||
|
||||
/* System functions */
|
||||
/* Timers */
|
||||
enum TIMERS{TIM_CARRIAGE,
|
||||
TIM_WHEEL,
|
||||
TIM_LINEFEED,
|
||||
TIMS};
|
||||
|
||||
#define TIMESCALE 4
|
||||
#define sleep_ms(channel, time_ms) sleep(channel, time_ms / TIMESCALE)
|
||||
volatile uint16_t timer[TIMS];
|
||||
|
||||
#define set_timer(channel, time_systicks) {timer[channel] = time_systicks;}
|
||||
uint8_t block_for(uint8_t channel, uint16_t time_systicks)
|
||||
{
|
||||
if (timer[channel] == 0) {
|
||||
timer[channel] = time_systicks;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ISR (TIMER1_COMPA_vect)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < TIMS; ++i) {
|
||||
if (timer[i] > 0) {
|
||||
timer[i]--;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Look-up-tables */
|
||||
/* Daisy wheel */
|
||||
#define PRINTER_CONTROL_CHAR 56
|
||||
#define PRINTER_NO_CHAR 128
|
||||
|
||||
const uint8_t ascii_translation_table[128 + 12] PROGMEM = {
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR, // ASCII 15
|
||||
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR,
|
||||
PRINTER_CONTROL_CHAR, // ASCII 31
|
||||
|
||||
PRINTER_NO_CHAR, // Space
|
||||
|
||||
52, // !
|
||||
66, // "
|
||||
44, // #
|
||||
40, // $
|
||||
29, // %
|
||||
74, // &
|
||||
58, // '
|
||||
88, // (
|
||||
86, // )
|
||||
82, // *
|
||||
84, // +
|
||||
0, // ,
|
||||
68, // -
|
||||
|
||||
1, // .
|
||||
28, // /
|
||||
38, // 0
|
||||
30, // 1
|
||||
32, // 2
|
||||
31, // 3
|
||||
33, // 4
|
||||
34, // 5
|
||||
35, // 6
|
||||
36, // 7
|
||||
37, // 8
|
||||
39, // 9
|
||||
|
||||
94, // :
|
||||
92, // ;
|
||||
PRINTER_NO_CHAR, // <
|
||||
71, // =
|
||||
PRINTER_NO_CHAR, // >
|
||||
|
||||
64, // ?
|
||||
PRINTER_NO_CHAR, // @
|
||||
76, // A
|
||||
72, // B
|
||||
67, // C
|
||||
65, // D
|
||||
70, // E
|
||||
69, // F
|
||||
63, // G
|
||||
87, // H
|
||||
90, // I
|
||||
62, // J
|
||||
85, // K
|
||||
78, // L
|
||||
95, // M
|
||||
91, // N
|
||||
61, // O
|
||||
80, // P
|
||||
59, // Q
|
||||
57, // R
|
||||
79, // S
|
||||
77, // T
|
||||
89, // U
|
||||
73, // V
|
||||
93, // W
|
||||
83, // X
|
||||
75, // Y
|
||||
81, // Z
|
||||
|
||||
PRINTER_NO_CHAR, // [
|
||||
PRINTER_NO_CHAR, // BACKSLASH
|
||||
PRINTER_NO_CHAR, // ]
|
||||
PRINTER_NO_CHAR, // ^
|
||||
|
||||
60, // _
|
||||
54, // `
|
||||
5, // a
|
||||
15, // b
|
||||
8, // c
|
||||
21, // d
|
||||
2, // e
|
||||
16, // f
|
||||
17, // g
|
||||
12, // h
|
||||
6, // i
|
||||
26, // j
|
||||
19, // k
|
||||
11, // l
|
||||
10, // m
|
||||
14, // n
|
||||
7, // o
|
||||
13, // p
|
||||
24, // q
|
||||
3, // r
|
||||
4, // s
|
||||
9, // t
|
||||
18, // u
|
||||
20, // v
|
||||
27, // w
|
||||
25, // x
|
||||
22, // y
|
||||
23, // z
|
||||
|
||||
PRINTER_NO_CHAR, // {
|
||||
48, // |
|
||||
PRINTER_NO_CHAR, // }
|
||||
PRINTER_NO_CHAR, // ~
|
||||
PRINTER_CONTROL_CHAR, // DEL
|
||||
|
||||
45, // ³
|
||||
47, // ²
|
||||
50, // ´
|
||||
51, // §
|
||||
56, // °
|
||||
41, // ö
|
||||
42, // ü
|
||||
43, // ä
|
||||
46, // Ö
|
||||
49, // ß
|
||||
53, // Ü
|
||||
55, // Ä
|
||||
};
|
||||
|
||||
|
||||
/* Hardware functions */
|
||||
|
||||
void uart_tx(char c)
|
||||
{
|
||||
while (!(UCSRA & (1 << UDRE)));
|
||||
UDR = c;
|
||||
}
|
||||
|
||||
void uart_write(char *c)
|
||||
{
|
||||
while (*c) {
|
||||
uart_tx(*c);
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int uart_printf(char *format,...)
|
||||
{
|
||||
va_list args;
|
||||
unsigned int i;
|
||||
char printbuffer[64];
|
||||
|
||||
va_start (args, format);
|
||||
|
||||
i = vsprintf (printbuffer, format, args);
|
||||
va_end (args);
|
||||
|
||||
uart_write(printbuffer);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* DC drive */
|
||||
#define MOTLIM(t) t##C
|
||||
#define PIN_DCMOTOR (1 << 4)
|
||||
#define PIN_LIMITSWITCH (1 << 5)
|
||||
|
||||
#define SOLENOID(t) t##D
|
||||
#define PIN_CORRECTION (1 << 2)
|
||||
#define PIN_ARMHAMMER (1 << 3)
|
||||
|
||||
|
||||
/* Stepper drive */
|
||||
|
||||
/* Drive pattern:
|
||||
* -A, +C
|
||||
* -B, +D
|
||||
* +A, -C
|
||||
* +B, -D
|
||||
*/
|
||||
|
||||
struct stepper_config {
|
||||
char port;
|
||||
uint8_t timch;
|
||||
uint8_t pin_a;
|
||||
uint8_t pin_b;
|
||||
uint8_t pin_c;
|
||||
uint8_t pin_d;
|
||||
uint8_t delay;
|
||||
uint16_t wraparound;
|
||||
};
|
||||
|
||||
struct stepper_status {
|
||||
uint8_t step;
|
||||
int8_t dir;
|
||||
int8_t ldir;
|
||||
uint8_t lpstate;
|
||||
uint16_t pos; /* Absolute position */
|
||||
uint16_t target_pos;
|
||||
};
|
||||
|
||||
/* Stepper configs */
|
||||
#define REVERSAL_MULTIPLIER 32
|
||||
|
||||
#define STEPPER_CFG_HW_CARRIAGE(t) t##C
|
||||
const struct stepper_config STEPPER_CFG_CARRIAGE = {
|
||||
.port = 'C',
|
||||
.timch = TIM_CARRIAGE,
|
||||
.pin_a = (1 << 3),
|
||||
.pin_b = (1 << 1),
|
||||
.pin_c = (1 << 0),
|
||||
.pin_d = (1 << 2),
|
||||
.delay = 3.5 * TIMESCALE,
|
||||
.wraparound = 0 /* No wraparonud */
|
||||
};
|
||||
|
||||
#define STEPPER_CFG_HW_WHEEL(t) t##B
|
||||
const struct stepper_config STEPPER_CFG_WHEEL = {
|
||||
.port = 'B',
|
||||
.timch = TIM_WHEEL,
|
||||
.pin_a = (1 << 7),
|
||||
.pin_b = (1 << 0),
|
||||
.pin_c = (1 << 1),
|
||||
.pin_d = (1 << 6),
|
||||
.delay = 3.5 * TIMESCALE,
|
||||
.wraparound = 96 * 2
|
||||
};
|
||||
|
||||
/* Stepper helpers */
|
||||
#define STEPPER_CFG(NAME) STEPPER_CFG_##NAME
|
||||
#define STEPPER_NEXT(NAME, DIR) stepper_next_f(&stepper_status_##NAME, \
|
||||
&STEPPER_CFG_##NAME, DIR)
|
||||
#define STEPPER_SET_IO(NAME) STEPPER_CFG_HW_##NAME(DDR) = \
|
||||
stepper_calc_ioc(STEPPER_CFG_HW_##NAME(DDR), \
|
||||
&STEPPER_CFG_##NAME)
|
||||
#define STEPPER_STOP(NAME) {STEPPER_NEXT(NAME, 0);}
|
||||
|
||||
/* Stepper vars */
|
||||
struct stepper_status stepper_status_WHEEL = {
|
||||
.step = 0,
|
||||
.dir = -1,
|
||||
.lpstate = 0
|
||||
};
|
||||
struct stepper_status stepper_status_CARRIAGE = {
|
||||
.step = 0,
|
||||
.dir = -1,
|
||||
.lpstate = 0
|
||||
};
|
||||
|
||||
/* Stepper functions */
|
||||
uint8_t stepper_calc_ioc(uint8_t pstate, const struct stepper_config *cfg)
|
||||
{
|
||||
pstate |= cfg->pin_a | cfg->pin_b | cfg->pin_c | cfg->pin_d;
|
||||
return pstate;
|
||||
}
|
||||
|
||||
void stepper_next_f(struct stepper_status *stat,
|
||||
const struct stepper_config *cfg,
|
||||
int8_t dir)
|
||||
{
|
||||
uint8_t pstate = 0;
|
||||
|
||||
/* Get current state of port */
|
||||
switch (cfg->port) {
|
||||
case 'B':
|
||||
pstate = PORTB;
|
||||
break;
|
||||
case 'C':
|
||||
pstate = PORTC;
|
||||
break;
|
||||
case 'D':
|
||||
pstate = PORTD;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Calculate next stepper state */
|
||||
if (stat->dir != 0) { /* Do not step for the recovery step */
|
||||
if (dir == 1 && stat->step == 3)
|
||||
stat->step = 0;
|
||||
else if (dir == -1 && stat->step == 0)
|
||||
stat->step = 3;
|
||||
else
|
||||
(stat->step) += dir;
|
||||
}
|
||||
|
||||
/* Apply current state */
|
||||
if (dir == 0) {
|
||||
stat->lpstate = pstate;
|
||||
//if (cfg->port == 'B') uart_printf("[%d] stop at: %x\r\n", stat->step, pstate & 0xF);
|
||||
pstate &= ~(cfg->pin_a | cfg->pin_b | cfg->pin_c | cfg->pin_d);
|
||||
} else {
|
||||
if (stat->dir == 0) { /* If this is the first step */
|
||||
pstate |= stat->lpstate & (cfg->pin_a | cfg->pin_b | cfg->pin_c | cfg->pin_d);
|
||||
//if (cfg->port == 'B') uart_printf("[%d] restore to : %x\r\n", stat->step, pstate & 0xF);
|
||||
} else {
|
||||
switch (stat->step) {
|
||||
case 0:
|
||||
pstate &= ~cfg->pin_a;
|
||||
pstate |= cfg->pin_c;
|
||||
break;
|
||||
case 1:
|
||||
pstate &= ~cfg->pin_b;
|
||||
pstate |= cfg->pin_d;
|
||||
break;
|
||||
case 2:
|
||||
pstate |= cfg->pin_a;
|
||||
pstate &= ~cfg->pin_c;
|
||||
break;
|
||||
case 3:
|
||||
pstate |= cfg->pin_b;
|
||||
pstate &= ~cfg->pin_d;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//if (cfg->port == 'B') uart_printf("[%d] set to : %x\r\n", stat->step, pstate & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update status information */
|
||||
if (stat->dir) { // Ignore recovery step
|
||||
if (stat->ldir == dir) { // Ignore reversal step
|
||||
stat->pos += dir;
|
||||
if (cfg->wraparound) {
|
||||
if (dir == 1) {
|
||||
if (stat->pos >= cfg->wraparound) {
|
||||
stat->pos = 0;
|
||||
}
|
||||
} else {
|
||||
if (stat->pos == 65535) { // Underflow
|
||||
stat->pos = cfg->wraparound - 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stat->dir)
|
||||
stat->ldir = stat->dir;
|
||||
stat->dir = dir;
|
||||
|
||||
/* Set new state of port */
|
||||
switch (cfg->port) {
|
||||
case 'B':
|
||||
PORTB = pstate;
|
||||
break;
|
||||
case 'C':
|
||||
PORTC = pstate;
|
||||
break;
|
||||
case 'D':
|
||||
PORTD = pstate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t stepper_required_direction(struct stepper_status *stat,
|
||||
const struct stepper_config *cfg)
|
||||
{
|
||||
int8_t dir = 0;
|
||||
uint16_t half;
|
||||
|
||||
if (stat->pos == stat->target_pos) {
|
||||
return 0;
|
||||
} else if (stat->pos > stat->target_pos) {
|
||||
dir = -1;
|
||||
} else {
|
||||
dir = 1;
|
||||
}
|
||||
|
||||
if (cfg->wraparound) {
|
||||
half = cfg->wraparound / 2;
|
||||
if ((stat->pos > half && stat->target_pos <= half) ||
|
||||
(stat->pos <= half && stat->target_pos > half)){
|
||||
dir *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
uint8_t stepper_perform_movement(struct stepper_status *stat,
|
||||
const struct stepper_config *cfg)
|
||||
{
|
||||
int8_t dir;
|
||||
|
||||
/* Check whether we are in an active movement state,
|
||||
or whether we need to go into one.*/
|
||||
if (stat->dir != 0 || stat->pos != stat->target_pos) {
|
||||
/* Set up direction */
|
||||
if (block_for(cfg->timch, cfg->delay)) {
|
||||
dir = stepper_required_direction(stat, cfg);
|
||||
if ((dir == -1) && (stat->dir == 1)) { /* Reversal */
|
||||
dir = 0;
|
||||
uart_write("[stp] Hard reversal detected. Pausing. -->|\r\n");
|
||||
set_timer(cfg->timch, cfg->delay * REVERSAL_MULTIPLIER);
|
||||
} else if ((dir == 1) && (stat->dir == -1)) { /* Reversal */
|
||||
dir = 0;
|
||||
uart_write("[stp] Hard reversal detected. Pausing. |<--\r\n");
|
||||
set_timer(cfg->timch, cfg->delay * REVERSAL_MULTIPLIER);
|
||||
}
|
||||
stepper_next_f(stat, cfg, dir);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define POSITION_REACHED(NAME) (stepper_status_##NAME.pos == stepper_status_##NAME.target_pos)
|
||||
|
||||
#define SET_TARGET(NAME, target) stepper_set_target(&stepper_status_##NAME, \
|
||||
&STEPPER_CFG_##NAME,\
|
||||
target)
|
||||
#define SET_TARGET_DELTA(NAME, delta) SET_TARGET(NAME, \
|
||||
stepper_status_##NAME.target_pos - (delta))
|
||||
void stepper_set_target(struct stepper_status *stat,
|
||||
const struct stepper_config *cfg,
|
||||
uint16_t target)
|
||||
{
|
||||
if (cfg->wraparound) {
|
||||
while (target >= -cfg->wraparound) {
|
||||
uart_printf("WRAP- %u\r\n", target);
|
||||
target += cfg->wraparound;
|
||||
}
|
||||
while (target >= cfg->wraparound) {
|
||||
uart_printf("WRAP+ %u\r\n", target);
|
||||
target -= cfg->wraparound;
|
||||
}
|
||||
}
|
||||
stat->target_pos = target;
|
||||
}
|
||||
|
||||
/* DC functions */
|
||||
void arm_hammer()
|
||||
{
|
||||
SOLENOID(PORT) |= PIN_ARMHAMMER;
|
||||
_delay_ms(30);
|
||||
SOLENOID(PORT) &= ~(PIN_ARMHAMMER);
|
||||
}
|
||||
|
||||
#define DCMOTOR_EN MOTLIM(PORT) |= PIN_DCMOTOR
|
||||
#define DCMOTOR_STOP MOTLIM(PORT) &= ~PIN_DCMOTOR
|
||||
#define LIMITSWITCH (!(MOTLIM(PIN) & PIN_LIMITSWITCH))
|
||||
|
||||
|
||||
/* Main program code */
|
||||
|
||||
void move_carriage_to_far_left(uint8_t reset)
|
||||
{
|
||||
uint16_t cnt = 0;
|
||||
|
||||
/* Init stepper controller */
|
||||
if (reset) {
|
||||
stepper_status_CARRIAGE.step = 0;
|
||||
}
|
||||
stepper_status_CARRIAGE.dir = -1;
|
||||
|
||||
uart_write("[car] Moving carriage to far left...\r\n");
|
||||
while (!LIMITSWITCH) {
|
||||
if (block_for(TIM_CARRIAGE, STEPPER_CFG_CARRIAGE.delay)) {
|
||||
cnt++;
|
||||
STEPPER_NEXT(CARRIAGE, -1);
|
||||
}
|
||||
|
||||
}
|
||||
STEPPER_STOP(CARRIAGE);
|
||||
|
||||
stepper_status_CARRIAGE.pos = 0;
|
||||
stepper_status_CARRIAGE.target_pos = 0;
|
||||
|
||||
uart_printf("[car] Carriage left after %u steps.\r\n", cnt);
|
||||
}
|
||||
|
||||
void align_daisy_wheel()
|
||||
{
|
||||
int i;
|
||||
|
||||
uart_write("[whl] Aligning wheel...\r\n");
|
||||
stepper_status_WHEEL.dir = 0;
|
||||
stepper_status_WHEEL.lpstate = 0;
|
||||
stepper_status_WHEEL.pos = 0;
|
||||
stepper_status_WHEEL.step = 0;
|
||||
stepper_status_WHEEL.target_pos = 0;
|
||||
stepper_status_WHEEL.ldir = 0;
|
||||
|
||||
for (i = 0; i < (96 + 1) * 2; ) {
|
||||
if (block_for(TIM_WHEEL, STEPPER_CFG_WHEEL.delay)) {
|
||||
STEPPER_NEXT(WHEEL, -1);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
STEPPER_STOP(WHEEL);
|
||||
_delay_ms(STEPPER_CFG_WHEEL.delay * REVERSAL_MULTIPLIER);
|
||||
|
||||
for (i = 0; i < 4;) {
|
||||
if (block_for(TIM_WHEEL, STEPPER_CFG_WHEEL.delay)) {
|
||||
STEPPER_NEXT(WHEEL, 1);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
STEPPER_STOP(WHEEL);
|
||||
|
||||
stepper_status_WHEEL.ldir = 1;
|
||||
stepper_status_WHEEL.target_pos = 0;
|
||||
stepper_status_WHEEL.pos = 4;
|
||||
|
||||
uart_write("[whl] Alignment completed.\r\n");
|
||||
}
|
||||
|
||||
void reset_printhead()
|
||||
{
|
||||
uart_write("[hmr] Resetting printhead...\r\n");
|
||||
DCMOTOR_EN;
|
||||
_delay_ms(200);
|
||||
DCMOTOR_STOP;
|
||||
uart_write("[hmr] Printhead reset completed.\r\n");
|
||||
}
|
||||
|
||||
int system_test_auto()
|
||||
{
|
||||
char c;
|
||||
int do_it = 0;
|
||||
int print_stat = 0;
|
||||
|
||||
uart_write("[sys] Entering system test mode\r\n");
|
||||
uart_write(">");
|
||||
|
||||
while(1) {
|
||||
if (UCSRA & (1 << RXC)) {
|
||||
print_stat = 1;
|
||||
c = UDR;
|
||||
|
||||
if (c >= '0' && c <= '9') {
|
||||
stepper_status_CARRIAGE.target_pos = 100 * (c - '0');
|
||||
} else {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
stepper_status_CARRIAGE.target_pos += 10;
|
||||
break;
|
||||
case 'z':
|
||||
if (stepper_status_CARRIAGE.target_pos >= 10)
|
||||
stepper_status_CARRIAGE.target_pos -= 10;
|
||||
break;
|
||||
case 'r':
|
||||
move_carriage_to_far_left(0);
|
||||
break;
|
||||
case 'h':
|
||||
DCMOTOR_EN;
|
||||
arm_hammer();
|
||||
_delay_ms(100); /* Note, this also locks the carriage movement -> important! */
|
||||
DCMOTOR_STOP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '\'':
|
||||
//if (stepper_status_WHEEL.target_pos >= 2)
|
||||
SET_TARGET_DELTA(WHEEL, -2);
|
||||
uart_printf("[whl] New wheel: %d\r\n", stepper_status_WHEEL.target_pos);
|
||||
break;
|
||||
case ',':
|
||||
SET_TARGET_DELTA(WHEEL, 2);
|
||||
uart_printf("[whl] New wheel: %d\r\n", stepper_status_WHEEL.target_pos);
|
||||
break;
|
||||
case 'w':
|
||||
align_daisy_wheel();
|
||||
break;
|
||||
case 't':
|
||||
stepper_status_WHEEL.target_pos += 2;
|
||||
stepper_status_CARRIAGE.target_pos += 10;
|
||||
do_it = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stepper_perform_movement(&stepper_status_CARRIAGE, &STEPPER_CFG_CARRIAGE);
|
||||
stepper_perform_movement(&stepper_status_WHEEL, &STEPPER_CFG_WHEEL);
|
||||
|
||||
if (POSITION_REACHED(WHEEL) && POSITION_REACHED(CARRIAGE) && print_stat) {
|
||||
print_stat = 0;
|
||||
uart_printf("[pos] CAR: %u\r\n[pos] WHL: %u\r\n",
|
||||
stepper_status_CARRIAGE.pos,
|
||||
stepper_status_WHEEL.pos);
|
||||
}
|
||||
|
||||
if (do_it) {
|
||||
if (stepper_status_CARRIAGE.pos == stepper_status_CARRIAGE.target_pos) {
|
||||
do_it = 0;
|
||||
DCMOTOR_EN;
|
||||
arm_hammer();
|
||||
_delay_ms(100);
|
||||
DCMOTOR_STOP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printer_test()
|
||||
{
|
||||
uint8_t buf[80] = {0};
|
||||
uint8_t *ptr = buf;
|
||||
uint8_t *rdptr = buf;
|
||||
uint8_t translated = 0;
|
||||
int state = 0;
|
||||
|
||||
uart_write("[sys] Entering printer test mode\r\n");
|
||||
|
||||
while(1) {
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
_delay_ms(100); // Motor turnoff delay
|
||||
DCMOTOR_STOP;
|
||||
|
||||
stepper_status_CARRIAGE.target_pos = 80;
|
||||
stepper_status_WHEEL.target_pos = 0;
|
||||
ptr = buf;
|
||||
uart_write(">");
|
||||
state++;
|
||||
break;
|
||||
case 1:
|
||||
if (UCSRA & (1 << RXC)) {
|
||||
//stepper_status_WHEEL.target_pos += 2;
|
||||
*ptr = UDR;
|
||||
uart_tx(*ptr);
|
||||
if (*ptr == '\r') {
|
||||
uart_write("\r\nOK.\r\n");
|
||||
DCMOTOR_EN;
|
||||
_delay_ms(100); // Let motor get up to speed
|
||||
|
||||
state++;
|
||||
|
||||
stepper_status_CARRIAGE.target_pos = 80;
|
||||
rdptr = buf;
|
||||
} else {
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
stepper_status_CARRIAGE.target_pos += 10;
|
||||
translated = pgm_read_byte(&ascii_translation_table[*rdptr]);
|
||||
if (translated != PRINTER_NO_CHAR) {
|
||||
//uart_printf("Prepare: %x (%c) -> %d", *rdptr, *rdptr, translated);
|
||||
SET_TARGET(WHEEL, translated * 2);
|
||||
state++;
|
||||
} else {
|
||||
//uart_printf("Skip: %x (%c) -> %d\r\n", *rdptr, *rdptr, translated);
|
||||
rdptr++;
|
||||
if (rdptr == ptr) {
|
||||
state = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (POSITION_REACHED(CARRIAGE) && POSITION_REACHED(WHEEL)) {
|
||||
//uart_write("!!!\r\n");
|
||||
//DCMOTOR_EN;
|
||||
arm_hammer();
|
||||
_delay_ms(50);
|
||||
//DCMOTOR_STOP;
|
||||
rdptr++;
|
||||
if (rdptr == ptr) {
|
||||
state = 0;
|
||||
} else {
|
||||
state--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
stepper_perform_movement(&stepper_status_CARRIAGE, &STEPPER_CFG_CARRIAGE);
|
||||
stepper_perform_movement(&stepper_status_WHEEL, &STEPPER_CFG_WHEEL);
|
||||
}
|
||||
}
|
||||
|
||||
void systick_test()
|
||||
{
|
||||
uart_write("[tmr] System timer test\r\n");
|
||||
while (1) {
|
||||
if (block_for(0, 1000*4)) {
|
||||
uart_write("hello");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
/* Pre-init I/O */
|
||||
DDRB = 0;
|
||||
DDRC = 0;
|
||||
DDRD = 0;
|
||||
PORTB = 0;
|
||||
PORTC = 0;
|
||||
PORTD = 0;
|
||||
|
||||
/* Set up UART */
|
||||
UCSRB = (1 << TXEN) | (1 << RXEN);
|
||||
UBRRH = (UBRR >> 8) & 0xFF;
|
||||
UBRRL = UBRR & 0xFF;
|
||||
|
||||
/* Set up DC components */
|
||||
MOTLIM(DDR) |= PIN_DCMOTOR;
|
||||
MOTLIM(DDR) &= ~(PIN_LIMITSWITCH);
|
||||
MOTLIM(PORT) |= PIN_LIMITSWITCH; /* Pullup for limit switch */
|
||||
SOLENOID(DDR) |= PIN_ARMHAMMER;
|
||||
SOLENOID(DDR) |= PIN_CORRECTION;
|
||||
|
||||
/* Set up steppers */
|
||||
STEPPER_SET_IO(CARRIAGE);
|
||||
STEPPER_SET_IO(WHEEL);
|
||||
|
||||
/* Set up SysTick Timer */
|
||||
TCCR1B = (1 << WGM12) | (1 << CS11); // f_tim = 8 MHz / 8
|
||||
OCR1A = 1000 / TIMESCALE;
|
||||
TIMSK = (1 << OCIE1A);
|
||||
|
||||
/* Init system */
|
||||
uart_write("\n\n\r[sys] STARTING IO CONTROLLER...\r\n");
|
||||
uart_write("[sys] Enabling interrupts.\r\n");
|
||||
sei();
|
||||
|
||||
/* Align printer */
|
||||
move_carriage_to_far_left(1);
|
||||
align_daisy_wheel();
|
||||
reset_printhead();
|
||||
|
||||
uart_write("[sys] Startup completed.\r\n");
|
||||
|
||||
/* Run system */
|
||||
printer_test();
|
||||
system_test_auto();
|
||||
systick_test();
|
||||
|
||||
uart_write("[sys] REACHED END OF MAIN. HALTING.\r\n");
|
||||
while (1);
|
||||
}
|
BIN
printer/avr/main.obj
Executable file
BIN
printer/avr/main.obj
Executable file
Binary file not shown.
9
printer/avr/printer.pro
Normal file
9
printer/avr/printer.pro
Normal file
@ -0,0 +1,9 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
CONFIG -= qt
|
||||
|
||||
INCLUDEPATH += /usr/avr/include
|
||||
|
||||
SOURCES += \
|
||||
main.c
|
Loading…
Reference in New Issue
Block a user