blink -> morse
This commit is contained in:
parent
1b0a6412ea
commit
fa73dbffbc
10 changed files with 401 additions and 28 deletions
|
@ -1,11 +1,11 @@
|
||||||
TARGET?= ch32v203
|
TARGET?= ch32v203
|
||||||
|
|
||||||
TOOL ?= gcc
|
#TOOL ?= gcc
|
||||||
#TOOL ?= clang
|
TOOL ?= clang
|
||||||
|
|
||||||
PRJ = example
|
PRJ = example
|
||||||
|
|
||||||
VPATH = . ./$(TARGET)
|
VPATH = . ./$(TARGET) ./common
|
||||||
BLD = ./build/
|
BLD = ./build/
|
||||||
DFLAGS = -d
|
DFLAGS = -d
|
||||||
LFLAGS = -g
|
LFLAGS = -g
|
||||||
|
@ -13,11 +13,11 @@ LDLIBS =
|
||||||
BFLAGS = --strip-unneeded
|
BFLAGS = --strip-unneeded
|
||||||
|
|
||||||
CFLAGS = -MMD -Wall -Wno-parentheses -ggdb -fno-exceptions -ffunction-sections -fdata-sections
|
CFLAGS = -MMD -Wall -Wno-parentheses -ggdb -fno-exceptions -ffunction-sections -fdata-sections
|
||||||
CFLAGS+= -I. -I./$(TARGET)
|
CFLAGS+= -I. -I./$(TARGET) -I./common
|
||||||
DEL = rm -f
|
DEL = rm -f
|
||||||
|
|
||||||
# zdrojaky
|
# zdrojaky
|
||||||
OBJS = main.o
|
OBJS = main.o pwmclass.o morse.o generator.o
|
||||||
#OBJS +=
|
#OBJS +=
|
||||||
|
|
||||||
include $(TARGET)/$(TOOL).mk
|
include $(TARGET)/$(TOOL).mk
|
||||||
|
|
1
V203F6P6/blink/common
Symbolic link
1
V203F6P6/blink/common
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../common/
|
28
V203F6P6/blink/generator.cpp
Normal file
28
V203F6P6/blink/generator.cpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include "generator.h"
|
||||||
|
#include "pwmclass.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
static constexpr unsigned W_TB = 8u;
|
||||||
|
static constexpr double AMPL = MAXPWM >> 1;
|
||||||
|
static constexpr int ULEN = 1 << W_TB;
|
||||||
|
|
||||||
|
static constexpr uint16_t u16_sin (const int x) {
|
||||||
|
const double a = (double (x) * D_PI) / double (ULEN);
|
||||||
|
const double s = AMPL * (1.0 + 0.96 * sincos (a, true));
|
||||||
|
return i_round (s);
|
||||||
|
}
|
||||||
|
static const TABLE<uint16_t, ULEN> sin_tab (u16_sin);
|
||||||
|
|
||||||
|
Generator::Generator (const unsigned f) noexcept : OneWay<uint16_t>(),
|
||||||
|
freq (f), base(0u), incr (0u), ms_count (0u) {
|
||||||
|
}
|
||||||
|
uint16_t Generator::step() {
|
||||||
|
const uint16_t v = sin_tab [base >> 24];
|
||||||
|
base += incr;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
unsigned int Generator::Send(uint16_t * const ptr, const unsigned int len) {
|
||||||
|
for (unsigned n=0u; n<len; n++) ptr [n] = step();
|
||||||
|
if (ms_count) ms_count -= 1u; // průchod zde je za 1 ms přesně
|
||||||
|
return len;
|
||||||
|
}
|
23
V203F6P6/blink/generator.h
Normal file
23
V203F6P6/blink/generator.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#ifndef GENERATOR_H
|
||||||
|
#define GENERATOR_H
|
||||||
|
#include "oneway.h"
|
||||||
|
/* Něco jako DDS, přesná frekvence není řešena (závisí na TIM1). */
|
||||||
|
class Generator : public OneWay<uint16_t> {
|
||||||
|
const unsigned freq;
|
||||||
|
unsigned base, incr;
|
||||||
|
volatile unsigned ms_count;
|
||||||
|
public:
|
||||||
|
explicit Generator (const unsigned f) noexcept;
|
||||||
|
unsigned Send (uint16_t * const ptr, const unsigned len) override;
|
||||||
|
|
||||||
|
void delay (const unsigned ms) {
|
||||||
|
ms_count = ms;
|
||||||
|
while (ms_count);
|
||||||
|
}
|
||||||
|
void on () volatile { incr = freq; }
|
||||||
|
void off () volatile { base = 0u; incr = 0u; }
|
||||||
|
protected:
|
||||||
|
uint16_t step ();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GENERATOR_H
|
|
@ -1,28 +1,24 @@
|
||||||
#include "system.h"
|
/* SIMPLE EXAMPLE: LED blinking */
|
||||||
#include "gpio.h"
|
/* Když už mám PWM hotové, tak to může pípat na pinu PA2. Je Tx pin pro
|
||||||
////////////////////////////////////////////////////////////////////////
|
* budič RS485, na tuto sběrnici je možné připojit "špunty do uší"
|
||||||
static constexpr unsigned ticks = SYSTEM_CORE_CLOCK / 1000u;
|
* 32Ohm v sérii a zvuk je dostatečně hlasitý, čip to utáhne.
|
||||||
static volatile unsigned counter = 0u;
|
* Frekvence je 1kHz - čistý sinus.
|
||||||
extern "C" [[gnu::interrupt]] void SysTick_Handler ();
|
*
|
||||||
////////////////////////////////////////////////////////////////////////
|
* Pro tento procesor je možné použít pro překlad clang. Pak je možné
|
||||||
void SysTick_Handler () {
|
* tabulky pro sinus i pro komprimovaný kód morse použít konstantní
|
||||||
SysTick.SR = 0u;
|
* výrazy. Nezvětšuje to délku kódu a je z toho vidět, jak se tyto
|
||||||
if (counter) counter -= 1u;
|
* věci počítají, aniž by bylo nutné použít nějaký externí nástroj.
|
||||||
}
|
*
|
||||||
static void delay (const unsigned dly = 200u) {
|
* Kód je fakticky recyklovaný z plného CH32V203, drobné úpravy tam jsou
|
||||||
counter = dly;
|
* protože je to pinově trochu jinak, princip je stejný.
|
||||||
while (counter);
|
* */
|
||||||
}
|
#include "morse.h"
|
||||||
|
//////////////////////////////////////
|
||||||
|
static GpioClass led (GPIOB, 8);
|
||||||
|
static Morse morse (led, 100u);
|
||||||
int main () {
|
int main () {
|
||||||
GpioClass led (GPIOB, 8);
|
|
||||||
SysTick.Config (ticks);
|
|
||||||
unsigned pass_cnt = 0u;
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
delay();
|
morse << "hello world";
|
||||||
const bool b = pass_cnt & 1u;
|
|
||||||
led << b;
|
|
||||||
pass_cnt += 1u;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
87
V203F6P6/blink/morse.cpp
Normal file
87
V203F6P6/blink/morse.cpp
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#include "morse.h"
|
||||||
|
#include "utils.h"
|
||||||
|
// Spočteme číslo (pro 1kHz) jako (1000 << 32) / 24000 (24 kHz je samplerate).
|
||||||
|
static constexpr unsigned F0 = (1000ull << 32) / 24000u;
|
||||||
|
|
||||||
|
static constexpr const char * const morse_code [] = { /* nedefinované znaky nahrazeny mezerou */
|
||||||
|
" ", /* */ " ", /*!*/ ".-..-.", /*\"*/ " ", /*#*/ " ", /*$*/
|
||||||
|
" ", /*%*/ " ", /*&*/ ".----.", /*\'*/ "-.--.", /*(*/ "-.--.-", /*)*/
|
||||||
|
" ", /***/ ".-.-.", /*+*/ "--..--", /*,*/ "-....-", /*-*/ ".-.-.-", /*.*/ "-..-." , /*/*/
|
||||||
|
"-----", /*0*/ ".----", /*1*/ "..---", /*2*/ "...--", /*3*/ "....-", /*4*/
|
||||||
|
".....", /*5*/ "-....", /*6*/ "--...", /*7*/ "---..", /*8*/ "----.", /*9*/
|
||||||
|
"---...", /*:*/ "-.-.-.", /*;*/ " ", /*<*/ "-...-" , /*=*/ " ", /*>*/ "..--..", /*?*/
|
||||||
|
".--.-.", /*@*/
|
||||||
|
".-", /*A*/ "-...", /*B*/ "-.-.", /*C*/ "-..", /*D*/ ".", /*E*/ "..-.", /*F*/
|
||||||
|
"--.", /*G*/ "....", /*H*/ "..", /*I*/ ".---", /*J*/ "-.-", /*K*/ ".-..", /*L*/
|
||||||
|
"--", /*M*/ "-.", /*N*/ "---", /*O*/ ".--.", /*P*/ "--.-", /*Q*/ ".-.", /*R*/
|
||||||
|
"...", /*S*/ "-", /*T*/ "..-", /*U*/ "...-", /*V*/ ".--", /*W*/ "-..-", /*X*/
|
||||||
|
"-.--", /*Y*/ "--..", /*Z*/ " ", " ", " ", " ", "..--.-", /*_*/
|
||||||
|
};
|
||||||
|
static constexpr unsigned slen (const char * const str) {
|
||||||
|
unsigned n = 0;
|
||||||
|
while (str[n]) n++;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
static const TABLE<unsigned char, array_size (morse_code)> compressed_table
|
||||||
|
([](const unsigned n) -> auto {
|
||||||
|
const char * const ptr = morse_code [n];
|
||||||
|
const unsigned len = slen (ptr);
|
||||||
|
unsigned char mb = 0u;
|
||||||
|
if (ptr [0] == ' ') return mb;
|
||||||
|
mb = (len & 7u) << 5;
|
||||||
|
for (unsigned n=0; n<len; n++) {
|
||||||
|
if (ptr [n] == '-') mb |= (1u << n);
|
||||||
|
}
|
||||||
|
return mb;
|
||||||
|
});
|
||||||
|
|
||||||
|
Morse::Morse(const GpioClass & pin, const unsigned int ms) noexcept : unit (ms), led (pin),
|
||||||
|
gen (F0), pwm () {
|
||||||
|
pwm.attach(gen);
|
||||||
|
}
|
||||||
|
const Morse & Morse::operator<< (const char * text) {
|
||||||
|
for (unsigned n=0; ; n++) {
|
||||||
|
const char c = text [n];
|
||||||
|
if (c == '\0') break;
|
||||||
|
morse_byte mb;
|
||||||
|
if (c < '\x20') {
|
||||||
|
} else if (c < '`') {
|
||||||
|
const int i = c - '\x20';
|
||||||
|
mb.byte = compressed_table [i];
|
||||||
|
} else if (c == '`') {
|
||||||
|
} else if (c <= 'z') {
|
||||||
|
const int i = c - '\x40';
|
||||||
|
mb.byte = compressed_table [i];
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
out (mb);
|
||||||
|
}
|
||||||
|
gen.delay (10 * unit);
|
||||||
|
return * this;
|
||||||
|
}
|
||||||
|
/* . => 1 x unit
|
||||||
|
* - => 3 x unit
|
||||||
|
* mezera mezi značkami => 1 x unit
|
||||||
|
* mezera mezi znaky => 3 x unit
|
||||||
|
* mezera mezi slovy => 7 x unit
|
||||||
|
* */
|
||||||
|
void Morse::out (const morse_byte mb) {
|
||||||
|
/* Finta je v tom, že i když se pole mlen a bits překrývají,
|
||||||
|
* nevadí to - maximální délka je 6, takže v nejnižším bitu
|
||||||
|
* mlen může být obsažen 1 bit 6.bitového znaku.
|
||||||
|
* Takhle napsáno to běhá jen na malém indiánu, přepisovat
|
||||||
|
* to do bitových posunů nebudu, i když by to bylo čistší.
|
||||||
|
* */
|
||||||
|
const unsigned len = mb.mlen > 6u ? 6u : mb.mlen;
|
||||||
|
if (!len) { gen.delay (4 * unit); return; }
|
||||||
|
for (unsigned n=0; n<len; n++) {
|
||||||
|
off ();
|
||||||
|
gen.delay (unit);
|
||||||
|
const unsigned v = (1u << n) & mb.bits;
|
||||||
|
const unsigned d = v ? 3u : 1u;
|
||||||
|
on ();
|
||||||
|
gen.delay (d * unit);
|
||||||
|
off ();
|
||||||
|
}
|
||||||
|
gen.delay (3 * unit);
|
||||||
|
}
|
36
V203F6P6/blink/morse.h
Normal file
36
V203F6P6/blink/morse.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef MORSE_H
|
||||||
|
#define MORSE_H
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "generator.h"
|
||||||
|
#include "pwmclass.h"
|
||||||
|
union morse_byte {
|
||||||
|
struct {
|
||||||
|
unsigned char bits : 5;
|
||||||
|
unsigned char mlen : 3;
|
||||||
|
};
|
||||||
|
unsigned char byte;
|
||||||
|
explicit constexpr morse_byte () noexcept : byte (0u) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Morse {
|
||||||
|
const unsigned unit;
|
||||||
|
const GpioClass & led;
|
||||||
|
Generator gen;
|
||||||
|
PwmClass pwm;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Morse (const GpioClass & pin, const unsigned ms = 100u) noexcept;
|
||||||
|
const Morse & operator<< (const char * text);
|
||||||
|
protected:
|
||||||
|
void out (const morse_byte mb);
|
||||||
|
void on () {
|
||||||
|
led << true; // LED je připojena proti GND, zde se tedy rozsvítí
|
||||||
|
gen.on ();
|
||||||
|
}
|
||||||
|
void off () {
|
||||||
|
led << false;
|
||||||
|
gen.off();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MORSE_H
|
107
V203F6P6/blink/pwmclass.cpp
Normal file
107
V203F6P6/blink/pwmclass.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
#include "pwmclass.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
extern "C" {
|
||||||
|
[[gnu::interrupt]] extern void DMA1_Channel2_IRQHandler( void );
|
||||||
|
};
|
||||||
|
static PwmClass * pInstance = nullptr;
|
||||||
|
void DMA1_Channel2_IRQHandler( void ) {
|
||||||
|
DMA1_Type::INTFR_DEF state (DMA1.INTFR);
|
||||||
|
if (state.B.GIF2 != RESET) {
|
||||||
|
DMA1.INTFCR.B.CGIF2 = SET;
|
||||||
|
} else return;
|
||||||
|
if (state.B.HTIF2 != RESET) {
|
||||||
|
DMA1.INTFCR.B.CHTIF2 = SET;
|
||||||
|
if (pInstance) pInstance->send(false);
|
||||||
|
}
|
||||||
|
if (state.B.TCIF2 != RESET) {
|
||||||
|
DMA1.INTFCR.B.CTCIF2 = SET;
|
||||||
|
if (pInstance) pInstance->send(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* initialize TIM2 for PWM
|
||||||
|
*/
|
||||||
|
inline void PwmClass::TimInit() noexcept {
|
||||||
|
// Enable GPIOA and TIM1
|
||||||
|
RCC.APB2PCENR.modify([] (RCC_Type::APB2PCENR_DEF & r) -> auto {
|
||||||
|
r.B.IOPAEN = SET;
|
||||||
|
r.B.IOPBEN = SET;
|
||||||
|
//r.B.AFIOEN = SET;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
RCC.APB1PCENR.B.TIM2EN = SET;
|
||||||
|
// PA2 is TIM2_CH3, 10MHz Output alt func, push-pull
|
||||||
|
GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
|
||||||
|
r.B.CNF2 = 2u;
|
||||||
|
r.B.MODE2 = 1u;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
// PB1 is DEN, active H Output 10 MHz, push-pull
|
||||||
|
GPIOB.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
|
||||||
|
r.B.CNF1 = 0u;
|
||||||
|
r.B.MODE1 = 1u;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
GPIOB.BSHR.B.BS1 = SET; // set to H
|
||||||
|
// Reset TIM2 to init all regs
|
||||||
|
RCC.APB1PRSTR.B.TIM2RST = SET;
|
||||||
|
RCC.APB1PRSTR.B.TIM2RST = RESET;
|
||||||
|
// CTLR1: default is up, events generated, edge align
|
||||||
|
// SMCFGR: default clk input is CK_INT
|
||||||
|
// Prescaler
|
||||||
|
TIM2.PSC.R = 0u; // 144 MHz
|
||||||
|
// Auto Reload - sets period
|
||||||
|
TIM2.ATRLR.R = MAXPWM - 1; // 24 kHz
|
||||||
|
|
||||||
|
// CH3 Mode is output, PWM1 (CC3S = 00, OC3M = 110)
|
||||||
|
TIM2.CHCTLR2_Output.modify([](TIM2_Type::CHCTLR2_Output_DEF & r) -> auto {
|
||||||
|
r.B.OC3M = 0x6u;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
// Enable TIM1 outputs
|
||||||
|
TIM2.CCER.modify([](TIM2_Type::CCER_DEF & r) -> auto {
|
||||||
|
// Enable CH3, CH3 output, positive pol
|
||||||
|
r.B.CC3E = SET;
|
||||||
|
//r.B.CC3P = SET; // negative
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
// Reload immediately + Trigger DMA
|
||||||
|
TIM2.SWEVGR.B.UG = SET;
|
||||||
|
TIM2.DMAINTENR.B.UDE = SET;
|
||||||
|
}
|
||||||
|
inline void PwmClass::DmaInit() noexcept {
|
||||||
|
// Enable DMA
|
||||||
|
RCC.AHBPCENR.modify([](RCC_Type::AHBPCENR_DEF & r) -> auto {
|
||||||
|
r.B.SRAMEN = SET;
|
||||||
|
r.B.DMA1EN = SET;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
// DMA can be configured to attach to T2UP
|
||||||
|
// The system can only DMA out at ~2.2MSPS. 2MHz is stable.
|
||||||
|
DMA1.CNTR2 .R = FULL_LEN;
|
||||||
|
DMA1.MADDR2.R = reinterpret_cast<size_t>(buffer);
|
||||||
|
DMA1.PADDR2.R = reinterpret_cast<size_t>(& TIM2.CH3CVR);
|
||||||
|
NVIC.EnableIRQ (DMA1_Channel2_IRQn);
|
||||||
|
DMA1.CFGR2.modify([](DMA1_Type::CFGR2_DEF & r) -> auto {
|
||||||
|
r.B.DIR = SET; // MEM2PERIPHERAL
|
||||||
|
r.B.PL = 2u; // High priority.
|
||||||
|
r.B.PSIZE = 1u; // 16-bit peripheral
|
||||||
|
r.B.MSIZE = 1u; // 16-bit memory
|
||||||
|
r.B.MINC = SET; // Increase memory.
|
||||||
|
r.B.CIRC = SET; // Circular mode.
|
||||||
|
r.B.HTIE = SET; // Half-trigger
|
||||||
|
r.B.TCIE = SET; // Whole-trigger
|
||||||
|
// Enable DMA1 CH2
|
||||||
|
r.B.EN = SET;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
PwmClass::PwmClass() noexcept : count(0u), pL(buffer), pH(buffer + HALF_LEN), src(nullptr) {
|
||||||
|
pInstance = this;
|
||||||
|
TimInit ();
|
||||||
|
DmaInit ();
|
||||||
|
// Enable TIM2
|
||||||
|
TIM2.CTLR1.B.CEN = SET;
|
||||||
|
}
|
35
V203F6P6/blink/pwmclass.h
Normal file
35
V203F6P6/blink/pwmclass.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#ifndef PWMCLASS_H
|
||||||
|
#define PWMCLASS_H
|
||||||
|
#include "system.h"
|
||||||
|
#include "oneway.h"
|
||||||
|
static constexpr unsigned MAXPWM = 6000u;
|
||||||
|
/* Používá TIM2, PWM kanál 3, DMA1 kanál 2, přerušení DMA1_Channel2_IRQHandler */
|
||||||
|
class PwmClass {
|
||||||
|
static constexpr unsigned HALF_LEN = 24u;
|
||||||
|
static constexpr unsigned FULL_LEN = 2u * HALF_LEN;
|
||||||
|
volatile unsigned count;
|
||||||
|
uint16_t * const pL;
|
||||||
|
uint16_t * const pH;
|
||||||
|
uint16_t buffer [FULL_LEN];
|
||||||
|
OneWay<uint16_t> * src;
|
||||||
|
public:
|
||||||
|
explicit PwmClass () noexcept;
|
||||||
|
void attach (OneWay<uint16_t> & s) { src = & s; }
|
||||||
|
void send (const bool b) {
|
||||||
|
if (!src) return;
|
||||||
|
if (b) src->Send (pH, HALF_LEN);
|
||||||
|
else src->Send (pL, HALF_LEN);
|
||||||
|
if (count) count -= 1u;
|
||||||
|
}
|
||||||
|
void delay (const unsigned frames = 50u) {
|
||||||
|
count = frames;
|
||||||
|
while (count) {
|
||||||
|
asm volatile ("nop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
void DmaInit () noexcept;
|
||||||
|
void TimInit () noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PWMCLASS_H
|
60
V203F6P6/blink/utils.h
Normal file
60
V203F6P6/blink/utils.h
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
template<class T, size_t N>constexpr size_t array_size (T (&) [N]) { return N; }
|
||||||
|
|
||||||
|
template<class T, const int N> class TABLE {
|
||||||
|
T data [N];
|
||||||
|
public:
|
||||||
|
/** @brief Konstruktor.
|
||||||
|
* @param f Ukazatel na constexpr funkci, která pak vytvoří tabulku.
|
||||||
|
* */
|
||||||
|
template<typename F> explicit constexpr TABLE (F f) noexcept {
|
||||||
|
for (int n=0; n<N; n++) data [n] = f (n);
|
||||||
|
}
|
||||||
|
/** operator[] vrátí konstantní odkaz na prvek pole, protože se předpokládá,
|
||||||
|
* že instance této třídy bude jako taková též konstantní
|
||||||
|
*/
|
||||||
|
const T & operator[] (const int index) const {
|
||||||
|
return data [index];
|
||||||
|
}
|
||||||
|
/** @class iterator
|
||||||
|
* @brief range-based for () */
|
||||||
|
class iterator {
|
||||||
|
const T * ptr;
|
||||||
|
public:
|
||||||
|
iterator(const T * _ptr) : ptr (_ptr) {}
|
||||||
|
iterator operator++ () { ++ptr; return * this; }
|
||||||
|
bool operator!= (const iterator & other) const { return ptr != other.ptr; }
|
||||||
|
const T & operator* () const { return * ptr; }
|
||||||
|
};
|
||||||
|
iterator begin () const { return iterator (data ); }
|
||||||
|
iterator end () const { return iterator (data + N); }
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr double X_PI = 3.14159265358979323846;
|
||||||
|
static constexpr double D_PI = 2.0 * X_PI;
|
||||||
|
/* cmath nejde použít, tak si to mírně zjednodušíme, ale musí to fungovat */
|
||||||
|
static constexpr double dabs (const double a) { return a < 0.0 ? -a : +a; }
|
||||||
|
static constexpr int i_round (const double a) { return a < 0.0 ? int (a - 0.5) : int (a + 0.5); }
|
||||||
|
/* tahle divná funkce počítá sinus, pokud even=true i kosinus, pokud even=false */
|
||||||
|
static constexpr double sincos (const double x, const bool even) {
|
||||||
|
double result (0.0), element(1.0), divider(0.0);
|
||||||
|
if (even) { element *= x; divider += 1.0; }
|
||||||
|
constexpr double eps = 1.0e-9; // maximální chyba výpočtu
|
||||||
|
const double aa = - (x * x);
|
||||||
|
for (;;) {
|
||||||
|
result += element;
|
||||||
|
if (dabs (element) < eps) break;
|
||||||
|
divider += 1.0;
|
||||||
|
double fact = divider;
|
||||||
|
divider += 1.0;
|
||||||
|
fact *= divider;
|
||||||
|
element *= aa / fact;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // UTILS_H
|
Loading…
Reference in a new issue