@@ -11,6 +11,7 @@ SRC += $(COMMON_DIR)/host.c \ | |||
$(COMMON_DIR)/print.c \ | |||
$(COMMON_DIR)/bootloader.c \ | |||
$(COMMON_DIR)/suspend.c \ | |||
$(COMMON_DIR)/xprintf.S \ | |||
$(COMMON_DIR)/util.c | |||
@@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "keyboard.h" | |||
#include "mousekey.h" | |||
#include "command.h" | |||
#include "debug.h" | |||
#include "led.h" | |||
#include "action_layer.h" | |||
#include "action_tapping.h" | |||
@@ -27,12 +26,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#include "action_macro.h" | |||
#include "action.h" | |||
#ifdef DEBUG_ACTION | |||
#include "debug.h" | |||
#else | |||
#include "nodebug.h" | |||
#endif | |||
void action_exec(keyevent_t event) | |||
{ | |||
if (!IS_NOEVENT(event)) { | |||
debug("\n---- action_exec: start -----\n"); | |||
debug("EVENT: "); debug_event(event); debug("\n"); | |||
dprint("\n---- action_exec: start -----\n"); | |||
dprint("EVENT: "); debug_event(event); dprintln(); | |||
} | |||
keyrecord_t record = { .event = event }; | |||
@@ -42,7 +47,7 @@ void action_exec(keyevent_t event) | |||
#else | |||
process_action(&record); | |||
if (!IS_NOEVENT(record.event)) { | |||
debug("processed: "); debug_record(record); debug("\n"); | |||
dprint("processed: "); debug_record(record); dprintln(); | |||
} | |||
#endif | |||
} | |||
@@ -57,12 +62,12 @@ void process_action(keyrecord_t *record) | |||
if (IS_NOEVENT(event)) { return; } | |||
action_t action = layer_switch_get_action(event.key); | |||
debug("ACTION: "); debug_action(action); | |||
dprint("ACTION: "); debug_action(action); | |||
#ifndef NO_ACTION_LAYER | |||
debug(" layer_state: "); layer_debug(); | |||
debug(" default_layer_state: "); default_layer_debug(); | |||
dprint(" layer_state: "); layer_debug(); | |||
dprint(" default_layer_state: "); default_layer_debug(); | |||
#endif | |||
debug("\n"); | |||
dprintln(); | |||
switch (action.kind.id) { | |||
/* Key and Mods */ | |||
@@ -98,37 +103,37 @@ void process_action(keyrecord_t *record) | |||
// Oneshot modifier | |||
if (event.pressed) { | |||
if (tap_count == 0) { | |||
debug("MODS_TAP: Oneshot: add_mods\n"); | |||
dprint("MODS_TAP: Oneshot: add_mods\n"); | |||
add_mods(mods); | |||
} | |||
else if (tap_count == 1) { | |||
debug("MODS_TAP: Oneshot: start\n"); | |||
dprint("MODS_TAP: Oneshot: start\n"); | |||
oneshot_start(mods); | |||
} | |||
else if (tap_count == TAPPING_TOGGLE) { | |||
debug("MODS_TAP: Oneshot: toggle\n"); | |||
dprint("MODS_TAP: Oneshot: toggle\n"); | |||
oneshot_toggle(); | |||
} | |||
else { | |||
debug("MODS_TAP: Oneshot: cancel&add_mods\n"); | |||
dprint("MODS_TAP: Oneshot: cancel&add_mods\n"); | |||
// double tap cancels oneshot and works as normal modifier. | |||
oneshot_cancel(); | |||
add_mods(mods); | |||
} | |||
} else { | |||
if (tap_count == 0) { | |||
debug("MODS_TAP: Oneshot: cancel/del_mods\n"); | |||
dprint("MODS_TAP: Oneshot: cancel/del_mods\n"); | |||
// cancel oneshot on hold | |||
oneshot_cancel(); | |||
del_mods(mods); | |||
} | |||
else if (tap_count == 1) { | |||
debug("MODS_TAP: Oneshot: del_mods\n"); | |||
dprint("MODS_TAP: Oneshot: del_mods\n"); | |||
// retain Oneshot | |||
del_mods(mods); | |||
} | |||
else { | |||
debug("MODS_TAP: Oneshot: del_mods\n"); | |||
dprint("MODS_TAP: Oneshot: del_mods\n"); | |||
// cancel Mods | |||
del_mods(mods); | |||
} | |||
@@ -139,24 +144,24 @@ void process_action(keyrecord_t *record) | |||
if (event.pressed) { | |||
if (tap_count > 0) { | |||
if (record->tap.interrupted) { | |||
debug("MODS_TAP: Tap: Cancel: add_mods\n"); | |||
dprint("MODS_TAP: Tap: Cancel: add_mods\n"); | |||
// ad hoc: set 0 to cancel tap | |||
record->tap.count = 0; | |||
add_mods(mods); | |||
} else { | |||
debug("MODS_TAP: Tap: register_code\n"); | |||
dprint("MODS_TAP: Tap: register_code\n"); | |||
register_code(action.key.code); | |||
} | |||
} else { | |||
debug("MODS_TAP: No tap: add_mods\n"); | |||
dprint("MODS_TAP: No tap: add_mods\n"); | |||
add_mods(mods); | |||
} | |||
} else { | |||
if (tap_count > 0) { | |||
debug("MODS_TAP: Tap: unregister_code\n"); | |||
dprint("MODS_TAP: Tap: unregister_code\n"); | |||
unregister_code(action.key.code); | |||
} else { | |||
debug("MODS_TAP: No tap: add_mods\n"); | |||
dprint("MODS_TAP: No tap: add_mods\n"); | |||
del_mods(mods); | |||
} | |||
} | |||
@@ -261,18 +266,18 @@ void process_action(keyrecord_t *record) | |||
/* tap key */ | |||
if (event.pressed) { | |||
if (tap_count > 0) { | |||
debug("KEYMAP_TAP_KEY: Tap: register_code\n"); | |||
dprint("KEYMAP_TAP_KEY: Tap: register_code\n"); | |||
register_code(action.layer_tap.code); | |||
} else { | |||
debug("KEYMAP_TAP_KEY: No tap: On on press\n"); | |||
dprint("KEYMAP_TAP_KEY: No tap: On on press\n"); | |||
layer_on(action.layer_tap.val); | |||
} | |||
} else { | |||
if (tap_count > 0) { | |||
debug("KEYMAP_TAP_KEY: Tap: unregister_code\n"); | |||
dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n"); | |||
unregister_code(action.layer_tap.code); | |||
} else { | |||
debug("KEYMAP_TAP_KEY: No tap: Off on release\n"); | |||
dprint("KEYMAP_TAP_KEY: No tap: Off on release\n"); | |||
layer_off(action.layer_tap.val); | |||
} | |||
} | |||
@@ -448,40 +453,33 @@ bool is_tap_key(key_t key) | |||
*/ | |||
void debug_event(keyevent_t event) | |||
{ | |||
debug_hex16((event.key.row<<8) | event.key.col); | |||
if (event.pressed) debug("d("); else debug("u("); | |||
debug_dec(event.time); debug(")"); | |||
dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time); | |||
} | |||
void debug_record(keyrecord_t record) | |||
{ | |||
debug_event(record.event); | |||
#ifndef NO_ACTION_TAPPING | |||
debug(":"); debug_dec(record.tap.count); | |||
if (record.tap.interrupted) debug("-"); | |||
dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' ')); | |||
#endif | |||
} | |||
void debug_action(action_t action) | |||
{ | |||
switch (action.kind.id) { | |||
case ACT_LMODS: debug("ACT_LMODS"); break; | |||
case ACT_RMODS: debug("ACT_RMODS"); break; | |||
case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break; | |||
case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break; | |||
case ACT_USAGE: debug("ACT_USAGE"); break; | |||
case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break; | |||
case ACT_LAYER: debug("ACT_LAYER"); break; | |||
case ACT_LAYER_TAP: debug("ACT_LAYER_TAP"); break; | |||
case ACT_LAYER_TAP1: debug("ACT_LAYER_TAP1"); break; | |||
case ACT_MACRO: debug("ACT_MACRO"); break; | |||
case ACT_COMMAND: debug("ACT_COMMAND"); break; | |||
case ACT_FUNCTION: debug("ACT_FUNCTION"); break; | |||
default: debug("UNKNOWN"); break; | |||
case ACT_LMODS: dprint("ACT_LMODS"); break; | |||
case ACT_RMODS: dprint("ACT_RMODS"); break; | |||
case ACT_LMODS_TAP: dprint("ACT_LMODS_TAP"); break; | |||
case ACT_RMODS_TAP: dprint("ACT_RMODS_TAP"); break; | |||
case ACT_USAGE: dprint("ACT_USAGE"); break; | |||
case ACT_MOUSEKEY: dprint("ACT_MOUSEKEY"); break; | |||
case ACT_LAYER: dprint("ACT_LAYER"); break; | |||
case ACT_LAYER_TAP: dprint("ACT_LAYER_TAP"); break; | |||
case ACT_LAYER_TAP1: dprint("ACT_LAYER_TAP1"); break; | |||
case ACT_MACRO: dprint("ACT_MACRO"); break; | |||
case ACT_COMMAND: dprint("ACT_COMMAND"); break; | |||
case ACT_FUNCTION: dprint("ACT_FUNCTION"); break; | |||
default: dprint("UNKNOWN"); break; | |||
} | |||
debug("["); | |||
debug_hex4(action.kind.param>>8); | |||
debug(":"); | |||
debug_hex8(action.kind.param & 0xff); | |||
debug("]"); | |||
dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff); | |||
} |
@@ -1,10 +1,15 @@ | |||
#include <stdint.h> | |||
#include "keyboard.h" | |||
#include "action.h" | |||
#include "debug.h" | |||
#include "util.h" | |||
#include "action_layer.h" | |||
#ifdef DEBUG_ACTION | |||
#include "debug.h" | |||
#else | |||
#include "nodebug.h" | |||
#endif | |||
/* | |||
* Default Layer State | |||
@@ -22,8 +27,7 @@ static void default_layer_state_set(uint32_t state) | |||
void default_layer_debug(void) | |||
{ | |||
debug_hex32(default_layer_state); | |||
debug("("); debug_dec(biton32(default_layer_state)); debug(")"); | |||
dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state)); | |||
} | |||
void default_layer_set(uint8_t layer) | |||
@@ -55,10 +59,10 @@ uint32_t layer_state = 0; | |||
static void layer_state_set(uint32_t state) | |||
{ | |||
debug("layer_state: "); | |||
layer_debug(); debug(" to "); | |||
dprint("layer_state: "); | |||
layer_debug(); dprint(" to "); | |||
layer_state = state; | |||
layer_debug(); debug("\n"); | |||
layer_debug(); dprintln(); | |||
clear_keyboard_but_mods(); // To avoid stuck keys | |||
} | |||
@@ -102,8 +106,7 @@ void layer_xor(uint32_t state) | |||
void layer_debug(void) | |||
{ | |||
debug_hex32(layer_state); | |||
debug("("); debug_dec(biton32(layer_state)); debug(")"); | |||
dprintf("%08lX(%u)", layer_state, biton32(layer_state)); | |||
} | |||
#endif | |||
@@ -15,10 +15,15 @@ You should have received a copy of the GNU General Public License | |||
along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
#include <util/delay.h> | |||
#include "debug.h" | |||
#include "action.h" | |||
#include "action_macro.h" | |||
#ifdef DEBUG_ACTION | |||
#include "debug.h" | |||
#else | |||
#include "nodebug.h" | |||
#endif | |||
#ifndef NO_ACTION_MACRO | |||
@@ -3,8 +3,12 @@ | |||
#include "action.h" | |||
#include "action_tapping.h" | |||
#include "timer.h" | |||
#include "debug.h" | |||
#ifdef DEBUG_ACTION | |||
#include "debug.h" | |||
#else | |||
#include "nodebug.h" | |||
#endif | |||
#ifndef NO_ACTION_TAPPING | |||
@@ -18,14 +18,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#ifndef DEBUG_H | |||
#define DEBUG_H 1 | |||
#include <stdbool.h> | |||
#include "print.h" | |||
#include "debug_config.h" | |||
#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 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_P(s) do { if (debug_enable) print_P(s); } while (0) | |||
#define debug_msg(s) do { \ | |||
@@ -50,58 +56,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
#define debug_bin_reverse(data) debug_bin8(data) | |||
#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 |
@@ -0,0 +1,51 @@ | |||
/* | |||
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 |
@@ -63,11 +63,11 @@ void host_keyboard_send(report_keyboard_t *report) | |||
(*driver->send_keyboard)(report); | |||
if (debug_keyboard) { | |||
print("keys: "); | |||
dprint("keys: "); | |||
for (int i = 0; i < REPORT_KEYS; i++) { | |||
phex(keyboard_report->keys[i]); print(" "); | |||
dprintf("%02X ", keyboard_report->keys[i]); | |||
} | |||
print(" mods: "); phex(keyboard_report->mods); print("\n"); | |||
dprintf(" mods: %02X\n", keyboard_report->mods); | |||
} | |||
} | |||
@@ -235,7 +235,7 @@ static inline void add_key_bit(uint8_t code) | |||
if ((code>>3) < REPORT_KEYS) { | |||
keyboard_report->keys[code>>3] |= 1<<(code&7); | |||
} else { | |||
debug("add_key_bit: can't add: "); phex(code); debug("\n"); | |||
dprintf("add_key_bit: can't add: %02X\n", code); | |||
} | |||
} | |||
@@ -244,6 +244,6 @@ static inline void del_key_bit(uint8_t code) | |||
if ((code>>3) < REPORT_KEYS) { | |||
keyboard_report->keys[code>>3] &= ~(1<<(code&7)); | |||
} else { | |||
debug("del_key_bit: can't del: "); phex(code); debug("\n"); | |||
dprintf("del_key_bit: can't del: %02X\n", code); | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
/* | |||
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 |
@@ -1,4 +1,4 @@ | |||
/* 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 | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2008 PJRC.COM, LLC | |||
@@ -29,20 +29,14 @@ | |||
#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)) | |||
{ | |||
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) | |||
{ | |||
uint8_t c; | |||
@@ -54,140 +48,15 @@ void print_S(const char *s) | |||
} | |||
} | |||
/* 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 |
@@ -28,6 +28,8 @@ | |||
#include <stdint.h> | |||
#include <stdbool.h> | |||
#include <avr/pgmspace.h> | |||
#include "xprintf.h" | |||
#include "util.h" | |||
// this macro allows you to write print("some text") and | |||
@@ -49,17 +51,17 @@ | |||
#define pbin_reverse16(data) print_bin_reverse16(data) | |||
/* 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)) | |||
@@ -68,34 +70,46 @@ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/* function pointer of sendchar to be used by print utility */ | |||
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); | |||
/* 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 */ | |||
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 */ | |||
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 */ | |||
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 | |||
} | |||
#endif | |||
@@ -105,7 +119,6 @@ void print_bin_reverse32(uint32_t data); | |||
#define print_set_sendchar(func) | |||
#define print_S(s) | |||
#define print_P(s) | |||
#define print_CRLF() | |||
#define print_dec(data) | |||
#define print_decs(data) | |||
#define print_hex4(data) |
@@ -77,3 +77,25 @@ uint8_t biton32(uint32_t bits) | |||
if (bits >> 1) { bits >>= 1; n += 1;} | |||
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; | |||
} |
@@ -36,4 +36,8 @@ uint8_t biton(uint8_t bits); | |||
uint8_t biton16(uint16_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 |
@@ -0,0 +1,500 @@ | |||
;---------------------------------------------------------------------------; | |||
; 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 | |||
@@ -0,0 +1,103 @@ | |||
/*--------------------------------------------------------------------------- | |||
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 | |||