diff --git a/keyboard/Makefile b/keyboard/Makefile new file mode 100644 index 0000000..3c6f1f7 --- /dev/null +++ b/keyboard/Makefile @@ -0,0 +1,54 @@ +# ch32v003 +TARGET?= ch32v003 +TOOL ?= gcc + +PRJ = example + +VPATH = . ./$(TARGET) +BLD = ./build/ +DFLAGS = -d +LFLAGS = -g +LDLIBS = +BFLAGS = --strip-unneeded + +CFLAGS = -MMD -Wall -ggdb -fno-exceptions -ffunction-sections -fdata-sections +CFLAGS+= -I. -I./common -I./$(TARGET) -I/usr/include/newlib +DEL = rm -f + +# zdrojaky +OBJS = main.o keyboard.o +OBJS += usart.o pcmdma.o sin.o + +include $(TARGET)/$(TOOL).mk +BOBJS = $(addprefix $(BLD),$(OBJS)) + +all: $(BLD) $(PRJ).elf +# ... atd. +-include $(BLD)*.d +# linker +$(PRJ).elf: $(BOBJS) + -@echo [LD $(TOOL),$(TARGET)] $@ + @$(LD) $(LFLAGS) -o $(PRJ).elf $(BOBJS) $(LDLIBS) + -@echo "size:" + @$(SIZE) $(PRJ).elf + -@echo "listing:" + $(DUMP) $(DFLAGS) $(PRJ).elf > $(PRJ).lst + -@echo "OK." + $(COPY) $(BFLAGS) -O binary $(PRJ).elf $(PRJ).bin +# preloz co je potreba +$(BLD)%.o: %.c + -@echo [CC $(TOOL),$(TARGET)] $@ + @$(CC) -c $(CFLAGS) $< -o $@ +$(BLD)%.o: %.cpp + -@echo [CX $(TOOL),$(TARGET)] $@ + @$(CXX) -std=c++17 -fno-rtti -c $(CFLAGS) $< -o $@ +$(BLD): + mkdir $(BLD) +sin.c: sin.py + ./sin.py +flash: $(PRJ).elf + minichlink -w $(PRJ).bin flash -b +# vycisti +clean: + $(DEL) $(BLD)* *.lst *.bin *.elf *.map sin.c *~ +.PHONY: all clean diff --git a/keyboard/ch32v003 b/keyboard/ch32v003 new file mode 120000 index 0000000..0bcf9a1 --- /dev/null +++ b/keyboard/ch32v003 @@ -0,0 +1 @@ +../ch32v003/ \ No newline at end of file diff --git a/keyboard/common b/keyboard/common new file mode 120000 index 0000000..8332399 --- /dev/null +++ b/keyboard/common @@ -0,0 +1 @@ +../common/ \ No newline at end of file diff --git a/keyboard/generator.h b/keyboard/generator.h new file mode 100644 index 0000000..d1172f3 --- /dev/null +++ b/keyboard/generator.h @@ -0,0 +1,22 @@ +#ifndef GENERATOR_H +#define GENERATOR_H +#include "oneway.h" +extern "C" const int16_t sin_tab[]; +/* Něco jako DDS, přesná frekvence není řešena (závisí na TIM1). */ +class Generator { + unsigned base, freq; + public: + explicit Generator () noexcept : base(0u), freq (0u) {}; + int16_t step () { + const int16_t r = sin_tab [base >> 24]; + base += freq; + return r; + } + void set (const unsigned f) { + if (!f) base = 0u; + freq = f; + } + protected: +}; + +#endif // GENERATOR_H diff --git a/keyboard/keyboard.cpp b/keyboard/keyboard.cpp new file mode 100644 index 0000000..fea78c3 --- /dev/null +++ b/keyboard/keyboard.cpp @@ -0,0 +1,92 @@ +#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> 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; + } +} diff --git a/keyboard/keyboard.h b/keyboard/keyboard.h new file mode 100644 index 0000000..7a19644 --- /dev/null +++ b/keyboard/keyboard.h @@ -0,0 +1,29 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H +#include "gpio.h" +#include "oneway.h" +#include "generator.h" +class Usart; + +class Keyboard : public OneWay { + enum PASSENUM { BEGIN = 0, END }; + Usart & usart; + GpioClass led, relay; + Generator gl,gh; + unsigned col_cnt, pas_cnt; + const char * password; + PASSENUM pas_num; + uint8_t status [4]; +public: + explicit Keyboard (Usart & serial) noexcept : OneWay(), usart (serial), led (GPIOD, 4u), relay (GPIOD, 3u), + gl (), gh (), col_cnt (0u), pas_cnt (0u), password (nullptr), pas_num (BEGIN) { + init(); + } + void setPassword (const char * const pwd) { password = pwd; } + unsigned int Send (uint16_t * const ptr, const unsigned int len) override; +protected: + void init () noexcept; + void out (const char c); +}; + +#endif // KEYBOARD_H diff --git a/keyboard/main.cpp b/keyboard/main.cpp new file mode 100644 index 0000000..b802c2c --- /dev/null +++ b/keyboard/main.cpp @@ -0,0 +1,26 @@ +#include "usart.h" +#include "pcmdma.h" +#include "keyboard.h" +////////////////////////////////////// +/* Klávesnice Tesla Jihlava je připojena + * k portu C, bity 1,2,3,4 řádky, 5,6,7 + * sloupce. Nejsou potřeba další součástky. + * + * Generuje DTMF (PWM PD0,PD2) a posílá + * znaky na USART (PD5, PD6). + * Může to fungovat např. jako el. zámek. + * Indikační LED je na PD4, relé na PD3. + * */ +////////////////////////////////////// +static Usart usart (115200u); +static Keyboard kbd (usart); +static PcmDma pcm; +////////////////////////////////////// +int main () { + pcm.attach(kbd); + kbd.setPassword("3*1415926"); + for (;;) { + // do nothing + } + return 0; +} diff --git a/keyboard/sin.py b/keyboard/sin.py new file mode 100755 index 0000000..83b05fb --- /dev/null +++ b/keyboard/sin.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +import math + +header = '''/* Generated file */ +#include +const int16_t sin_tab[] = {{{0:s} +}}; +''' + +def generate(): + s = '' + for n in range(0,256): + if (n % 16) == 0: + s += '\n ' + a = float(n) * math.pi / 128.0 + v = int (round (480.0 * (math.sin (a)))); + s += '{0:+6d},'.format(v) + return s +def dtmf(): + f0 = 24000.0 + mf = math.pow (2.0, 32.0) / f0 + dtmf_l = [ 941, 852, 770, 697 ] + dtmf_h = [1209, 1336, 1477, 1633] + s = 'const unsigned dtmf_low_tab [] = {' + for f in dtmf_l: + n = int (f * mf) + s += ' 0x{0:08x},'.format (n) + s += ' };\n' + s += 'const unsigned dtmf_hi__tab [] = {' + for f in dtmf_h: + n = int (f * mf) + s += ' 0x{0:08x},'.format (n) + s += ' };\n' + return s + + +if __name__ == '__main__': + s = generate() + f = open ('sin.c','w') + f.write(header.format(s)) + f.write(dtmf()) + f.close() +