diff --git a/examples/Makefile b/examples/Makefile index ace5778..d861544 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -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 diff --git a/examples/lcd_test.c b/examples/lcd_test.c index 4e6aba3..f43a834 100644 --- a/examples/lcd_test.c +++ b/examples/lcd_test.c @@ -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!"); diff --git a/examples/sonar_simple.c b/examples/sonar_simple.c index fceff97..cb9db0e 100644 --- a/examples/sonar_simple.c +++ b/examples/sonar_simple.c @@ -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"); } diff --git a/examples/sonar_simple.lst b/examples/sonar_simple.lst new file mode 100644 index 0000000..ca0e966 --- /dev/null +++ b/examples/sonar_simple.lst @@ -0,0 +1,1351 @@ + +sonar_simple.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: 49 c0 rjmp .+146 ; 0xa0 <__vector_3> + e: 00 00 nop + 10: 47 c0 rjmp .+142 ; 0xa0 <__vector_3> + 12: 00 00 nop + 14: 45 c0 rjmp .+138 ; 0xa0 <__vector_3> + 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: 58 c0 rjmp .+176 ; 0xe6 <__vector_13> + 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: e2 e9 ldi r30, 0x92 ; 146 + 7c: f7 e0 ldi r31, 0x07 ; 7 + 7e: 02 c0 rjmp .+4 ; 0x84 <__do_copy_data+0x10> + 80: 05 90 lpm r0, Z+ + 82: 0d 92 st X+, r0 + 84: a6 31 cpi r26, 0x16 ; 22 + 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 e1 ldi r26, 0x16 ; 22 + 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: a5 33 cpi r26, 0x35 ; 53 + 96: b1 07 cpc r27, r17 + 98: e1 f7 brne .-8 ; 0x92 <.do_clear_bss_loop> + 9a: 48 d0 rcall .+144 ; 0x12c
+ 9c: 78 c3 rjmp .+1776 ; 0x78e <_exit> + +0000009e <__bad_interrupt>: + 9e: b0 cf rjmp .-160 ; 0x0 <__vectors> + +000000a0 <__vector_3>: + + + +// All PCINT vectors must call sonar_handle_pci +ISR(PCINT0_vect) +{ + a0: 1f 92 push r1 + a2: 0f 92 push r0 + a4: 0f b6 in r0, 0x3f ; 63 + a6: 0f 92 push r0 + a8: 11 24 eor r1, r1 + aa: 2f 93 push r18 + ac: 3f 93 push r19 + ae: 4f 93 push r20 + b0: 5f 93 push r21 + b2: 6f 93 push r22 + b4: 7f 93 push r23 + b6: 8f 93 push r24 + b8: 9f 93 push r25 + ba: af 93 push r26 + bc: bf 93 push r27 + be: ef 93 push r30 + c0: ff 93 push r31 + if (sonar_handle_pci()) return; + c2: 9b d1 rcall .+822 ; 0x3fa + c4: ff 91 pop r31 + + // Here you can do your other stuff +} + c6: ef 91 pop r30 + c8: bf 91 pop r27 + ca: af 91 pop r26 + cc: 9f 91 pop r25 + ce: 8f 91 pop r24 + d0: 7f 91 pop r23 + d2: 6f 91 pop r22 + d4: 5f 91 pop r21 + d6: 4f 91 pop r20 + d8: 3f 91 pop r19 + da: 2f 91 pop r18 + dc: 0f 90 pop r0 + de: 0f be out 0x3f, r0 ; 63 + e0: 0f 90 pop r0 + e2: 1f 90 pop r1 + e4: 18 95 reti + +000000e6 <__vector_13>: + + + +// Timer overflow - if sonar has a timeout -> 0xFFFF in result. +ISR(TIMER1_OVF_vect) +{ + e6: 1f 92 push r1 + e8: 0f 92 push r0 + ea: 0f b6 in r0, 0x3f ; 63 + ec: 0f 92 push r0 + ee: 11 24 eor r1, r1 + f0: 2f 93 push r18 + f2: 3f 93 push r19 + f4: 4f 93 push r20 + f6: 5f 93 push r21 + f8: 6f 93 push r22 + fa: 7f 93 push r23 + fc: 8f 93 push r24 + fe: 9f 93 push r25 + 100: af 93 push r26 + 102: bf 93 push r27 + 104: ef 93 push r30 + 106: ff 93 push r31 + if (sonar_handle_t1ovf()) return; + 108: 62 d1 rcall .+708 ; 0x3ce + 10a: ff 91 pop r31 + + // ... +} + 10c: ef 91 pop r30 + 10e: bf 91 pop r27 + 110: af 91 pop r26 + 112: 9f 91 pop r25 + 114: 8f 91 pop r24 + 116: 7f 91 pop r23 + 118: 6f 91 pop r22 + 11a: 5f 91 pop r21 + 11c: 4f 91 pop r20 + 11e: 3f 91 pop r19 + 120: 2f 91 pop r18 + 122: 0f 90 pop r0 + 124: 0f be out 0x3f, r0 ; 63 + 126: 0f 90 pop r0 + 128: 1f 90 pop r1 + 12a: 18 95 reti + +0000012c
: + + + + +void main() +{ + 12c: cf 93 push r28 + 12e: df 93 push r29 + 130: cd b7 in r28, 0x3d ; 61 + 132: de b7 in r29, 0x3e ; 62 + 134: 27 97 sbiw r28, 0x07 ; 7 + 136: 0f b6 in r0, 0x3f ; 63 + 138: f8 94 cli + 13a: de bf out 0x3e, r29 ; 62 + 13c: 0f be out 0x3f, r0 ; 63 + 13e: cd bf out 0x3d, r28 ; 61 + // Init UART communication + uart_init(9600); + 140: 87 e6 ldi r24, 0x67 ; 103 + 142: 90 e0 ldi r25, 0x00 ; 0 + 144: 3e d0 rcall .+124 ; 0x1c2 <_uart_init_do> + 146: 38 9a sbi 0x07, 0 ; 7 + + // Create and init Sonar instance + sonar_t so; + + // Args: pointer to your sonar_t, and 2 pin aliases - Trig & Echo + sonar_init(&so, A0, A1); + 148: 39 98 cbi 0x07, 1 ; 7 + 14a: 41 9a sbi 0x08, 1 ; 8 + 14c: 01 e0 ldi r16, 0x01 ; 1 + 14e: 26 e2 ldi r18, 0x26 ; 38 + 150: 30 e0 ldi r19, 0x00 ; 0 + 152: 40 e0 ldi r20, 0x00 ; 0 + 154: 68 e2 ldi r22, 0x28 ; 40 + 156: 70 e0 ldi r23, 0x00 ; 0 + 158: ce 01 movw r24, r28 + 15a: 01 96 adiw r24, 0x01 ; 1 + 15c: 56 d0 rcall .+172 ; 0x20a <_sonar_init_do> + 15e: 78 94 sei + 160: ce 01 movw r24, r28 + + // You can have more than one sonar connected, but only one can measure at a time + + + // Allow interrupts + sei(); + 162: 01 96 adiw r24, 0x01 ; 1 + + + while(1) { + + // Measure + sonar_start(&so); + 164: 6b d0 rcall .+214 ; 0x23c + 166: 80 91 32 01 lds r24, 0x0132 + 16a: 81 11 cpse r24, r1 + + while(sonar_busy) { + 16c: fe cf rjmp .-4 ; 0x16a + 16e: 60 91 30 01 lds r22, 0x0130 + 172: 70 91 31 01 lds r23, 0x0131 + // Sonar is asynchronous + // Here we just wait for it to complete + } + + int16_t res = sonar_result; + 176: 77 ff sbrs r23, 7 + 178: 03 c0 rjmp .+6 ; 0x180 + 17a: 80 e0 ldi r24, 0x00 ; 0 + + + + // Print + if (res < 0) { + 17c: 91 e0 ldi r25, 0x01 ; 1 + 17e: 08 c0 rjmp .+16 ; 0x190 + uart_puts("NO OBSTACLES\r\n"); + 180: 41 e0 ldi r20, 0x01 ; 1 + 182: 80 91 2e 01 lds r24, 0x012E + } else { + put_i16f(uart, res, 1); // one decimal place + 186: 90 91 2f 01 lds r25, 0x012F + 18a: ec d1 rcall .+984 ; 0x564 + 18c: 8f e0 ldi r24, 0x0F ; 15 + 18e: 91 e0 ldi r25, 0x01 ; 1 + 190: 31 d0 rcall .+98 ; 0x1f4 + 192: 2f ef ldi r18, 0xFF ; 255 + 194: 89 e6 ldi r24, 0x69 ; 105 + 196: 98 e1 ldi r25, 0x18 ; 24 + 198: 21 50 subi r18, 0x01 ; 1 + 19a: 80 40 sbci r24, 0x00 ; 0 + #else + //round up by default + __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); + #endif + + __builtin_avr_delay_cycles(__ticks_dc); + 19c: 90 40 sbci r25, 0x00 ; 0 + 19e: e1 f7 brne .-8 ; 0x198 + 1a0: 00 c0 rjmp .+0 ; 0x1a2 + 1a2: 00 00 nop + 1a4: dd cf rjmp .-70 ; 0x160 + +000001a6 : + +/** Send byte over UART */ +void uart_tx(uint8_t data) +{ + // Wait for transmit buffer + while (!uart_tx_ready()); + 1a6: 90 91 c0 00 lds r25, 0x00C0 + 1aa: 95 ff sbrs r25, 5 + 1ac: fc cf rjmp .-8 ; 0x1a6 + // send it + UDR0 = data; + 1ae: 80 93 c6 00 sts 0x00C6, r24 + 1b2: 08 95 ret + +000001b4 : + +/** Receive one byte over UART */ +uint8_t uart_rx() +{ + // Wait for data to be received + while (!uart_rx_ready()); + 1b4: 80 91 c0 00 lds r24, 0x00C0 + 1b8: 87 ff sbrs r24, 7 + 1ba: fc cf rjmp .-8 ; 0x1b4 + // Get and return received data from buffer + return UDR0; + 1bc: 80 91 c6 00 lds r24, 0x00C6 +} + 1c0: 08 95 ret + +000001c2 <_uart_init_do>: +STREAM* uart; + + +void _uart_init_do(uint16_t ubrr) { + /*Set baud rate */ + UBRR0H = (uint8_t) (ubrr >> 8); + 1c2: 90 93 c5 00 sts 0x00C5, r25 + UBRR0L = (uint8_t) ubrr; + 1c6: 80 93 c4 00 sts 0x00C4, r24 + + // Enable Rx and Tx + UCSR0B = (1 << RXEN0) | (1 << TXEN0); + 1ca: 88 e1 ldi r24, 0x18 ; 24 + 1cc: 80 93 c1 00 sts 0x00C1, r24 + + // 8-bit data, 1 stop bit + UCSR0C = (0b11 << UCSZ00); + 1d0: 86 e0 ldi r24, 0x06 ; 6 + 1d2: 80 93 c2 00 sts 0x00C2, r24 + + uart_singleton.tx = &uart_tx; + 1d6: ea e2 ldi r30, 0x2A ; 42 + 1d8: f1 e0 ldi r31, 0x01 ; 1 + 1da: 83 ed ldi r24, 0xD3 ; 211 + 1dc: 90 e0 ldi r25, 0x00 ; 0 + 1de: 91 83 std Z+1, r25 ; 0x01 + 1e0: 80 83 st Z, r24 + uart_singleton.rx = &uart_rx; + 1e2: 8a ed ldi r24, 0xDA ; 218 + 1e4: 90 e0 ldi r25, 0x00 ; 0 + 1e6: 93 83 std Z+3, r25 ; 0x03 + 1e8: 82 83 std Z+2, r24 ; 0x02 + + uart = &uart_singleton; + 1ea: f0 93 2f 01 sts 0x012F, r31 + 1ee: e0 93 2e 01 sts 0x012E, r30 + 1f2: 08 95 ret + +000001f4 : +} + + +/** Send string over UART */ +void uart_puts(const char* str) +{ + 1f4: cf 93 push r28 + 1f6: df 93 push r29 + 1f8: ec 01 movw r28, r24 + while (*str) { + 1fa: 89 91 ld r24, Y+ + 1fc: 88 23 and r24, r24 + 1fe: 11 f0 breq .+4 ; 0x204 + uart_tx(*str++); + 200: d2 df rcall .-92 ; 0x1a6 + 202: fb cf rjmp .-10 ; 0x1fa + 204: df 91 pop r29 + } +} + 206: cf 91 pop r28 + 208: 08 95 ret + +0000020a <_sonar_init_do>: +// Result of last measurement, in millimeters +int16_t sonar_result; + + +void _sonar_init_do(sonar_t* so, PORT_P port, uint8_t ntx, PORT_P pin, uint8_t nrx) +{ + 20a: 0f 93 push r16 + 20c: fc 01 movw r30, r24 + so->port = port; + 20e: 71 83 std Z+1, r23 ; 0x01 + 210: 60 83 st Z, r22 + so->ntx = ntx; + 212: 42 83 std Z+2, r20 ; 0x02 + so->pin = pin; + 214: 34 83 std Z+4, r19 ; 0x04 + 216: 23 83 std Z+3, r18 ; 0x03 + so->nrx = nrx; + 218: 05 83 std Z+5, r16 ; 0x05 + + switch((const uint16_t) pin) { + 21a: 26 32 cpi r18, 0x26 ; 38 + 21c: 31 05 cpc r19, r1 + 21e: 41 f0 breq .+16 ; 0x230 <_sonar_init_do+0x26> + 220: 29 32 cpi r18, 0x29 ; 41 + 222: 31 05 cpc r19, r1 + 224: 39 f0 breq .+14 ; 0x234 <_sonar_init_do+0x2a> + 226: 23 32 cpi r18, 0x23 ; 35 + 228: 31 05 cpc r19, r1 + 22a: 31 f4 brne .+12 ; 0x238 <_sonar_init_do+0x2e> + case (const uint16_t)&PINB: + so->bank = 0; + 22c: 16 82 std Z+6, r1 ; 0x06 + break; + 22e: 04 c0 rjmp .+8 ; 0x238 <_sonar_init_do+0x2e> + case (const uint16_t)&PINC: + so->bank = 1; + 230: 81 e0 ldi r24, 0x01 ; 1 + 232: 01 c0 rjmp .+2 ; 0x236 <_sonar_init_do+0x2c> + break; + case (const uint16_t)&PIND: + so->bank = 2; + 234: 82 e0 ldi r24, 0x02 ; 2 + 236: 86 83 std Z+6, r24 ; 0x06 + break; + } +} + 238: 0f 91 pop r16 + 23a: 08 95 ret + +0000023c : + * Interrupts must be enabled + * TIMER 1 will be used for the async measurement + * Timer 1 overflow and Pin Change interrupts must invoke Sonar handlers. + */ +bool sonar_start(sonar_t* so) +{ + 23c: fc 01 movw r30, r24 + if (sonar_busy) return false; + 23e: 80 91 32 01 lds r24, 0x0132 + 242: 81 11 cpse r24, r1 + 244: 82 c0 rjmp .+260 ; 0x34a + + _sonar_active_so = so; + 246: f0 93 34 01 sts 0x0134, r31 + 24a: e0 93 33 01 sts 0x0133, r30 + + sonar_busy = true; + 24e: 81 e0 ldi r24, 0x01 ; 1 + 250: 80 93 32 01 sts 0x0132, r24 + + // make sure the timer is stopped (set clock to NONE) + TCCR1B = 0; + 254: 10 92 81 00 sts 0x0081, r1 + + // Timer overflow interrupt enable + // We'll stop measuring on overflow + TIMSK1 |= (1 << TOIE1); + 258: 80 91 6f 00 lds r24, 0x006F + 25c: 81 60 ori r24, 0x01 ; 1 + 25e: 80 93 6f 00 sts 0x006F, r24 + + // Clear the timer value + TCNT1 = 0; + 262: 10 92 85 00 sts 0x0085, r1 + 266: 10 92 84 00 sts 0x0084, r1 + + // Set up pin change interrupt mask for the RX pin + switch(so->bank) { + 26a: 86 81 ldd r24, Z+6 ; 0x06 + 26c: 81 30 cpi r24, 0x01 ; 1 + 26e: f9 f0 breq .+62 ; 0x2ae + 270: 80 f0 brcs .+32 ; 0x292 + 272: 82 30 cpi r24, 0x02 ; 2 + 274: 49 f5 brne .+82 ; 0x2c8 + break; + case 1: + PCMSK1 |= (1 << (so->nrx)); + break; + case 2: + PCMSK2 |= (1 << (so->nrx)); + 276: 20 91 6d 00 lds r18, 0x006D + 27a: 81 e0 ldi r24, 0x01 ; 1 + 27c: 90 e0 ldi r25, 0x00 ; 0 + 27e: 05 80 ldd r0, Z+5 ; 0x05 + 280: 02 c0 rjmp .+4 ; 0x286 + 282: 88 0f add r24, r24 + 284: 99 1f adc r25, r25 + 286: 0a 94 dec r0 + 288: e2 f7 brpl .-8 ; 0x282 + 28a: 82 2b or r24, r18 + 28c: 80 93 6d 00 sts 0x006D, r24 + break; + 290: 1b c0 rjmp .+54 ; 0x2c8 + TCNT1 = 0; + + // Set up pin change interrupt mask for the RX pin + switch(so->bank) { + case 0: + PCMSK0 |= (1 << (so->nrx)); + 292: 20 91 6b 00 lds r18, 0x006B + 296: 81 e0 ldi r24, 0x01 ; 1 + 298: 90 e0 ldi r25, 0x00 ; 0 + 29a: 05 80 ldd r0, Z+5 ; 0x05 + 29c: 02 c0 rjmp .+4 ; 0x2a2 + 29e: 88 0f add r24, r24 + 2a0: 99 1f adc r25, r25 + 2a2: 0a 94 dec r0 + 2a4: e2 f7 brpl .-8 ; 0x29e + 2a6: 82 2b or r24, r18 + 2a8: 80 93 6b 00 sts 0x006B, r24 + break; + 2ac: 0d c0 rjmp .+26 ; 0x2c8 + case 1: + PCMSK1 |= (1 << (so->nrx)); + 2ae: 20 91 6c 00 lds r18, 0x006C + 2b2: 81 e0 ldi r24, 0x01 ; 1 + 2b4: 90 e0 ldi r25, 0x00 ; 0 + 2b6: 05 80 ldd r0, Z+5 ; 0x05 + 2b8: 02 c0 rjmp .+4 ; 0x2be + 2ba: 88 0f add r24, r24 + 2bc: 99 1f adc r25, r25 + 2be: 0a 94 dec r0 + 2c0: e2 f7 brpl .-8 ; 0x2ba + 2c2: 82 2b or r24, r18 + 2c4: 80 93 6c 00 sts 0x006C, r24 + PCMSK2 |= (1 << (so->nrx)); + break; + } + + // send positive pulse + *(so->port) |= (1 << so->ntx); + 2c8: a0 81 ld r26, Z + 2ca: b1 81 ldd r27, Z+1 ; 0x01 + 2cc: 4c 91 ld r20, X + 2ce: 81 e0 ldi r24, 0x01 ; 1 + 2d0: 90 e0 ldi r25, 0x00 ; 0 + 2d2: 9c 01 movw r18, r24 + 2d4: 02 80 ldd r0, Z+2 ; 0x02 + 2d6: 02 c0 rjmp .+4 ; 0x2dc + 2d8: 22 0f add r18, r18 + 2da: 33 1f adc r19, r19 + 2dc: 0a 94 dec r0 + 2de: e2 f7 brpl .-8 ; 0x2d8 + 2e0: 24 2b or r18, r20 + 2e2: 2c 93 st X, r18 + #else + //round up by default + __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); + #endif + + __builtin_avr_delay_cycles(__ticks_dc); + 2e4: 25 e3 ldi r18, 0x35 ; 53 + 2e6: 2a 95 dec r18 + 2e8: f1 f7 brne .-4 ; 0x2e6 + 2ea: 00 00 nop + _delay_us(_SNR_TRIG_TIME); + *(so->port) &= ~(1 << so->ntx); + 2ec: a0 81 ld r26, Z + 2ee: b1 81 ldd r27, Z+1 ; 0x01 + 2f0: 3c 91 ld r19, X + 2f2: ac 01 movw r20, r24 + 2f4: 02 80 ldd r0, Z+2 ; 0x02 + 2f6: 02 c0 rjmp .+4 ; 0x2fc + 2f8: 44 0f add r20, r20 + 2fa: 55 1f adc r21, r21 + 2fc: 0a 94 dec r0 + 2fe: e2 f7 brpl .-8 ; 0x2f8 + 300: 24 2f mov r18, r20 + 302: 20 95 com r18 + 304: 23 23 and r18, r19 + 306: 2c 93 st X, r18 + + // Wait for start of response + while ( (*(so->pin) & (1 << so->nrx)) == 0 ); + 308: a3 81 ldd r26, Z+3 ; 0x03 + 30a: b4 81 ldd r27, Z+4 ; 0x04 + 30c: 9c 01 movw r18, r24 + 30e: 05 80 ldd r0, Z+5 ; 0x05 + 310: 02 c0 rjmp .+4 ; 0x316 + 312: 22 0f add r18, r18 + 314: 33 1f adc r19, r19 + 316: 0a 94 dec r0 + 318: e2 f7 brpl .-8 ; 0x312 + 31a: 8c 91 ld r24, X + 31c: 90 e0 ldi r25, 0x00 ; 0 + 31e: 82 23 and r24, r18 + 320: 93 23 and r25, r19 + 322: 89 2b or r24, r25 + 324: d1 f3 breq .-12 ; 0x31a + + // Set timer clock source: F_CPU / 8 (0.5 us resolution) + TCCR1B = (0b010 << CS10); + 326: 82 e0 ldi r24, 0x02 ; 2 + 328: 80 93 81 00 sts 0x0081, r24 + + // Enable pin change interrupt + PCICR |= (1 << (so->bank)); + 32c: 20 91 68 00 lds r18, 0x0068 + 330: 81 e0 ldi r24, 0x01 ; 1 + 332: 90 e0 ldi r25, 0x00 ; 0 + 334: 06 80 ldd r0, Z+6 ; 0x06 + 336: 02 c0 rjmp .+4 ; 0x33c + 338: 88 0f add r24, r24 + 33a: 99 1f adc r25, r25 + 33c: 0a 94 dec r0 + 33e: e2 f7 brpl .-8 ; 0x338 + 340: 82 2b or r24, r18 + 342: 80 93 68 00 sts 0x0068, r24 + + return true; + 346: 81 e0 ldi r24, 0x01 ; 1 + 348: 08 95 ret + * TIMER 1 will be used for the async measurement + * Timer 1 overflow and Pin Change interrupts must invoke Sonar handlers. + */ +bool sonar_start(sonar_t* so) +{ + if (sonar_busy) return false; + 34a: 80 e0 ldi r24, 0x00 ; 0 + + // Enable pin change interrupt + PCICR |= (1 << (so->bank)); + + return true; +} + 34c: 08 95 ret + +0000034e <_sonar_stop>: + +/** Stop the timer */ +void _sonar_stop() +{ + // stop timer + TCCR1B = 0; + 34e: 10 92 81 00 sts 0x0081, r1 + + // Disable RX pin interrupt mask + switch(_sonar_active_so->bank) { + 352: e0 91 33 01 lds r30, 0x0133 + 356: f0 91 34 01 lds r31, 0x0134 + 35a: 86 81 ldd r24, Z+6 ; 0x06 + 35c: 81 30 cpi r24, 0x01 ; 1 + 35e: 09 f1 breq .+66 ; 0x3a2 <_sonar_stop+0x54> + 360: 88 f0 brcs .+34 ; 0x384 <_sonar_stop+0x36> + 362: 82 30 cpi r24, 0x02 ; 2 + 364: 61 f5 brne .+88 ; 0x3be <_sonar_stop+0x70> + break; + case 1: + PCMSK1 &= ~(1 << (_sonar_active_so->nrx)); + break; + case 2: + PCMSK2 &= ~(1 << (_sonar_active_so->nrx)); + 366: 20 91 6d 00 lds r18, 0x006D + 36a: 81 e0 ldi r24, 0x01 ; 1 + 36c: 90 e0 ldi r25, 0x00 ; 0 + 36e: 05 80 ldd r0, Z+5 ; 0x05 + 370: 02 c0 rjmp .+4 ; 0x376 <_sonar_stop+0x28> + 372: 88 0f add r24, r24 + 374: 99 1f adc r25, r25 + 376: 0a 94 dec r0 + 378: e2 f7 brpl .-8 ; 0x372 <_sonar_stop+0x24> + 37a: 80 95 com r24 + 37c: 82 23 and r24, r18 + 37e: 80 93 6d 00 sts 0x006D, r24 + break; + 382: 1d c0 rjmp .+58 ; 0x3be <_sonar_stop+0x70> + TCCR1B = 0; + + // Disable RX pin interrupt mask + switch(_sonar_active_so->bank) { + case 0: + PCMSK0 &= ~(1 << (_sonar_active_so->nrx)); + 384: 20 91 6b 00 lds r18, 0x006B + 388: 81 e0 ldi r24, 0x01 ; 1 + 38a: 90 e0 ldi r25, 0x00 ; 0 + 38c: 05 80 ldd r0, Z+5 ; 0x05 + 38e: 02 c0 rjmp .+4 ; 0x394 <_sonar_stop+0x46> + 390: 88 0f add r24, r24 + 392: 99 1f adc r25, r25 + 394: 0a 94 dec r0 + 396: e2 f7 brpl .-8 ; 0x390 <_sonar_stop+0x42> + 398: 80 95 com r24 + 39a: 82 23 and r24, r18 + 39c: 80 93 6b 00 sts 0x006B, r24 + break; + 3a0: 0e c0 rjmp .+28 ; 0x3be <_sonar_stop+0x70> + case 1: + PCMSK1 &= ~(1 << (_sonar_active_so->nrx)); + 3a2: 20 91 6c 00 lds r18, 0x006C + 3a6: 81 e0 ldi r24, 0x01 ; 1 + 3a8: 90 e0 ldi r25, 0x00 ; 0 + 3aa: 05 80 ldd r0, Z+5 ; 0x05 + 3ac: 02 c0 rjmp .+4 ; 0x3b2 <_sonar_stop+0x64> + 3ae: 88 0f add r24, r24 + 3b0: 99 1f adc r25, r25 + 3b2: 0a 94 dec r0 + 3b4: e2 f7 brpl .-8 ; 0x3ae <_sonar_stop+0x60> + 3b6: 80 95 com r24 + 3b8: 82 23 and r24, r18 + 3ba: 80 93 6c 00 sts 0x006C, r24 + PCMSK2 &= ~(1 << (_sonar_active_so->nrx)); + break; + } + + // Disable timer1 overflow interrupt + TIMSK1 &= ~(1 << TOIE1); + 3be: 80 91 6f 00 lds r24, 0x006F + 3c2: 8e 7f andi r24, 0xFE ; 254 + 3c4: 80 93 6f 00 sts 0x006F, r24 + + sonar_busy = false; + 3c8: 10 92 32 01 sts 0x0132, r1 + 3cc: 08 95 ret + +000003ce : +} + + +/** Handle TIMER1_OVF (returns true if consumed) */ +inline bool sonar_handle_t1ovf() +{ + 3ce: cf 93 push r28 + 3d0: df 93 push r29 + 3d2: 1f 92 push r1 + 3d4: cd b7 in r28, 0x3d ; 61 + 3d6: de b7 in r29, 0x3e ; 62 + if (!sonar_busy) return false; // nothing + 3d8: 80 91 32 01 lds r24, 0x0132 + 3dc: 88 23 and r24, r24 + 3de: 49 f0 breq .+18 ; 0x3f2 + + sonar_result = -1; + 3e0: 2f ef ldi r18, 0xFF ; 255 + 3e2: 3f ef ldi r19, 0xFF ; 255 + 3e4: 30 93 31 01 sts 0x0131, r19 + 3e8: 20 93 30 01 sts 0x0130, r18 + _sonar_stop(); + 3ec: 89 83 std Y+1, r24 ; 0x01 + 3ee: af df rcall .-162 ; 0x34e <_sonar_stop> + 3f0: 89 81 ldd r24, Y+1 ; 0x01 + 3f2: 0f 90 pop r0 + + return true; +} + 3f4: df 91 pop r29 + 3f6: cf 91 pop r28 + 3f8: 08 95 ret + +000003fa : + + +/** Handle pin change interrupt (returns true if consumed) */ +inline bool sonar_handle_pci() +{ + 3fa: af 92 push r10 + 3fc: bf 92 push r11 + 3fe: cf 92 push r12 + 400: df 92 push r13 + 402: ef 92 push r14 + 404: ff 92 push r15 + 406: 0f 93 push r16 + 408: 1f 93 push r17 + 40a: cf 93 push r28 + if (!sonar_busy) { + 40c: c0 91 32 01 lds r28, 0x0132 + 410: cc 23 and r28, r28 + 412: 09 f4 brne .+2 ; 0x416 + 414: 4e c0 rjmp .+156 ; 0x4b2 + return false; // nothing + } + + if (*(_sonar_active_so->pin) & (1 << _sonar_active_so->nrx)) { + 416: e0 91 33 01 lds r30, 0x0133 + 41a: f0 91 34 01 lds r31, 0x0134 + 41e: a3 81 ldd r26, Z+3 ; 0x03 + 420: b4 81 ldd r27, Z+4 ; 0x04 + 422: 2c 91 ld r18, X + 424: 30 e0 ldi r19, 0x00 ; 0 + 426: 05 80 ldd r0, Z+5 ; 0x05 + 428: 02 c0 rjmp .+4 ; 0x42e + 42a: 35 95 asr r19 + 42c: 27 95 ror r18 + 42e: 0a 94 dec r0 + 430: e2 f7 brpl .-8 ; 0x42a + 432: 20 fd sbrc r18, 0 + 434: 3d c0 rjmp .+122 ; 0x4b0 + // rx is high, not our pin change event + return false; + } + + uint64_t x = TCNT1; + 436: 40 91 84 00 lds r20, 0x0084 + 43a: 50 91 85 00 lds r21, 0x0085 + x /= _SNR_DIV_CONST; + 43e: 8a e3 ldi r24, 0x3A ; 58 + 440: a8 2e mov r10, r24 + 442: b1 2c mov r11, r1 + 444: c1 2c mov r12, r1 + 446: d1 2c mov r13, r1 + 448: e1 2c mov r14, r1 + 44a: f1 2c mov r15, r1 + 44c: 00 e0 ldi r16, 0x00 ; 0 + 44e: 10 e0 ldi r17, 0x00 ; 0 + 450: 9a 01 movw r18, r20 + 452: 40 e0 ldi r20, 0x00 ; 0 + 454: 50 e0 ldi r21, 0x00 ; 0 + 456: 60 e0 ldi r22, 0x00 ; 0 + 458: 70 e0 ldi r23, 0x00 ; 0 + 45a: 80 e0 ldi r24, 0x00 ; 0 + 45c: 90 e0 ldi r25, 0x00 ; 0 + 45e: a8 d0 rcall .+336 ; 0x5b0 <__udivdi3> + 460: a1 2c mov r10, r1 + x *= 100000000L; + 462: e1 ee ldi r30, 0xE1 ; 225 + 464: be 2e mov r11, r30 + 466: f5 ef ldi r31, 0xF5 ; 245 + 468: cf 2e mov r12, r31 + 46a: a5 e0 ldi r26, 0x05 ; 5 + 46c: da 2e mov r13, r26 + 46e: ab d0 rcall .+342 ; 0x5c6 <__muldi3> + 470: b4 e2 ldi r27, 0x24 ; 36 + 472: bb 2e mov r11, r27 + x /= F_CPU; + 474: e4 ef ldi r30, 0xF4 ; 244 + 476: ce 2e mov r12, r30 + 478: d1 2c mov r13, r1 + 47a: 9a d0 rcall .+308 ; 0x5b0 <__udivdi3> + 47c: f2 2f mov r31, r18 + 47e: e3 2f mov r30, r19 + 480: 20 3a cpi r18, 0xA0 ; 160 + 482: 3f 40 sbci r19, 0x0F ; 15 + 484: 41 05 cpc r20, r1 + sonar_result = (int16_t) x; + + // no obstacle + if (sonar_result > _SNR_MAX_DIST) sonar_result = -1; + 486: 51 05 cpc r21, r1 + 488: 61 05 cpc r22, r1 + 48a: 71 05 cpc r23, r1 + 48c: 81 05 cpc r24, r1 + 48e: 91 05 cpc r25, r1 + 490: 09 f0 breq .+2 ; 0x494 + 492: 30 f4 brcc .+12 ; 0x4a0 + 494: cf 01 movw r24, r30 + 496: 90 93 30 01 sts 0x0130, r25 + + uint64_t x = TCNT1; + x /= _SNR_DIV_CONST; + x *= 100000000L; + x /= F_CPU; + sonar_result = (int16_t) x; + 49a: 80 93 31 01 sts 0x0131, r24 + 49e: 06 c0 rjmp .+12 ; 0x4ac + 4a0: 8f ef ldi r24, 0xFF ; 255 + 4a2: 9f ef ldi r25, 0xFF ; 255 + 4a4: 90 93 31 01 sts 0x0131, r25 + + // no obstacle + if (sonar_result > _SNR_MAX_DIST) sonar_result = -1; + 4a8: 80 93 30 01 sts 0x0130, r24 + 4ac: 50 df rcall .-352 ; 0x34e <_sonar_stop> + 4ae: 01 c0 rjmp .+2 ; 0x4b2 + 4b0: c0 e0 ldi r28, 0x00 ; 0 + + _sonar_stop(); + 4b2: 8c 2f mov r24, r28 + 4b4: cf 91 pop r28 + + return true; + 4b6: 1f 91 pop r17 + +/** Handle pin change interrupt (returns true if consumed) */ +inline bool sonar_handle_pci() +{ + if (!sonar_busy) { + return false; // nothing + 4b8: 0f 91 pop r16 + if (sonar_result > _SNR_MAX_DIST) sonar_result = -1; + + _sonar_stop(); + + return true; +} + 4ba: ff 90 pop r15 + 4bc: ef 90 pop r14 + 4be: df 90 pop r13 + 4c0: cf 90 pop r12 + 4c2: bf 90 pop r11 + 4c4: af 90 pop r10 + 4c6: 08 95 ret + +000004c8 <_putnf.isra.0>: + _putnf(p, places); +} + + +/** Print number in tmp string as float with given decimal point position */ +void _putnf(const STREAM *p, const uint8_t places) + 4c8: cf 92 push r12 + 4ca: df 92 push r13 + 4cc: ef 92 push r14 + 4ce: ff 92 push r15 + 4d0: 0f 93 push r16 + 4d2: 1f 93 push r17 + 4d4: cf 93 push r28 + 4d6: df 93 push r29 + 4d8: 8c 01 movw r16, r24 +{ + // measure text length + uint8_t len = 0; + 4da: d0 e0 ldi r29, 0x00 ; 0 + while(tmpstr[len] != 0) len++; + 4dc: ed 2f mov r30, r29 + 4de: f0 e0 ldi r31, 0x00 ; 0 + 4e0: ea 5e subi r30, 0xEA ; 234 + 4e2: fe 4f sbci r31, 0xFE ; 254 + 4e4: 80 81 ld r24, Z + 4e6: 88 23 and r24, r24 + 4e8: 11 f0 breq .+4 ; 0x4ee <_putnf.isra.0+0x26> + 4ea: df 5f subi r29, 0xFF ; 255 + 4ec: f7 cf rjmp .-18 ; 0x4dc <_putnf.isra.0+0x14> + + int8_t at = len - places; + 4ee: cd 2f mov r28, r29 + 4f0: c6 1b sub r28, r22 + + // print virtual zeros + if (at <= 0) { + 4f2: 1c 16 cp r1, r28 + 4f4: a4 f0 brlt .+40 ; 0x51e <_putnf.isra.0+0x56> + p->tx('0'); + 4f6: d8 01 movw r26, r16 + 4f8: ed 91 ld r30, X+ + 4fa: fc 91 ld r31, X + 4fc: 80 e3 ldi r24, 0x30 ; 48 + 4fe: 09 95 icall + p->tx('.'); + 500: d8 01 movw r26, r16 + 502: ed 91 ld r30, X+ + 504: fc 91 ld r31, X + 506: 8e e2 ldi r24, 0x2E ; 46 + 508: 09 95 icall + while(at <= -1) { + 50a: cc 23 and r28, r28 + 50c: 39 f0 breq .+14 ; 0x51c <_putnf.isra.0+0x54> + p->tx('0'); + 50e: d8 01 movw r26, r16 + 510: ed 91 ld r30, X+ + 512: fc 91 ld r31, X + 514: 80 e3 ldi r24, 0x30 ; 48 + 516: 09 95 icall + 518: cf 5f subi r28, 0xFF ; 255 + 51a: f7 cf rjmp .-18 ; 0x50a <_putnf.isra.0+0x42> + at++; + } + at = -1; + 51c: cf ef ldi r28, 0xFF ; 255 + 51e: 86 e1 ldi r24, 0x16 ; 22 + 520: c8 2e mov r12, r24 + 522: 81 e0 ldi r24, 0x01 ; 1 + 524: d8 2e mov r13, r24 + 526: 76 01 movw r14, r12 + 528: cc 0d add r28, r12 + 52a: 9e 2d mov r25, r14 + 52c: 8e 2d mov r24, r14 + 52e: 8c 19 sub r24, r12 + } + + // print the number + uint8_t i = 0; + while(i < len) { + 530: 8d 17 cp r24, r29 + 532: 78 f4 brcc .+30 ; 0x552 <_putnf.isra.0+0x8a> + if (at-- == 0) { + 534: c9 13 cpse r28, r25 + 536: 05 c0 rjmp .+10 ; 0x542 <_putnf.isra.0+0x7a> + p->tx('.'); + 538: d8 01 movw r26, r16 + 53a: ed 91 ld r30, X+ + 53c: fc 91 ld r31, X + 53e: 8e e2 ldi r24, 0x2E ; 46 + 540: 09 95 icall + } + + p->tx(tmpstr[i++]); + 542: d8 01 movw r26, r16 + 544: ed 91 ld r30, X+ + 546: fc 91 ld r31, X + 548: d7 01 movw r26, r14 + 54a: 8d 91 ld r24, X+ + 54c: 7d 01 movw r14, r26 + 54e: 09 95 icall + 550: ec cf rjmp .-40 ; 0x52a <_putnf.isra.0+0x62> + } +} + 552: df 91 pop r29 + 554: cf 91 pop r28 + 556: 1f 91 pop r17 + 558: 0f 91 pop r16 + 55a: ff 90 pop r15 + 55c: ef 90 pop r14 + 55e: df 90 pop r13 + 560: cf 90 pop r12 + 562: 08 95 ret + +00000564 : +} + + +/** Send signed int as float */ +void put_i16f(const STREAM *p, const int16_t num, const uint8_t places) +{ + 564: ff 92 push r15 + 566: 0f 93 push r16 + 568: 1f 93 push r17 + 56a: cf 93 push r28 + 56c: df 93 push r29 + 56e: 8c 01 movw r16, r24 + 570: eb 01 movw r28, r22 + 572: f4 2e mov r15, r20 + if (num < 0) { + 574: 77 ff sbrs r23, 7 + 576: 0d c0 rjmp .+26 ; 0x592 + p->tx('-'); + 578: dc 01 movw r26, r24 + 57a: ed 91 ld r30, X+ + 57c: fc 91 ld r31, X + 57e: 8d e2 ldi r24, 0x2D ; 45 + 580: 09 95 icall + } 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); + 582: 4a e0 ldi r20, 0x0A ; 10 + 584: 66 e1 ldi r22, 0x16 ; 22 + 586: 71 e0 ldi r23, 0x01 ; 1 + 588: 88 27 eor r24, r24 + 58a: 99 27 eor r25, r25 + 58c: 8c 1b sub r24, r28 + 58e: 9d 0b sbc r25, r29 + 590: 04 c0 rjmp .+8 ; 0x59a + 592: 4a e0 ldi r20, 0x0A ; 10 + 594: 66 e1 ldi r22, 0x16 ; 22 + 596: 71 e0 ldi r23, 0x01 ; 1 + 598: ce 01 movw r24, r28 + 59a: c6 d0 rcall .+396 ; 0x728 <__itoa_ncheck> + 59c: 6f 2d mov r22, r15 + itoa(-num, tmpstr, 10); + } else { + itoa(num, tmpstr, 10); + } + + _putnf(p, places); + 59e: c8 01 movw r24, r16 + 5a0: df 91 pop r29 +} + 5a2: cf 91 pop r28 + 5a4: 1f 91 pop r17 + 5a6: 0f 91 pop r16 + 5a8: ff 90 pop r15 + 5aa: 8e cf rjmp .-228 ; 0x4c8 <_putnf.isra.0> + +000005ac <__umoddi3>: + itoa(-num, tmpstr, 10); + } else { + itoa(num, tmpstr, 10); + } + + _putnf(p, places); + 5ac: 68 94 set + 5ae: 01 c0 rjmp .+2 ; 0x5b2 <__udivdi3_umoddi3> + +000005b0 <__udivdi3>: + 5b0: e8 94 clt + +000005b2 <__udivdi3_umoddi3>: + 5b2: 8f 92 push r8 + 5b4: 9f 92 push r9 + 5b6: cf 93 push r28 + 5b8: df 93 push r29 + 5ba: 56 d0 rcall .+172 ; 0x668 <__udivmod64> + 5bc: df 91 pop r29 + 5be: cf 91 pop r28 + 5c0: 9f 90 pop r9 + 5c2: 8f 90 pop r8 + 5c4: 08 95 ret + +000005c6 <__muldi3>: + 5c6: df 93 push r29 + 5c8: cf 93 push r28 + 5ca: 1f 93 push r17 + 5cc: 0f 93 push r16 + 5ce: 9a 9d mul r25, r10 + 5d0: f0 2d mov r31, r0 + 5d2: 21 9f mul r18, r17 + 5d4: f0 0d add r31, r0 + 5d6: 8b 9d mul r24, r11 + 5d8: f0 0d add r31, r0 + 5da: 8a 9d mul r24, r10 + 5dc: e0 2d mov r30, r0 + 5de: f1 0d add r31, r1 + 5e0: 03 9f mul r16, r19 + 5e2: f0 0d add r31, r0 + 5e4: 02 9f mul r16, r18 + 5e6: e0 0d add r30, r0 + 5e8: f1 1d adc r31, r1 + 5ea: 4e 9d mul r20, r14 + 5ec: e0 0d add r30, r0 + 5ee: f1 1d adc r31, r1 + 5f0: 5e 9d mul r21, r14 + 5f2: f0 0d add r31, r0 + 5f4: 4f 9d mul r20, r15 + 5f6: f0 0d add r31, r0 + 5f8: 7f 93 push r23 + 5fa: 6f 93 push r22 + 5fc: bf 92 push r11 + 5fe: af 92 push r10 + 600: 5f 93 push r21 + 602: 4f 93 push r20 + 604: d5 01 movw r26, r10 + 606: 81 d0 rcall .+258 ; 0x70a <__umulhisi3> + 608: 8b 01 movw r16, r22 + 60a: ac 01 movw r20, r24 + 60c: d7 01 movw r26, r14 + 60e: 7d d0 rcall .+250 ; 0x70a <__umulhisi3> + 610: eb 01 movw r28, r22 + 612: e8 0f add r30, r24 + 614: f9 1f adc r31, r25 + 616: d6 01 movw r26, r12 + 618: 1f d0 rcall .+62 ; 0x658 <__muldi3_6> + 61a: 2f 91 pop r18 + 61c: 3f 91 pop r19 + 61e: d6 01 movw r26, r12 + 620: 74 d0 rcall .+232 ; 0x70a <__umulhisi3> + 622: c6 0f add r28, r22 + 624: d7 1f adc r29, r23 + 626: e8 1f adc r30, r24 + 628: f9 1f adc r31, r25 + 62a: af 91 pop r26 + 62c: bf 91 pop r27 + 62e: 14 d0 rcall .+40 ; 0x658 <__muldi3_6> + 630: 2f 91 pop r18 + 632: 3f 91 pop r19 + 634: 6a d0 rcall .+212 ; 0x70a <__umulhisi3> + 636: c6 0f add r28, r22 + 638: d7 1f adc r29, r23 + 63a: e8 1f adc r30, r24 + 63c: f9 1f adc r31, r25 + 63e: d6 01 movw r26, r12 + 640: 64 d0 rcall .+200 ; 0x70a <__umulhisi3> + 642: e6 0f add r30, r22 + 644: f7 1f adc r31, r23 + 646: 98 01 movw r18, r16 + 648: be 01 movw r22, r28 + 64a: cf 01 movw r24, r30 + 64c: 11 24 eor r1, r1 + 64e: 0f 91 pop r16 + 650: 1f 91 pop r17 + 652: cf 91 pop r28 + 654: df 91 pop r29 + 656: 08 95 ret + +00000658 <__muldi3_6>: + 658: 58 d0 rcall .+176 ; 0x70a <__umulhisi3> + 65a: 46 0f add r20, r22 + 65c: 57 1f adc r21, r23 + 65e: c8 1f adc r28, r24 + 660: d9 1f adc r29, r25 + 662: 08 f4 brcc .+2 ; 0x666 <__muldi3_6+0xe> + 664: 31 96 adiw r30, 0x01 ; 1 + 666: 08 95 ret + +00000668 <__udivmod64>: + 668: 88 24 eor r8, r8 + 66a: 99 24 eor r9, r9 + 66c: f4 01 movw r30, r8 + 66e: e4 01 movw r28, r8 + 670: b0 e4 ldi r27, 0x40 ; 64 + 672: 9f 93 push r25 + 674: aa 27 eor r26, r26 + 676: 9a 15 cp r25, r10 + 678: 8b 04 cpc r8, r11 + 67a: 9c 04 cpc r9, r12 + 67c: ed 05 cpc r30, r13 + 67e: fe 05 cpc r31, r14 + 680: cf 05 cpc r28, r15 + 682: d0 07 cpc r29, r16 + 684: a1 07 cpc r26, r17 + 686: 98 f4 brcc .+38 ; 0x6ae <__udivmod64+0x46> + 688: ad 2f mov r26, r29 + 68a: dc 2f mov r29, r28 + 68c: cf 2f mov r28, r31 + 68e: fe 2f mov r31, r30 + 690: e9 2d mov r30, r9 + 692: 98 2c mov r9, r8 + 694: 89 2e mov r8, r25 + 696: 98 2f mov r25, r24 + 698: 87 2f mov r24, r23 + 69a: 76 2f mov r23, r22 + 69c: 65 2f mov r22, r21 + 69e: 54 2f mov r21, r20 + 6a0: 43 2f mov r20, r19 + 6a2: 32 2f mov r19, r18 + 6a4: 22 27 eor r18, r18 + 6a6: b8 50 subi r27, 0x08 ; 8 + 6a8: 31 f7 brne .-52 ; 0x676 <__udivmod64+0xe> + 6aa: bf 91 pop r27 + 6ac: 27 c0 rjmp .+78 ; 0x6fc <__udivmod64+0x94> + 6ae: 1b 2e mov r1, r27 + 6b0: bf 91 pop r27 + 6b2: bb 27 eor r27, r27 + 6b4: 22 0f add r18, r18 + 6b6: 33 1f adc r19, r19 + 6b8: 44 1f adc r20, r20 + 6ba: 55 1f adc r21, r21 + 6bc: 66 1f adc r22, r22 + 6be: 77 1f adc r23, r23 + 6c0: 88 1f adc r24, r24 + 6c2: 99 1f adc r25, r25 + 6c4: 88 1c adc r8, r8 + 6c6: 99 1c adc r9, r9 + 6c8: ee 1f adc r30, r30 + 6ca: ff 1f adc r31, r31 + 6cc: cc 1f adc r28, r28 + 6ce: dd 1f adc r29, r29 + 6d0: aa 1f adc r26, r26 + 6d2: bb 1f adc r27, r27 + 6d4: 8a 14 cp r8, r10 + 6d6: 9b 04 cpc r9, r11 + 6d8: ec 05 cpc r30, r12 + 6da: fd 05 cpc r31, r13 + 6dc: ce 05 cpc r28, r14 + 6de: df 05 cpc r29, r15 + 6e0: a0 07 cpc r26, r16 + 6e2: b1 07 cpc r27, r17 + 6e4: 48 f0 brcs .+18 ; 0x6f8 <__udivmod64+0x90> + 6e6: 8a 18 sub r8, r10 + 6e8: 9b 08 sbc r9, r11 + 6ea: ec 09 sbc r30, r12 + 6ec: fd 09 sbc r31, r13 + 6ee: ce 09 sbc r28, r14 + 6f0: df 09 sbc r29, r15 + 6f2: a0 0b sbc r26, r16 + 6f4: b1 0b sbc r27, r17 + 6f6: 21 60 ori r18, 0x01 ; 1 + 6f8: 1a 94 dec r1 + 6fa: e1 f6 brne .-72 ; 0x6b4 <__udivmod64+0x4c> + 6fc: 2e f4 brtc .+10 ; 0x708 <__udivmod64+0xa0> + 6fe: 94 01 movw r18, r8 + 700: af 01 movw r20, r30 + 702: be 01 movw r22, r28 + 704: cd 01 movw r24, r26 + 706: 00 0c add r0, r0 + 708: 08 95 ret + +0000070a <__umulhisi3>: + 70a: a2 9f mul r26, r18 + 70c: b0 01 movw r22, r0 + 70e: b3 9f mul r27, r19 + 710: c0 01 movw r24, r0 + 712: a3 9f mul r26, r19 + 714: 70 0d add r23, r0 + 716: 81 1d adc r24, r1 + 718: 11 24 eor r1, r1 + 71a: 91 1d adc r25, r1 + 71c: b2 9f mul r27, r18 + 71e: 70 0d add r23, r0 + 720: 81 1d adc r24, r1 + 722: 11 24 eor r1, r1 + 724: 91 1d adc r25, r1 + 726: 08 95 ret + +00000728 <__itoa_ncheck>: + 728: bb 27 eor r27, r27 + 72a: 4a 30 cpi r20, 0x0A ; 10 + 72c: 31 f4 brne .+12 ; 0x73a <__itoa_ncheck+0x12> + 72e: 99 23 and r25, r25 + 730: 22 f4 brpl .+8 ; 0x73a <__itoa_ncheck+0x12> + 732: bd e2 ldi r27, 0x2D ; 45 + 734: 90 95 com r25 + 736: 81 95 neg r24 + 738: 9f 4f sbci r25, 0xFF ; 255 + 73a: 01 c0 rjmp .+2 ; 0x73e <__utoa_common> + +0000073c <__utoa_ncheck>: + 73c: bb 27 eor r27, r27 + +0000073e <__utoa_common>: + 73e: fb 01 movw r30, r22 + 740: 55 27 eor r21, r21 + 742: aa 27 eor r26, r26 + 744: 88 0f add r24, r24 + 746: 99 1f adc r25, r25 + 748: aa 1f adc r26, r26 + 74a: a4 17 cp r26, r20 + 74c: 10 f0 brcs .+4 ; 0x752 <__utoa_common+0x14> + 74e: a4 1b sub r26, r20 + 750: 83 95 inc r24 + 752: 50 51 subi r21, 0x10 ; 16 + 754: b9 f7 brne .-18 ; 0x744 <__utoa_common+0x6> + 756: a0 5d subi r26, 0xD0 ; 208 + 758: aa 33 cpi r26, 0x3A ; 58 + 75a: 08 f0 brcs .+2 ; 0x75e <__utoa_common+0x20> + 75c: a9 5d subi r26, 0xD9 ; 217 + 75e: a1 93 st Z+, r26 + 760: 00 97 sbiw r24, 0x00 ; 0 + 762: 79 f7 brne .-34 ; 0x742 <__utoa_common+0x4> + 764: b1 11 cpse r27, r1 + 766: b1 93 st Z+, r27 + 768: 11 92 st Z+, r1 + 76a: cb 01 movw r24, r22 + 76c: 00 c0 rjmp .+0 ; 0x76e + +0000076e : + 76e: dc 01 movw r26, r24 + 770: fc 01 movw r30, r24 + 772: 67 2f mov r22, r23 + 774: 71 91 ld r23, Z+ + 776: 77 23 and r23, r23 + 778: e1 f7 brne .-8 ; 0x772 + 77a: 32 97 sbiw r30, 0x02 ; 2 + 77c: 04 c0 rjmp .+8 ; 0x786 + 77e: 7c 91 ld r23, X + 780: 6d 93 st X+, r22 + 782: 70 83 st Z, r23 + 784: 62 91 ld r22, -Z + 786: ae 17 cp r26, r30 + 788: bf 07 cpc r27, r31 + 78a: c8 f3 brcs .-14 ; 0x77e + 78c: 08 95 ret + +0000078e <_exit>: + 78e: f8 94 cli + +00000790 <__stop_program>: + 790: ff cf rjmp .-2 ; 0x790 <__stop_program> diff --git a/examples/uart_simple.c b/examples/uart_simple.c index 9fb360b..0c86e76 100644 --- a/examples/uart_simple.c +++ b/examples/uart_simple.c @@ -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 --- diff --git a/examples/uart_stream.c b/examples/uart_stream.c new file mode 100644 index 0000000..d4b6109 --- /dev/null +++ b/examples/uart_stream.c @@ -0,0 +1,31 @@ +// +// Example of using UART with stream +// + +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/examples/uart_stream.lst b/examples/uart_stream.lst new file mode 100644 index 0000000..8a8ff2a --- /dev/null +++ b/examples/uart_stream.lst @@ -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
+ 9c: 46 c0 rjmp .+140 ; 0x12a <_exit> + +0000009e <__bad_interrupt>: + 9e: b0 cf rjmp .-160 ; 0x0 <__vectors> + +000000a0
: +#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 + b4: ff cf rjmp .-2 ; 0xb4 + +000000b6 : + +/** 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 + // send it + UDR0 = data; + be: 80 93 c6 00 sts 0x00C6, r24 + c2: 08 95 ret + +000000c4 : + +/** 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 + // 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 : + +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 + 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 +} + 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> diff --git a/examples/uart_stream.pre b/examples/uart_stream.pre new file mode 100644 index 0000000..b598aff --- /dev/null +++ b/examples/uart_stream.pre @@ -0,0 +1,885 @@ +# 1 "uart_stream.c" +# 1 "/home/ondra/git/avr-lib/examples//" +# 1 "" +# 1 "" +# 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); +} diff --git a/lib/lcd.c b/lib/lcd.c index d9162c2..50f61c7 100644 --- a/lib/lcd.c +++ b/lib/lcd.c @@ -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)); } diff --git a/lib/lcd.h b/lib/lcd.h index 8e37415..cff8943 100644 --- a/lib/lcd.h +++ b/lib/lcd.h @@ -21,9 +21,18 @@ #include #include +#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); diff --git a/lib/sonar.c b/lib/sonar.c index c92830a..7a5f80c 100644 --- a/lib/sonar.c +++ b/lib/sonar.c @@ -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; -} diff --git a/lib/sonar.h b/lib/sonar.h index a302242..63c48d2 100644 --- a/lib/sonar.h +++ b/lib/sonar.h @@ -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 diff --git a/lib/stream.c b/lib/stream.c new file mode 100644 index 0000000..5c0ea6c --- /dev/null +++ b/lib/stream.c @@ -0,0 +1,162 @@ +#include +#include +#include + +#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); +} diff --git a/lib/stream.h b/lib/stream.h new file mode 100644 index 0000000..3d9feb6 --- /dev/null +++ b/lib/stream.h @@ -0,0 +1,71 @@ +#pragma once + +// +// Stream utilities - printing abstraction +// Works with eg. UART +// + +#include +#include +#include +#include + +/** 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); diff --git a/lib/uart.c b/lib/uart.c index 4f18f52..c1d3b9f 100644 --- a/lib/uart.c +++ b/lib/uart.c @@ -6,6 +6,11 @@ #include #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++]); - } -} - diff --git a/lib/uart.h b/lib/uart.h index fc0a45d..5813803 100644 --- a/lib/uart.h +++ b/lib/uart.h @@ -13,6 +13,11 @@ #include #include +#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(); diff --git a/lib/uart_ansi.c b/lib/uart_ansi.c index 48d3d20..4f696a2 100644 --- a/lib/uart_ansi.c +++ b/lib/uart_ansi.c @@ -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")); }