1
0

Merge branch 'fix_print'

This commit is contained in:
tmk 2013-05-14 23:03:23 +09:00
commit cbb9c408e4
15 changed files with 861 additions and 284 deletions

View File

@ -11,6 +11,7 @@ SRC += $(COMMON_DIR)/host.c \
$(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

View File

@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "keyboard.h" #include "keyboard.h"
#include "mousekey.h" #include "mousekey.h"
#include "command.h" #include "command.h"
#include "debug.h"
#include "led.h" #include "led.h"
#include "action_layer.h" #include "action_layer.h"
#include "action_tapping.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_macro.h"
#include "action.h" #include "action.h"
#ifdef DEBUG_ACTION
#include "debug.h"
#else
#include "nodebug.h"
#endif
void action_exec(keyevent_t event) void action_exec(keyevent_t event)
{ {
if (!IS_NOEVENT(event)) { if (!IS_NOEVENT(event)) {
debug("\n---- action_exec: start -----\n"); dprint("\n---- action_exec: start -----\n");
debug("EVENT: "); debug_event(event); debug("\n"); dprint("EVENT: "); debug_event(event); dprintln();
} }
keyrecord_t record = { .event = event }; keyrecord_t record = { .event = event };
@ -42,7 +47,7 @@ void action_exec(keyevent_t event)
#else #else
process_action(&record); process_action(&record);
if (!IS_NOEVENT(record.event)) { if (!IS_NOEVENT(record.event)) {
debug("processed: "); debug_record(record); debug("\n"); dprint("processed: "); debug_record(record); dprintln();
} }
#endif #endif
} }
@ -57,12 +62,12 @@ void process_action(keyrecord_t *record)
if (IS_NOEVENT(event)) { return; } if (IS_NOEVENT(event)) { return; }
action_t action = layer_switch_get_action(event.key); action_t action = layer_switch_get_action(event.key);
debug("ACTION: "); debug_action(action); dprint("ACTION: "); debug_action(action);
#ifndef NO_ACTION_LAYER #ifndef NO_ACTION_LAYER
debug(" layer_state: "); layer_debug(); dprint(" layer_state: "); layer_debug();
debug(" default_layer_state: "); default_layer_debug(); dprint(" default_layer_state: "); default_layer_debug();
#endif #endif
debug("\n"); dprintln();
switch (action.kind.id) { switch (action.kind.id) {
/* Key and Mods */ /* Key and Mods */
@ -98,37 +103,37 @@ void process_action(keyrecord_t *record)
// Oneshot modifier // Oneshot modifier
if (event.pressed) { if (event.pressed) {
if (tap_count == 0) { if (tap_count == 0) {
debug("MODS_TAP: Oneshot: add_mods\n"); dprint("MODS_TAP: Oneshot: add_mods\n");
add_mods(mods); add_mods(mods);
} }
else if (tap_count == 1) { else if (tap_count == 1) {
debug("MODS_TAP: Oneshot: start\n"); dprint("MODS_TAP: Oneshot: start\n");
oneshot_start(mods); oneshot_start(mods);
} }
else if (tap_count == TAPPING_TOGGLE) { else if (tap_count == TAPPING_TOGGLE) {
debug("MODS_TAP: Oneshot: toggle\n"); dprint("MODS_TAP: Oneshot: toggle\n");
oneshot_toggle(); oneshot_toggle();
} }
else { 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. // double tap cancels oneshot and works as normal modifier.
oneshot_cancel(); oneshot_cancel();
add_mods(mods); add_mods(mods);
} }
} else { } else {
if (tap_count == 0) { if (tap_count == 0) {
debug("MODS_TAP: Oneshot: cancel/del_mods\n"); dprint("MODS_TAP: Oneshot: cancel/del_mods\n");
// cancel oneshot on hold // cancel oneshot on hold
oneshot_cancel(); oneshot_cancel();
del_mods(mods); del_mods(mods);
} }
else if (tap_count == 1) { else if (tap_count == 1) {
debug("MODS_TAP: Oneshot: del_mods\n"); dprint("MODS_TAP: Oneshot: del_mods\n");
// retain Oneshot // retain Oneshot
del_mods(mods); del_mods(mods);
} }
else { else {
debug("MODS_TAP: Oneshot: del_mods\n"); dprint("MODS_TAP: Oneshot: del_mods\n");
// cancel Mods // cancel Mods
del_mods(mods); del_mods(mods);
} }
@ -139,24 +144,24 @@ void process_action(keyrecord_t *record)
if (event.pressed) { if (event.pressed) {
if (tap_count > 0) { if (tap_count > 0) {
if (record->tap.interrupted) { 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 // ad hoc: set 0 to cancel tap
record->tap.count = 0; record->tap.count = 0;
add_mods(mods); add_mods(mods);
} else { } else {
debug("MODS_TAP: Tap: register_code\n"); dprint("MODS_TAP: Tap: register_code\n");
register_code(action.key.code); register_code(action.key.code);
} }
} else { } else {
debug("MODS_TAP: No tap: add_mods\n"); dprint("MODS_TAP: No tap: add_mods\n");
add_mods(mods); add_mods(mods);
} }
} else { } else {
if (tap_count > 0) { if (tap_count > 0) {
debug("MODS_TAP: Tap: unregister_code\n"); dprint("MODS_TAP: Tap: unregister_code\n");
unregister_code(action.key.code); unregister_code(action.key.code);
} else { } else {
debug("MODS_TAP: No tap: add_mods\n"); dprint("MODS_TAP: No tap: add_mods\n");
del_mods(mods); del_mods(mods);
} }
} }
@ -261,18 +266,18 @@ void process_action(keyrecord_t *record)
/* tap key */ /* tap key */
if (event.pressed) { if (event.pressed) {
if (tap_count > 0) { 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); register_code(action.layer_tap.code);
} else { } 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); layer_on(action.layer_tap.val);
} }
} else { } else {
if (tap_count > 0) { 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); unregister_code(action.layer_tap.code);
} else { } 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); layer_off(action.layer_tap.val);
} }
} }
@ -448,40 +453,33 @@ bool is_tap_key(key_t key)
*/ */
void debug_event(keyevent_t event) void debug_event(keyevent_t event)
{ {
debug_hex16((event.key.row<<8) | event.key.col); dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
if (event.pressed) debug("d("); else debug("u(");
debug_dec(event.time); debug(")");
} }
void debug_record(keyrecord_t record) void debug_record(keyrecord_t record)
{ {
debug_event(record.event); debug_event(record.event);
#ifndef NO_ACTION_TAPPING #ifndef NO_ACTION_TAPPING
debug(":"); debug_dec(record.tap.count); dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
if (record.tap.interrupted) debug("-");
#endif #endif
} }
void debug_action(action_t action) void debug_action(action_t action)
{ {
switch (action.kind.id) { switch (action.kind.id) {
case ACT_LMODS: debug("ACT_LMODS"); break; case ACT_LMODS: dprint("ACT_LMODS"); break;
case ACT_RMODS: debug("ACT_RMODS"); break; case ACT_RMODS: dprint("ACT_RMODS"); break;
case ACT_LMODS_TAP: debug("ACT_LMODS_TAP"); break; case ACT_LMODS_TAP: dprint("ACT_LMODS_TAP"); break;
case ACT_RMODS_TAP: debug("ACT_RMODS_TAP"); break; case ACT_RMODS_TAP: dprint("ACT_RMODS_TAP"); break;
case ACT_USAGE: debug("ACT_USAGE"); break; case ACT_USAGE: dprint("ACT_USAGE"); break;
case ACT_MOUSEKEY: debug("ACT_MOUSEKEY"); break; case ACT_MOUSEKEY: dprint("ACT_MOUSEKEY"); break;
case ACT_LAYER: debug("ACT_LAYER"); break; case ACT_LAYER: dprint("ACT_LAYER"); break;
case ACT_LAYER_TAP: debug("ACT_LAYER_TAP"); break; case ACT_LAYER_TAP: dprint("ACT_LAYER_TAP"); break;
case ACT_LAYER_TAP1: debug("ACT_LAYER_TAP1"); break; case ACT_LAYER_TAP1: dprint("ACT_LAYER_TAP1"); break;
case ACT_MACRO: debug("ACT_MACRO"); break; case ACT_MACRO: dprint("ACT_MACRO"); break;
case ACT_COMMAND: debug("ACT_COMMAND"); break; case ACT_COMMAND: dprint("ACT_COMMAND"); break;
case ACT_FUNCTION: debug("ACT_FUNCTION"); break; case ACT_FUNCTION: dprint("ACT_FUNCTION"); break;
default: debug("UNKNOWN"); break; default: dprint("UNKNOWN"); break;
} }
debug("["); dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
debug_hex4(action.kind.param>>8);
debug(":");
debug_hex8(action.kind.param & 0xff);
debug("]");
} }

View File

@ -1,10 +1,15 @@
#include <stdint.h> #include <stdint.h>
#include "keyboard.h" #include "keyboard.h"
#include "action.h" #include "action.h"
#include "debug.h"
#include "util.h" #include "util.h"
#include "action_layer.h" #include "action_layer.h"
#ifdef DEBUG_ACTION
#include "debug.h"
#else
#include "nodebug.h"
#endif
/* /*
* Default Layer State * Default Layer State
@ -22,8 +27,7 @@ static void default_layer_state_set(uint32_t state)
void default_layer_debug(void) void default_layer_debug(void)
{ {
debug_hex32(default_layer_state); dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
debug("("); debug_dec(biton32(default_layer_state)); debug(")");
} }
void default_layer_set(uint8_t layer) void default_layer_set(uint8_t layer)
@ -55,10 +59,10 @@ uint32_t layer_state = 0;
static void layer_state_set(uint32_t state) static void layer_state_set(uint32_t state)
{ {
debug("layer_state: "); dprint("layer_state: ");
layer_debug(); debug(" to "); layer_debug(); dprint(" to ");
layer_state = state; layer_state = state;
layer_debug(); debug("\n"); layer_debug(); dprintln();
clear_keyboard_but_mods(); // To avoid stuck keys clear_keyboard_but_mods(); // To avoid stuck keys
} }
@ -102,8 +106,7 @@ void layer_xor(uint32_t state)
void layer_debug(void) void layer_debug(void)
{ {
debug_hex32(layer_state); dprintf("%08lX(%u)", layer_state, biton32(layer_state));
debug("("); debug_dec(biton32(layer_state)); debug(")");
} }
#endif #endif

View File

@ -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/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <util/delay.h> #include <util/delay.h>
#include "debug.h"
#include "action.h" #include "action.h"
#include "action_macro.h" #include "action_macro.h"
#ifdef DEBUG_ACTION
#include "debug.h"
#else
#include "nodebug.h"
#endif
#ifndef NO_ACTION_MACRO #ifndef NO_ACTION_MACRO

View File

@ -3,8 +3,12 @@
#include "action.h" #include "action.h"
#include "action_tapping.h" #include "action_tapping.h"
#include "timer.h" #include "timer.h"
#include "debug.h"
#ifdef DEBUG_ACTION
#include "debug.h"
#else
#include "nodebug.h"
#endif
#ifndef NO_ACTION_TAPPING #ifndef NO_ACTION_TAPPING

View File

@ -18,14 +18,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#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 { \
@ -50,58 +56,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define debug_bin_reverse(data) debug_bin8(data) #define debug_bin_reverse(data) debug_bin8(data)
#else #else
#include "nodebug.h"
#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
}
#endif #endif
#endif #endif

51
common/debug_config.h Normal file
View File

@ -0,0 +1,51 @@
/*
Copyright 2013 Jun Wako <wakojun@gmail.com>
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

View File

@ -63,11 +63,11 @@ void host_keyboard_send(report_keyboard_t *report)
(*driver->send_keyboard)(report); (*driver->send_keyboard)(report);
if (debug_keyboard) { if (debug_keyboard) {
print("keys: "); dprint("keys: ");
for (int i = 0; i < REPORT_KEYS; i++) { 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) { if ((code>>3) < REPORT_KEYS) {
keyboard_report->keys[code>>3] |= 1<<(code&7); keyboard_report->keys[code>>3] |= 1<<(code&7);
} else { } 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) { if ((code>>3) < REPORT_KEYS) {
keyboard_report->keys[code>>3] &= ~(1<<(code&7)); keyboard_report->keys[code>>3] &= ~(1<<(code&7));
} else { } else {
debug("del_key_bit: can't del: "); phex(code); debug("\n"); dprintf("del_key_bit: can't del: %02X\n", code);
} }
} }

49
common/nodebug.h Normal file
View File

@ -0,0 +1,49 @@
/*
Copyright 2013 Jun Wako <wakojun@gmail.com>
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

View File

@ -1,4 +1,4 @@
/* Copyright 2012 Jun Wako <wakojun@gmail.com> */ /* Copyright 2012,2013 Jun Wako <wakojun@gmail.com> */
/* 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
@ -29,20 +29,14 @@
#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;
@ -54,140 +48,15 @@ void print_S(const char *s)
} }
} }
/* print string stored in program memory(FLASH) void print_lf(void)
* print_P(PSTR("hello world");
* This consumes relatively abundant FLASH memory area not SRAM.
*/
void print_P(const char *s)
{ {
uint8_t c; sendchar('\n');
while (1) {
c = pgm_read_byte(s++);
if (!c) break;
if (c == '\n') sendchar('\r');
sendchar(c);
}
} }
void print_CRLF(void) void print_crlf(void)
{ {
sendchar('\r'); sendchar('\n'); 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)
{
print_bin_reverse8(data);
print_bin_reverse8(data>>8);
}
void print_bin_reverse32(uint32_t data)
{
print_bin_reverse8(data);
print_bin_reverse8(data>>8);
print_bin_reverse8(data>>16);
print_bin_reverse8(data>>24);
} }
#endif #endif

View File

@ -28,6 +28,8 @@
#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
@ -49,17 +51,17 @@
#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_dec(v) xprintf(#v ": %u\n", v)
#define print_val_decs(v) do { print_P(PSTR(#v ": ")); print_decs(v); print_P(PSTR("\n")); } while (0) #define print_val_decs(v) xprintf(#v ": %d\n", v)
#define print_val_hex8(v) do { print_P(PSTR(#v ": ")); print_hex8(v); print_P(PSTR("\n")); } while (0) #define print_val_hex8(v) xprintf(#v ": %X\n", v)
#define print_val_hex16(v) do { print_P(PSTR(#v ": ")); print_hex16(v); print_P(PSTR("\n")); } while (0) #define print_val_hex16(v) xprintf(#v ": %02X\n", v)
#define print_val_hex32(v) do { print_P(PSTR(#v ": ")); print_hex32(v); print_P(PSTR("\n")); } while (0) #define print_val_hex32(v) xprintf(#v ": %04lX\n", v)
#define print_val_bin8(v) do { print_P(PSTR(#v ": ")); print_bin8(v); print_P(PSTR("\n")); } while (0) #define print_val_bin8(v) xprintf(#v ": %08b\n", v)
#define print_val_bin16(v) do { print_P(PSTR(#v ": ")); print_bin16(v); print_P(PSTR("\n")); } while (0) #define print_val_bin16(v) xprintf(#v ": %016b\n", v)
#define print_val_bin32(v) do { print_P(PSTR(#v ": ")); print_bin32(v); print_P(PSTR("\n")); } while (0) #define print_val_bin32(v) xprintf(#v ": %032lb\n", v)
#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_reverse8(v) xprintf(#v ": %08b\n", bitrev(v))
#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_reverse16(v) xprintf(#v ": %016b\n", bitrev16(v))
#define print_val_bin_reverse32(v) do { print_P(PSTR(#v ": ")); print_bin_reverse32(v); print_P(PSTR("\n")); } while (0) #define print_val_bin_reverse32(v) xprintf(#v ": %032lb\n", bitrev32(v))
@ -68,34 +70,46 @@
#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); #define print_dec(i) xprintf("%u", i)
void print_decs(int16_t data); #define print_decs(i) xprintf("%d", i)
/* hex */ /* hex */
void print_hex4(uint8_t data); #define print_hex4(i) xprintf("%X", i)
void print_hex8(uint8_t data); #define print_hex8(i) xprintf("%02X", i)
void print_hex16(uint16_t data); #define print_hex16(i) xprintf("%04X", i)
void print_hex32(uint32_t data); #define print_hex32(i) xprintf("%08lX", i)
/* binary */ /* binary */
void print_bin4(uint8_t data); #define print_bin4(i) xprintf("%04b", i)
void print_bin8(uint8_t data); #define print_bin8(i) xprintf("%08b", i)
void print_bin16(uint16_t data); #define print_bin16(i) xprintf("%016b", i)
void print_bin32(uint32_t data); #define print_bin32(i) xprintf("%032lb", i)
void print_bin_reverse8(uint8_t data);
void print_bin_reverse16(uint16_t data); #define print_bin_reverse8(i) xprintf("%08b", bitrev(i))
void print_bin_reverse32(uint32_t data); #define print_bin_reverse16(i) xprintf("%016b", bitrev16(i))
#define print_bin_reverse32(i) xprintf("%032lb", bitrev32(i))
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
@ -105,7 +119,6 @@ void print_bin_reverse32(uint32_t data);
#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)

View File

@ -77,3 +77,25 @@ uint8_t biton32(uint32_t bits)
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;
}

View File

@ -36,4 +36,8 @@ uint8_t biton(uint8_t 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

500
common/xprintf.S Normal file
View File

@ -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

103
common/xprintf.h Normal file
View File

@ -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