~ruther/qmk_firmware

862f519e241b83113566eebde71841958b2d00b7 — tmk 11 years ago 01fa462
Add software UART and battery monitor
M keyboard/hhkb_rn42/Makefile => keyboard/hhkb_rn42/Makefile +1 -0
@@ 53,6 53,7 @@ SRC +=	keymap_common.c \
	matrix.c \
	led.c \
	serial_uart.c \
	suart.S \
	rn42.c \
	main.c


M keyboard/hhkb_rn42/config.h => keyboard/hhkb_rn42/config.h +7 -0
@@ 76,6 76,13 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
#endif


/* for debug */
#define SUART_OUT_PORT  PORTD
#define SUART_OUT_BIT   0
#define SUART_IN_PIN    PIND
#define SUART_IN_BIT    1


/*
 * Feature disable options
 *  These options are also useful to firmware size reduction.

M keyboard/hhkb_rn42/main.c => keyboard/hhkb_rn42/main.c +46 -3
@@ 12,10 12,16 @@
#include "action.h"
#include "action_util.h"
#include "wait.h"

#include "suart.h"

bool config_mode = false;

static int8_t sendchar_func(uint8_t c)
{
    sendchar(c);    // LUFA
    xmit(c);        // SUART
}

static void SetupHardware(void)
{
    /* Disable watchdog if enabled by bootloader/fuses */


@@ 32,7 38,16 @@ static void SetupHardware(void)

    // for Console_Task
    USB_Device_EnableSOFEvents();
    print_set_sendchar(sendchar);
    print_set_sendchar(sendchar_func);

    // SUART PD0:output, PD1:input
    DDRD |= (1<<0);
    PORTD |= (1<<0);
    DDRD &= ~(1<<1);
    PORTD |= (1<<1);

    // CTS control
    CTS_INIT();
}

static bool force_usb = false;


@@ 70,6 85,12 @@ int main(void)
    sleep_led_init();
#endif

    // ADC for battery
    //ADMUX = (1<<REFS0); // Ref:AVCC, Input:ADC0(PF0)
    ADMUX = (1<<REFS1) | (1<<REFS0); // Ref:AVCC, Input:ADC0(PF0)
    ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Prescale:128
    ADCSRA |= (1<<ADEN); // enable ADC

    print("Keyboard start.\n");
    while (1) {
/*


@@ 89,7 110,12 @@ int main(void)

        int16_t c;
        if (config_mode) {
            while ((c = serial_recv2()) != -1) xprintf("%c", c);
            while ((c = serial_recv2()) != -1) {
                // without flow control it'll fail to receive data when flooded
                CTS_HI();
                xprintf("%c", c);
                CTS_LO();
            }
        } else {
            while ((c = serial_recv2()) != -1) {
                // LED Out report: 0xFE, 0x02, 0x01, <leds>


@@ 146,6 172,7 @@ bool command_extra(uint8_t code)
            print("a:   Bluetooth auto connect\n");
            print("del: Bluetooth disconnect\n");
            print("i:   info\n");
            print("b:   battery voltage\n");

            if (config_mode) {
                return true;


@@ 208,6 235,22 @@ bool command_extra(uint8_t code)
            xprintf("rn42_ready(): %X\n", rn42_ready());
            xprintf("config_mode: %X\n", config_mode);
            return true;
        case KC_B:
            // battery monitor
            ADCSRA |= (1<<ADEN) | (1<<ADSC);
            while (ADCSRA & (1<<ADSC)) ;
            uint16_t bat = ADCL;
            bat = ADCH<<8 | bat;
            xprintf("BAT: %04X\n", bat);

            ADCSRA |= (1<<ADEN) | (1<<ADSC);
            while (ADCSRA & (1<<ADSC)) ;
            bat = ADCL;
            bat = ADCH<<8 | bat;
            xprintf("BAT: %04X\n", bat);

            ADCSRA &= ~(1<<ADEN);
            return true;
        default:
            if (config_mode)
                return true;

M keyboard/hhkb_rn42/rn42.c => keyboard/hhkb_rn42/rn42.c +4 -0
@@ 70,9 70,11 @@ static uint8_t keyboard_leds(void) { return 0; }
static void send_keyboard(report_keyboard_t *report)
{
    // wake from deep sleep
/*
    PORTD |= (1<<5);    // high
    wait_ms(5);
    PORTD &= ~(1<<5);   // low
*/

    serial_send(0xFD);  // Raw report mode
    serial_send(9);     // length


@@ 90,9 92,11 @@ static void send_keyboard(report_keyboard_t *report)
static void send_mouse(report_mouse_t *report)
{
    // wake from deep sleep
/*
    PORTD |= (1<<5);    // high
    wait_ms(5);
    PORTD &= ~(1<<5);   // low
*/

    serial_send(0xFD);  // Raw report mode
    serial_send(5);     // length

M keyboard/hhkb_rn42/rn42.h => keyboard/hhkb_rn42/rn42.h +5 -0
@@ 3,6 3,11 @@

#include <stdbool.h>

// RN-42 CTS pin
#define CTS_INIT()  (DDRD  |=  (1<<5))
#define CTS_HI()    (PORTD |=  (1<<5))
#define CTS_LO()    (PORTD &= ~(1<<5))

host_driver_t rn42_driver;
host_driver_t rn42_config_driver;


A keyboard/hhkb_rn42/suart.S => keyboard/hhkb_rn42/suart.S +156 -0
@@ 0,0 1,156 @@
;---------------------------------------------------------------------------;
; Software implemented UART module                                          ;
; (C)ChaN, 2005 (http://elm-chan.org/)                                      ;
;---------------------------------------------------------------------------;
; Bit rate settings:
;
;            1MHz  2MHz  4MHz  6MHz  8MHz  10MHz  12MHz  16MHz  20MHz
;   2.4kbps   138     -     -     -     -      -      -      -      -
;   4.8kbps    68   138     -     -     -      -      -      -      -
;   9.6kbps    33    68   138   208     -      -      -      -      -
;  19.2kbps     -    33    68   102   138    173    208      -      -
;  38.4kbps     -     -    33    50    68     85    102    138    172
;  57.6kbps     -     -    21    33    44     56     68     91    114
; 115.2kbps     -     -     -     -    21     27     33     44     56

.nolist
#include <avr/io.h>
.list

#define	BPS	44 	/* Bit delay. (see above table) */
#define	BIDIR	0	/* 0:Separated Tx/Rx, 1:Shared Tx/Rx */

#define	OUT_1		sbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT	/* Output 1 */
#define	OUT_0		cbi _SFR_IO_ADDR(SUART_OUT_PORT), SUART_OUT_BIT	/* Output 0 */
#define	SKIP_IN_1	sbis _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT	/* Skip if 1 */
#define	SKIP_IN_0	sbic _SFR_IO_ADDR(SUART_IN_PIN), SUART_IN_BIT	/* Skip if 0 */



#ifdef SPM_PAGESIZE
.macro	_LPMI	reg
	lpm	\reg, Z+
.endm
.macro	_MOVW	dh,dl, sh,sl
	movw	\dl, \sl
.endm
#else
.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



;---------------------------------------------------------------------------;
; Transmit a byte in serial format of N81
;
;Prototype: void xmit (uint8_t data);
;Size: 16 words

.global xmit
.func xmit
xmit:
#if BIDIR
	ldi	r23, BPS-1	;Pre-idle time for bidirectional data line
5:	dec	r23     	;
	brne	5b		;/
#endif
	in	r0, _SFR_IO_ADDR(SREG)	;Save flags

	com	r24		;C = start bit
	ldi	r25, 10		;Bit counter
	cli			;Start critical section

1:	ldi	r23, BPS-1	;----- Bit transferring loop 
2:	dec	r23     	;Wait for a bit time
	brne	2b		;/
	brcs	3f		;MISO = bit to be sent
	OUT_1			;
3:	brcc	4f		;
	OUT_0			;/
4:	lsr	r24     	;Get next bit into C
	dec	r25     	;All bits sent?
	brne	1b	     	;  no, coutinue

	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
	ret
.endfunc



;---------------------------------------------------------------------------;
; Receive a byte
;
;Prototype: uint8_t rcvr (void);
;Size: 19 words

.global rcvr
.func rcvr
rcvr:
	in	r0, _SFR_IO_ADDR(SREG)	;Save flags

	ldi	r24, 0x80	;Receiving shift reg
	cli			;Start critical section

1:	SKIP_IN_1		;Wait for idle
	rjmp	1b
2:	SKIP_IN_0		;Wait for start bit
	rjmp	2b
	ldi	r25, BPS/2	;Wait for half bit time
3:	dec	r25
	brne	3b

4:	ldi	r25, BPS	;----- Bit receiving loop
5:	dec	r25     	;Wait for a bit time
	brne	5b		;/
	lsr	r24     	;Next bit
	SKIP_IN_0		;Get a data bit into r24.7
	ori	r24, 0x80
	brcc	4b	     	;All bits received?  no, continue

	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
	ret
.endfunc


; Not wait for start bit. This should be called after detecting start bit.
.global recv
.func recv
recv:
	in	r0, _SFR_IO_ADDR(SREG)	;Save flags

	ldi	r24, 0x80	;Receiving shift reg
	cli			;Start critical section

;1:	SKIP_IN_1		;Wait for idle
;	rjmp	1b
;2:	SKIP_IN_0		;Wait for start bit
;	rjmp	2b
	ldi	r25, BPS/2	;Wait for half bit time
3:	dec	r25
	brne	3b

4:	ldi	r25, BPS	;----- Bit receiving loop
5:	dec	r25     	;Wait for a bit time
	brne	5b		;/
	lsr	r24     	;Next bit
	SKIP_IN_0		;Get a data bit into r24.7
	ori	r24, 0x80
	brcc	4b	     	;All bits received?  no, continue

	ldi	r25, BPS/2	;Wait for half bit time
6:	dec	r25
	brne	6b
7:	SKIP_IN_1		;Wait for stop bit
	rjmp	7b

	out	_SFR_IO_ADDR(SREG), r0	;End of critical section
	ret
.endfunc

A keyboard/hhkb_rn42/suart.h => keyboard/hhkb_rn42/suart.h +8 -0
@@ 0,0 1,8 @@
#ifndef SUART
#define SUART

void xmit(uint8_t);
uint8_t rcvr(void);
uint8_t recv(void);

#endif	/* SUART */