Ага, щас. Это на Си просто: #include "control.h"
#include "timer.h"
#include "irq.h"
#include "stm32f1regs.h"
#include "myassert.h"
#include <stdbool.h>
#define HOLD_TIMEOUT (3 * TIMER_TPS / 4)
#define REPEAT_TIMEOUT (TIMER_TPS / 10)
#define SEG2DISP(a,b,c,d,e,f,g,d1) ((a<<5)|(b<<7)|(c<<2)|(d<<0)|(e<<4)|(f<<6)|(g<<3)|(d1<<1))
static const uint8_t chartab[][2] = {
{ ' ', SEG2DISP(0,0,0,0,0,0,0,0) },
{ '-', SEG2DISP(0,0,0,0,0,0,1,0) },
{ '0', SEG2DISP(1,1,1,1,1,1,0,0) },
{ '1', SEG2DISP(0,1,1,0,0,0,0,0) },
{ '2', SEG2DISP(1,1,0,1,1,0,1,0) },
{ '3', SEG2DISP(1,1,1,1,0,0,1,0) },
{ '4', SEG2DISP(0,1,1,0,0,1,1,0) },
{ '5', SEG2DISP(1,0,1,1,0,1,1,0) },
{ '6', SEG2DISP(1,0,1,1,1,1,1,0) },
{ '7', SEG2DISP(1,1,1,0,0,0,0,0) },
{ '8', SEG2DISP(1,1,1,1,1,1,1,0) },
{ '9', SEG2DISP(1,1,1,1,0,1,1,0) },
{ 'A', SEG2DISP(1,1,1,0,1,1,1,0) },
{ 'b', SEG2DISP(0,0,1,1,1,1,1,0) },
{ 'C', SEG2DISP(1,0,0,1,1,1,0,0) },
{ 'c', SEG2DISP(0,0,0,1,1,0,1,0) },
{ 'd', SEG2DISP(0,1,1,1,1,0,1,0) },
{ 'E', SEG2DISP(1,0,0,1,1,1,1,0) },
{ 'F', SEG2DISP(1,0,0,0,1,1,1,0) },
{ 'G', SEG2DISP(1,0,1,1,1,1,0,0) },
{ 'H', SEG2DISP(0,1,1,0,1,1,1,0) },
{ 'h', SEG2DISP(0,0,1,0,1,1,1,0) },
{ 'I', SEG2DISP(0,1,1,0,0,0,0,0) },
{ 'J', SEG2DISP(0,1,1,1,1,0,0,0) },
{ 'L', SEG2DISP(0,0,0,1,1,1,0,0) },
{ 'n', SEG2DISP(0,0,1,0,1,0,1,0) },
{ 'O', SEG2DISP(1,1,1,1,1,1,0,0) },
{ 'o', SEG2DISP(0,0,1,1,1,0,1,0) },
{ 'P', SEG2DISP(1,1,0,0,1,1,1,0) },
{ 'q', SEG2DISP(1,1,1,0,0,1,1,0) },
{ 'r', SEG2DISP(0,0,0,0,1,0,1,0) },
{ 'S', SEG2DISP(1,0,1,1,0,1,1,0) },
{ 't', SEG2DISP(0,0,0,1,1,1,1,0) },
{ 'U', SEG2DISP(0,1,1,1,1,1,0,0) },
{ 'u', SEG2DISP(0,0,1,1,1,0,0,0) },
{ 'Y', SEG2DISP(0,1,1,1,0,1,1,0) }
};
static uint8_t disp[3];
static int leds = 7;
static int volatile pressed;
static struct control_combo latest;
static bool new_event;
static void
systick_handler(void)
{
static int i, keymask;
int j, dout = disp[i] | (1 << (9 + i)) | (leds << 12) | 0xFFFF0000;
/* configure DATA as output */
GPIOC_CRH = (GPIOC_CRH & 0xFFF0FFFF) | 0x00020000; /* P10=GP P-P 1 MHz */
for (j = 0; j < 16; j++)
{
GPIOC_BSRR = (dout & 0x10001) << 12;
GPIOA_BSRR = (1 << 15);
GPIOA_BSRR = (1 << 31);
dout >>= 1;
}
/* configure DATA as input with pull-up */
GPIOC_BSRR = (1 << 12);
timer_delay(TIMER_TPS / 500000);
GPIOC_CRH = (GPIOC_CRH & 0xFFF0FFFF) | 0x00080000; /* PC12=IN with PU */
timer_delay(TIMER_TPS / 500000);
if (!(GPIOC_IDR & (1 << 12)))
{
keymask |= (1 << i);
}
if (++i == 3)
{
i = 0;
switch (keymask)
{
case 1: pressed = 1; break;
case 2: pressed = 2; break;
case 4: pressed = 3; break;
default: pressed = 0; break;
}
keymask = 0;
}
}
void
control_init(int prio)
{
RCC_APB2ENR |= (1 << 2) /* enable clocking of port A */
| (1 << 3) /* enable clocking of port B */
| (1 << 4);/* enable clocking of port C */
/* configure LEDY */
GPIOA_CRL = (GPIOA_CRL & 0xFFFFFFF0) | 0x00000002; /* PA0=GP P-P 2 MHz */
/* configure SHCLK */
GPIOA_CRH = (GPIOA_CRH & 0x0FFFFFFF) | 0x20000000; /* PA15=GP P-P 2 MHz */
/* configure DATA */
GPIOC_CRH = (GPIOC_CRH & 0xFFF0FFFF) | 0x00020000; /* PC12=GP P-P 2 MHz */
/* configure SHRST */
GPIOB_CRL = (GPIOB_CRL & 0xFFFFF0FF) | 0x00000200; /* PB2=GP P-P 2 MHz */
/* deassert SHRST */
GPIOB_BSRR = (1 << 2);
irq_install(15, 32, systick_handler);
/* reloads 200 times per second @ 72 MHz */
SYSTICK_RVR = 72000000 / 8 / 200 - 1;
SYSTICK_CVR = 0;
SYSTICK_CSR = (1 << 1) /* enable SysTick exception */
| (1 << 0);/* start counter */
}
static void
trigger_event(enum control_event event)
{
latest.event = event;
new_event = true;
}
void
control_poll(void)
{
static int prev_pressed;
static unsigned int prev, prev_event, timeout;
unsigned int now = timer_get();
if (now - prev > TIMER_TPS / 20)
{
int p = pressed;
prev = now;
if (p != prev_pressed)
{
if (prev_pressed == 0)
{
static const enum control_key keys[3] = {
// KEY_LEFT, KEY_CENTER, KEY_RIGHT
KEY_LEFT, KEY_RIGHT, KEY_CENTER
};
trigger_event(CTRL_PRESS);
latest.key = keys[p - 1];
prev_event = now;
timeout = HOLD_TIMEOUT;
}
else if (latest.event != CTRL_RELEASE)
{
trigger_event(CTRL_RELEASE);
}
prev_pressed = p;
}
else if (p != 0 && now - prev_event > timeout)
{
switch (latest.event)
{
case CTRL_PRESS:
trigger_event(CTRL_HOLD);
timeout = REPEAT_TIMEOUT;
break;
case CTRL_HOLD:
case CTRL_REPEAT:
trigger_event(CTRL_REPEAT);
break;
default:
myassert(0);
break;
}
prev_event = now;
}
}
}
void
control_leds(int offmask, int onmask)
{
leds = (leds | offmask) & ~onmask;
}
void
control_show(const char* str)
{
int i = 0;
do
{
if (*str == '.')
{
const uint8_t dot = SEG2DISP(0,0,0,0,0,0,0,1);
if (i == 0)
{
disp[i++] = dot;
}
else
{
disp[i - 1] |= dot;
}
}
else
{
int j;
for (j = sizeof(chartab) / sizeof(chartab[0]) - 2; j >= 0; j--)
{
if (chartab[j][0] == *str)
{
disp[i++] = chartab[j][1];
break;
}
}
myassert(j >= 0);
}
str++;
}
while (i < ((*str == '.') ? 4 : 3));
}
struct control_combo
control_getevent(void)
{
if (new_event)
{
new_event = false;
return latest;
}
else
{
const struct control_combo empty_event = { CTRL_NONE, KEY_NONE };
return empty_event;
}
}
ส็็็็็็็็็็็็็็็็็็็็็็็็็༼ ຈل͜ຈ༽ส้้้้้้้้้้้้้้้้้้้้้้้
-
- Размазал на 100500 строк то, что можно в 10 написать. И линейный поиск -- атас! Лучше бы switch написал, оно бы само за O(LOG2(N)) выбирало... - fk0(08.02.2015 16:45)
- ничё, ничё! Нам пойдет. Что там место в тексте экономить? - Лагунов(09.02.2015 07:42)
- По-хорошему, надо в две колонки оба варианта: "понятный" и "правильный" :) - Николай Коровин(08.02.2015 21:08)
- А ещё я могу bubble sort... Надо же куда-то девать эти мегагерцы! :-))) - SciFi(08.02.2015 17:01)
- Размазал на 100500 строк то, что можно в 10 написать. И линейный поиск -- атас! Лучше бы switch написал, оно бы само за O(LOG2(N)) выбирало... - fk0(08.02.2015 16:45)