RISC-V/V003/keyboard/keyboard.cpp
2024-05-07 11:46:49 +02:00

92 lines
2.9 KiB
C++

#include "keyboard.h"
#include "usart.h"
extern "C" {
extern const unsigned dtmf_low_tab [];
extern const unsigned dtmf_hi__tab [];
};
static const uint32_t col_table [] = {
0x0002'001Cu,
0x0004'001Au,
0x0008'0016u,
0x0010'000Eu,
};
static const char * out_table [] = {
"*741", "0852", "#963"
};
unsigned int Keyboard::Send(uint16_t * const ptr, const unsigned int len) {
for (unsigned n=0u; n<len; n++) ptr [n] = 1000 + gl.step() + gh.step();
const unsigned index = (col_cnt >> 1) & 3u;
if ((col_cnt & 1) == 0u) { // sudý cnt zapíše 0 na port (řádek)
GPIOC.BSHR.R = col_table [ index ];
} else { // lichý, následný přečte sloupec
const uint32_t row = (~GPIOC.INDR.R >> 5) & 0x7u;
if (status [index] != row) { // změna - je potřeba něco udělat
if (row) led << false;
else led << true;
char c = '\0';
gl.set(dtmf_low_tab [index]);
if (row & 1u) { // ono to row je vlastně sloupec,
c = out_table [2] [index]; // nechce se mi to přepisovat
gh.set (dtmf_hi__tab [2]);
} else if (row & 2u) {
c = out_table [0] [index];
gh.set (dtmf_hi__tab [0]);
} else if (row & 4u) {
c = out_table [1] [index];
gh.set (dtmf_hi__tab [1]);
} else { // konec stisku tlačítka
gh.set(0u); gl.set(0u); // ticho
}
if (c) out(c);
status [index] = row;
}
}
col_cnt += 1u;
return len;
}
void Keyboard::init() {
for (unsigned n=0u; n<4u; n++) status [n] = 0u;
led << true;
RCC.APB2PCENR.B.IOPCEN = SET;
GPIOC.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
r.B.MODE1 = 1u; // Output mode, maximum speed 10MHz
r.B.CNF1 = 1u; // Universal open-drain output mode
r.B.MODE2 = 1u; // Output mode, maximum speed 10MHz
r.B.CNF2 = 1u; // Universal open-drain output mode
r.B.MODE3 = 1u; // Output mode, maximum speed 10MHz
r.B.CNF3 = 1u; // Universal open-drain output mode
r.B.MODE4 = 1u; // Output mode, maximum speed 10MHz
r.B.CNF4 = 1u; // Universal open-drain output mode
r.B.MODE5 = 0u; // Input mode
r.B.CNF5 = 2u; // With pull-up and pull-down mode
r.B.MODE6 = 0u; // Input mode
r.B.CNF6 = 2u; // With pull-up and pull-down mode
r.B.MODE7 = 0u; // Input mode
r.B.CNF7 = 2u; // With pull-up and pull-down mode
return r.R;
});
GPIOC.OUTDR.R |= 0xE0u; // pull-up vstupů
}
void Keyboard::out(const char c) {
usart.Down (&c, 1u);
if (c == '#') {
usart.Down ("\r\n", 2u);
pas_num = BEGIN;
pas_cnt = 0u;
relay << false;
return;
}
if (c == password [pas_cnt] and pas_num == BEGIN) {
pas_cnt += 1u;
if (password [pas_cnt] == '\0') { // konec
pas_num = END;
pas_cnt = 0u;
relay << true;
}
} else {
pas_num = BEGIN;
pas_cnt = 0u;
relay << false;
}
}