diff --git a/hdo/adcclass.cpp b/ch32v003/adcdma.cpp similarity index 94% rename from hdo/adcclass.cpp rename to ch32v003/adcdma.cpp index 0868fd8..739320f 100644 --- a/hdo/adcclass.cpp +++ b/ch32v003/adcdma.cpp @@ -1,8 +1,8 @@ #include "system.h" #include "oneway.h" -#include "adcclass.h" +#include "adcdma.h" -static AdcClass * pInstance = nullptr; +static AdcDma * pInstance = nullptr; extern "C" void DMA1_Channel1_IRQHandler( void ) __attribute__((interrupt)); void DMA1_Channel1_IRQHandler( void ) { @@ -90,7 +90,7 @@ static inline void AdcPostInit (void) noexcept { }); } //////////////////////////////////////////////////////////////////////////////////// -AdcClass::AdcClass() noexcept : pL (buffer), pH (buffer + HALF_LEN), dst (nullptr) { +AdcDma::AdcDma() noexcept : pL (buffer), pH (buffer + HALF_LEN), dst (nullptr) { pInstance = this; EnableClock (); Timer2Init (1000u); @@ -101,7 +101,7 @@ AdcClass::AdcClass() noexcept : pL (buffer), pH (buffer + HALF_LEN), dst (nullpt // start timer TIM2.CTLR1.B.CEN = SET; } -inline void AdcClass::send(const bool b) { +inline void AdcDma::send(const bool b) { if (!dst) return; if (b) dst->Send (pH, HALF_LEN); else dst->Send (pL, HALF_LEN); diff --git a/ch32v003/config.h b/ch32v003/config.h new file mode 100644 index 0000000..44bc625 --- /dev/null +++ b/ch32v003/config.h @@ -0,0 +1,10 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#define LED_CFG GPIOD,2 +#define REL_CFG GPIOD,4 + +#define SW__ON false +#define SW_OFF true + +#endif // CONFIG_H diff --git a/ch32v003/usart.cpp b/ch32v003/usart.cpp new file mode 100644 index 0000000..4077485 --- /dev/null +++ b/ch32v003/usart.cpp @@ -0,0 +1,80 @@ +#include "system.h" +#include "usart.h" +static Usart * pInstance = nullptr; +static constexpr unsigned HCLK = 48'000'000u; + +extern "C" void USART1_IRQHandler (void) __attribute__((interrupt)); +void USART1_IRQHandler (void) { + if (pInstance) pInstance->irq(); +}; + +Usart::Usart(const uint32_t _baud) noexcept : BaseLayer (), tx_ring () { + pInstance = this; + // 1. Clock Enable + RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> auto { + r.B.USART1EN = SET; + r.B.IOPDEN = SET; + return r.R; + }); + // 2. GPIO Alternate Config - default TX/PD5, RX/PD6 + GPIOD.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto { + r.B.MODE5 = 1u; + r.B.CNF5 = 2u; // or 3u for open drain + r.B.MODE6 = 0u; + r.B.CNF6 = 1u; // floating input + return r.R; + }); + // 4. NVIC + NVIC.EnableIRQ (USART1_IRQn); + // 5. USART registry 8.bit bez parity + USART1.CTLR1.modify([] (USART1_Type::CTLR1_DEF & r) -> auto { + r.B.RE = SET; + r.B.TE = SET; + r.B.RXNEIE = SET; + return r.R; + }); + USART1.CTLR2.R = 0; + //USART1.CTLR3.B.OVRDIS = SET; + const uint32_t tmp = HCLK / _baud; + USART1.BRR.R = tmp; + USART1.CTLR1.B.UE = SET; // nakonec povolit globálně +} +void Usart::irq () { + volatile USART1_Type::STATR_DEF status (USART1.STATR); // načti status přerušení + char rdata, tdata; + + if (status.B.TXE) { // od vysílače + if (tx_ring.Read (tdata)) { // pokud máme data + USART1.DATAR.B.DR = (uint8_t) tdata; // zapíšeme do výstupu + } else { // pokud ne + // Předpoklad je half-duplex i.e. RS485, jinak jen zakázat TXEIE + rdata = (USART1.DATAR.B.DR); // dummy read + USART1.CTLR1.modify([](USART1_Type::CTLR1_DEF & r) -> auto { + r.B.RE = SET; // povol prijem + r.B.TXEIE = RESET; // je nutné zakázat přerušení od vysílače + return r.R; + }); + } + } + if (status.B.RXNE) { // od přijímače + rdata = (USART1.DATAR.B.DR); // načteme data + Up (&rdata, 1u); // a pošleme dál + } +} +uint32_t Usart::Down(const char * data, const uint32_t len) { + unsigned n = 0u; + for (n=0u; n auto { + r.B.RE = RESET; + r.B.TXEIE = SET; // po povolení přerušení okamžitě přeruší + return r.R; + }); + return n; +} +void Usart::SetRS485 (const bool polarity) const { +} +void Usart::SetHalfDuplex (const bool on) const { +} + diff --git a/hdo/adcclass.h b/common/adcdma.h similarity index 73% rename from hdo/adcclass.h rename to common/adcdma.h index a49481e..8e91222 100644 --- a/hdo/adcclass.h +++ b/common/adcdma.h @@ -1,21 +1,21 @@ -#ifndef ADCCLASS_H -#define ADCCLASS_H +#ifndef ADCDMA_H +#define ADCDMA_H #include class OneWay; static constexpr unsigned HALF_LEN = 120u; static constexpr unsigned FULL_LEN = HALF_LEN * 2u; -class AdcClass { +class AdcDma { uint16_t * pL; uint16_t * pH; uint16_t buffer [FULL_LEN]; OneWay * dst; public: - explicit AdcClass () noexcept; + explicit AdcDma () noexcept; void attach (OneWay & d) { dst = & d; } void send (const bool b); }; -#endif // ADCCLASS_H +#endif // ADCDMA_H diff --git a/common/usart.h b/common/usart.h new file mode 100644 index 0000000..7ae814c --- /dev/null +++ b/common/usart.h @@ -0,0 +1,21 @@ +#ifndef USART_H +#define USART_H +#include "fifo.h" +#include "baselayer.h" +/** @class Usart + * @brief Sériový port. + * + * Zde RS485, jen výstup. + */ +class Usart : public BaseLayer { + FIFO tx_ring; + public: + explicit Usart (const uint32_t baud = 9600) noexcept; + uint32_t Down (const char * data, const uint32_t len) override; + void SetRS485 (const bool polarity) const; + + void irq (void); + void SetHalfDuplex (const bool on) const; +}; + +#endif // USART_H diff --git a/hdo/Makefile b/hdo/Makefile index d38e4a2..f0bd8f0 100644 --- a/hdo/Makefile +++ b/hdo/Makefile @@ -16,8 +16,8 @@ CFLAGS+= -I. -I./common -I./$(TARGET) -I/usr/include/newlib -DUSE_HSE=1 DEL = rm -f # zdrojaky -OBJS = main.o adcclass.o hdo.o -OBJS += usartclass.o print.o +OBJS = main.o adcdma.o hdo.o +OBJS += usart.o print.o include $(TARGET)/$(TOOL).mk BOBJS = $(addprefix $(BLD),$(OBJS)) diff --git a/hdo/hdo.cpp b/hdo/hdo.cpp index 2686767..da72c9e 100644 --- a/hdo/hdo.cpp +++ b/hdo/hdo.cpp @@ -37,8 +37,8 @@ void Hdo::pass () { cout << value << " \r"; value -= trigger; - if (value > 0) led << false; // LED je zapojená proti VCC - else led << true; + if (value > 0) led << SW__ON; // LED je zapojená proti VCC + else led << SW_OFF; // Konečné vyhodnocení. if (Decode (value, buf1)) { // Telegram OK. HumanRead (buf1, buf2); // Převeď ho do čitelné podoby diff --git a/hdo/hdo.h b/hdo/hdo.h index cf886a0..6738722 100644 --- a/hdo/hdo.h +++ b/hdo/hdo.h @@ -1,9 +1,10 @@ #ifndef HDO_H #define HDO_H #include "gpio.h" -#include "usartclass.h" +#include "usart.h" #include "print.h" #include "oneway.h" +#include "config.h" static constexpr int ISHIFT = 12; /* Tady je ten výpočet proveden externě. @@ -28,7 +29,7 @@ static constexpr int TBUFLEN = 64; class Hdo : public OneWay { GpioClass led, relay; - UsartClass serial; + Usart serial; Print cout; FIFO data; const int coeff; @@ -44,7 +45,7 @@ class Hdo : public OneWay { public: explicit Hdo (const char * command) noexcept : OneWay (), - led (GPIOD, 2), relay (GPIOD, 4), serial (115200u), cout (DEC), data(), coeff (1706), trigger (0x4000), + led (LED_CFG), relay (REL_CFG), serial (115200u), cout (DEC), data(), coeff (1706), trigger (0x4000), cmd (command), suma (0), bits (0), counter (0), status (WAIT_FOR_BEGIN) { /* trigger musí být nastaven tak do 1/3 až do 1/2 maximální vyhodnocené hodnoty (viz výpis) * Je nutné použít HSE, tj. krystal 24 HHz. Bez toho to fakt nechodí a to i na procesorech i.e. STM. diff --git a/hdo/main.cpp b/hdo/main.cpp index 2ce6fb0..0b7397a 100644 --- a/hdo/main.cpp +++ b/hdo/main.cpp @@ -1,4 +1,4 @@ -#include "adcclass.h" +#include "adcdma.h" #include "hdo.h" /////////////////////////////////////////////////////////////// /* Tohle je trochu komplexnější příklad. @@ -27,8 +27,8 @@ * !!! Krystal 24 MHz nutný !!! * */ /////////////////////////////////////////////////////////////// -static AdcClass adc; -static Hdo hdo ("A1B8DP1"); +static AdcDma adc; +static Hdo hdo ("A1B8DP1"); int main () { adc.attach(hdo); for (;;) { diff --git a/ch32v003/usartclass.cpp b/serial/usartclass.cpp similarity index 100% rename from ch32v003/usartclass.cpp rename to serial/usartclass.cpp diff --git a/ch32v003/usartclass.h b/serial/usartclass.h similarity index 100% rename from ch32v003/usartclass.h rename to serial/usartclass.h