added stream system & improved LCD string handling (crlf)

pull/1/head
Ondřej Hruška 9 years ago
parent 256e96afc3
commit f0f216469b
  1. 10
      examples/Makefile
  2. 20
      examples/lcd_test.c
  3. 11
      examples/sonar_simple.c
  4. 1351
      examples/sonar_simple.lst
  5. 16
      examples/uart_simple.c
  6. 31
      examples/uart_stream.c
  7. 225
      examples/uart_stream.lst
  8. 885
      examples/uart_stream.pre
  9. 74
      lib/lcd.c
  10. 15
      lib/lcd.h
  11. 38
      lib/sonar.c
  12. 12
      lib/sonar.h
  13. 162
      lib/stream.c
  14. 71
      lib/stream.h
  15. 138
      lib/uart.c
  16. 32
      lib/uart.h
  17. 163
      lib/uart_ansi.c

@ -11,14 +11,14 @@ EFUSE = 0x05
## === Source files ===
# Main C file
MAIN = sonar_simple.c
MAIN = lcd_test.c
# Extra C files in this folder
LOCAL_SOURCE =
# Library directory (with C files)
EXTRA_SOURCE_DIR = lib/
# C files in the library directory
EXTRA_SOURCE_FILES = uart.c lcd.c sonar.c uart_ansi.c
EXTRA_SOURCE_FILES = uart.c lcd.c sonar.c uart_ansi.c stream.c
## === Programmer ===
@ -87,6 +87,12 @@ debug:
@echo
flser: all flash serial
serial:
gtkterm -p /dev/ttyUSB0
# Disassemble the ELF
disassemble: $(TARGET).lst
dis: disassemble

@ -30,26 +30,28 @@ void main()
{
lcd_init();
// Define custom glyph at character 0
lcd_glyph_pgm(0, glyph);
// After writing a glyph, the address is changed
// So we need to fix that:
lcd_xy(0, 0);
// Example of using the LCD stream
put_u32f(lcd, 271828, 5);
// Print a string
lcd_puts("Hello");
lcd_puts(" Hello\r\n");
// Use _pgm for strings in program memory
// Here we print string at position xy
lcd_puts_xy_pgm(0, 1, PSTR("String from PGM "));
lcd_puts_P(PSTR("String from PGM "));
// declare custom glyph
lcd_glyph_P(0, glyph);
// print the custom glyph
// and show it
lcd_putc(0);
lcd_puts(" !");
// enable blink/bar cursor type
lcd_cursor(CURSOR_BOTH);
// print at given position
lcd_puts_xy(5, 2, "Third line?");
lcd_puts_xy(3, 3, "Fourth line!");

@ -11,6 +11,7 @@
#include "lib/uart.h"
#include "lib/arduino_pins.h"
#include "lib/sonar.h"
#include "lib/stream.h"
@ -64,21 +65,21 @@ void main()
// Measure
sonar_start(&so);
while(sonar_busy()) {
while(sonar_busy) {
// Sonar is asynchronous
// Here we just wait for it to complete
}
int16_t res = sonar_result();
int16_t res = sonar_result;
// Print
if (res < 0) {
uart_puts("NO OBSTACLES\r\n");
put_str(uart, "NO OBSTACLES\r\n");
} else {
uart_puti(res, 1); // one decimal place
uart_puts(" cm\r\n");
put_i16f(uart, res, 1); // one decimal place
put_str(uart, " cm\r\n");
}

File diff suppressed because it is too large Load Diff

@ -16,8 +16,6 @@ void main()
// Enable UART with baud rate 9600
uart_init(9600);
// --- some examples of printing functions ---
@ -26,22 +24,12 @@ void main()
// Use _pgm for strings in program memory
// (PSTR macro is defined in avr/pgmspace.h)
uart_puts_pgm(PSTR("Program memory string example\r\n"));
uart_puts_P(PSTR("Program memory string example\r\n"));
// print a char. This is an alias for uart_tx
uart_putc('a');
// print a newline
uart_nl();
// Printing numbers is also easy
// Look in `uart.h` for more info
uart_putn(123);
uart_nl();
// Print int as float (adds decimal point at 4th place from the end)
uart_puti(31415, 4);
uart_nl();
// For printing numbers, please check "uart_stream.c" example
// --- receive example ---

@ -0,0 +1,31 @@
//
// Example of using UART with stream
//
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <stdint.h>
#include <stdlib.h>
#include "lib/uart.h"
#include "lib/stream.h"
void main()
{
// Enable UART with baud rate 9600
uart_init(9600);
// Functions from `stream.h` will work with any stream
// "uart" is a pointer to the UART stream
put_str(uart, "UART is 1337");
put_nl(uart);
put_str_P(uart, PSTR("String from program memory!!!"));
put_nl(uart);
put_u16f(uart, 31416, 4);
while(1);
}

@ -0,0 +1,225 @@
uart_stream.elf: file format elf32-avr
Disassembly of section .text:
00000000 <__vectors>:
0: 33 c0 rjmp .+102 ; 0x68 <__ctors_end>
2: 00 00 nop
4: 4c c0 rjmp .+152 ; 0x9e <__bad_interrupt>
6: 00 00 nop
8: 4a c0 rjmp .+148 ; 0x9e <__bad_interrupt>
a: 00 00 nop
c: 48 c0 rjmp .+144 ; 0x9e <__bad_interrupt>
e: 00 00 nop
10: 46 c0 rjmp .+140 ; 0x9e <__bad_interrupt>
12: 00 00 nop
14: 44 c0 rjmp .+136 ; 0x9e <__bad_interrupt>
16: 00 00 nop
18: 42 c0 rjmp .+132 ; 0x9e <__bad_interrupt>
1a: 00 00 nop
1c: 40 c0 rjmp .+128 ; 0x9e <__bad_interrupt>
1e: 00 00 nop
20: 3e c0 rjmp .+124 ; 0x9e <__bad_interrupt>
22: 00 00 nop
24: 3c c0 rjmp .+120 ; 0x9e <__bad_interrupt>
26: 00 00 nop
28: 3a c0 rjmp .+116 ; 0x9e <__bad_interrupt>
2a: 00 00 nop
2c: 38 c0 rjmp .+112 ; 0x9e <__bad_interrupt>
2e: 00 00 nop
30: 36 c0 rjmp .+108 ; 0x9e <__bad_interrupt>
32: 00 00 nop
34: 34 c0 rjmp .+104 ; 0x9e <__bad_interrupt>
36: 00 00 nop
38: 32 c0 rjmp .+100 ; 0x9e <__bad_interrupt>
3a: 00 00 nop
3c: 30 c0 rjmp .+96 ; 0x9e <__bad_interrupt>
3e: 00 00 nop
40: 2e c0 rjmp .+92 ; 0x9e <__bad_interrupt>
42: 00 00 nop
44: 2c c0 rjmp .+88 ; 0x9e <__bad_interrupt>
46: 00 00 nop
48: 2a c0 rjmp .+84 ; 0x9e <__bad_interrupt>
4a: 00 00 nop
4c: 28 c0 rjmp .+80 ; 0x9e <__bad_interrupt>
4e: 00 00 nop
50: 26 c0 rjmp .+76 ; 0x9e <__bad_interrupt>
52: 00 00 nop
54: 24 c0 rjmp .+72 ; 0x9e <__bad_interrupt>
56: 00 00 nop
58: 22 c0 rjmp .+68 ; 0x9e <__bad_interrupt>
5a: 00 00 nop
5c: 20 c0 rjmp .+64 ; 0x9e <__bad_interrupt>
5e: 00 00 nop
60: 1e c0 rjmp .+60 ; 0x9e <__bad_interrupt>
62: 00 00 nop
64: 1c c0 rjmp .+56 ; 0x9e <__bad_interrupt>
...
00000068 <__ctors_end>:
68: 11 24 eor r1, r1
6a: 1f be out 0x3f, r1 ; 63
6c: cf ef ldi r28, 0xFF ; 255
6e: d8 e0 ldi r29, 0x08 ; 8
70: de bf out 0x3e, r29 ; 62
72: cd bf out 0x3d, r28 ; 61
00000074 <__do_copy_data>:
74: 11 e0 ldi r17, 0x01 ; 1
76: a0 e0 ldi r26, 0x00 ; 0
78: b1 e0 ldi r27, 0x01 ; 1
7a: ee e2 ldi r30, 0x2E ; 46
7c: f1 e0 ldi r31, 0x01 ; 1
7e: 02 c0 rjmp .+4 ; 0x84 <__do_copy_data+0x10>
80: 05 90 lpm r0, Z+
82: 0d 92 st X+, r0
84: a6 30 cpi r26, 0x06 ; 6
86: b1 07 cpc r27, r17
88: d9 f7 brne .-10 ; 0x80 <__do_copy_data+0xc>
0000008a <__do_clear_bss>:
8a: 11 e0 ldi r17, 0x01 ; 1
8c: a6 e0 ldi r26, 0x06 ; 6
8e: b1 e0 ldi r27, 0x01 ; 1
90: 01 c0 rjmp .+2 ; 0x94 <.do_clear_bss_start>
00000092 <.do_clear_bss_loop>:
92: 1d 92 st X+, r1
00000094 <.do_clear_bss_start>:
94: ac 30 cpi r26, 0x0C ; 12
96: b1 07 cpc r27, r17
98: e1 f7 brne .-8 ; 0x92 <.do_clear_bss_loop>
9a: 02 d0 rcall .+4 ; 0xa0 <main>
9c: 46 c0 rjmp .+140 ; 0x12a <_exit>
0000009e <__bad_interrupt>:
9e: b0 cf rjmp .-160 ; 0x0 <__vectors>
000000a0 <main>:
#include "lib/stream.h"
void main()
{
// Enable UART with baud rate 9600
uart_init(9600);
a0: 87 e6 ldi r24, 0x67 ; 103
a2: 90 e0 ldi r25, 0x00 ; 0
a4: 16 d0 rcall .+44 ; 0xd2 <_uart_init_do>
a6: 60 e0 ldi r22, 0x00 ; 0
put_str(uart, "hello");
a8: 71 e0 ldi r23, 0x01 ; 1
aa: 80 91 0a 01 lds r24, 0x010A
ae: 90 91 0b 01 lds r25, 0x010B
b2: 28 d0 rcall .+80 ; 0x104 <put_str>
b4: ff cf rjmp .-2 ; 0xb4 <main+0x14>
000000b6 <uart_tx>:
/** Send byte over UART */
void uart_tx(uint8_t data)
{
// Wait for transmit buffer
while (!uart_tx_ready());
b6: 90 91 c0 00 lds r25, 0x00C0
ba: 95 ff sbrs r25, 5
bc: fc cf rjmp .-8 ; 0xb6 <uart_tx>
// send it
UDR0 = data;
be: 80 93 c6 00 sts 0x00C6, r24
c2: 08 95 ret
000000c4 <uart_rx>:
/** Receive one byte over UART */
uint8_t uart_rx()
{
// Wait for data to be received
while (!uart_rx_ready());
c4: 80 91 c0 00 lds r24, 0x00C0
c8: 87 ff sbrs r24, 7
ca: fc cf rjmp .-8 ; 0xc4 <uart_rx>
// Get and return received data from buffer
return UDR0;
cc: 80 91 c6 00 lds r24, 0x00C6
}
d0: 08 95 ret
000000d2 <_uart_init_do>:
STREAM* uart;
inline void _uart_init_do(uint16_t ubrr) {
/*Set baud rate */
UBRR0H = (uint8_t) (ubrr >> 8);
d2: 90 93 c5 00 sts 0x00C5, r25
UBRR0L = (uint8_t) ubrr;
d6: 80 93 c4 00 sts 0x00C4, r24
// Enable Rx and Tx
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
da: 88 e1 ldi r24, 0x18 ; 24
dc: 80 93 c1 00 sts 0x00C1, r24
// 8-bit data, 1 stop bit
UCSR0C = (0b11 << UCSZ00);
e0: 86 e0 ldi r24, 0x06 ; 6
e2: 80 93 c2 00 sts 0x00C2, r24
uart_singleton.tx = &uart_tx;
e6: e6 e0 ldi r30, 0x06 ; 6
e8: f1 e0 ldi r31, 0x01 ; 1
ea: 8b e5 ldi r24, 0x5B ; 91
ec: 90 e0 ldi r25, 0x00 ; 0
ee: 91 83 std Z+1, r25 ; 0x01
f0: 80 83 st Z, r24
uart_singleton.rx = &uart_rx;
f2: 82 e6 ldi r24, 0x62 ; 98
f4: 90 e0 ldi r25, 0x00 ; 0
f6: 93 83 std Z+3, r25 ; 0x03
f8: 82 83 std Z+2, r24 ; 0x02
uart = &uart_singleton;
fa: f0 93 0b 01 sts 0x010B, r31
fe: e0 93 0a 01 sts 0x010A, r30
102: 08 95 ret
00000104 <put_str>:
char tmpstr[20]; // buffer for number rendering
void put_str(const STREAM *p, char* str)
{
104: 0f 93 push r16
106: 1f 93 push r17
108: cf 93 push r28
10a: df 93 push r29
10c: 8c 01 movw r16, r24
10e: eb 01 movw r28, r22
char c;
while ((c = *str++))
110: 89 91 ld r24, Y+
112: 88 23 and r24, r24
114: 29 f0 breq .+10 ; 0x120 <put_str+0x1c>
p->tx(c);
116: d8 01 movw r26, r16
118: ed 91 ld r30, X+
11a: fc 91 ld r31, X
11c: 09 95 icall
11e: f8 cf rjmp .-16 ; 0x110 <put_str+0xc>
}
120: df 91 pop r29
122: cf 91 pop r28
124: 1f 91 pop r17
126: 0f 91 pop r16
128: 08 95 ret
0000012a <_exit>:
12a: f8 94 cli
0000012c <__stop_program>:
12c: ff cf rjmp .-2 ; 0x12c <__stop_program>

@ -0,0 +1,885 @@
# 1 "uart_stream.c"
# 1 "/home/ondra/git/avr-lib/examples//"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "uart_stream.c"
# 1 "/usr/avr/include/avr/io.h" 1 3
# 99 "/usr/avr/include/avr/io.h" 3
# 1 "/usr/avr/include/avr/sfr_defs.h" 1 3
# 126 "/usr/avr/include/avr/sfr_defs.h" 3
# 1 "/usr/avr/include/inttypes.h" 1 3
# 37 "/usr/avr/include/inttypes.h" 3
# 1 "/usr/lib/gcc/avr/4.9.2/include/stdint.h" 1 3 4
# 9 "/usr/lib/gcc/avr/4.9.2/include/stdint.h" 3 4
# 1 "/usr/avr/include/stdint.h" 1 3 4
# 122 "/usr/avr/include/stdint.h" 3 4
typedef signed int int8_t __attribute__((__mode__(__QI__)));
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
typedef signed int int16_t __attribute__ ((__mode__ (__HI__)));
typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__)));
typedef signed int int32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int uint32_t __attribute__ ((__mode__ (__SI__)));
typedef signed int int64_t __attribute__((__mode__(__DI__)));
typedef unsigned int uint64_t __attribute__((__mode__(__DI__)));
# 143 "/usr/avr/include/stdint.h" 3 4
typedef int16_t intptr_t;
typedef uint16_t uintptr_t;
# 160 "/usr/avr/include/stdint.h" 3 4
typedef int8_t int_least8_t;
typedef uint8_t uint_least8_t;
typedef int16_t int_least16_t;
typedef uint16_t uint_least16_t;
typedef int32_t int_least32_t;
typedef uint32_t uint_least32_t;
typedef int64_t int_least64_t;
typedef uint64_t uint_least64_t;
# 214 "/usr/avr/include/stdint.h" 3 4
typedef int8_t int_fast8_t;
typedef uint8_t uint_fast8_t;
typedef int16_t int_fast16_t;
typedef uint16_t uint_fast16_t;
typedef int32_t int_fast32_t;
typedef uint32_t uint_fast32_t;
typedef int64_t int_fast64_t;
typedef uint64_t uint_fast64_t;
# 274 "/usr/avr/include/stdint.h" 3 4
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
# 10 "/usr/lib/gcc/avr/4.9.2/include/stdint.h" 2 3 4
# 38 "/usr/avr/include/inttypes.h" 2 3
# 77 "/usr/avr/include/inttypes.h" 3
typedef int32_t int_farptr_t;
typedef uint32_t uint_farptr_t;
# 127 "/usr/avr/include/avr/sfr_defs.h" 2 3
# 100 "/usr/avr/include/avr/io.h" 2 3
# 248 "/usr/avr/include/avr/io.h" 3
# 1 "/usr/avr/include/avr/iom328p.h" 1 3
# 249 "/usr/avr/include/avr/io.h" 2 3
# 534 "/usr/avr/include/avr/io.h" 3
# 1 "/usr/avr/include/avr/portpins.h" 1 3
# 535 "/usr/avr/include/avr/io.h" 2 3
# 1 "/usr/avr/include/avr/common.h" 1 3
# 537 "/usr/avr/include/avr/io.h" 2 3
# 1 "/usr/avr/include/avr/version.h" 1 3
# 539 "/usr/avr/include/avr/io.h" 2 3
# 1 "/usr/avr/include/avr/fuse.h" 1 3
# 239 "/usr/avr/include/avr/fuse.h" 3
typedef struct
{
unsigned char low;
unsigned char high;
unsigned char extended;
} __fuse_t;
# 546 "/usr/avr/include/avr/io.h" 2 3
# 1 "/usr/avr/include/avr/lock.h" 1 3
# 549 "/usr/avr/include/avr/io.h" 2 3
# 6 "uart_stream.c" 2
# 1 "/usr/avr/include/util/delay.h" 1 3
# 43 "/usr/avr/include/util/delay.h" 3
# 1 "/usr/avr/include/util/delay_basic.h" 1 3
# 40 "/usr/avr/include/util/delay_basic.h" 3
static inline void _delay_loop_1(uint8_t __count) __attribute__((always_inline));
static inline void _delay_loop_2(uint16_t __count) __attribute__((always_inline));
# 80 "/usr/avr/include/util/delay_basic.h" 3
void
_delay_loop_1(uint8_t __count)
{
__asm__ volatile (
"1: dec %0" "\n\t"
"brne 1b"
: "=r" (__count)
: "0" (__count)
);
}
# 102 "/usr/avr/include/util/delay_basic.h" 3
void
_delay_loop_2(uint16_t __count)
{
__asm__ volatile (
"1: sbiw %0,1" "\n\t"
"brne 1b"
: "=w" (__count)
: "0" (__count)
);
}
# 44 "/usr/avr/include/util/delay.h" 2 3
# 1 "/usr/avr/include/math.h" 1 3
# 127 "/usr/avr/include/math.h" 3
extern double cos(double __x) __attribute__((__const__));
extern double sin(double __x) __attribute__((__const__));
extern double tan(double __x) __attribute__((__const__));
extern double fabs(double __x) __attribute__((__const__));
extern double fmod(double __x, double __y) __attribute__((__const__));
# 168 "/usr/avr/include/math.h" 3
extern double modf(double __x, double *__iptr);
extern float modff (float __x, float *__iptr);
extern double sqrt(double __x) __attribute__((__const__));
extern float sqrtf (float) __attribute__((__const__));
extern double cbrt(double __x) __attribute__((__const__));
# 194 "/usr/avr/include/math.h" 3
extern double hypot (double __x, double __y) __attribute__((__const__));
extern double square(double __x) __attribute__((__const__));
extern double floor(double __x) __attribute__((__const__));
extern double ceil(double __x) __attribute__((__const__));
# 234 "/usr/avr/include/math.h" 3
extern double frexp(double __x, int *__pexp);
extern double ldexp(double __x, int __exp) __attribute__((__const__));
extern double exp(double __x) __attribute__((__const__));
extern double cosh(double __x) __attribute__((__const__));
extern double sinh(double __x) __attribute__((__const__));
extern double tanh(double __x) __attribute__((__const__));
extern double acos(double __x) __attribute__((__const__));
extern double asin(double __x) __attribute__((__const__));
extern double atan(double __x) __attribute__((__const__));
# 298 "/usr/avr/include/math.h" 3
extern double atan2(double __y, double __x) __attribute__((__const__));
extern double log(double __x) __attribute__((__const__));
extern double log10(double __x) __attribute__((__const__));
extern double pow(double __x, double __y) __attribute__((__const__));
extern int isnan(double __x) __attribute__((__const__));
# 333 "/usr/avr/include/math.h" 3
extern int isinf(double __x) __attribute__((__const__));
__attribute__((__const__)) static inline int isfinite (double __x)
{
unsigned char __exp;
__asm__ (
"mov %0, %C1 \n\t"
"lsl %0 \n\t"
"mov %0, %D1 \n\t"
"rol %0 "
: "=r" (__exp)
: "r" (__x) );
return __exp != 0xff;
}
__attribute__((__const__)) static inline double copysign (double __x, double __y)
{
__asm__ (
"bst %D2, 7 \n\t"
"bld %D0, 7 "
: "=r" (__x)
: "0" (__x), "r" (__y) );
return __x;
}
# 376 "/usr/avr/include/math.h" 3
extern int signbit (double __x) __attribute__((__const__));
extern double fdim (double __x, double __y) __attribute__((__const__));
# 392 "/usr/avr/include/math.h" 3
extern double fma (double __x, double __y, double __z) __attribute__((__const__));
extern double fmax (double __x, double __y) __attribute__((__const__));
extern double fmin (double __x, double __y) __attribute__((__const__));
extern double trunc (double __x) __attribute__((__const__));
# 426 "/usr/avr/include/math.h" 3
extern double round (double __x) __attribute__((__const__));
# 439 "/usr/avr/include/math.h" 3
extern long lround (double __x) __attribute__((__const__));
# 453 "/usr/avr/include/math.h" 3
extern long lrint (double __x) __attribute__((__const__));
# 45 "/usr/avr/include/util/delay.h" 2 3
# 84 "/usr/avr/include/util/delay.h" 3
static inline void _delay_us(double __us) __attribute__((always_inline));
static inline void _delay_ms(double __ms) __attribute__((always_inline));
# 141 "/usr/avr/include/util/delay.h" 3
void
_delay_ms(double __ms)
{
double __tmp ;
# 166 "/usr/avr/include/util/delay.h" 3
uint16_t __ticks;
__tmp = ((16000000UL) / 4e3) * __ms;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp > 65535)
{
__ticks = (uint16_t) (__ms * 10.0);
while(__ticks)
{
_delay_loop_2(((16000000UL) / 4e3) / 10);
__ticks --;
}
return;
}
else
__ticks = (uint16_t)__tmp;
_delay_loop_2(__ticks);
}
# 223 "/usr/avr/include/util/delay.h" 3
void
_delay_us(double __us)
{
double __tmp ;
# 248 "/usr/avr/include/util/delay.h" 3
uint8_t __ticks;
double __tmp2 ;
__tmp = ((16000000UL) / 3e6) * __us;
__tmp2 = ((16000000UL) / 4e6) * __us;
if (__tmp < 1.0)
__ticks = 1;
else if (__tmp2 > 65535)
{
_delay_ms(__us / 1000.0);
}
else if (__tmp > 255)
{
uint16_t __ticks=(uint16_t)__tmp2;
_delay_loop_2(__ticks);
return;
}
else
__ticks = (uint8_t)__tmp;
_delay_loop_1(__ticks);
}
# 7 "uart_stream.c" 2
# 1 "/usr/avr/include/avr/pgmspace.h" 1 3
# 87 "/usr/avr/include/avr/pgmspace.h" 3
# 1 "/usr/lib/gcc/avr/4.9.2/include/stddef.h" 1 3 4
# 212 "/usr/lib/gcc/avr/4.9.2/include/stddef.h" 3 4
typedef unsigned int size_t;
# 88 "/usr/avr/include/avr/pgmspace.h" 2 3
# 1064 "/usr/avr/include/avr/pgmspace.h" 3
extern const void * memchr_P(const void *, int __val, size_t __len) __attribute__((__const__));
extern int memcmp_P(const void *, const void *, size_t) __attribute__((__pure__));
extern void *memccpy_P(void *, const void *, int __val, size_t);
extern void *memcpy_P(void *, const void *, size_t);
extern void *memmem_P(const void *, size_t, const void *, size_t) __attribute__((__pure__));
extern const void * memrchr_P(const void *, int __val, size_t __len) __attribute__((__const__));
extern char *strcat_P(char *, const char *);
extern const char * strchr_P(const char *, int __val) __attribute__((__const__));
extern const char * strchrnul_P(const char *, int __val) __attribute__((__const__));
extern int strcmp_P(const char *, const char *) __attribute__((__pure__));
extern char *strcpy_P(char *, const char *);
extern int strcasecmp_P(const char *, const char *) __attribute__((__pure__));
extern char *strcasestr_P(const char *, const char *) __attribute__((__pure__));
extern size_t strcspn_P(const char *__s, const char * __reject) __attribute__((__pure__));
extern size_t strlcat_P (char *, const char *, size_t );
extern size_t strlcpy_P (char *, const char *, size_t );
extern size_t __strlen_P(const char *) __attribute__((__const__));
extern size_t strnlen_P(const char *, size_t) __attribute__((__const__));
extern int strncmp_P(const char *, const char *, size_t) __attribute__((__pure__));
extern int strncasecmp_P(const char *, const char *, size_t) __attribute__((__pure__));
extern char *strncat_P(char *, const char *, size_t);
extern char *strncpy_P(char *, const char *, size_t);
extern char *strpbrk_P(const char *__s, const char * __accept) __attribute__((__pure__));
extern const char * strrchr_P(const char *, int __val) __attribute__((__const__));
extern char *strsep_P(char **__sp, const char * __delim);
extern size_t strspn_P(const char *__s, const char * __accept) __attribute__((__pure__));
extern char *strstr_P(const char *, const char *) __attribute__((__pure__));
extern char *strtok_P(char *__s, const char * __delim);
extern char *strtok_rP(char *__s, const char * __delim, char **__last);
extern size_t strlen_PF (uint_farptr_t src) __attribute__((__const__));
extern size_t strnlen_PF (uint_farptr_t src, size_t len) __attribute__((__const__));
extern void *memcpy_PF (void *dest, uint_farptr_t src, size_t len);
extern char *strcpy_PF (char *dest, uint_farptr_t src);
extern char *strncpy_PF (char *dest, uint_farptr_t src, size_t len);
extern char *strcat_PF (char *dest, uint_farptr_t src);
extern size_t strlcat_PF (char *dst, uint_farptr_t src, size_t siz);
extern char *strncat_PF (char *dest, uint_farptr_t src, size_t len);
extern int strcmp_PF (const char *s1, uint_farptr_t s2) __attribute__((__pure__));
extern int strncmp_PF (const char *s1, uint_farptr_t s2, size_t n) __attribute__((__pure__));
extern int strcasecmp_PF (const char *s1, uint_farptr_t s2) __attribute__((__pure__));
extern int strncasecmp_PF (const char *s1, uint_farptr_t s2, size_t n) __attribute__((__pure__));
extern char *strstr_PF (const char *s1, uint_farptr_t s2);
extern size_t strlcpy_PF (char *dst, uint_farptr_t src, size_t siz);
extern int memcmp_PF(const void *, uint_farptr_t, size_t) __attribute__((__pure__));
__attribute__((__always_inline__)) static __inline__ size_t strlen_P(const char * s);
static __inline__ size_t strlen_P(const char *s) {
return __builtin_constant_p(__builtin_strlen(s))
? __builtin_strlen(s) : __strlen_P(s);
}
# 8 "uart_stream.c" 2
# 1 "/usr/avr/include/avr/interrupt.h" 1 3
# 9 "uart_stream.c" 2
# 1 "/usr/avr/include/stdlib.h" 1 3
# 47 "/usr/avr/include/stdlib.h" 3
# 1 "/usr/lib/gcc/avr/4.9.2/include/stddef.h" 1 3 4
# 324 "/usr/lib/gcc/avr/4.9.2/include/stddef.h" 3 4
typedef int wchar_t;
# 48 "/usr/avr/include/stdlib.h" 2 3
# 68 "/usr/avr/include/stdlib.h" 3
typedef struct {
int quot;
int rem;
} div_t;
typedef struct {
long quot;
long rem;
} ldiv_t;
typedef int (*__compar_fn_t)(const void *, const void *);
# 114 "/usr/avr/include/stdlib.h" 3
extern void abort(void) __attribute__((__noreturn__));
extern int abs(int __i) __attribute__((__const__));
# 128 "/usr/avr/include/stdlib.h" 3
extern long labs(long __i) __attribute__((__const__));
# 151 "/usr/avr/include/stdlib.h" 3
extern void *bsearch(const void *__key, const void *__base, size_t __nmemb,
size_t __size, int (*__compar)(const void *, const void *));
extern div_t div(int __num, int __denom) __asm__("__divmodhi4") __attribute__((__const__));
extern ldiv_t ldiv(long __num, long __denom) __asm__("__divmodsi4") __attribute__((__const__));
# 183 "/usr/avr/include/stdlib.h" 3
extern void qsort(void *__base, size_t __nmemb, size_t __size,
__compar_fn_t __compar);
# 216 "/usr/avr/include/stdlib.h" 3
extern long strtol(const char *__nptr, char **__endptr, int __base);
# 250 "/usr/avr/include/stdlib.h" 3
extern unsigned long strtoul(const char *__nptr, char **__endptr, int __base);
# 262 "/usr/avr/include/stdlib.h" 3
extern long atol(const char *__s) __attribute__((__pure__));
# 274 "/usr/avr/include/stdlib.h" 3
extern int atoi(const char *__s) __attribute__((__pure__));
# 286 "/usr/avr/include/stdlib.h" 3
extern void exit(int __status) __attribute__((__noreturn__));
# 298 "/usr/avr/include/stdlib.h" 3
extern void *malloc(size_t __size) __attribute__((__malloc__));
extern void free(void *__ptr);
extern size_t __malloc_margin;
extern char *__malloc_heap_start;
extern char *__malloc_heap_end;
extern void *calloc(size_t __nele, size_t __size) __attribute__((__malloc__));
# 346 "/usr/avr/include/stdlib.h" 3
extern void *realloc(void *__ptr, size_t __size) __attribute__((__malloc__));
extern double strtod(const char *__nptr, char **__endptr);
extern double atof(const char *__nptr);
# 372 "/usr/avr/include/stdlib.h" 3
extern int rand(void);
extern void srand(unsigned int __seed);
extern int rand_r(unsigned long *__ctx);
# 417 "/usr/avr/include/stdlib.h" 3
extern __inline__ __attribute__((__gnu_inline__))
char *itoa (int __val, char *__s, int __radix)
{
if (!__builtin_constant_p (__radix)) {
extern char *__itoa (int, char *, int);
return __itoa (__val, __s, __radix);
} else if (__radix < 2 || __radix > 36) {
*__s = 0;
return __s;
} else {
extern char *__itoa_ncheck (int, char *, unsigned char);
return __itoa_ncheck (__val, __s, __radix);
}
}
# 462 "/usr/avr/include/stdlib.h" 3
extern __inline__ __attribute__((__gnu_inline__))
char *ltoa (long __val, char *__s, int __radix)
{
if (!__builtin_constant_p (__radix)) {
extern char *__ltoa (long, char *, int);
return __ltoa (__val, __s, __radix);
} else if (__radix < 2 || __radix > 36) {
*__s = 0;
return __s;
} else {
extern char *__ltoa_ncheck (long, char *, unsigned char);
return __ltoa_ncheck (__val, __s, __radix);
}
}
# 505 "/usr/avr/include/stdlib.h" 3
extern __inline__ __attribute__((__gnu_inline__))
char *utoa (unsigned int __val, char *__s, int __radix)
{
if (!__builtin_constant_p (__radix)) {
extern char *__utoa (unsigned int, char *, int);
return __utoa (__val, __s, __radix);
} else if (__radix < 2 || __radix > 36) {
*__s = 0;
return __s;
} else {
extern char *__utoa_ncheck (unsigned int, char *, unsigned char);
return __utoa_ncheck (__val, __s, __radix);
}
}
# 547 "/usr/avr/include/stdlib.h" 3
extern __inline__ __attribute__((__gnu_inline__))
char *ultoa (unsigned long __val, char *__s, int __radix)
{
if (!__builtin_constant_p (__radix)) {
extern char *__ultoa (unsigned long, char *, int);
return __ultoa (__val, __s, __radix);
} else if (__radix < 2 || __radix > 36) {
*__s = 0;
return __s;
} else {
extern char *__ultoa_ncheck (unsigned long, char *, unsigned char);
return __ultoa_ncheck (__val, __s, __radix);
}
}
# 579 "/usr/avr/include/stdlib.h" 3
extern long random(void);
extern void srandom(unsigned long __seed);
extern long random_r(unsigned long *__ctx);
# 638 "/usr/avr/include/stdlib.h" 3
extern char *dtostre(double __val, char *__s, unsigned char __prec,
unsigned char __flags);
# 655 "/usr/avr/include/stdlib.h" 3
extern char *dtostrf(double __val, signed char __width,
unsigned char __prec, char *__s);
# 672 "/usr/avr/include/stdlib.h" 3
extern int atexit(void (*)(void));
extern int system (const char *);
extern char *getenv (const char *);
# 11 "uart_stream.c" 2
# 1 "lib/uart.h" 1
# 13 "lib/uart.h"
# 1 "/usr/lib/gcc/avr/4.9.2/include/stdbool.h" 1 3 4
# 14 "lib/uart.h" 2
# 1 "lib/stream.h" 1
# 12 "lib/stream.h"
typedef struct {
void (*tx) (uint8_t b);
uint8_t (*rx) (void);
} STREAM;
void put_str(const STREAM *p, char* str);
void put_u8(const STREAM *p, const uint8_t num);
void put_i8(const STREAM *p, const int8_t num);
void put_u16(const STREAM *p, const uint16_t num);
void put_i16(const STREAM *p, const int16_t num);
void put_u32(const STREAM *p, const uint32_t num);
void put_i32(const STREAM *p, const int32_t num);
void put_u16f(const STREAM *p, const uint16_t num, const uint8_t places);
void put_i16f(const STREAM *p, const int16_t num, const uint8_t places);
void put_u32f(const STREAM *p, const uint32_t num, const uint8_t places);
void put_i32f(const STREAM *p, const int32_t num, const uint8_t places);
# 17 "lib/uart.h" 2
extern STREAM* uart;
void _uart_init_do(uint16_t ubrr);
# 36 "lib/uart.h"
void uart_isr_rx(_Bool enable);
void uart_isr_tx(_Bool enable);
void uart_isr_dre(_Bool enable);
uint8_t uart_rx();
void uart_tx(uint8_t data);
void uart_flush();
void uart_puts(const char* str);
void uart_puts_pgm(const char* str);
void uart_putu(const uint8_t num);
void uart_putn(const int8_t num);
void uart_puti(const int16_t num, const uint8_t places);
void uart_putiu(const uint16_t num, const uint8_t places);
void uart_putl(const int32_t num, const uint8_t places);
void uart_putlu(const uint32_t num, const uint8_t places);
void uart_nl();
# 13 "uart_stream.c" 2
void main()
{
_uart_init_do(16000000UL / 16 / (9600) - 1);
put_str(uart, "hello");
while(1);
}

@ -13,6 +13,12 @@
// Start address of rows
const uint8_t LCD_ROW_ADDR[] = {0x00, 0x40, 0x14, 0x54};
// Shared stream instance
static STREAM _lcd_singleton;
STREAM* lcd;
// Internal prototypes
void _lcd_mode_r();
void _lcd_mode_w();
@ -36,6 +42,16 @@ uint8_t _lcd_read_byte();
// 0 W, 1 R
bool _lcd_mode;
struct {
uint8_t x;
uint8_t y;
} _pos;
enum {
TEXT = 0,
CG = 1
} _addrtype;
/** Initialize the display */
void lcd_init()
@ -68,6 +84,16 @@ void lcd_init()
// mark as enabled
lcd_enable();
_lcd_singleton.tx = &lcd_write;
_lcd_singleton.rx = &lcd_read;
// Stream
lcd = &_lcd_singleton;
_pos.x = 0;
_pos.y = 0;
_addrtype = TEXT;
}
@ -75,7 +101,7 @@ void lcd_init()
void _lcd_clk()
{
pin_up(LCD_E);
delay_ns(420);
delay_ns(450);
pin_down(LCD_E);
}
@ -141,6 +167,24 @@ void lcd_command(uint8_t bb)
/** Write a data byte */
void lcd_write(uint8_t bb)
{
if (_addrtype == TEXT) {
if (bb == '\r') {
// CR
_pos.x = 0;
lcd_xy(_pos.x, _pos.y);
return;
}
if (bb == '\n') {
// LF
_pos.y++;
lcd_xy(_pos.x, _pos.y);
return;
}
_pos.x++;
}
_lcd_wait_bf();
pin_up(LCD_RS); // select data register
_lcd_write_byte(bb); // send data byte
@ -158,12 +202,14 @@ uint8_t lcd_read_bf_addr()
/** Read CGRAM or DDRAM */
uint8_t lcd_read()
{
if (_addrtype == TEXT) _pos.x++;
pin_up(LCD_RS);
return _lcd_read_byte();
}
/** Write a byte using the 8-bit interface */
/** Write a byte using the 4-bit interface */
void _lcd_write_byte(uint8_t bb)
{
_lcd_mode_w(); // enter W mode
@ -189,13 +235,14 @@ void _lcd_wait_bf()
/** Send a string to LCD */
void lcd_puts(char* str_p)
{
while (*str_p)
lcd_putc(*str_p++);
char c;
while ((c = *str_p++))
lcd_putc(c);
}
/** Print from progmem */
void lcd_puts_pgm(const char* str_p)
void lcd_puts_P(const char* str_p)
{
char c;
while ((c = pgm_read_byte(str_p++)))
@ -213,6 +260,8 @@ void lcd_putc(const char c)
/** Set cursor position */
void lcd_xy(const uint8_t x, const uint8_t y)
{
_pos.x = x;
_pos.y = y;
lcd_addr(LCD_ROW_ADDR[y] + (x));
}
@ -249,6 +298,9 @@ void lcd_enable()
void lcd_home()
{
lcd_command(LCD_HOME);
_pos.x = 0;
_pos.y = 0;
_addrtype = TEXT;
}
@ -266,22 +318,31 @@ void lcd_glyph(const uint8_t index, const uint8_t* array)
for (uint8_t i = 0; i < 8; ++i) {
lcd_write(array[i]);
}
// restore previous position
lcd_xy(_pos.x, _pos.y);
_addrtype = TEXT;
}
/** Define a glyph */
void lcd_glyph_pgm(const uint8_t index, const uint8_t* array)
void lcd_glyph_P(const uint8_t index, const uint8_t* array)
{
lcd_addr_cg(index * 8);
for (uint8_t i = 0; i < 8; ++i) {
lcd_write(pgm_read_byte(&array[i]));
}
// restore previous position
lcd_xy(_pos.x, _pos.y);
_addrtype = TEXT;
}
/** Set address in CGRAM */
void lcd_addr_cg(const uint8_t acg)
{
_addrtype = CG;
lcd_command(0b01000000 | ((acg) & 0b00111111));
}
@ -289,5 +350,6 @@ void lcd_addr_cg(const uint8_t acg)
/** Set address in DDRAM */
void lcd_addr(const uint8_t add)
{
_addrtype = TEXT;
lcd_command(0b10000000 | ((add) & 0b01111111));
}

@ -21,9 +21,18 @@
#include <stdint.h>
#include <stdbool.h>
#include "stream.h"
// File with configs
#include "lcd_config.h"
// Shared LCD stream object
// Can be used with functions from stream.h once LCD is initialized
extern STREAM* lcd;
// --- Commands ---
// Clear screen (reset)
@ -88,7 +97,7 @@ uint8_t lcd_read();
void lcd_puts(char* str_p);
/** Send a string to LCD from program memory */
void lcd_puts_pgm(const char* str_p);
void lcd_puts_P(const char* str_p);
/** Sedn a char to LCD */
void lcd_putc(const char c);
@ -97,7 +106,7 @@ void lcd_putc(const char c);
#define lcd_puts_xy(x, y, str_p) do { lcd_xy((x), (y)); lcd_puts((str_p)); } while(0)
/** Show string at X, Y */
#define lcd_puts_xy_pgm(x, y, str_p) do { lcd_xy((x), (y)); lcd_puts_pgm((str_p)); } while(0)
#define lcd_puts_xy_P(x, y, str_p) do { lcd_xy((x), (y)); lcd_puts_P((str_p)); } while(0)
/** Show char at X, Y */
#define lcd_putc_xy(x, y, c) do { lcd_xy((x), (y)); lcd_putc((c)); } while(0)
@ -128,7 +137,7 @@ void lcd_clear();
void lcd_glyph(const uint8_t index, const uint8_t* array);
/** Define a glyph that's in PROGMEM */
void lcd_glyph_pgm(const uint8_t index, const uint8_t* array);
void lcd_glyph_P(const uint8_t index, const uint8_t* array);
/** Set address in CGRAM */
void lcd_addr_cg(const uint8_t acg);

@ -7,13 +7,13 @@
#include "sonar.h"
// Currently measured sonar
volatile sonar_t *_sonar_active_so;
sonar_t* _sonar_active_so;
// Flag that measurement is in progress
volatile bool _busy;
volatile bool sonar_busy;
// Result of last measurement, in millimeters
volatile int16_t _result = 0xFFFF;
volatile int16_t sonar_result;
void _sonar_init_do(sonar_t* so, PORT_P port, uint8_t ntx, PORT_P pin, uint8_t nrx)
@ -45,11 +45,11 @@ void _sonar_init_do(sonar_t* so, PORT_P port, uint8_t ntx, PORT_P pin, uint8_t n
*/
bool sonar_start(sonar_t* so)
{
if (_busy) return false;
if (sonar_busy) return false;
_sonar_active_so = so;
_busy = true;
sonar_busy = true;
// make sure the timer is stopped (set clock to NONE)
TCCR1B = 0;
@ -114,16 +114,16 @@ void _sonar_stop()
// Disable timer1 overflow interrupt
TIMSK1 &= ~(1 << TOIE1);
_busy = false;
sonar_busy = false;
}
/** Handle TIMER1_OVF (returns true if consumed) */
bool sonar_handle_t1ovf()
inline bool sonar_handle_t1ovf()
{
if (!_busy) return false; // nothing
if (!sonar_busy) return false; // nothing
_result = -1;
sonar_result = -1;
_sonar_stop();
return true;
@ -131,9 +131,9 @@ bool sonar_handle_t1ovf()
/** Handle pin change interrupt (returns true if consumed) */
bool sonar_handle_pci()
inline bool sonar_handle_pci()
{
if (!_busy) {
if (!sonar_busy) {
return false; // nothing
}
@ -146,24 +146,12 @@ bool sonar_handle_pci()
x /= _SNR_DIV_CONST;
x *= 100000000L;
x /= F_CPU;
_result = (int16_t) x;
sonar_result = (int16_t) x;
// no obstacle
if (_result > _SNR_MAX_DIST) _result = -1;
if (sonar_result > _SNR_MAX_DIST) sonar_result = -1;
_sonar_stop();
return true;
}
bool sonar_busy()
{
return _busy;
}
int16_t sonar_result()
{
return _result;
}

@ -34,6 +34,10 @@ typedef struct {
} sonar_t;
extern volatile bool sonar_busy;
extern volatile int16_t sonar_result;
// Create a Sonar port
// Args: sonar_t* so, Trig pin, Echo pin
#define sonar_init(so, trig, echo) do { \
@ -46,14 +50,6 @@ typedef struct {
void _sonar_init_do(sonar_t* so, PORT_P port, uint8_t ntx, PORT_P pin, uint8_t nrx);
/** Check if sonar is busy */
bool sonar_busy();
/** Get result of last measurement, in millimeters. Returns -1 if no obstacle detected */
int16_t sonar_result();
/**
* Start sonar measurement
* Interrupts must be enabled

@ -0,0 +1,162 @@
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "stream.h"
static char tmpstr[20]; // buffer for number rendering
void put_str(const STREAM *p, char* str)
{
char c;
while ((c = *str++))
p->tx(c);
}
void put_str_P(const STREAM *p, const char* str)
{
char c;
while ((c = pgm_read_byte(str++)))
p->tx(c);
}
static void _putnf(const STREAM *p, const uint8_t places);
/** Send signed int8 */
void put_u8(const STREAM *p, const uint8_t num)
{
utoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send unsigned int8 */
void put_i8(const STREAM *p, const int8_t num)
{
itoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send unsigned int */
void put_u16(const STREAM *p, const uint16_t num)
{
utoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send signed int */
void put_i16(const STREAM *p, const int16_t num)
{
itoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send unsigned long */
void put_u32(const STREAM *p, const uint32_t num)
{
ultoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
/** Send signed long */
void put_i32(const STREAM *p, const int32_t num)
{
ltoa(num, tmpstr, 10);
put_str(p, tmpstr);
}
// float variant doesn't make sense for 8-bit int
/** Send unsigned int as float */
void put_u16f(const STREAM *p, const uint16_t num, const uint8_t places)
{
utoa(num, tmpstr, 10);
_putnf(p, places);
}
/** Send signed int as float */
void put_i16f(const STREAM *p, const int16_t num, const uint8_t places)
{
if (num < 0) {
p->tx('-');
itoa(-num, tmpstr, 10);
} else {
itoa(num, tmpstr, 10);
}
_putnf(p, places);
}
/** Send unsigned long as float */
void put_u32f(const STREAM *p, const uint32_t num, const uint8_t places)
{
ultoa(num, tmpstr, 10);
_putnf(p, places);
}
/** Send signed long as float */
void put_i32f(const STREAM *p, const int32_t num, const uint8_t places)
{
if (num < 0) {
p->tx('-');
ltoa(-num, tmpstr, 10);
} else {
ltoa(num, tmpstr, 10);
}
_putnf(p, places);
}
/** Print number in tmp string as float with given decimal point position */
void _putnf(const STREAM *p, const uint8_t places)
{
// measure text length
uint8_t len = 0;
while(tmpstr[len] != 0) len++;
int8_t at = len - places;
// print virtual zeros
if (at <= 0) {
p->tx('0');
p->tx('.');
while(at <= -1) {
p->tx('0');
at++;
}
at = -1;
}
// print the number
uint8_t i = 0;
while(i < len) {
if (at-- == 0) {
p->tx('.');
}
p->tx(tmpstr[i++]);
}
}
/** Print CR LF */
void put_nl(const STREAM *p)
{
p->tx(13);
p->tx(10);
}

@ -0,0 +1,71 @@
#pragma once
//
// Stream utilities - printing abstraction
// Works with eg. UART
//
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <avr/pgmspace.h>
/** Stream structure */
typedef struct {
void (*tx) (uint8_t b);
uint8_t (*rx) (void);
} STREAM;
/** Print string into a stream */
void put_str(const STREAM *p, char* str);
/** Print a programspace string into a stream */
void put_str_P(const STREAM *p, const char* str);
/** Send signed int8 */
void put_u8(const STREAM *p, const uint8_t num);
/** Send unsigned int8 */
void put_i8(const STREAM *p, const int8_t num);
/** Send unsigned int */
void put_u16(const STREAM *p, const uint16_t num);
/** Send signed int */
void put_i16(const STREAM *p, const int16_t num);
/** Send unsigned long */
void put_u32(const STREAM *p, const uint32_t num);
/** Send signed long */
void put_i32(const STREAM *p, const int32_t num);
// float variant doesn't make sense for 8-bit int
/** Send unsigned int as float */
void put_u16f(const STREAM *p, const uint16_t num, const uint8_t places);
/** Send signed int as float */
void put_i16f(const STREAM *p, const int16_t num, const uint8_t places);
/** Send unsigned long as float */
void put_u32f(const STREAM *p, const uint32_t num, const uint8_t places);
/** Send signed long as float */
void put_i32f(const STREAM *p, const int32_t num, const uint8_t places);
/** Print CR LF */
void put_nl(const STREAM *p);

@ -6,6 +6,11 @@
#include <stdlib.h>
#include "uart.h"
#include "stream.h"
// Shared stream instance
static STREAM _uart_singleton;
STREAM* uart;
void _uart_init_do(uint16_t ubrr) {
@ -18,6 +23,11 @@ void _uart_init_do(uint16_t ubrr) {
// 8-bit data, 1 stop bit
UCSR0C = (0b11 << UCSZ00);
_uart_singleton.tx = &uart_tx;
_uart_singleton.rx = &uart_rx;
uart = &_uart_singleton;
}
@ -84,7 +94,7 @@ void uart_puts(const char* str)
/** Send progmem string over UART */
void uart_puts_pgm(const char* str)
void uart_puts_P(const char* str)
{
char c;
while ((c = pgm_read_byte(str++))) {
@ -100,129 +110,3 @@ void uart_flush()
while (UCSR0A & (1 << RXC0))
dummy = UDR0;
}
/** Send CRLF */
void uart_nl()
{
uart_tx(13);
uart_tx(10);
}
char tmpstr[12]; // buffer for number rendering
void _uart_putnf(const uint8_t places);
/** Send signed int8 */
void uart_putu(const uint8_t num)
{
utoa(num, tmpstr, 10);
uart_puts(tmpstr);
}
/** Send unsigned int8 */
void uart_putn(const int8_t num)
{
itoa(num, tmpstr, 10);
uart_puts(tmpstr);
}
/** Send unsigned int as float */
void uart_putiu(const uint16_t num, const uint8_t places)
{
if (!places) {
utoa(num, tmpstr, 10);
uart_puts(tmpstr);
} else {
utoa(num, tmpstr, 10);
_uart_putnf(places);
}
}
/** Send signed int as float */
void uart_puti(const int16_t num, const uint8_t places)
{
if (!places) {
itoa(num, tmpstr, 10);
uart_puts(tmpstr);
} else {
if (num < 0) {
uart_tx('-');
itoa(-num, tmpstr, 10);
} else {
itoa(num, tmpstr, 10);
}
_uart_putnf(places);
}
}
/** Send unsigned long as float */
void uart_putlu(const uint32_t num, const uint8_t places)
{
if (!places) {
ultoa(num, tmpstr, 10);
uart_puts(tmpstr);
} else {
ultoa(num, tmpstr, 10);
_uart_putnf(places);
}
}
/** Send signed long as float */
void uart_putl(const int32_t num, const uint8_t places)
{
if (!places) {
ltoa(num, tmpstr, 10);
uart_puts(tmpstr);
} else {
if (num < 0) {
uart_tx('-');
ltoa(-num, tmpstr, 10);
} else {
ltoa(num, tmpstr, 10);
}
_uart_putnf(places);
}
}
/** Print number in tmp string as float with given decimal point position */
void _uart_putnf(const uint8_t places)
{
// measure text length
uint8_t len = 0;
while(tmpstr[len] != 0) len++;
int8_t at = len - places;
// print virtual zeros
if (at <= 0) {
uart_tx('0');
uart_tx('.');
while(at <= -1) {
uart_tx('0');
at++;
}
at = -1;
}
// print the number
uint8_t i = 0;
while(i < len) {
if (at-- == 0) {
uart_tx('.');
}
uart_tx(tmpstr[i++]);
}
}

@ -13,6 +13,11 @@
#include <stdbool.h>
#include <stdint.h>
#include "stream.h"
// Shared UART stream object
// Can be used with functions from stream.h once UART is initialized
extern STREAM* uart;
/** Init UART for given baudrate */
void _uart_init_do(uint16_t ubrr); // internal, needed for the macro.
@ -59,30 +64,5 @@ void uart_flush();
void uart_puts(const char* str);
/** Send progmem string over UART */
void uart_puts_pgm(const char* str);
// Numbers
/** Send unsigned int */
void uart_putu(const uint8_t num);
/** Send signed int */
void uart_putn(const int8_t num);
/** Send unsigned int */
void uart_puti(const int16_t num, const uint8_t places);
/** Send signed int */
void uart_putiu(const uint16_t num, const uint8_t places);
/** Send signed long */
void uart_putl(const int32_t num, const uint8_t places);
/** Send unsigned long */
void uart_putlu(const uint32_t num, const uint8_t places);
// Extras
void uart_puts_P(const char* str);
/** Send CRLF */
void uart_nl();

@ -6,6 +6,7 @@
#include "uart.h"
#include "uart_ansi.h"
#include "stream.h"
void _vt_apply_style();
void _vt_reset_attribs_do();
@ -15,30 +16,30 @@ void _vt_color_do();
void vt_goto(uint8_t x, uint8_t y)
{
uart_putc(27);
uart_putc('[');
uart_putu(y+1); // one-based !
uart_putc(';');
uart_putu(x+1);
uart_putc('H');
uart_tx(27);
uart_tx('[');
put_u8(uart, y+1); // one-based !
uart_tx(';');
put_u8(uart, x+1);
uart_tx('H');
}
void vt_goto_x(uint8_t x)
{
uart_putc(27);
uart_putc('[');
uart_putu(x+1);
uart_putc('`');
uart_tx(27);
uart_tx('[');
put_u8(uart, x+1);
uart_tx('`');
}
void vt_goto_y(uint8_t y)
{
uart_putc(27);
uart_putc('[');
uart_putu(y+1);
uart_putc('d');
uart_tx(27);
uart_tx('[');
put_u8(uart, y+1);
uart_tx('d');
}
@ -72,54 +73,54 @@ void vt_move_y(int8_t y)
void vt_up(uint8_t y)
{
if (y == 0) return;
uart_putc(27);
uart_putc('[');
uart_putu(y);
uart_putc('A');
uart_tx(27);
uart_tx('[');
put_u8(uart, y);
uart_tx('A');
}
void vt_down(uint8_t y)
{
if (y == 0) return;
uart_putc(27);
uart_putc('[');
uart_putu(y);
uart_putc('B');
uart_tx(27);
uart_tx('[');
put_u8(uart, y);
uart_tx('B');
}
void vt_left(uint8_t x)
{
if (x == 0) return;
uart_putc(27);
uart_putc('[');
uart_putu(x);
uart_putc('D');
uart_tx(27);
uart_tx('[');
put_u8(uart, x);
uart_tx('D');
}
void vt_right(uint8_t x)
{
if (x == 0) return;
uart_putc(27);
uart_putc('[');
uart_putu(x);
uart_putc('C');
uart_tx(27);
uart_tx('[');
put_u8(uart, x);
uart_tx('C');
}
void vt_scroll(int8_t y)
{
while (y < 0) {
uart_putc(27);
uart_putc('D'); // up
uart_tx(27);
uart_tx('D'); // up
y++;
}
while (y > 0) {
uart_putc(27);
uart_putc('M'); // down
uart_tx(27);
uart_tx('M'); // down
y--;
}
}
@ -127,20 +128,20 @@ void vt_scroll(int8_t y)
void vt_scroll_set(uint8_t from, uint8_t to)
{
uart_putc(27);
uart_putc('[');
uart_putu(from);
uart_putc(';');
uart_putu(to);
uart_putc('r');
uart_tx(27);
uart_tx('[');
put_u8(uart, from);
uart_tx(';');
put_u8(uart, to);
uart_tx('r');
}
void vt_scroll_reset()
{
uart_putc(27);
uart_putc('[');
uart_putc('r');
uart_tx(27);
uart_tx('[');
uart_tx('r');
}
@ -156,7 +157,7 @@ vt_style_t current_style;
void vt_save()
{
uart_puts_pgm(PSTR("\x1B[s"));
uart_puts_P(PSTR("\x1B[s"));
saved_style = current_style;
}
@ -164,7 +165,7 @@ void vt_save()
void vt_restore()
{
uart_puts_pgm(PSTR("\x1B[u"));
uart_puts_P(PSTR("\x1B[u"));
current_style = saved_style;
}
@ -246,7 +247,7 @@ void vt_color_bg(uint8_t bg)
/** Send reset command */
inline void _vt_reset_attribs_do()
{
uart_puts_pgm(PSTR("\x1B[m")); // reset
uart_puts_P(PSTR("\x1B[m")); // reset
}
@ -254,27 +255,27 @@ inline void _vt_reset_attribs_do()
void _vt_style_do()
{
if (current_style.flags & VT_BOLD) {
uart_puts_pgm(PSTR("\x1B[1m"));
uart_puts_P(PSTR("\x1B[1m"));
}
if (current_style.flags & VT_FAINT) {
uart_puts_pgm(PSTR("\x1B[2m"));
uart_puts_P(PSTR("\x1B[2m"));
}
if (current_style.flags & VT_ITALIC) {
uart_puts_pgm(PSTR("\x1B[3m"));
uart_puts_P(PSTR("\x1B[3m"));
}
if (current_style.flags & VT_UNDERLINE) {
uart_puts_pgm(PSTR("\x1B[4m"));
uart_puts_P(PSTR("\x1B[4m"));
}
if (current_style.flags & VT_BLINK) {
uart_puts_pgm(PSTR("\x1B[5m"));
uart_puts_P(PSTR("\x1B[5m"));
}
if (current_style.flags & VT_REVERSE) {
uart_puts_pgm(PSTR("\x1B[7m"));
uart_puts_P(PSTR("\x1B[7m"));
}
}
@ -282,93 +283,93 @@ void _vt_style_do()
/** Send commands for xolor */
void _vt_color_do()
{
uart_putc(27);
uart_putc('[');
uart_putu(30 + current_style.fg);
uart_putc(';');
uart_putu(40 + current_style.bg);
uart_putc('m');
uart_tx(27);
uart_tx('[');
put_u8(uart, 30 + current_style.fg);
uart_tx(';');
put_u8(uart, 40 + current_style.bg);
uart_tx('m');
}
/** Insert blank lines febore the current line */
void vt_insert_lines(uint8_t count)
{
uart_putc(27);
uart_putc('[');
uart_putu(count);
uart_putc('L');
uart_tx(27);
uart_tx('[');
put_u8(uart, count);
uart_tx('L');
}
/** Delete lines from the current line down */
void vt_delete_lines(uint8_t count)
{
uart_putc(27);
uart_putc('[');
uart_putu(count);
uart_putc('M');
uart_tx(27);
uart_tx('[');
put_u8(uart, count);
uart_tx('M');
}
/** Insert empty characters at cursor */
void vt_insert_chars(uint8_t count)
{
uart_putc(27);
uart_putc('[');
uart_putu(count);
uart_putc('@');
uart_tx(27);
uart_tx('[');
put_u8(uart, count);
uart_tx('@');
}
/** Delete characters at cursor */
void vt_delete_chars(uint8_t count)
{
uart_putc(27);
uart_putc('[');
uart_putu(count);
uart_putc('P');
uart_tx(27);
uart_tx('[');
put_u8(uart, count);
uart_tx('P');
}
void vt_clear()
{
uart_puts_pgm(PSTR("\x1B[2J"));
uart_puts_P(PSTR("\x1B[2J"));
}
void vt_erase_forth()
{
uart_puts_pgm(PSTR("\x1B[K"));
uart_puts_P(PSTR("\x1B[K"));
}
void vt_erase_back()
{
uart_puts_pgm(PSTR("\x1B[1K"));
uart_puts_P(PSTR("\x1B[1K"));
}
void vt_erase_line()
{
uart_puts_pgm(PSTR("\x1B[2K"));
uart_puts_P(PSTR("\x1B[2K"));
}
void vt_erase_above()
{
uart_puts_pgm(PSTR("\x1B[1J"));
uart_puts_P(PSTR("\x1B[1J"));
}
void vt_erase_below()
{
uart_puts_pgm(PSTR("\x1B[J"));
uart_puts_P(PSTR("\x1B[J"));
}
void vt_home()
{
uart_puts_pgm(PSTR("\x1B[H"));
uart_puts_P(PSTR("\x1B[H"));
}

Loading…
Cancel
Save