$(COMMON_DIR)/print.c \ | $(COMMON_DIR)/print.c \ | ||||
$(COMMON_DIR)/bootloader.c \ | $(COMMON_DIR)/bootloader.c \ | ||||
$(COMMON_DIR)/suspend.c \ | $(COMMON_DIR)/suspend.c \ | ||||
$(COMMON_DIR)/xprintf.S \ | |||||
$(COMMON_DIR)/util.c | $(COMMON_DIR)/util.c | ||||
#ifndef DEBUG_H | #ifndef DEBUG_H | ||||
#define DEBUG_H 1 | #define DEBUG_H 1 | ||||
#include <stdbool.h> | |||||
#include "print.h" | #include "print.h" | ||||
#include "debug_config.h" | |||||
#ifndef NO_DEBUG | #ifndef NO_DEBUG | ||||
#define dprint(s) do { if (debug_enable) print(s); } while (0) | |||||
#define dprintln() do { if (debug_enable) print_crlf(); } while (0) | |||||
#define dprintf(fmt, ...) do { if (debug_enable) __xprintf(PSTR(fmt), ##__VA_ARGS__); } while (0) | |||||
#define dmsg(s) dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s)) | |||||
/* DO NOT USE these anymore */ | |||||
#define debug(s) do { if (debug_enable) print(s); } while (0) | #define debug(s) do { if (debug_enable) print(s); } while (0) | ||||
#define debugln(s) do { if (debug_enable) println(s); } while (0) | |||||
#define debugln(s) do { if (debug_enable) print_crlf(); } while (0) | |||||
#define debug_S(s) do { if (debug_enable) print_S(s); } while (0) | #define debug_S(s) do { if (debug_enable) print_S(s); } while (0) | ||||
#define debug_P(s) do { if (debug_enable) print_P(s); } while (0) | #define debug_P(s) do { if (debug_enable) print_P(s); } while (0) | ||||
#define debug_msg(s) do { \ | #define debug_msg(s) do { \ | ||||
#define debug_bin_reverse(data) debug_bin8(data) | #define debug_bin_reverse(data) debug_bin8(data) | ||||
#else | #else | ||||
#define debug(s) | |||||
#define debugln(s) | |||||
#define debug_S(s) | |||||
#define debug_P(s) | |||||
#define debug_msg(s) | |||||
#define debug_dec(data) | |||||
#define debug_decs(data) | |||||
#define debug_hex4(data) | |||||
#define debug_hex8(data) | |||||
#define debug_hex16(data) | |||||
#define debug_hex32(data) | |||||
#define debug_bin8(data) | |||||
#define debug_bin16(data) | |||||
#define debug_bin32(data) | |||||
#define debug_bin_reverse8(data) | |||||
#define debug_bin_reverse16(data) | |||||
#define debug_bin_reverse32(data) | |||||
#define debug_hex(data) | |||||
#define debug_bin(data) | |||||
#define debug_bin_reverse(data) | |||||
#endif | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/* NOTE: Not portable. Bit field order depends on implementation */ | |||||
typedef union { | |||||
uint8_t raw; | |||||
struct { | |||||
bool enable:1; | |||||
bool matrix:1; | |||||
bool keyboard:1; | |||||
bool mouse:1; | |||||
uint8_t reserved:4; | |||||
}; | |||||
} debug_config_t; | |||||
debug_config_t debug_config; | |||||
/* for backward compatibility */ | |||||
#define debug_enable (debug_config.enable) | |||||
#define debug_matrix (debug_config.matrix) | |||||
#define debug_keyboard (debug_config.keyboard) | |||||
#define debug_mouse (debug_config.mouse) | |||||
#ifdef __cplusplus | |||||
} | |||||
#include "nodebug.h" | |||||
#endif | #endif | ||||
#endif | #endif |
/* | |||||
Copyright 2013 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef DEBUG_CONFIG_H | |||||
#define DEBUG_CONFIG_H 1 | |||||
#include <stdbool.h> | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/* NOTE: Not portable. Bit field order depends on implementation */ | |||||
typedef union { | |||||
uint8_t raw; | |||||
struct { | |||||
bool enable:1; | |||||
bool matrix:1; | |||||
bool keyboard:1; | |||||
bool mouse:1; | |||||
uint8_t reserved:4; | |||||
}; | |||||
} debug_config_t; | |||||
debug_config_t debug_config; | |||||
/* for backward compatibility */ | |||||
#define debug_enable (debug_config.enable) | |||||
#define debug_matrix (debug_config.matrix) | |||||
#define debug_keyboard (debug_config.keyboard) | |||||
#define debug_mouse (debug_config.mouse) | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif |
/* | |||||
Copyright 2013 Jun Wako <[email protected]> | |||||
This program is free software: you can redistribute it and/or modify | |||||
it under the terms of the GNU General Public License as published by | |||||
the Free Software Foundation, either version 2 of the License, or | |||||
(at your option) any later version. | |||||
This program is distributed in the hope that it will be useful, | |||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU General Public License for more details. | |||||
You should have received a copy of the GNU General Public License | |||||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
*/ | |||||
#ifndef NODEBUG_H | |||||
#define NODEBUG_H 1 | |||||
#include "debug_config.h" | |||||
#define dprint(s) | |||||
#define dprintln(s) | |||||
#define dprintf(fmt, ...) | |||||
#define dmsg(s) | |||||
#define debug(s) | |||||
#define debugln(s) | |||||
#define debug_S(s) | |||||
#define debug_P(s) | |||||
#define debug_msg(s) | |||||
#define debug_dec(data) | |||||
#define debug_decs(data) | |||||
#define debug_hex4(data) | |||||
#define debug_hex8(data) | |||||
#define debug_hex16(data) | |||||
#define debug_hex32(data) | |||||
#define debug_bin8(data) | |||||
#define debug_bin16(data) | |||||
#define debug_bin32(data) | |||||
#define debug_bin_reverse8(data) | |||||
#define debug_bin_reverse16(data) | |||||
#define debug_bin_reverse32(data) | |||||
#define debug_hex(data) | |||||
#define debug_bin(data) | |||||
#define debug_bin_reverse(data) | |||||
#endif |
/* Copyright 2012 Jun Wako <[email protected]> */ | |||||
/* Copyright 2012,2013 Jun Wako <[email protected]> */ | |||||
/* Very basic print functions, intended to be used with usb_debug_only.c | /* Very basic print functions, intended to be used with usb_debug_only.c | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2008 PJRC.COM, LLC | * Copyright (c) 2008 PJRC.COM, LLC | ||||
#ifndef NO_PRINT | #ifndef NO_PRINT | ||||
#define sendchar(c) do { if (print_sendchar_func) (print_sendchar_func)(c); } while (0) | |||||
#define sendchar(c) xputc(c) | |||||
static int8_t (*print_sendchar_func)(uint8_t) = 0; | |||||
void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) | void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) | ||||
{ | { | ||||
print_sendchar_func = sendchar_func; | |||||
xdev_out(sendchar_func); | |||||
} | } | ||||
/* print string stored in data memory(SRAM) | |||||
* print_P("hello world"); | |||||
* This consumes precious SRAM memory space for string. | |||||
*/ | |||||
void print_S(const char *s) | void print_S(const char *s) | ||||
{ | { | ||||
uint8_t c; | uint8_t c; | ||||
} | } | ||||
} | } | ||||
/* print string stored in program memory(FLASH) | |||||
* print_P(PSTR("hello world"); | |||||
* This consumes relatively abundant FLASH memory area not SRAM. | |||||
*/ | |||||
void print_P(const char *s) | |||||
{ | |||||
uint8_t c; | |||||
while (1) { | |||||
c = pgm_read_byte(s++); | |||||
if (!c) break; | |||||
if (c == '\n') sendchar('\r'); | |||||
sendchar(c); | |||||
} | |||||
} | |||||
void print_CRLF(void) | |||||
{ | |||||
sendchar('\r'); sendchar('\n'); | |||||
} | |||||
#define SIGNED 0x80 | |||||
#define BIN 2 | |||||
#define OCT 8 | |||||
#define DEC 10 | |||||
#define HEX 16 | |||||
static inline | |||||
char itoc(uint8_t i) | |||||
{ | |||||
return (i < 10 ? '0' + i : 'A' + i - 10); | |||||
} | |||||
static inline | |||||
void print_int(uint16_t data, uint8_t base) | |||||
{ | |||||
char buf[7] = {'\0'}; | |||||
char *p = &buf[6]; | |||||
if ((base & SIGNED) && (data & 0x8000)) { | |||||
data = -data; | |||||
buf[0] = '-'; | |||||
} | |||||
base &= ~SIGNED; | |||||
uint16_t n; | |||||
do { | |||||
n = data; | |||||
data /= base; | |||||
*(--p) = itoc(n - data*base); | |||||
} while (data); | |||||
if (buf[0]) *(--p) = buf[0]; | |||||
print_S(p); | |||||
} | |||||
void print_dec(uint16_t data) | |||||
{ | |||||
print_int(data, DEC); | |||||
} | |||||
void print_decs(int16_t data) | |||||
{ | |||||
print_int(data, DEC|SIGNED); | |||||
} | |||||
void print_hex4(uint8_t data) | |||||
{ | |||||
sendchar(data + ((data < 10) ? '0' : 'A' - 10)); | |||||
} | |||||
void print_hex8(uint8_t data) | |||||
{ | |||||
print_hex4(data>>4); | |||||
print_hex4(data&0x0F); | |||||
} | |||||
void print_hex16(uint16_t data) | |||||
{ | |||||
print_hex8(data>>8); | |||||
print_hex8(data); | |||||
} | |||||
void print_hex32(uint32_t data) | |||||
{ | |||||
print_hex16(data>>16); | |||||
print_hex16(data); | |||||
} | |||||
void print_bin4(uint8_t data) | |||||
{ | |||||
for (int i = 4; i >= 0; i--) { | |||||
sendchar((data & (1<<i)) ? '1' : '0'); | |||||
} | |||||
} | |||||
void print_bin8(uint8_t data) | |||||
{ | |||||
for (int i = 7; i >= 0; i--) { | |||||
sendchar((data & (1<<i)) ? '1' : '0'); | |||||
} | |||||
} | |||||
void print_bin16(uint16_t data) | |||||
{ | |||||
print_bin8(data>>8); | |||||
print_bin8(data); | |||||
} | |||||
void print_bin32(uint32_t data) | |||||
{ | |||||
print_bin8(data>>24); | |||||
print_bin8(data>>16); | |||||
print_bin8(data>>8); | |||||
print_bin8(data); | |||||
} | |||||
void print_bin_reverse8(uint8_t data) | |||||
{ | |||||
for (int i = 0; i < 8; i++) { | |||||
sendchar((data & (1<<i)) ? '1' : '0'); | |||||
} | |||||
} | |||||
void print_bin_reverse16(uint16_t data) | |||||
void print_lf(void) | |||||
{ | { | ||||
print_bin_reverse8(data); | |||||
print_bin_reverse8(data>>8); | |||||
sendchar('\n'); | |||||
} | } | ||||
void print_bin_reverse32(uint32_t data) | |||||
void print_crlf(void) | |||||
{ | { | ||||
print_bin_reverse8(data); | |||||
print_bin_reverse8(data>>8); | |||||
print_bin_reverse8(data>>16); | |||||
print_bin_reverse8(data>>24); | |||||
sendchar('\r'); | |||||
sendchar('\n'); | |||||
} | } | ||||
#endif | #endif |
#include <stdint.h> | #include <stdint.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <avr/pgmspace.h> | #include <avr/pgmspace.h> | ||||
#include "xprintf.h" | |||||
#include "util.h" | |||||
// this macro allows you to write print("some text") and | // this macro allows you to write print("some text") and | ||||
#define pbin_reverse16(data) print_bin_reverse16(data) | #define pbin_reverse16(data) print_bin_reverse16(data) | ||||
/* print value utility */ | /* print value utility */ | ||||
#define print_val_dec(v) do { print_P(PSTR(#v ": ")); print_dec(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_decs(v) do { print_P(PSTR(#v ": ")); print_decs(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_hex8(v) do { print_P(PSTR(#v ": ")); print_hex8(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_hex16(v) do { print_P(PSTR(#v ": ")); print_hex16(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_hex32(v) do { print_P(PSTR(#v ": ")); print_hex32(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_bin8(v) do { print_P(PSTR(#v ": ")); print_bin8(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_bin16(v) do { print_P(PSTR(#v ": ")); print_bin16(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_bin32(v) do { print_P(PSTR(#v ": ")); print_bin32(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_bin_reverse8(v) do { print_P(PSTR(#v ": ")); print_bin_reverse8(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_bin_reverse16(v) do { print_P(PSTR(#v ": ")); print_bin_reverse16(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_bin_reverse32(v) do { print_P(PSTR(#v ": ")); print_bin_reverse32(v); print_P(PSTR("\n")); } while (0) | |||||
#define print_val_dec(v) xprintf(#v ": %u\n", v) | |||||
#define print_val_decs(v) xprintf(#v ": %d\n", v) | |||||
#define print_val_hex8(v) xprintf(#v ": %X\n", v) | |||||
#define print_val_hex16(v) xprintf(#v ": %02X\n", v) | |||||
#define print_val_hex32(v) xprintf(#v ": %04lX\n", v) | |||||
#define print_val_bin8(v) xprintf(#v ": %08b\n", v) | |||||
#define print_val_bin16(v) xprintf(#v ": %016b\n", v) | |||||
#define print_val_bin32(v) xprintf(#v ": %032lb\n", v) | |||||
#define print_val_bin_reverse8(v) xprintf(#v ": %08b\n", bitrev(v)) | |||||
#define print_val_bin_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v)) | |||||
#define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v)) | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
/* function pointer of sendchar to be used by print utility */ | /* function pointer of sendchar to be used by print utility */ | ||||
void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t)); | void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t)); | ||||
/* print string stored in data memory(SRAM) */ | |||||
/* print string stored in data memory(SRAM) | |||||
* print_S("hello world"); | |||||
* This consumes precious SRAM memory space for string. | |||||
*/ | |||||
void print_S(const char *s); | void print_S(const char *s); | ||||
/* print string stored in program memory(FLASH) */ | |||||
void print_P(const char *s); | |||||
void print_CRLF(void); | |||||
void print_lf(void); | |||||
void print_crlf(void); | |||||
/* print string stored in program memory(FLASH) | |||||
* print_P(PSTR("hello world"); | |||||
* This consumes relatively abundant FLASH memory area not SRAM. | |||||
*/ | |||||
#define print_P(s) xputs(s) | |||||
/* decimal */ | /* decimal */ | ||||
void print_dec(uint16_t data); | |||||
void print_decs(int16_t data); | |||||
#define print_dec(i) xprintf("%u", i) | |||||
#define print_decs(i) xprintf("%d", i) | |||||
/* hex */ | /* hex */ | ||||
void print_hex4(uint8_t data); | |||||
void print_hex8(uint8_t data); | |||||
void print_hex16(uint16_t data); | |||||
void print_hex32(uint32_t data); | |||||
#define print_hex4(i) xprintf("%X", i) | |||||
#define print_hex8(i) xprintf("%02X", i) | |||||
#define print_hex16(i) xprintf("%04X", i) | |||||
#define print_hex32(i) xprintf("%08lX", i) | |||||
/* binary */ | /* binary */ | ||||
void print_bin4(uint8_t data); | |||||
void print_bin8(uint8_t data); | |||||
void print_bin16(uint16_t data); | |||||
void print_bin32(uint32_t data); | |||||
void print_bin_reverse8(uint8_t data); | |||||
void print_bin_reverse16(uint16_t data); | |||||
void print_bin_reverse32(uint32_t data); | |||||
#define print_bin4(i) xprintf("%04b", i) | |||||
#define print_bin8(i) xprintf("%08b", i) | |||||
#define print_bin16(i) xprintf("%016b", i) | |||||
#define print_bin32(i) xprintf("%032lb", i) | |||||
#define print_bin_reverse8(i) xprintf("%08b", bitrev(i)) | |||||
#define print_bin_reverse16(i) xprintf("%016b", bitrev16(i)) | |||||
#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i)) | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif | ||||
#define print_set_sendchar(func) | #define print_set_sendchar(func) | ||||
#define print_S(s) | #define print_S(s) | ||||
#define print_P(s) | #define print_P(s) | ||||
#define print_CRLF() | |||||
#define print_dec(data) | #define print_dec(data) | ||||
#define print_decs(data) | #define print_decs(data) | ||||
#define print_hex4(data) | #define print_hex4(data) |
if (bits >> 1) { bits >>= 1; n += 1;} | if (bits >> 1) { bits >>= 1; n += 1;} | ||||
return n; | return n; | ||||
} | } | ||||
uint8_t bitrev(uint8_t bits) | |||||
{ | |||||
bits = (bits & 0x0f)<<4 | (bits & 0xf0)>>4; | |||||
bits = (bits & 0b00110011)<<2 | (bits & 0b11001100)>>2; | |||||
bits = (bits & 0b01010101)<<1 | (bits & 0b10101010)>>1; | |||||
return bits; | |||||
} | |||||
uint16_t bitrev16(uint16_t bits) | |||||
{ | |||||
bits = bitrev(bits & 0x00ff)<<8 | bitrev((bits & 0xff00)>>8); | |||||
return bits; | |||||
} | |||||
uint32_t bitrev32(uint32_t bits) | |||||
{ | |||||
bits = (uint32_t)bitrev16(bits & 0x0000ffff)<<16 | bitrev16((bits & 0xffff0000)>>16); | |||||
return bits; | |||||
} |
uint8_t biton16(uint16_t bits); | uint8_t biton16(uint16_t bits); | ||||
uint8_t biton32(uint32_t bits); | uint8_t biton32(uint32_t bits); | ||||
uint8_t bitrev(uint8_t bits); | |||||
uint16_t bitrev16(uint16_t bits); | |||||
uint32_t bitrev32(uint32_t bits); | |||||
#endif | #endif |
;---------------------------------------------------------------------------; | |||||
; Extended itoa, puts, printf and atoi (C)ChaN, 2011 | |||||
;---------------------------------------------------------------------------; | |||||
// Base size is 152 bytes | |||||
#define CR_CRLF 0 // Convert \n to \r\n (+10 bytes) | |||||
#define USE_XPRINTF 1 // Enable xprintf function (+194 bytes) | |||||
#define USE_XSPRINTF 0 // Add xsprintf function (+78 bytes) | |||||
#define USE_XFPRINTF 0 // Add xfprintf function (+54 bytes) | |||||
#define USE_XATOI 0 // Enable xatoi function (+182 bytes) | |||||
#if FLASHEND > 0x1FFFF | |||||
#error xitoa module does not support 256K devices | |||||
#endif | |||||
.nolist | |||||
#include <avr/io.h> // Include device specific definitions. | |||||
.list | |||||
#ifdef SPM_PAGESIZE // Recent devices have "lpm Rd,Z+" and "movw". | |||||
.macro _LPMI reg | |||||
lpm \reg, Z+ | |||||
.endm | |||||
.macro _MOVW dh,dl, sh,sl | |||||
movw \dl, \sl | |||||
.endm | |||||
#else // Earlier devices do not have "lpm Rd,Z+" nor "movw". | |||||
.macro _LPMI reg | |||||
lpm | |||||
mov \reg, r0 | |||||
adiw ZL, 1 | |||||
.endm | |||||
.macro _MOVW dh,dl, sh,sl | |||||
mov \dl, \sl | |||||
mov \dh, \sh | |||||
.endm | |||||
#endif | |||||
;--------------------------------------------------------------------------- | |||||
; Stub function to forward to user output function | |||||
; | |||||
;Prototype: void xputc (char chr // a character to be output | |||||
; ); | |||||
;Size: 12/12 words | |||||
.section .bss | |||||
.global xfunc_out ; xfunc_out must be initialized before using this module. | |||||
xfunc_out: .ds.w 1 | |||||
.section .text | |||||
.func xputc | |||||
.global xputc | |||||
xputc: | |||||
#if CR_CRLF | |||||
cpi r24, 10 ;LF --> CRLF | |||||
brne 1f ; | |||||
ldi r24, 13 ; | |||||
rcall 1f ; | |||||
ldi r24, 10 ;/ | |||||
1: | |||||
#endif | |||||
push ZH | |||||
push ZL | |||||
lds ZL, xfunc_out+0 ;Pointer to the registered output function. | |||||
lds ZH, xfunc_out+1 ;/ | |||||
sbiw ZL, 0 ;Skip if null | |||||
breq 2f ;/ | |||||
icall | |||||
2: pop ZL | |||||
pop ZH | |||||
ret | |||||
.endfunc | |||||
;--------------------------------------------------------------------------- | |||||
; Direct ROM string output | |||||
; | |||||
;Prototype: void xputs (const prog_char *str // rom string to be output | |||||
; ); | |||||
.func xputs | |||||
.global xputs | |||||
xputs: | |||||
_MOVW ZH,ZL, r25,r24 ; Z = pointer to rom string | |||||
1: _LPMI r24 | |||||
cpi r24, 0 | |||||
breq 2f | |||||
rcall xputc | |||||
rjmp 1b | |||||
2: ret | |||||
.endfunc | |||||
;--------------------------------------------------------------------------- | |||||
; Extended direct numeral string output (32bit version) | |||||
; | |||||
;Prototype: void xitoa (long value, // value to be output | |||||
; char radix, // radix | |||||
; char width); // minimum width | |||||
; | |||||
.func xitoa | |||||
.global xitoa | |||||
xitoa: | |||||
;r25:r22 = value, r20 = base, r18 = digits | |||||
clr r31 ;r31 = stack level | |||||
ldi r30, ' ' ;r30 = sign | |||||
ldi r19, ' ' ;r19 = filler | |||||
sbrs r20, 7 ;When base indicates signd format and the value | |||||
rjmp 0f ;is minus, add a '-'. | |||||
neg r20 ; | |||||
sbrs r25, 7 ; | |||||
rjmp 0f ; | |||||
ldi r30, '-' ; | |||||
com r22 ; | |||||
com r23 ; | |||||
com r24 ; | |||||
com r25 ; | |||||
adc r22, r1 ; | |||||
adc r23, r1 ; | |||||
adc r24, r1 ; | |||||
adc r25, r1 ;/ | |||||
0: sbrs r18, 7 ;When digits indicates zero filled, | |||||
rjmp 1f ;filler is '0'. | |||||
neg r18 ; | |||||
ldi r19, '0' ;/ | |||||
;----- string conversion loop | |||||
1: ldi r21, 32 ;r26 = r25:r22 % r20 | |||||
clr r26 ;r25:r22 /= r20 | |||||
2: lsl r22 ; | |||||
rol r23 ; | |||||
rol r24 ; | |||||
rol r25 ; | |||||
rol r26 ; | |||||
cp r26, r20 ; | |||||
brcs 3f ; | |||||
sub r26, r20 ; | |||||
inc r22 ; | |||||
3: dec r21 ; | |||||
brne 2b ;/ | |||||
cpi r26, 10 ;r26 is a numeral digit '0'-'F' | |||||
brcs 4f ; | |||||
subi r26, -7 ; | |||||
4: subi r26, -'0' ;/ | |||||
push r26 ;Stack it | |||||
inc r31 ;/ | |||||
cp r22, r1 ;Repeat until r25:r22 gets zero | |||||
cpc r23, r1 ; | |||||
cpc r24, r1 ; | |||||
cpc r25, r1 ; | |||||
brne 1b ;/ | |||||
cpi r30, '-' ;Minus sign if needed | |||||
brne 5f ; | |||||
push r30 ; | |||||
inc r31 ;/ | |||||
5: cp r31, r18 ;Filler | |||||
brcc 6f ; | |||||
push r19 ; | |||||
inc r31 ; | |||||
rjmp 5b ;/ | |||||
6: pop r24 ;Flush stacked digits and exit | |||||
rcall xputc ; | |||||
dec r31 ; | |||||
brne 6b ;/ | |||||
ret | |||||
.endfunc | |||||
;---------------------------------------------------------------------------; | |||||
; Formatted string output (16/32bit version) | |||||
; | |||||
;Prototype: | |||||
; void xprintf (const prog_char *format, ...); | |||||
; void xsprintf(char*, const prog_char *format, ...); | |||||
; void xfprintf(void(*func)(char), const prog_char *format, ...); | |||||
; | |||||
#if USE_XPRINTF | |||||
.func xvprintf | |||||
xvprintf: | |||||
ld ZL, Y+ ;Z = pointer to format string | |||||
ld ZH, Y+ ;/ | |||||
0: _LPMI r24 ;Get a format char | |||||
cpi r24, 0 ;End of format string? | |||||
breq 90f ;/ | |||||
cpi r24, '%' ;Is format? | |||||
breq 20f ;/ | |||||
1: rcall xputc ;Put a normal character | |||||
rjmp 0b ;/ | |||||
90: ret | |||||
20: ldi r18, 0 ;r18: digits | |||||
clt ;T: filler | |||||
_LPMI r21 ;Get flags | |||||
cpi r21, '%' ;Is a %? | |||||
breq 1b ;/ | |||||
cpi r21, '0' ;Zero filled? | |||||
brne 23f ; | |||||
set ;/ | |||||
22: _LPMI r21 ;Get width | |||||
23: cpi r21, '9'+1 ; | |||||
brcc 24f ; | |||||
subi r21, '0' ; | |||||
brcs 90b ; | |||||
lsl r18 ; | |||||
mov r0, r18 ; | |||||
lsl r18 ; | |||||
lsl r18 ; | |||||
add r18, r0 ; | |||||
add r18, r21 ; | |||||
rjmp 22b ;/ | |||||
24: brtc 25f ;get value (low word) | |||||
neg r18 ; | |||||
25: ld r24, Y+ ; | |||||
ld r25, Y+ ;/ | |||||
cpi r21, 'c' ;Is type character? | |||||
breq 1b ;/ | |||||
cpi r21, 's' ;Is type RAM string? | |||||
breq 50f ;/ | |||||
cpi r21, 'S' ;Is type ROM string? | |||||
breq 60f ;/ | |||||
_MOVW r23,r22,r25,r24 ;r25:r22 = value | |||||
clr r24 ; | |||||
clr r25 ; | |||||
clt ;/ | |||||
cpi r21, 'l' ;Is long int? | |||||
brne 26f ; | |||||
ld r24, Y+ ;get value (high word) | |||||
ld r25, Y+ ; | |||||
set ; | |||||
_LPMI r21 ;/ | |||||
26: cpi r21, 'd' ;Is type signed decimal? | |||||
brne 27f ;/ | |||||
ldi r20, -10 ; | |||||
brts 40f ; | |||||
sbrs r23, 7 ; | |||||
rjmp 40f ; | |||||
ldi r24, -1 ; | |||||
ldi r25, -1 ; | |||||
rjmp 40f ;/ | |||||
27: cpi r21, 'u' ;Is type unsigned decimal? | |||||
ldi r20, 10 ; | |||||
breq 40f ;/ | |||||
cpi r21, 'X' ;Is type hexdecimal? | |||||
ldi r20, 16 ; | |||||
breq 40f ;/ | |||||
cpi r21, 'b' ;Is type binary? | |||||
ldi r20, 2 ; | |||||
breq 40f ;/ | |||||
ret ;abort | |||||
40: push ZH ;Output the value | |||||
push ZL ; | |||||
rcall xitoa ; | |||||
42: pop ZL ; | |||||
pop ZH ; | |||||
rjmp 0b ;/ | |||||
50: push ZH ;Put a string on the RAM | |||||
push ZL | |||||
_MOVW ZH,ZL, r25,r24 | |||||
51: ld r24, Z+ | |||||
cpi r24, 0 | |||||
breq 42b | |||||
rcall xputc | |||||
rjmp 51b | |||||
60: push ZH ;Put a string on the ROM | |||||
push ZL | |||||
rcall xputs | |||||
rjmp 42b | |||||
.endfunc | |||||
.func __xprintf | |||||
.global __xprintf | |||||
__xprintf: | |||||
push YH | |||||
push YL | |||||
in YL, _SFR_IO_ADDR(SPL) | |||||
#ifdef SPH | |||||
in YH, _SFR_IO_ADDR(SPH) | |||||
#else | |||||
clr YH | |||||
#endif | |||||
adiw YL, 5 ;Y = pointer to arguments | |||||
rcall xvprintf | |||||
pop YL | |||||
pop YH | |||||
ret | |||||
.endfunc | |||||
#if USE_XSPRINTF | |||||
.func __xsprintf | |||||
putram: | |||||
_MOVW ZH,ZL, r15,r14 | |||||
st Z+, r24 | |||||
_MOVW r15,r14, ZH,ZL | |||||
ret | |||||
.global __xsprintf | |||||
__xsprintf: | |||||
push YH | |||||
push YL | |||||
in YL, _SFR_IO_ADDR(SPL) | |||||
#ifdef SPH | |||||
in YH, _SFR_IO_ADDR(SPH) | |||||
#else | |||||
clr YH | |||||
#endif | |||||
adiw YL, 5 ;Y = pointer to arguments | |||||
lds ZL, xfunc_out+0 ;Save registered output function | |||||
lds ZH, xfunc_out+1 ; | |||||
push ZL ; | |||||
push ZH ;/ | |||||
ldi ZL, lo8(pm(putram));Set local output function | |||||
ldi ZH, hi8(pm(putram)); | |||||
sts xfunc_out+0, ZL ; | |||||
sts xfunc_out+1, ZH ;/ | |||||
push r15 ;Initialize pointer to string buffer | |||||
push r14 ; | |||||
ld r14, Y+ ; | |||||
ld r15, Y+ ;/ | |||||
rcall xvprintf | |||||
_MOVW ZH,ZL, r15,r14 ;Terminate string | |||||
st Z, r1 ; | |||||
pop r14 ; | |||||
pop r15 ;/ | |||||
pop ZH ;Restore registered output function | |||||
pop ZL ; | |||||
sts xfunc_out+0, ZL ; | |||||
sts xfunc_out+1, ZH ;/ | |||||
pop YL | |||||
pop YH | |||||
ret | |||||
.endfunc | |||||
#endif | |||||
#if USE_XFPRINTF | |||||
.func __xfprintf | |||||
.global __xfprintf | |||||
__xfprintf: | |||||
push YH | |||||
push YL | |||||
in YL, _SFR_IO_ADDR(SPL) | |||||
#ifdef SPH | |||||
in YH, _SFR_IO_ADDR(SPH) | |||||
#else | |||||
clr YH | |||||
#endif | |||||
adiw YL, 5 ;Y = pointer to arguments | |||||
lds ZL, xfunc_out+0 ;Save registered output function | |||||
lds ZH, xfunc_out+1 ; | |||||
push ZL ; | |||||
push ZH ;/ | |||||
ld ZL, Y+ ;Set output function | |||||
ld ZH, Y+ ; | |||||
sts xfunc_out+0, ZL ; | |||||
sts xfunc_out+1, ZH ;/ | |||||
rcall xvprintf | |||||
pop ZH ;Restore registered output function | |||||
pop ZL ; | |||||
sts xfunc_out+0, ZL ; | |||||
sts xfunc_out+1, ZH ;/ | |||||
pop YL | |||||
pop YH | |||||
ret | |||||
.endfunc | |||||
#endif | |||||
#endif | |||||
;--------------------------------------------------------------------------- | |||||
; Extended numeral string input | |||||
; | |||||
;Prototype: | |||||
; char xatoi ( /* 1: Successful, 0: Failed */ | |||||
; const char **str, /* pointer to pointer to source string */ | |||||
; long *res /* result */ | |||||
; ); | |||||
; | |||||
#if USE_XATOI | |||||
.func xatoi | |||||
.global xatoi | |||||
xatoi: | |||||
_MOVW r1, r0, r23, r22 | |||||
_MOVW XH, XL, r25, r24 | |||||
ld ZL, X+ | |||||
ld ZH, X+ | |||||
clr r18 ;r21:r18 = 0; | |||||
clr r19 ; | |||||
clr r20 ; | |||||
clr r21 ;/ | |||||
clt ;T = 0; | |||||
ldi r25, 10 ;r25 = 10; | |||||
rjmp 41f ;/ | |||||
40: adiw ZL, 1 ;Z++; | |||||
41: ld r22, Z ;r22 = *Z; | |||||
cpi r22, ' ' ;if(r22 == ' ') continue | |||||
breq 40b ;/ | |||||
brcs 70f ;if(r22 < ' ') error; | |||||
cpi r22, '-' ;if(r22 == '-') { | |||||
brne 42f ; T = 1; | |||||
set ; continue; | |||||
rjmp 40b ;} | |||||
42: cpi r22, '9'+1 ;if(r22 > '9') error; | |||||
brcc 70f ;/ | |||||
cpi r22, '0' ;if(r22 < '0') error; | |||||
brcs 70f ;/ | |||||
brne 51f ;if(r22 > '0') cv_start; | |||||
ldi r25, 8 ;r25 = 8; | |||||
adiw ZL, 1 ;r22 = *(++Z); | |||||
ld r22, Z ;/ | |||||
cpi r22, ' '+1 ;if(r22 <= ' ') exit; | |||||
brcs 80f ;/ | |||||
cpi r22, 'b' ;if(r22 == 'b') { | |||||
brne 43f ; r25 = 2; | |||||
ldi r25, 2 ; cv_start; | |||||
rjmp 50f ;} | |||||
43: cpi r22, 'x' ;if(r22 != 'x') error; | |||||
brne 51f ;/ | |||||
ldi r25, 16 ;r25 = 16; | |||||
50: adiw ZL, 1 ;Z++; | |||||
ld r22, Z ;r22 = *Z; | |||||
51: cpi r22, ' '+1 ;if(r22 <= ' ') break; | |||||
brcs 80f ;/ | |||||
cpi r22, 'a' ;if(r22 >= 'a') r22 =- 0x20; | |||||
brcs 52f ; | |||||
subi r22, 0x20 ;/ | |||||
52: subi r22, '0' ;if((r22 -= '0') < 0) error; | |||||
brcs 70f ;/ | |||||
cpi r22, 10 ;if(r22 >= 10) { | |||||
brcs 53f ; r22 -= 7; | |||||
subi r22, 7 ; if(r22 < 10) | |||||
cpi r22, 10 ; | |||||
brcs 70f ;} | |||||
53: cp r22, r25 ;if(r22 >= r25) error; | |||||
brcc 70f ;/ | |||||
60: ldi r24, 33 ;r21:r18 *= r25; | |||||
sub r23, r23 ; | |||||
61: brcc 62f ; | |||||
add r23, r25 ; | |||||
62: lsr r23 ; | |||||
ror r21 ; | |||||
ror r20 ; | |||||
ror r19 ; | |||||
ror r18 ; | |||||
dec r24 ; | |||||
brne 61b ;/ | |||||
add r18, r22 ;r21:r18 += r22; | |||||
adc r19, r24 ; | |||||
adc r20, r24 ; | |||||
adc r21, r24 ;/ | |||||
rjmp 50b ;repeat | |||||
70: ldi r24, 0 | |||||
rjmp 81f | |||||
80: ldi r24, 1 | |||||
81: brtc 82f | |||||
clr r22 | |||||
com r18 | |||||
com r19 | |||||
com r20 | |||||
com r21 | |||||
adc r18, r22 | |||||
adc r19, r22 | |||||
adc r20, r22 | |||||
adc r21, r22 | |||||
82: st -X, ZH | |||||
st -X, ZL | |||||
_MOVW XH, XL, r1, r0 | |||||
st X+, r18 | |||||
st X+, r19 | |||||
st X+, r20 | |||||
st X+, r21 | |||||
clr r1 | |||||
ret | |||||
.endfunc | |||||
#endif | |||||
/*--------------------------------------------------------------------------- | |||||
Extended itoa, puts and printf (C)ChaN, 2011 | |||||
-----------------------------------------------------------------------------*/ | |||||
#ifndef XPRINTF_H | |||||
#define XPRINTF_H | |||||
#include <inttypes.h> | |||||
#include <avr/pgmspace.h> | |||||
extern void (*xfunc_out)(uint8_t); | |||||
#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func) | |||||
/* This is a pointer to user defined output function. It must be initialized | |||||
before using this modle. | |||||
*/ | |||||
void xputc(char chr); | |||||
/* This is a stub function to forward outputs to user defined output function. | |||||
All outputs from this module are output via this function. | |||||
*/ | |||||
/*-----------------------------------------------------------------------------*/ | |||||
void xputs(const prog_char *string); | |||||
/* The string placed in the ROM is forwarded to xputc() directly. | |||||
*/ | |||||
/*-----------------------------------------------------------------------------*/ | |||||
void xitoa(long value, char radix, char width); | |||||
/* Extended itoa(). | |||||
value radix width output | |||||
100 10 6 " 100" | |||||
100 10 -6 "000100" | |||||
100 10 0 "100" | |||||
4294967295 10 0 "4294967295" | |||||
4294967295 -10 0 "-1" | |||||
655360 16 -8 "000A0000" | |||||
1024 16 0 "400" | |||||
0x55 2 -8 "01010101" | |||||
*/ | |||||
/*-----------------------------------------------------------------------------*/ | |||||
#define xprintf(format, ...) __xprintf(PSTR(format), ##__VA_ARGS__) | |||||
#define xsprintf(str, format, ...) __xsprintf(str, PSTR(format), ##__VA_ARGS__) | |||||
#define xfprintf(func, format, ...) __xfprintf(func, PSTR(format), ##__VA_ARGS__) | |||||
void __xprintf(const prog_char *format, ...); /* Send formatted string to the registered device */ | |||||
void __xsprintf(char*, const prog_char *format, ...); /* Put formatted string to the memory */ | |||||
void __xfprintf(void(*func)(uint8_t), const prog_char *format, ...); /* Send formatted string to the specified device */ | |||||
/* Format string is placed in the ROM. The format flags is similar to printf(). | |||||
%[flag][width][size]type | |||||
flag | |||||
A '0' means filled with '0' when output is shorter than width. | |||||
' ' is used in default. This is effective only numeral type. | |||||
width | |||||
Minimum width in decimal number. This is effective only numeral type. | |||||
Default width is zero. | |||||
size | |||||
A 'l' means the argument is long(32bit). Default is short(16bit). | |||||
This is effective only numeral type. | |||||
type | |||||
'c' : Character, argument is the value | |||||
's' : String placed on the RAM, argument is the pointer | |||||
'S' : String placed on the ROM, argument is the pointer | |||||
'd' : Signed decimal, argument is the value | |||||
'u' : Unsigned decimal, argument is the value | |||||
'X' : Hexdecimal, argument is the value | |||||
'b' : Binary, argument is the value | |||||
'%' : '%' | |||||
*/ | |||||
/*-----------------------------------------------------------------------------*/ | |||||
char xatoi(char **str, long *ret); | |||||
/* Get value of the numeral string. | |||||
str | |||||
Pointer to pointer to source string | |||||
"0b11001010" binary | |||||
"0377" octal | |||||
"0xff800" hexdecimal | |||||
"1250000" decimal | |||||
"-25000" decimal | |||||
ret | |||||
Pointer to return value | |||||
*/ | |||||
#endif | |||||