PIN input CIR support change
This commit is contained in:
25
ChangeLog
25
ChangeLog
@@ -1,5 +1,30 @@
|
|||||||
2011-11-01 Niibe Yutaka <gniibe@fsij.org>
|
2011-11-01 Niibe Yutaka <gniibe@fsij.org>
|
||||||
|
|
||||||
|
* boards/STBEE_MINI/board.h (TIMx): Define.
|
||||||
|
boards/STBEE/board.h (TIMx): Ditto.
|
||||||
|
boards/STM8S_DISCOVERY/board.h: Ditto.
|
||||||
|
|
||||||
|
* src/pin-cir.c (pinpad_getline): New.
|
||||||
|
(cir_timer_interrupt, cir_ext_interrupt): Use TIMx.
|
||||||
|
(cir_key_is_backspace, cir_key_is_enter, pin_main, pindisp):
|
||||||
|
Remove.
|
||||||
|
(cir_codetable_dell_mr425, cir_codetable_aquos)
|
||||||
|
(cir_codetable_regza, cir_codetable_bravia, ch_is_backspace)
|
||||||
|
(ch_is_enter, find_char_codetable, hex, cir_getchar): New.
|
||||||
|
(cir_timer_interrupt): Don't filter out ADDRESS.
|
||||||
|
|
||||||
|
* src/openpgp.c (get_pinpad_input): Don't invoke thread,
|
||||||
|
but just call pinpad_getline.
|
||||||
|
|
||||||
|
* src/main.c (display_interaction, display_fatal_code)
|
||||||
|
(display_status_code, led_blink): New.
|
||||||
|
(main): Call display_* routine.
|
||||||
|
(fatal): Notify main thread.
|
||||||
|
* src/usb_prop.c (gnuk_device_SetConfiguration): Notify main
|
||||||
|
thread.
|
||||||
|
|
||||||
|
* src/pin-cir.c (pindisp): Remove.
|
||||||
|
|
||||||
* boards/FST_01_00: New (for 8MHz FST-01).
|
* boards/FST_01_00: New (for 8MHz FST-01).
|
||||||
|
|
||||||
* src/ac.c (calc_md): Fix comparison.
|
* src/ac.c (calc_md): Fix comparison.
|
||||||
|
|||||||
@@ -40,6 +40,10 @@
|
|||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
#define HAVE_7SEGLED 1
|
#define HAVE_7SEGLED 1
|
||||||
|
/*
|
||||||
|
* Timer assignment for CIR
|
||||||
|
*/
|
||||||
|
#define TIMx TIM3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -41,6 +41,10 @@
|
|||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
#define HAVE_7SEGLED 1
|
#define HAVE_7SEGLED 1
|
||||||
|
/*
|
||||||
|
* Timer assignment for CIR
|
||||||
|
*/
|
||||||
|
#define TIMx TIM3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -56,6 +56,11 @@
|
|||||||
*/
|
*/
|
||||||
#define GPIOA_LED 8
|
#define GPIOA_LED 8
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timer assignment for CIR
|
||||||
|
*/
|
||||||
|
#define TIMx TIM3
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I/O ports initial setup, this configuration is established soon after reset
|
* I/O ports initial setup, this configuration is established soon after reset
|
||||||
* in the initialization code.
|
* in the initialization code.
|
||||||
|
|||||||
13
src/gnuk.h
13
src/gnuk.h
@@ -348,5 +348,16 @@ extern void dial_sw_enable (void);
|
|||||||
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
extern uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||||
extern uint8_t pin_input_len;
|
extern uint8_t pin_input_len;
|
||||||
|
|
||||||
extern msg_t pin_main (void *arg);
|
extern int pinpad_getline (int msg_code, systime_t timeout);
|
||||||
|
|
||||||
|
#define LED_ONESHOT_SHORT ((eventmask_t)1)
|
||||||
|
#define LED_ONESHOT_LONG ((eventmask_t)2)
|
||||||
|
#define LED_TWOSHOT ((eventmask_t)4)
|
||||||
|
#define LED_STATUS_MODE ((eventmask_t)8)
|
||||||
|
#define LED_INPUT_MODE ((eventmask_t)16)
|
||||||
|
#define LED_FATAL_MODE ((eventmask_t)32)
|
||||||
|
extern Thread *main_thread;
|
||||||
|
extern void led_blink (int spec);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
280
src/main.c
280
src/main.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* main.c - main routine of Gnuk
|
* main.c - main routine of Gnuk
|
||||||
*
|
*
|
||||||
* Copyright (C) 2010 Free Software Initiative of Japan
|
* Copyright (C) 2010, 2011 Free Software Initiative of Japan
|
||||||
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
* Author: NIIBE Yutaka <gniibe@fsij.org>
|
||||||
*
|
*
|
||||||
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
* This file is a part of Gnuk, a GnuPG USB Token implementation.
|
||||||
@@ -196,6 +196,161 @@ device_initialize_once (void)
|
|||||||
|
|
||||||
static volatile uint8_t fatal_code;
|
static volatile uint8_t fatal_code;
|
||||||
|
|
||||||
|
Thread *main_thread;
|
||||||
|
|
||||||
|
#define GNUK_INIT 0
|
||||||
|
#define GNUK_RUNNING 1
|
||||||
|
#define GNUK_INPUT_WAIT 2
|
||||||
|
#define GNUK_FATAL 255
|
||||||
|
/*
|
||||||
|
* 0 for initializing
|
||||||
|
* 1 for normal mode
|
||||||
|
* 2 for input waiting
|
||||||
|
* 255 for fatal
|
||||||
|
*/
|
||||||
|
static uint8_t main_mode;
|
||||||
|
|
||||||
|
static void display_interaction (void)
|
||||||
|
{
|
||||||
|
eventmask_t m;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
m = chEvtWaitOne (ALL_EVENTS);
|
||||||
|
set_led (1);
|
||||||
|
switch (m)
|
||||||
|
{
|
||||||
|
case LED_ONESHOT_SHORT:
|
||||||
|
chThdSleep (MS2ST (100));
|
||||||
|
break;
|
||||||
|
case LED_ONESHOT_LONG:
|
||||||
|
chThdSleep (MS2ST (400));
|
||||||
|
break;
|
||||||
|
case LED_TWOSHOT:
|
||||||
|
chThdSleep (MS2ST (50));
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (MS2ST (50));
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (MS2ST (50));
|
||||||
|
break;
|
||||||
|
case LED_STATUS_MODE:
|
||||||
|
chThdSleep (MS2ST (400));
|
||||||
|
set_led (0);
|
||||||
|
return;
|
||||||
|
case LED_FATAL_MODE:
|
||||||
|
main_mode = GNUK_FATAL;
|
||||||
|
set_led (0);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
set_led (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_fatal_code (void)
|
||||||
|
{
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP);
|
||||||
|
set_led (1);
|
||||||
|
if (fatal_code & 1)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
if (fatal_code & 2)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void display_status_code (void)
|
||||||
|
{
|
||||||
|
if (icc_state == ICC_STATE_START)
|
||||||
|
{
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP * 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* GPGthread running */
|
||||||
|
{
|
||||||
|
set_led (1);
|
||||||
|
if ((auth_status & AC_ADMIN_AUTHORIZED) != 0)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
if ((auth_status & AC_OTHER_AUTHORIZED) != 0)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
if ((auth_status & AC_PSO_CDS_AUTHORIZED) != 0)
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
else
|
||||||
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
|
|
||||||
|
if (icc_state == ICC_STATE_WAIT)
|
||||||
|
{
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP * 2);
|
||||||
|
}
|
||||||
|
else if (icc_state == ICC_STATE_RECEIVE)
|
||||||
|
{
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_ONE);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
set_led (1);
|
||||||
|
chThdSleep (LED_TIMEOUT_STOP);
|
||||||
|
set_led (0);
|
||||||
|
chThdSleep (LED_TIMEOUT_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
led_blink (int spec)
|
||||||
|
{
|
||||||
|
if (spec == 0)
|
||||||
|
chEvtSignal (main_thread, LED_ONESHOT_SHORT);
|
||||||
|
else if (spec == 1)
|
||||||
|
chEvtSignal (main_thread, LED_ONESHOT_LONG);
|
||||||
|
else
|
||||||
|
chEvtSignal (main_thread, LED_TWOSHOT);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Entry point.
|
* Entry point.
|
||||||
*
|
*
|
||||||
@@ -210,6 +365,8 @@ main (int argc, char **argv)
|
|||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
|
main_thread = chThdSelf ();
|
||||||
|
|
||||||
flash_unlock ();
|
flash_unlock ();
|
||||||
device_initialize_once ();
|
device_initialize_once ();
|
||||||
usb_lld_init ();
|
usb_lld_init ();
|
||||||
@@ -231,105 +388,47 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
eventmask_t m;
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
m = chEvtWaitOneTimeout (ALL_EVENTS, LED_TIMEOUT_INTERVAL);
|
||||||
if (fatal_code != 0)
|
switch (m)
|
||||||
{
|
{
|
||||||
|
case LED_STATUS_MODE:
|
||||||
|
main_mode = GNUK_RUNNING;
|
||||||
|
break;
|
||||||
|
case LED_FATAL_MODE:
|
||||||
|
main_mode = GNUK_FATAL;
|
||||||
|
break;
|
||||||
|
case LED_INPUT_MODE:
|
||||||
|
main_mode = GNUK_INPUT_WAIT;
|
||||||
set_led (1);
|
set_led (1);
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
chThdSleep (MS2ST (400));
|
||||||
set_led (0);
|
set_led (0);
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
break;
|
||||||
set_led (1);
|
default:
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
break;
|
||||||
set_led (0);
|
}
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP);
|
|
||||||
set_led (1);
|
|
||||||
if (fatal_code & 1)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
if (fatal_code & 2)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bDeviceState != CONFIGURED)
|
switch (main_mode)
|
||||||
{
|
{
|
||||||
|
case GNUK_FATAL:
|
||||||
|
display_fatal_code ();
|
||||||
|
break;
|
||||||
|
case GNUK_INIT:
|
||||||
set_led (1);
|
set_led (1);
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
chThdSleep (LED_TIMEOUT_ZERO);
|
||||||
set_led (0);
|
set_led (0);
|
||||||
chThdSleep (LED_TIMEOUT_STOP * 3);
|
chThdSleep (LED_TIMEOUT_STOP * 3);
|
||||||
}
|
break;
|
||||||
else
|
case GNUK_INPUT_WAIT:
|
||||||
/* Device configured */
|
display_interaction ();
|
||||||
if (icc_state == ICC_STATE_START)
|
break;
|
||||||
{
|
case GNUK_RUNNING:
|
||||||
set_led (1);
|
default:
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
display_status_code ();
|
||||||
set_led (0);
|
break;
|
||||||
chThdSleep (LED_TIMEOUT_STOP * 3);
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
/* GPGthread running */
|
|
||||||
{
|
|
||||||
set_led (1);
|
|
||||||
if ((auth_status & AC_ADMIN_AUTHORIZED) != 0)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
if ((auth_status & AC_OTHER_AUTHORIZED) != 0)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
if ((auth_status & AC_PSO_CDS_AUTHORIZED) != 0)
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
else
|
|
||||||
chThdSleep (LED_TIMEOUT_ZERO);
|
|
||||||
|
|
||||||
if (icc_state == ICC_STATE_WAIT)
|
|
||||||
{
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP * 2);
|
|
||||||
}
|
|
||||||
else if (icc_state == ICC_STATE_RECEIVE)
|
|
||||||
{
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
chThdSleep (LED_TIMEOUT_ONE);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
set_led (1);
|
|
||||||
chThdSleep (LED_TIMEOUT_STOP);
|
|
||||||
set_led (0);
|
|
||||||
chThdSleep (LED_TIMEOUT_INTERVAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG_MORE
|
#ifdef DEBUG_MORE
|
||||||
if (bDeviceState == CONFIGURED && (count % 10) == 0)
|
if (bDeviceState == CONFIGURED && (count % 10) == 0)
|
||||||
@@ -349,6 +448,7 @@ void
|
|||||||
fatal (uint8_t code)
|
fatal (uint8_t code)
|
||||||
{
|
{
|
||||||
fatal_code = code;
|
fatal_code = code;
|
||||||
|
chEvtSignal (main_thread, LED_FATAL_MODE);
|
||||||
_write ("fatal\r\n", 7);
|
_write ("fatal\r\n", 7);
|
||||||
for (;;);
|
for (;;);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,24 +97,19 @@ gpg_fini (void)
|
|||||||
|
|
||||||
#if defined(PINPAD_SUPPORT)
|
#if defined(PINPAD_SUPPORT)
|
||||||
/*
|
/*
|
||||||
* Invoke the thread PIN_MAIN, and let user input PIN string.
|
* Let user input PIN string.
|
||||||
* Return length of the string.
|
* Return length of the string.
|
||||||
* The string itself is in PIN_INPUT_BUFFER.
|
* The string itself is in PIN_INPUT_BUFFER.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
get_pinpad_input (int msg_code)
|
get_pinpad_input (int msg_code)
|
||||||
{
|
{
|
||||||
Thread *t;
|
int r;
|
||||||
|
|
||||||
t = chThdCreateFromHeap (NULL, THD_WA_SIZE (128),
|
chEvtSignal (main_thread, LED_INPUT_MODE);
|
||||||
NORMALPRIO, pin_main, (void *)msg_code);
|
r = pinpad_getline (msg_code, MS2ST (8000));
|
||||||
if (t == NULL)
|
chEvtSignal (main_thread, LED_STATUS_MODE);
|
||||||
return -1;
|
return r;
|
||||||
else
|
|
||||||
{
|
|
||||||
chThdWait (t);
|
|
||||||
return pin_input_len;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
682
src/pin-cir.c
682
src/pin-cir.c
@@ -27,13 +27,41 @@
|
|||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "gnuk.h"
|
#include "gnuk.h"
|
||||||
|
|
||||||
#if 0
|
#ifdef DEBUG
|
||||||
#define DEBUG_CIR 1
|
#define DEBUG_CIR 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
uint8_t pin_input_buffer[MAX_PIN_CHARS];
|
||||||
uint8_t pin_input_len;
|
uint8_t pin_input_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supported/tested TV controllers:
|
||||||
|
*
|
||||||
|
* Controller of Toshiba REGZA
|
||||||
|
* Controller of Sony BRAVIA
|
||||||
|
* Controller of Sharp AQUOS
|
||||||
|
* Dell Wireless Travel Remote MR425
|
||||||
|
*
|
||||||
|
* The code supports RC-5 protocol in fact, but I don't have any
|
||||||
|
* controller at hand which I can test with, so I don't have any data
|
||||||
|
* for controller of RC-5.
|
||||||
|
*
|
||||||
|
* Current code assumes following mapping:
|
||||||
|
*
|
||||||
|
* --------------------------------------
|
||||||
|
* Protocol Controller
|
||||||
|
* --------------------------------------
|
||||||
|
* RC-6 Dell MR425
|
||||||
|
* NEC Toshiba REGZA
|
||||||
|
* Sharp Sharp AQUOS
|
||||||
|
* Sony Sony BRAVIA
|
||||||
|
* --------------------------------------
|
||||||
|
*
|
||||||
|
* In future, when I will have other controllers, this mapping will be
|
||||||
|
* (should be) configurable, at compile time at least, preferably at
|
||||||
|
* runtime.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Philips RC-5 Protocol: 14-bit (MSB first)
|
* Philips RC-5 Protocol: 14-bit (MSB first)
|
||||||
*
|
*
|
||||||
@@ -69,18 +97,26 @@ uint8_t pin_input_len;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PB0 / TIM3_CH3
|
* The implementation note of CIR signal decoding (on STM32).
|
||||||
|
*
|
||||||
|
* (1) Use EXTI interrupt to detect the first edge of signal.
|
||||||
|
* (2) Use Timer (with PWM input mode) to measure timings of square wave.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Timer settings.
|
||||||
|
*
|
||||||
|
* See THE reference manual (RM0008) section 15.3.6 PWM input mode.
|
||||||
*
|
*
|
||||||
* 72MHz
|
* 72MHz
|
||||||
*
|
|
||||||
* Prescaler = 72
|
* Prescaler = 72
|
||||||
*
|
*
|
||||||
* 1us
|
* 1us
|
||||||
*
|
*
|
||||||
*
|
* TIMx_CR1
|
||||||
* TIM3_CR1
|
* CKD = 00 (tDTS = tCK_INT)
|
||||||
* CKD = 10 (sampling x4)
|
* ARPE = 1 (buffered)
|
||||||
* ARPE = 0 (not buffered)
|
|
||||||
* CMS = 00 (up counter)
|
* CMS = 00 (up counter)
|
||||||
* DIR = 0 (up counter)
|
* DIR = 0 (up counter)
|
||||||
* OPM = 0 (up counter)
|
* OPM = 0 (up counter)
|
||||||
@@ -88,13 +124,13 @@ uint8_t pin_input_len;
|
|||||||
* UDIS = 0 (UEV (update event) enabled)
|
* UDIS = 0 (UEV (update event) enabled)
|
||||||
* CEN = 1 (counter enable)
|
* CEN = 1 (counter enable)
|
||||||
*
|
*
|
||||||
* TIM3_CR2
|
* TIMx_CR2
|
||||||
* TI1S = 1 (TI1 is XOR of ch1, ch2, ch3)
|
* TI1S = 1 (TI1 is XOR of ch1, ch2, ch3)
|
||||||
* MMS = 000 (TRGO at Reset)
|
* MMS = 000 (TRGO at Reset)
|
||||||
* CCDS = 0 (DMA on capture)
|
* CCDS = 0 (DMA on capture)
|
||||||
* RSVD = 000
|
* RSVD = 000
|
||||||
*
|
*
|
||||||
* TIM3_SMCR
|
* TIMx_SMCR
|
||||||
* ETP = 0
|
* ETP = 0
|
||||||
* ECE = 0
|
* ECE = 0
|
||||||
* ETPS = 00
|
* ETPS = 00
|
||||||
@@ -104,60 +140,37 @@ uint8_t pin_input_len;
|
|||||||
* RSVD = 0
|
* RSVD = 0
|
||||||
* SMS = 100 (Reset-mode)
|
* SMS = 100 (Reset-mode)
|
||||||
*
|
*
|
||||||
* TIM3_DIER
|
* TIMx_DIER
|
||||||
*
|
*
|
||||||
* TIM3_SR
|
* TIMx_SR
|
||||||
*
|
*
|
||||||
* TIM3_EGR
|
* TIMx_EGR
|
||||||
*
|
*
|
||||||
* TIM3_CCMR1
|
* TIMx_CCMR1
|
||||||
* CC1S = 01 (TI1 selected)
|
* CC1S = 01 (TI1 selected)
|
||||||
* CC2S = 10 (TI1 selected)
|
* CC2S = 10 (TI1 selected)
|
||||||
|
* IC1F = 1001 (fSAMPLING=fDTS/8, N=8)
|
||||||
|
* IC2F = 1001 (fSAMPLING=fDTS/8, N=8)
|
||||||
*
|
*
|
||||||
* TIM3_CCMR2
|
* TIMx_CCMR2
|
||||||
*
|
*
|
||||||
* TIM3_CCER
|
* TIMx_CCER
|
||||||
* CC2P = 1 (polarity = falling edge: TI1FP1)
|
* CC2P = 1 (polarity = falling edge: TI1FP1)
|
||||||
* CC2E = 1
|
* CC2E = 1
|
||||||
* CC1P = 0 (polarity = rising edge: TI1FP1)
|
* CC1P = 0 (polarity = rising edge: TI1FP1)
|
||||||
* CC1E = 1
|
* CC1E = 1
|
||||||
*
|
*
|
||||||
* TIM3_CNT
|
* TIMx_CNT
|
||||||
* TIM3_PSC = 71
|
* TIMx_PSC = 71
|
||||||
* TIM3_ARR = 18000
|
* TIMx_ARR = 18000
|
||||||
*
|
*
|
||||||
* TIM3_CCR1 period
|
* TIMx_CCR1 period
|
||||||
* TIM3_CCR2 duty
|
* TIMx_CCR2 duty
|
||||||
*
|
*
|
||||||
* TIM3_DCR
|
* TIMx_DCR
|
||||||
* TIM3_DMAR
|
* TIMx_DMAR
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PINDISP_TIMEOUT_INTERVAL0 MS2ST(25)
|
|
||||||
#define PINDISP_TIMEOUT_INTERVAL1 MS2ST(300)
|
|
||||||
|
|
||||||
static void
|
|
||||||
pindisp (uint8_t c)
|
|
||||||
{
|
|
||||||
#if defined(HAVE_7SEGLED)
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case 'G':
|
|
||||||
palWritePort (IOPORT2, 0xa1ff);
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
palWritePort (IOPORT2, 0x98ff);
|
|
||||||
break;
|
|
||||||
case '.':
|
|
||||||
palWritePort (IOPORT2, 0x7fff);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
palWritePort (IOPORT2, 0xffff);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
(void)c;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(DEBUG_CIR)
|
#if defined(DEBUG_CIR)
|
||||||
static uint16_t intr_ext;
|
static uint16_t intr_ext;
|
||||||
@@ -179,14 +192,6 @@ static uint8_t cir_proto;
|
|||||||
#define CIR_PROTO_NEC 5
|
#define CIR_PROTO_NEC 5
|
||||||
#define CIR_PROTO_SHARP 6
|
#define CIR_PROTO_SHARP 6
|
||||||
|
|
||||||
#define CIR_KEY_RC6_ENTER 0x0d /* Mute */
|
|
||||||
#define CIR_KEY_RC6_BACKSPACE 0xa4 /* <= */
|
|
||||||
#define CIR_KEY_NEC_ENTER 0x3d /* 'kettei' */
|
|
||||||
#define CIR_KEY_NEC_BACKSPACE 0x3b /* 'modoru' */
|
|
||||||
#define CIR_KEY_SONY_ENTER 0x65 /* 'kettei' */
|
|
||||||
#define CIR_KEY_SONY_BACKSPACE 0xa3 /* 'modoru' */
|
|
||||||
#define CIR_KEY_SHARP_ENTER 0x0252 /* 'kettei' */
|
|
||||||
#define CIR_KEY_SHARP_BACKSPACE 0xe4 /* 'modoru' */
|
|
||||||
|
|
||||||
/* CIR_DATA_ZERO: Used for zero-bit handling of RC-5/RC-6 */
|
/* CIR_DATA_ZERO: Used for zero-bit handling of RC-5/RC-6 */
|
||||||
static uint8_t cir_data_zero;
|
static uint8_t cir_data_zero;
|
||||||
@@ -196,6 +201,388 @@ static uint8_t cir_seq;
|
|||||||
static systime_t cir_input_last;
|
static systime_t cir_input_last;
|
||||||
#define CIR_PERIOD_INHIBIT_CHATTER 200 /* mili second */
|
#define CIR_PERIOD_INHIBIT_CHATTER 200 /* mili second */
|
||||||
|
|
||||||
|
static void
|
||||||
|
cir_init (void)
|
||||||
|
{
|
||||||
|
cir_data = 0;
|
||||||
|
cir_seq = 0;
|
||||||
|
/* Don't touch cir_proto here */
|
||||||
|
cir_ext_enable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define CH_RETURN 0x0d
|
||||||
|
#define CH_BACKSPACE 0x08
|
||||||
|
|
||||||
|
struct codetable {
|
||||||
|
uint16_t cir_code;
|
||||||
|
uint8_t char_code;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* NOTE: no way to input '0' */
|
||||||
|
static const struct codetable
|
||||||
|
cir_codetable_dell_mr425[] = {
|
||||||
|
{0x10, '7' }, /* Speaker Louder */
|
||||||
|
{0x11, '8' }, /* Speaker Quieter */
|
||||||
|
{0x0d, '9' }, /* Speaker Mute */
|
||||||
|
{0xce, 'a' }, /* Black triangle UP */
|
||||||
|
{0xcf, 'b' }, /* Black triangle DOWN */
|
||||||
|
{0x58, 'c' }, /* White triangle UP */
|
||||||
|
{0x5a, 'd' }, /* White triangle LEFT */
|
||||||
|
{0x5c, CH_RETURN }, /* Check */
|
||||||
|
{0x5b, 'e' }, /* White triangle RIGHT */
|
||||||
|
{0xa4, CH_BACKSPACE }, /* Back */
|
||||||
|
{0x59, 'f' }, /* White triangle DOWN */
|
||||||
|
{0x2f, '1' }, /* Rewind */
|
||||||
|
{0x2c, '2' }, /* Play / Pause */
|
||||||
|
{0x2e, '3' }, /* Forward */
|
||||||
|
{0x21, '4' }, /* Skip backward */
|
||||||
|
{0x31, '5' }, /* Stop */
|
||||||
|
{0x20, '6' }, /* Skip forward */
|
||||||
|
|
||||||
|
{0, 0} /* <<END>> */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CIR_ADDR_SHARP_AQUOS 0x028f
|
||||||
|
static const struct codetable
|
||||||
|
cir_codetable_aquos[] = {
|
||||||
|
{ 0x0116, ' ' }, /* Power */
|
||||||
|
{ 0x025e, '0' }, /* d */
|
||||||
|
{ 0x024e, '1' }, /* 1 */
|
||||||
|
{ 0x024f, '2' }, /* 2 */
|
||||||
|
{ 0x0250, '3' }, /* 3 */
|
||||||
|
{ 0x0251, '4' }, /* 4 */
|
||||||
|
{ 0x0252, '5' }, /* 5 */
|
||||||
|
{ 0x0253, '6' }, /* 6 */
|
||||||
|
{ 0x0254, '7' }, /* 7 */
|
||||||
|
{ 0x0255, '8' }, /* 8 */
|
||||||
|
{ 0x0256, '9' }, /* 9 */
|
||||||
|
{ 0x0257, 'a' }, /* 10/0 */
|
||||||
|
{ 0x0258, 'b' }, /* 11 */
|
||||||
|
{ 0x0259, 'c' }, /* 12 */
|
||||||
|
{ 0x0111, 'd' }, /* Ch ^ */
|
||||||
|
{ 0x0112, 'e' }, /* Ch v */
|
||||||
|
{ 0x0114, 'f' }, /* Vol + */
|
||||||
|
{ 0x0115, 'g' }, /* Vol - */
|
||||||
|
{ 0x0117, 'h' }, /* Mute */
|
||||||
|
{ 0x0280, 'i' }, /* BLUE */
|
||||||
|
{ 0x0281, 'j' }, /* RED */
|
||||||
|
{ 0x0282, 'k' }, /* GREEN */
|
||||||
|
{ 0x0283, 'l' }, /* YELLOW */
|
||||||
|
{ 0x011b, 'm' }, /* DISPLAY CONTROL (gamen hyouji) */
|
||||||
|
{ 0x01d5, 'n' }, /* DISPLAY SIZE */
|
||||||
|
{ 0x0157, 'o' }, /* UP */
|
||||||
|
{ 0x01d7, 'p' }, /* LEFT */
|
||||||
|
{ 0x01d8, 'q' }, /* RIGHT */
|
||||||
|
{ 0x0120, 'r' }, /* DOWN */
|
||||||
|
{ 0x0152, CH_RETURN }, /* Commit (kettei) */
|
||||||
|
{ 0x01e4, CH_BACKSPACE }, /* Back (modoru) */
|
||||||
|
{ 0x01f5, 's' }, /* Quit (shuuryou) */
|
||||||
|
{ 0x0b03, 't' }, /* Rewind (hayamodoshi) */
|
||||||
|
{ 0x0b01, 'u' }, /* Play (saisei) */
|
||||||
|
{ 0x0b04, 'v' }, /* Forward (hayaokuri) */
|
||||||
|
{ 0x0b02, 'w' }, /* Stop (teishi) */
|
||||||
|
{ 0x028a, 'x' }, /* BS */
|
||||||
|
{ 0x028b, 'y' }, /* CS */
|
||||||
|
{ 0x025f, 'z' }, /* Program information (bangumi jouhou) */
|
||||||
|
{ 0x0260, '\\' }, /* Program table (bangumi hyou) */
|
||||||
|
{ 0x0118, '|' }, /* Sound channel (onsei kirikae) */
|
||||||
|
{ 0x028e, '[' }, /* Ground Analog (chijou A) */
|
||||||
|
{ 0x0289, ']' }, /* Ground Digital (chijou D) */
|
||||||
|
|
||||||
|
{ 0x0b07, '\"' }, /* Feature select (kinou sentaku) */
|
||||||
|
{ 0x026b, '.' }, /* TV/Radio/Data (terebi/rajio/data) */
|
||||||
|
{ 0x025a, ',' }, /* 3 code input (3 keta nyuuryoku) */
|
||||||
|
{ 0x0267, ':' }, /* subtitle (jimaku) */
|
||||||
|
{ 0x0159, ';' }, /* hold (seishi) */
|
||||||
|
|
||||||
|
{ 0x01c4, 'A' }, /* Menu */
|
||||||
|
{ 0x011a, 'B' }, /* Off timer */
|
||||||
|
{ 0x0121, 'C' }, /* CATV */
|
||||||
|
{ 0x0b05, 'D' }, /* Record */
|
||||||
|
{ 0x0b06, 'E' }, /* Recording stop */
|
||||||
|
{ 0x0113, 'F' }, /* Inputs (nyuuryoku kirikae) */
|
||||||
|
{ 0x0275, 'G' }, /* other programs (ura bangumi) */
|
||||||
|
{ 0x0266, 'H' }, /* signal control (eizou kirikae) */
|
||||||
|
{ 0x01e7, 'I' }, /* AV position */
|
||||||
|
{ 0x027f, 'J' }, /* i.LINK */
|
||||||
|
{ 0x0b00, 'K' }, /* Recorder power */
|
||||||
|
{ 0x028f, 'L' }, /* as you like it (okonomi senkyoku) */
|
||||||
|
|
||||||
|
{0, 0} /* <<END>> */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CIR_ADDR_TOSHIBA_REGZA 0xbf40
|
||||||
|
static const struct codetable
|
||||||
|
cir_codetable_regza[] = {
|
||||||
|
{ 0x12, ' ' }, /* Power */
|
||||||
|
{ 0x14, '0' }, /* d (data) */
|
||||||
|
{ 0x01, '1' }, /* 1 */
|
||||||
|
{ 0x02, '2' }, /* 2 */
|
||||||
|
{ 0x03, '3' }, /* 3 */
|
||||||
|
{ 0x04, '4' }, /* 4 */
|
||||||
|
{ 0x05, '5' }, /* 5 */
|
||||||
|
{ 0x06, '6' }, /* 6 */
|
||||||
|
{ 0x07, '7' }, /* 7 */
|
||||||
|
{ 0x08, '8' }, /* 8 */
|
||||||
|
{ 0x09, '9' }, /* 9 */
|
||||||
|
{ 0x0a, 'a' }, /* 10 */
|
||||||
|
{ 0x0b, 'b' }, /* 11 */
|
||||||
|
{ 0x0c, 'c' }, /* 12 */
|
||||||
|
{ 0x1b, 'd' }, /* Ch ^ */
|
||||||
|
{ 0x1f, 'e' }, /* Ch v */
|
||||||
|
{ 0x1a, 'f' }, /* Vol + */
|
||||||
|
{ 0x1e, 'g' }, /* Vol - */
|
||||||
|
{ 0x10, 'h' }, /* Mute */
|
||||||
|
{ 0x73, 'i' }, /* BLUE */
|
||||||
|
{ 0x74, 'j' }, /* RED */
|
||||||
|
{ 0x75, 'k' }, /* GREEN */
|
||||||
|
{ 0x76, 'l' }, /* YELLOW */
|
||||||
|
{ 0x1c, 'm' }, /* Display control */
|
||||||
|
{ 0x2b, 'n' }, /* Display size */
|
||||||
|
{ 0x3e, 'o' }, /* UP */
|
||||||
|
{ 0x5f, 'p' }, /* LEFT */
|
||||||
|
{ 0x5b, 'q' }, /* RIGHT */
|
||||||
|
{ 0x3f, 'r' }, /* DOWN */
|
||||||
|
{ 0x3d, CH_RETURN }, /* Commit (kettei) */
|
||||||
|
{ 0x3b, CH_BACKSPACE }, /* Back (modoru) */
|
||||||
|
{ 0x3c, 's' }, /* Quit (shuuryou) */
|
||||||
|
{ 0x2c, 't' }, /* << (Rewind) */
|
||||||
|
{ 0x2d, 'u' }, /* >/|| (Play/Stop) */
|
||||||
|
{ 0x2e, 'v' }, /* >> (Forward) */
|
||||||
|
{ 0x2b, 'w' }, /* Stop (teishi) */
|
||||||
|
{ 0x7c, 'x' }, /* BS */
|
||||||
|
{ 0x7d, 'y' }, /* CS */
|
||||||
|
{ 0x71, 'z' }, /* Program information (bangumi setsumei) */
|
||||||
|
{ 0x77, '\\' }, /* Mini program table (mini bangumihyou) */
|
||||||
|
{ 0x13, '|' }, /* Sound (onta kirikae) */
|
||||||
|
{ 0x7a, '[' }, /* Ground Digital (chideji) */
|
||||||
|
{ 0x7b, ']' }, /* Ground Analog (chiana) */
|
||||||
|
|
||||||
|
{ 0xd0, '\"' }, /* Settings Menu (settei menu) */
|
||||||
|
{ 0x6d, '.' }, /* Radio/Data (rajio/data) */
|
||||||
|
{ 0x60, ',' }, /* CH 10-key input (search) */
|
||||||
|
{ 0x52, ':' }, /* subtitle (jimaku) */
|
||||||
|
{ 0x50, ';' }, /* hold (seishi) */
|
||||||
|
|
||||||
|
{ 0x3a, 'A' }, /* Input- (nyuuryokukirikae-) */
|
||||||
|
{ 0x0f, 'B' }, /* Input+ (nyuuryokukirikae+) */
|
||||||
|
{ 0x29, 'C' }, /* Two screens (nigamen) */
|
||||||
|
{ 0x25, 'D' }, /* Broadband */
|
||||||
|
{ 0x27, 'E' }, /* |<< Skip backward */
|
||||||
|
{ 0x26, 'F' }, /* >>| Skip forward */
|
||||||
|
{ 0x61, '!' }, /* 1 NHK1 */
|
||||||
|
{ 0x62, '@' }, /* 2 NHK2 */
|
||||||
|
{ 0x63, '#' }, /* 3 NHKh */
|
||||||
|
{ 0x64, '$' }, /* 4 BS Nihon TV */
|
||||||
|
{ 0x65, '%' }, /* 5 BS Asashi */
|
||||||
|
{ 0x66, '^' }, /* 6 BS-i */
|
||||||
|
{ 0x67, '&' }, /* 7 BSJ */
|
||||||
|
{ 0x68, '*' }, /* 8 BS Fuji */
|
||||||
|
{ 0x69, '(' }, /* 9 WOW */
|
||||||
|
{ 0x6a, ')' }, /* 10 Star */
|
||||||
|
{ 0x6b, '-' }, /* 11 BS11 */
|
||||||
|
{ 0x6c, '+' }, /* 12 TwellV */
|
||||||
|
{ 0x27, '=' }, /* Quick (Delete) */
|
||||||
|
{ 0x34, '<' }, /* REGZA link */
|
||||||
|
{ 0x6e, '>' }, /* Program Table */
|
||||||
|
{ 0x20, '/' }, /* ^^ */
|
||||||
|
{ 0x22, '\'' }, /* << */
|
||||||
|
{ 0x23, '?' }, /* >> */
|
||||||
|
{ 0x21, '_' }, /* vv */
|
||||||
|
|
||||||
|
{0, 0} /* <<END>> */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct codetable
|
||||||
|
cir_codetable_bravia[] = {
|
||||||
|
{ 0x15, ' ' }, /* Power */
|
||||||
|
{ 0x95, '0' }, /* d (16-bit: 0x4b) */
|
||||||
|
{ 0x00, '1' }, /* 1 */
|
||||||
|
{ 0x01, '2' }, /* 2 */
|
||||||
|
{ 0x02, '3' }, /* 3 */
|
||||||
|
{ 0x03, '4' }, /* 4 */
|
||||||
|
{ 0x04, '5' }, /* 5 */
|
||||||
|
{ 0x05, '6' }, /* 6 */
|
||||||
|
{ 0x06, '7' }, /* 7 */
|
||||||
|
{ 0x07, '8' }, /* 8 */
|
||||||
|
{ 0x08, '9' }, /* 9 */
|
||||||
|
{ 0x09, 'a' }, /* 10 */
|
||||||
|
{ 0x0a, 'b' }, /* 11 */
|
||||||
|
{ 0x0b, 'c' }, /* 12 */
|
||||||
|
{ 0x10, 'd' }, /* CH+ */
|
||||||
|
{ 0x11, 'd' }, /* CH- */
|
||||||
|
{ 0x12, 'f' }, /* Vol+ */
|
||||||
|
{ 0x13, 'g' }, /* Vol- */
|
||||||
|
{ 0x14, 'h' }, /* Mute */
|
||||||
|
{ 0xa4, 'i' }, /* BLUE (16-bit: 0x4b) */
|
||||||
|
{ 0xa5, 'j' }, /* RED (16-bit: 0x4b) */
|
||||||
|
{ 0xa6, 'k' }, /* GREEN (16-bit: 0x4b) */
|
||||||
|
{ 0xa7, 'l' }, /* YELLOW (16-bit: 0x4b) */
|
||||||
|
{ 0x3a, 'm' }, /* DISPLAY control (gamen hyouji) */
|
||||||
|
{ 0x3d, 'n' }, /* Display Wide (waido kirikae) */
|
||||||
|
{ 0x74, 'o' }, /* UP */
|
||||||
|
{ 0x75, 'p' }, /* DOWN */
|
||||||
|
{ 0x33, 'q' }, /* RIGHT */
|
||||||
|
{ 0x34, 'r' }, /* LEFT */
|
||||||
|
{ 0x65, CH_RETURN }, /* Commit (kettei) */
|
||||||
|
{ 0xa3, CH_BACKSPACE }, /* Back (modoru) (16-bit: 0x4b) */
|
||||||
|
{ 0xac, 's' }, /* BS (16-bit: 0x4b) */
|
||||||
|
{ 0xab, 't' }, /* CS (16-bit: 0x4b) */
|
||||||
|
{ 0x5b, 'u' }, /* Program table (bangumi hyou) (16-bit: 0x52) */
|
||||||
|
{ 0x17, 'v' }, /* Sound channel (onsei kirikae) */
|
||||||
|
{ 0xa8, 'w' }, /* subtitle (jimaku) (16-bit: 0x4b) */
|
||||||
|
{ 0x5c, 'x' }, /* hold (memo) */
|
||||||
|
{ 0xb6, 'y' }, /* Tool (16-bit: 0x4b) */
|
||||||
|
{ 0x8c, 'z' }, /* 10 key input (10ki-) (16-bit: 0x4b) */
|
||||||
|
{ 0x60, '!' }, /* Menu */
|
||||||
|
{ 0xae, '@' }, /* Analog (16-bit: 0x4b) */
|
||||||
|
{ 0xb2, '#' }, /* Digital (16-bit: 0x4b) */
|
||||||
|
{ 0x25, '$' }, /* Input (nyuuryoku kirikae) */
|
||||||
|
|
||||||
|
{0, 0} /* <<END>> */,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
ch_is_backspace (int ch)
|
||||||
|
{
|
||||||
|
return ch == CH_BACKSPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ch_is_enter (int ch)
|
||||||
|
{
|
||||||
|
return ch == CH_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* liner search is good enough for this small amount of data */
|
||||||
|
static uint8_t
|
||||||
|
find_char_codetable (uint32_t cir_code, const struct codetable *ctp)
|
||||||
|
{
|
||||||
|
while (ctp->cir_code != 0x0000 || ctp->char_code != 0x00)
|
||||||
|
if (ctp->cir_code == cir_code)
|
||||||
|
return ctp->char_code;
|
||||||
|
else
|
||||||
|
ctp++;
|
||||||
|
|
||||||
|
/* Not found */
|
||||||
|
return cir_code & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
hex (int x)
|
||||||
|
{
|
||||||
|
if (x < 10)
|
||||||
|
return x + '0';
|
||||||
|
else
|
||||||
|
return (x - 10) + 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cir_getchar (systime_t timeout)
|
||||||
|
{
|
||||||
|
uint16_t cir_addr;
|
||||||
|
eventmask_t m;
|
||||||
|
#if defined(DEBUG_CIR)
|
||||||
|
uint16_t *p;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DEBUG_CIR)
|
||||||
|
cirinput_p = cirinput;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
chEvtClear (ALL_EVENTS);
|
||||||
|
cir_init ();
|
||||||
|
|
||||||
|
m = chEvtWaitOneTimeout (ALL_EVENTS, timeout);
|
||||||
|
if (m == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
#if defined(DEBUG_CIR)
|
||||||
|
DEBUG_INFO ("****\r\n");
|
||||||
|
DEBUG_SHORT (intr_ext);
|
||||||
|
DEBUG_SHORT (intr_trg);
|
||||||
|
DEBUG_SHORT (intr_ovf);
|
||||||
|
DEBUG_INFO ("----\r\n");
|
||||||
|
for (p = cirinput; p < cirinput_p; p++)
|
||||||
|
DEBUG_SHORT (*p);
|
||||||
|
DEBUG_INFO ("====\r\n");
|
||||||
|
|
||||||
|
cirinput_p = cirinput;
|
||||||
|
|
||||||
|
DEBUG_INFO ("**** CIR data:");
|
||||||
|
DEBUG_WORD (cir_data);
|
||||||
|
if (cir_seq > 48)
|
||||||
|
DEBUG_SHORT (cir_data_more);
|
||||||
|
DEBUG_BYTE (cir_seq);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (cir_proto)
|
||||||
|
{
|
||||||
|
case CIR_PROTO_RC5:
|
||||||
|
cir_data &= 0x003f;
|
||||||
|
goto err;
|
||||||
|
case CIR_PROTO_RC6:
|
||||||
|
cir_addr = cir_data >> 8; /* in case of cir_seq == 16. 32??? */
|
||||||
|
cir_data &= 0x00ff;
|
||||||
|
return find_char_codetable (cir_data, cir_codetable_dell_mr425);
|
||||||
|
case CIR_PROTO_NEC:
|
||||||
|
cir_addr = cir_data&0xffff;
|
||||||
|
if (cir_addr == CIR_ADDR_TOSHIBA_REGZA)
|
||||||
|
{
|
||||||
|
cir_data = (cir_data >> 16) & 0x00ff;
|
||||||
|
return find_char_codetable (cir_data, cir_codetable_regza);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto err;
|
||||||
|
case CIR_PROTO_SHARP:
|
||||||
|
cir_addr = cir_data&0x0fff;
|
||||||
|
if (cir_addr == CIR_ADDR_SHARP_AQUOS)
|
||||||
|
{
|
||||||
|
cir_data = (cir_data>>16)&0x0fff;
|
||||||
|
return find_char_codetable (cir_data, cir_codetable_aquos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto err;
|
||||||
|
case CIR_PROTO_SONY:
|
||||||
|
/* Remove ADDRESS bits and filter COMMAND bits */
|
||||||
|
if (cir_seq == 1 + 12)
|
||||||
|
{
|
||||||
|
cir_addr = cir_data >> 7;
|
||||||
|
cir_data = cir_data & 0x007f;
|
||||||
|
/* ADDRESS = 0x01 (5-bit) */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cir_addr = cir_data >> 8;
|
||||||
|
cir_data = cir_data & 0x00ff;
|
||||||
|
/* ADDRESS = 0x4b or 0x52 (7-bit) */
|
||||||
|
}
|
||||||
|
return find_char_codetable (cir_data, cir_codetable_bravia);
|
||||||
|
err:
|
||||||
|
default:
|
||||||
|
/* encode debug information */
|
||||||
|
pin_input_len = 16;
|
||||||
|
pin_input_buffer[0] = hex (cir_proto >> 4);
|
||||||
|
pin_input_buffer[1] = hex (cir_proto & 0x0f);
|
||||||
|
pin_input_buffer[2] = ':';
|
||||||
|
pin_input_buffer[3] = hex ((cir_data >> 28) & 0x0f);
|
||||||
|
pin_input_buffer[4] = hex ((cir_data >> 24) & 0x0f);
|
||||||
|
pin_input_buffer[5] = hex ((cir_data >> 20) & 0x0f);
|
||||||
|
pin_input_buffer[6] = hex ((cir_data >> 16) & 0x0f);
|
||||||
|
pin_input_buffer[7] = hex ((cir_data >> 12) & 0x0f);
|
||||||
|
pin_input_buffer[8] = hex ((cir_data >> 8) & 0x0f);
|
||||||
|
pin_input_buffer[9] = hex ((cir_data >> 4) & 0x0f);
|
||||||
|
pin_input_buffer[10] = hex (cir_data & 0x0f);
|
||||||
|
pin_input_buffer[11] = ':';
|
||||||
|
pin_input_buffer[12] = hex ((cir_data_more >> 12) & 0x0f);
|
||||||
|
pin_input_buffer[13] = hex ((cir_data_more >> 8) & 0x0f);
|
||||||
|
pin_input_buffer[14] = hex ((cir_data_more >> 4) & 0x0f);
|
||||||
|
pin_input_buffer[15] = hex (cir_data_more & 0x0f);
|
||||||
|
return CH_RETURN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RC-5 protocol doesn't have a start bit, while any other protocols
|
* RC-5 protocol doesn't have a start bit, while any other protocols
|
||||||
* have the one.
|
* have the one.
|
||||||
@@ -207,125 +594,56 @@ static systime_t cir_input_last;
|
|||||||
#define CIR_BIT_PERIOD 1500
|
#define CIR_BIT_PERIOD 1500
|
||||||
#define CIR_BIT_SIRC_PERIOD_ON 1000
|
#define CIR_BIT_SIRC_PERIOD_ON 1000
|
||||||
|
|
||||||
static void
|
|
||||||
cir_init (void)
|
|
||||||
{
|
|
||||||
cir_data = 0;
|
|
||||||
cir_seq = 0;
|
|
||||||
/* Don't touch cir_proto here */
|
|
||||||
cir_ext_enable ();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Thread *pin_thread;
|
static Thread *pin_thread;
|
||||||
|
|
||||||
static int
|
/*
|
||||||
cir_key_is_backspace (void)
|
* Let user input PIN string.
|
||||||
|
* Return length of the string.
|
||||||
|
* The string itself is in PIN_INPUT_BUFFER.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
pinpad_getline (int msg_code, systime_t timeout)
|
||||||
{
|
{
|
||||||
return (cir_proto == CIR_PROTO_RC6 && cir_data == CIR_KEY_RC6_BACKSPACE)
|
|
||||||
|| (cir_proto == CIR_PROTO_NEC && cir_data == CIR_KEY_NEC_BACKSPACE)
|
|
||||||
|| (cir_proto == CIR_PROTO_SONY && cir_data == CIR_KEY_SONY_BACKSPACE)
|
|
||||||
|| (cir_proto == CIR_PROTO_SHARP && cir_data == CIR_KEY_SHARP_BACKSPACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
cir_key_is_enter (void)
|
|
||||||
{
|
|
||||||
return (cir_proto == CIR_PROTO_RC6 && cir_data == CIR_KEY_RC6_ENTER)
|
|
||||||
|| (cir_proto == CIR_PROTO_NEC && cir_data == CIR_KEY_NEC_ENTER)
|
|
||||||
|| (cir_proto == CIR_PROTO_SONY && cir_data == CIR_KEY_SONY_ENTER)
|
|
||||||
|| (cir_proto == CIR_PROTO_SHARP && cir_data == CIR_KEY_SHARP_ENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_t
|
|
||||||
pin_main (void *arg)
|
|
||||||
{
|
|
||||||
uint8_t s = 0;
|
|
||||||
int msg_code = (int)arg;
|
|
||||||
|
|
||||||
(void)msg_code;
|
(void)msg_code;
|
||||||
|
|
||||||
pin_thread = chThdSelf ();
|
pin_thread = chThdSelf ();
|
||||||
|
|
||||||
#if defined(DEBUG_CIR)
|
DEBUG_INFO (">>>\r\n");
|
||||||
cirinput_p = cirinput;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pin_input_len = 0;
|
pin_input_len = 0;
|
||||||
chEvtClear (ALL_EVENTS);
|
while (1)
|
||||||
cir_init ();
|
|
||||||
|
|
||||||
while (!chThdShouldTerminate ())
|
|
||||||
{
|
{
|
||||||
eventmask_t m;
|
int ch;
|
||||||
|
|
||||||
m = chEvtWaitOneTimeout (ALL_EVENTS, PINDISP_TIMEOUT_INTERVAL1);
|
ch = cir_getchar (timeout);
|
||||||
|
if (ch < 0)
|
||||||
|
return 0; /* timeout */
|
||||||
|
|
||||||
if (m)
|
if (ch_is_backspace (ch))
|
||||||
{
|
{
|
||||||
#if defined(DEBUG_CIR)
|
led_blink (2);
|
||||||
uint16_t *p;
|
if (pin_input_len > 0)
|
||||||
|
pin_input_len--;
|
||||||
DEBUG_INFO ("****\r\n");
|
|
||||||
DEBUG_SHORT (intr_ext);
|
|
||||||
DEBUG_SHORT (intr_trg);
|
|
||||||
DEBUG_SHORT (intr_ovf);
|
|
||||||
DEBUG_INFO ("----\r\n");
|
|
||||||
for (p = cirinput; p < cirinput_p; p++)
|
|
||||||
DEBUG_SHORT (*p);
|
|
||||||
DEBUG_INFO ("====\r\n");
|
|
||||||
|
|
||||||
cirinput_p = cirinput;
|
|
||||||
#endif
|
|
||||||
DEBUG_INFO ("**** CIR data:");
|
|
||||||
DEBUG_WORD (cir_data);
|
|
||||||
if (cir_seq > 48)
|
|
||||||
{
|
|
||||||
DEBUG_SHORT (cir_data_more);
|
|
||||||
}
|
|
||||||
DEBUG_BYTE (cir_seq);
|
|
||||||
|
|
||||||
if (cir_key_is_backspace ())
|
|
||||||
{
|
|
||||||
if (pin_input_len > 0)
|
|
||||||
pin_input_len--;
|
|
||||||
}
|
|
||||||
else if (cir_key_is_enter ())
|
|
||||||
{
|
|
||||||
pindisp (' ');
|
|
||||||
chThdExit (0);
|
|
||||||
}
|
|
||||||
else if (pin_input_len < MAX_PIN_CHARS)
|
|
||||||
pin_input_buffer[pin_input_len++] = (uint8_t)cir_data;
|
|
||||||
|
|
||||||
cir_init ();
|
|
||||||
}
|
}
|
||||||
|
else if (ch_is_enter (ch))
|
||||||
switch (s++)
|
break;
|
||||||
|
else if (pin_input_len < MAX_PIN_CHARS)
|
||||||
{
|
{
|
||||||
case 0:
|
led_blink (0);
|
||||||
pindisp ('G');
|
pin_input_buffer[pin_input_len++] = ch;
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
pindisp ('P');
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
pindisp ('G');
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
pindisp ('.');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pindisp (' ');
|
|
||||||
s = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chThdSleep (PINDISP_TIMEOUT_INTERVAL0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cir_ext_disable ();
|
cir_ext_disable ();
|
||||||
return 0;
|
|
||||||
|
return pin_input_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interrupt handler of EXTI.
|
||||||
|
* @note This handler will be invoked at the beginning of signal.
|
||||||
|
* Setup timer to measure period and duty using PWM input mode.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
cir_ext_interrupt (void)
|
cir_ext_interrupt (void)
|
||||||
{
|
{
|
||||||
@@ -340,29 +658,33 @@ cir_ext_interrupt (void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TIM3->EGR = TIM_EGR_UG; /* Generate UEV to load PSC and ARR */
|
TIMx->EGR = TIM_EGR_UG; /* Generate UEV to load PSC and ARR */
|
||||||
/* Enable Timer */
|
/* Enable Timer */
|
||||||
TIM3->SR &= ~(TIM_SR_UIF
|
TIMx->SR &= ~(TIM_SR_UIF
|
||||||
| TIM_SR_CC1IF | TIM_SR_CC2IF
|
| TIM_SR_CC1IF | TIM_SR_CC2IF
|
||||||
| TIM_SR_TIF
|
| TIM_SR_TIF
|
||||||
| TIM_SR_CC1OF | TIM_SR_CC2OF);
|
| TIM_SR_CC1OF | TIM_SR_CC2OF);
|
||||||
TIM3->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/;
|
TIMx->DIER = TIM_DIER_UIE /*overflow*/ | TIM_DIER_TIE /*trigger*/;
|
||||||
TIM3->CR1 |= TIM_CR1_CEN;
|
TIMx->CR1 |= TIM_CR1_CEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \
|
#define CIR_PERIOD_ON_RC5_OR_RC6 (((cir_proto == CIR_PROTO_RC5) ? 2 : 1) \
|
||||||
* CIR_BIT_PERIOD_RC6 * 3 / 2)
|
* CIR_BIT_PERIOD_RC6 * 3 / 2)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Interrupt handler of timer.
|
||||||
|
* @note Timer is PWM input mode, this handler will be invoked on each cycle
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
cir_timer_interrupt (void)
|
cir_timer_interrupt (void)
|
||||||
{
|
{
|
||||||
uint16_t period, on, off;
|
uint16_t period, on, off;
|
||||||
|
|
||||||
period = TIM3->CCR1;
|
period = TIMx->CCR1;
|
||||||
on = TIM3->CCR2;
|
on = TIMx->CCR2;
|
||||||
off = period - on;
|
off = period - on;
|
||||||
|
|
||||||
if ((TIM3->SR & TIM_SR_TIF))
|
if ((TIMx->SR & TIM_SR_TIF))
|
||||||
{
|
{
|
||||||
if (cir_seq == 0)
|
if (cir_seq == 0)
|
||||||
{
|
{
|
||||||
@@ -477,23 +799,23 @@ cir_timer_interrupt (void)
|
|||||||
intr_trg++;
|
intr_trg++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TIM3->EGR = TIM_EGR_UG; /* Generate UEV */
|
TIMx->EGR = TIM_EGR_UG; /* Generate UEV */
|
||||||
TIM3->SR &= ~TIM_SR_TIF;
|
TIMx->SR &= ~TIM_SR_TIF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* overflow occurred */
|
/* overflow occurred */
|
||||||
{
|
{
|
||||||
systime_t now = chTimeNow ();
|
systime_t now = chTimeNow ();
|
||||||
|
|
||||||
TIM3->SR &= ~TIM_SR_UIF;
|
TIMx->SR &= ~TIM_SR_UIF;
|
||||||
|
|
||||||
if (on > 0)
|
if (on > 0)
|
||||||
{
|
{
|
||||||
uint8_t ignore_input = 0;
|
uint8_t ignore_input = 0;
|
||||||
|
|
||||||
/* Disable the timer */
|
/* Disable the timer */
|
||||||
TIM3->CR1 &= ~TIM_CR1_CEN;
|
TIMx->CR1 &= ~TIM_CR1_CEN;
|
||||||
TIM3->DIER = 0;
|
TIMx->DIER = 0;
|
||||||
|
|
||||||
if (cir_seq == 12 || cir_seq == 15)
|
if (cir_seq == 12 || cir_seq == 15)
|
||||||
{
|
{
|
||||||
@@ -536,14 +858,9 @@ cir_timer_interrupt (void)
|
|||||||
cir_input_last = now;
|
cir_input_last = now;
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
/* Remove ADDRESS bits and filter COMMAND bits */
|
|
||||||
else if (cir_proto == CIR_PROTO_SONY)
|
else if (cir_proto == CIR_PROTO_SONY)
|
||||||
{
|
{
|
||||||
if (cir_seq == 1 + 12)
|
if (cir_seq != 1 + 12 && cir_seq != 1 + 15)
|
||||||
cir_data = cir_data & 0x007f;
|
|
||||||
else if (cir_seq == 1 + 15)
|
|
||||||
cir_data = cir_data & 0x00ff;
|
|
||||||
else
|
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
else if (cir_proto == CIR_PROTO_OTHER)
|
else if (cir_proto == CIR_PROTO_OTHER)
|
||||||
@@ -551,10 +868,7 @@ cir_timer_interrupt (void)
|
|||||||
if (cir_seq == 1 + 32)
|
if (cir_seq == 1 + 32)
|
||||||
{
|
{
|
||||||
if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff))
|
if (((cir_data >> 16) & 0xff) == ((cir_data >> 24) ^ 0xff))
|
||||||
{
|
cir_proto = CIR_PROTO_NEC;
|
||||||
cir_proto = CIR_PROTO_NEC;
|
|
||||||
cir_data = (cir_data >> 16) & 0x00ff;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
@@ -569,10 +883,7 @@ cir_timer_interrupt (void)
|
|||||||
^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f)
|
^ ((cir_data >> 20) & 0x0f) ^ ((cir_data >> 16) & 0x0f)
|
||||||
^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f)
|
^ ((cir_data >> 12) & 0x0f) ^ ((cir_data >> 8) & 0x0f)
|
||||||
^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f)))
|
^ ((cir_data >> 4) & 0x0f) ^ (cir_data & 0x0f)))
|
||||||
{
|
cir_proto = CIR_PROTO_SHARP;
|
||||||
cir_proto = CIR_PROTO_SHARP;
|
|
||||||
cir_data = (cir_data >> 16) & 0x0fff;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
@@ -581,16 +892,12 @@ cir_timer_interrupt (void)
|
|||||||
}
|
}
|
||||||
else if (cir_proto == CIR_PROTO_RC6)
|
else if (cir_proto == CIR_PROTO_RC6)
|
||||||
{
|
{
|
||||||
if (cir_seq == 16 || cir_seq == 32)
|
if (cir_seq != 16 && cir_seq != 32)
|
||||||
cir_data &= 0x00ff;
|
|
||||||
else
|
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
else if (cir_proto == CIR_PROTO_RC5)
|
else if (cir_proto == CIR_PROTO_RC5)
|
||||||
{
|
{
|
||||||
if (cir_seq == 14)
|
if (cir_seq != 14)
|
||||||
cir_data &= 0x003f;
|
|
||||||
else
|
|
||||||
ignore_input = 1;
|
ignore_input = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -603,7 +910,8 @@ cir_timer_interrupt (void)
|
|||||||
{
|
{
|
||||||
cir_input_last = now;
|
cir_input_last = now;
|
||||||
/* Notify thread */
|
/* Notify thread */
|
||||||
chEvtSignal (pin_thread, (eventmask_t)1);
|
if (pin_thread)
|
||||||
|
chEvtSignalI (pin_thread, (eventmask_t)1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DEBUG_CIR)
|
#if defined(DEBUG_CIR)
|
||||||
|
|||||||
@@ -120,8 +120,14 @@ gnuk_device_SetConfiguration (void)
|
|||||||
DEVICE_INFO *pInfo = &Device_Info;
|
DEVICE_INFO *pInfo = &Device_Info;
|
||||||
|
|
||||||
if (pInfo->Current_Configuration != 0)
|
if (pInfo->Current_Configuration != 0)
|
||||||
/* Device configured */
|
{ /* Device configured */
|
||||||
bDeviceState = CONFIGURED;
|
extern void *main_thread;
|
||||||
|
extern void chEvtSignalI (void *, unsigned long);
|
||||||
|
#define LED_STATUS_MODE (8)
|
||||||
|
|
||||||
|
bDeviceState = CONFIGURED;
|
||||||
|
chEvtSignalI (main_thread, LED_STATUS_MODE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
Reference in New Issue
Block a user