add gsm
This commit is contained in:
parent
fa73dbffbc
commit
f11366d182
14 changed files with 445 additions and 0 deletions
38
V203F6P6/gsm/GsmDecoder.cpp
Normal file
38
V203F6P6/gsm/GsmDecoder.cpp
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include "pwmclass.h"
|
||||||
|
#include "GsmDecoder.h"
|
||||||
|
|
||||||
|
static const unsigned int DataLenght = 2529384u;
|
||||||
|
extern "C" void * memcpy(void * dest, const void * src, size_t n);
|
||||||
|
|
||||||
|
GsmDecoder::GsmDecoder(GpioClass & io) noexcept : OneWay<uint16_t>(),
|
||||||
|
led(io), flash(), gsm(), count(0u), pass(false) {
|
||||||
|
}
|
||||||
|
static constexpr int INPUT_BIT_RANGE = 16;
|
||||||
|
static constexpr unsigned SIGMA_MASK = (1u << (INPUT_BIT_RANGE + 0)) - 1u;
|
||||||
|
static constexpr unsigned SIGNED_OFFEST = (1u << (INPUT_BIT_RANGE - 1));
|
||||||
|
// Předpokládá se na vstupu signed int o šířce INPUT_BIT_RANGE
|
||||||
|
// přičemž 0 na vstupu odpovídá MAXPWM / 2 na výstupu. Vypadá to divně, ale funguje.
|
||||||
|
static unsigned pwm_sd (const int input) {
|
||||||
|
static unsigned sigma = 0; // podstatné je, že proměnná je statická
|
||||||
|
const unsigned sample = (input + SIGNED_OFFEST) * MAXPWM;
|
||||||
|
sigma &= SIGMA_MASK; // v podstatě se odečte hodnota PWM
|
||||||
|
sigma += sample; // integrace prostým součtem
|
||||||
|
return sigma >> INPUT_BIT_RANGE;
|
||||||
|
}
|
||||||
|
unsigned GsmDecoder::Send(uint16_t * dptr, const unsigned len) {
|
||||||
|
led << pass;
|
||||||
|
pass = ! pass;
|
||||||
|
const unsigned step = sizeof(gsm_frame);
|
||||||
|
static gsm_frame e;
|
||||||
|
flash.ReadBlock(count, e, step);
|
||||||
|
count += step;
|
||||||
|
gsm.decode (e, tmp_buf);
|
||||||
|
if (count >= DataLenght) count = 0u;
|
||||||
|
for (unsigned n=0u, k=0u; k<len; n++) {
|
||||||
|
const int16_t s = tmp_buf[n];
|
||||||
|
dptr [k++] = pwm_sd (s); // vyzkoušená metoda jak vylepšit PWM
|
||||||
|
dptr [k++] = pwm_sd (s); // pokud máme frekvenci PWM větší
|
||||||
|
dptr [k++] = pwm_sd (s); // než vzorkovací frekvence signálu ft = n * fs, n = 3
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
22
V203F6P6/gsm/GsmDecoder.h
Normal file
22
V203F6P6/gsm/GsmDecoder.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef GSMDECODER_H
|
||||||
|
#define GSMDECODER_H
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "oneway.h"
|
||||||
|
#include "gsm.h"
|
||||||
|
#include "norflash.h"
|
||||||
|
|
||||||
|
static constexpr int GSMLEN = 160;
|
||||||
|
|
||||||
|
class GsmDecoder : public OneWay<uint16_t> {
|
||||||
|
GpioClass & led;
|
||||||
|
NorFlash flash;
|
||||||
|
GsmStatic gsm;
|
||||||
|
unsigned count;
|
||||||
|
bool pass;
|
||||||
|
gsm_signal tmp_buf [GSMLEN];
|
||||||
|
public:
|
||||||
|
explicit GsmDecoder(GpioClass & io) noexcept;
|
||||||
|
unsigned Send (uint16_t * ptr, const unsigned len) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GSMDECODER_H
|
60
V203F6P6/gsm/Makefile
Normal file
60
V203F6P6/gsm/Makefile
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
TARGET?= ch32v203
|
||||||
|
|
||||||
|
TOOL ?= gcc
|
||||||
|
#TOOL ?= clang
|
||||||
|
|
||||||
|
PRJ = example
|
||||||
|
|
||||||
|
VPATH = . ./$(TARGET)
|
||||||
|
BLD = ./build/
|
||||||
|
DFLAGS = -d
|
||||||
|
LFLAGS = -g
|
||||||
|
LDLIBS =
|
||||||
|
BFLAGS = --strip-unneeded
|
||||||
|
|
||||||
|
CFLAGS = -MMD -Wall -Wno-parentheses -ggdb -fno-exceptions -ffunction-sections -fdata-sections
|
||||||
|
CFLAGS+= -I. -I./$(TARGET) -I./common -I./lib/gsm/inc
|
||||||
|
DEL = rm -f
|
||||||
|
|
||||||
|
# zdrojaky
|
||||||
|
OBJS = main.o pwmclass.o
|
||||||
|
OBJS += GsmDecoder.o wrap.o
|
||||||
|
OBJS += spiblocked.o norflash.o
|
||||||
|
|
||||||
|
include $(TARGET)/$(TOOL).mk
|
||||||
|
BOBJS = $(addprefix $(BLD),$(OBJS))
|
||||||
|
|
||||||
|
all: $(BLD) $(PRJ).elf
|
||||||
|
# ... atd.
|
||||||
|
-include $(BLD)*.d
|
||||||
|
LDLIBS += -L./lib -lgsm
|
||||||
|
# linker
|
||||||
|
$(PRJ).elf: $(BOBJS) ./lib/libgsm.a
|
||||||
|
-@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) -std=gnu99 -c $(CFLAGS) $< -o $@
|
||||||
|
$(BLD)%.o: %.cpp
|
||||||
|
-@echo [CX $(TOOL),$(TARGET)] $@
|
||||||
|
@$(CXX) -std=c++17 -fno-rtti -c $(CFLAGS) $< -o $@
|
||||||
|
$(BLD)%.o: %.s
|
||||||
|
-@echo [AS $(TOOL),$(TARGET)] $@
|
||||||
|
@$(AS) $(CCPU) $< -o $@
|
||||||
|
$(BLD):
|
||||||
|
mkdir $(BLD)
|
||||||
|
./lib/libgsm.a:
|
||||||
|
cd ./lib/gsm/src && $(MAKE) TARGET=$(TARGET) all
|
||||||
|
flash: $(PRJ).elf
|
||||||
|
minichlink -w $(PRJ).bin flash -b
|
||||||
|
# vycisti
|
||||||
|
clean:
|
||||||
|
$(DEL) $(BLD)* *.lst *.bin *.elf *.map *~
|
||||||
|
.PHONY: all clean flash run
|
1
V203F6P6/gsm/ch32v203
Symbolic link
1
V203F6P6/gsm/ch32v203
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../ch32v203/
|
1
V203F6P6/gsm/common
Symbolic link
1
V203F6P6/gsm/common
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../common/
|
1
V203F6P6/gsm/lib
Symbolic link
1
V203F6P6/gsm/lib
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../../V203/gsm/lib/
|
22
V203F6P6/gsm/main.cpp
Normal file
22
V203F6P6/gsm/main.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include "pwmclass.h"
|
||||||
|
#include "GsmDecoder.h"
|
||||||
|
#include "norflash.h"
|
||||||
|
#include "oneway.h"
|
||||||
|
#include "gpio.h"
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
/* GSM kecátko funguje i na tomto menším procesoru.
|
||||||
|
* Jen pak nusí být data v externí flash (připojené) přes
|
||||||
|
* SPI. Číst je je možné i v přerušení DMA, trvá to krátce.
|
||||||
|
* */
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
static PwmClass pwm;
|
||||||
|
static GpioClass pwr (GPIOB, 8);
|
||||||
|
static GsmDecoder decoder (pwr);
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
pwr << true;
|
||||||
|
pwm.attach (decoder);
|
||||||
|
for (;;) {
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
45
V203F6P6/gsm/norflash.cpp
Normal file
45
V203F6P6/gsm/norflash.cpp
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include "string.h"
|
||||||
|
#include "norflash.h"
|
||||||
|
|
||||||
|
/// Enumerace povelů pro SPI FLASH.
|
||||||
|
enum FLASH_COMMANDS : uint8_t {
|
||||||
|
/* single byte commands */
|
||||||
|
FLASH_WRDI = 0x04, // nepoužito
|
||||||
|
FLASH_WREN = 0x06,
|
||||||
|
FLASH_RDID = 0x9F,
|
||||||
|
FLASHRSTEN = 0x66, // nepoužito
|
||||||
|
FLASH__RST = 0x99, // nepoužito
|
||||||
|
FLASH__RES = 0xAB, // release from power down, nepoužito
|
||||||
|
FLASH__DPD = 0xB9, // power down, nepoužito
|
||||||
|
// multi - byte
|
||||||
|
FLASH_RDSR1 = 0x05,
|
||||||
|
// dále se mohou povely lišit
|
||||||
|
FLASH_RDSR2 = 0x35, // nepoužito
|
||||||
|
FLASH_4READ = 0x03,
|
||||||
|
FLASH_4PP = 0x02,
|
||||||
|
FLASH_4SE = 0x20,
|
||||||
|
};
|
||||||
|
union FlashCommandHeader {
|
||||||
|
struct {
|
||||||
|
FLASH_COMMANDS cmd : 8;
|
||||||
|
uint32_t adr : 24; // adresa je BIG ENDIEN - vyšší byte vystupuje po SPI dříve (MSB FIRST).
|
||||||
|
}__attribute__((packed));
|
||||||
|
uint8_t bytes [4];
|
||||||
|
}__attribute__((packed));
|
||||||
|
static inline uint32_t be_set_24 (const uint32_t p) {
|
||||||
|
return ((p & 0x000000ff) << 16)
|
||||||
|
| ((p & 0x0000ff00) << 0)
|
||||||
|
| ((p & 0x00ff0000) >> 16);
|
||||||
|
}
|
||||||
|
/* Nic jiného zatím není potřeba, ale šlo by dodělat i zápis včetně mazání bloku.
|
||||||
|
*/
|
||||||
|
unsigned int NorFlash::ReadBlock(const unsigned int addr, uint8_t * data, const unsigned int len) {
|
||||||
|
FlashCommandHeader header;
|
||||||
|
header.cmd = FLASH_4READ;
|
||||||
|
header.adr = be_set_24(addr);
|
||||||
|
spi.ChipSelect(true);
|
||||||
|
for (unsigned n=0u; n<sizeof(header); n++) spi.ReadWriteByte(header.bytes[n]);
|
||||||
|
for (unsigned n=0u; n<len; n++) data [n] = spi.ReadWriteByte(0xff);
|
||||||
|
spi.ChipSelect(false);
|
||||||
|
return len;
|
||||||
|
}
|
13
V203F6P6/gsm/norflash.h
Normal file
13
V203F6P6/gsm/norflash.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef NORFLASH_H
|
||||||
|
#define NORFLASH_H
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "spiblocked.h"
|
||||||
|
|
||||||
|
class NorFlash {
|
||||||
|
SpiBlocked spi;
|
||||||
|
public:
|
||||||
|
explicit NorFlash () noexcept : spi() {}
|
||||||
|
unsigned ReadBlock (const unsigned addr, uint8_t * data, const unsigned len);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NORFLASH_H
|
107
V203F6P6/gsm/pwmclass.cpp
Normal file
107
V203F6P6/gsm/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 * pPwmInstance = 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 (pPwmInstance) pPwmInstance->send(false);
|
||||||
|
}
|
||||||
|
if (state.B.TCIF2 != RESET) {
|
||||||
|
DMA1.INTFCR.B.CTCIF2 = SET;
|
||||||
|
if (pPwmInstance) pPwmInstance->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) {
|
||||||
|
pPwmInstance = this;
|
||||||
|
TimInit ();
|
||||||
|
DmaInit ();
|
||||||
|
// Enable TIM2
|
||||||
|
TIM2.CTLR1.B.CEN = SET;
|
||||||
|
}
|
35
V203F6P6/gsm/pwmclass.h
Normal file
35
V203F6P6/gsm/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 = 3u * 160u;
|
||||||
|
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
|
66
V203F6P6/gsm/spiblocked.cpp
Normal file
66
V203F6P6/gsm/spiblocked.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#include "system.h"
|
||||||
|
#include "spiblocked.h"
|
||||||
|
enum SPICLK : uint32_t {
|
||||||
|
FPCLK_2 = 0u, // 72 MHz
|
||||||
|
FPCLK_4, // 36 MHz
|
||||||
|
FPCLK_8, // 18 MHz
|
||||||
|
FPCLK_16, // 9 MHz
|
||||||
|
FPCLK_32, // 4.5 MHz
|
||||||
|
FPCLK_64, // 2.25 MHz
|
||||||
|
FPCLK_128, // 1.125 MHz
|
||||||
|
FPCLK_256, // 0.5625 MHz
|
||||||
|
};
|
||||||
|
static constexpr unsigned FM = 3u; // 50 MHz
|
||||||
|
static void InitPins () noexcept {
|
||||||
|
// PA4 - NSS, PA5 - SCK, PA6 - MISO, PA7 - MOSI
|
||||||
|
GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> uint32_t {
|
||||||
|
r.B.MODE4 = FM;
|
||||||
|
r.B.CNF4 = 0u; // gen push - pull
|
||||||
|
r.B.MODE5 = FM;
|
||||||
|
r.B.CNF5 = 2u; // alt push - pull
|
||||||
|
r.B.MODE6 = 0u; // input mode
|
||||||
|
r.B.CNF6 = 1u; // floating
|
||||||
|
r.B.MODE7 = FM;
|
||||||
|
r.B.CNF7 = 2u; // alt push - pull
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
// AFIO - default
|
||||||
|
GPIOA.BSHR.B.BS4 = SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpiBlocked::SpiBlocked() noexcept {
|
||||||
|
RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> uint32_t {
|
||||||
|
r.B.SPI1EN = SET;
|
||||||
|
r.B.IOPAEN = SET;
|
||||||
|
//r.B.AFIOEN = SET;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
InitPins();
|
||||||
|
RCC.APB2PRSTR.B.SPI1RST = SET;
|
||||||
|
RCC.APB2PRSTR.B.SPI1RST = RESET;
|
||||||
|
SPI1.CTLR1.modify([](SPI1_Type::CTLR1_DEF & r) -> uint32_t {
|
||||||
|
r.B.CPHA = RESET;
|
||||||
|
r.B.CPOL = RESET;
|
||||||
|
r.B.MSTR = SET; // master
|
||||||
|
r.B.DFF = RESET; // 8 bit
|
||||||
|
r.B.SSM = SET; // software
|
||||||
|
r.B.SSI = SET; // !!! netuším proč, ale jinak se nenastaví MSTR a SPE
|
||||||
|
r.B.LSBFIRST = RESET;
|
||||||
|
r.B.BR = FPCLK_64;
|
||||||
|
return r.R;
|
||||||
|
});
|
||||||
|
SPI1.CRCR.R = 7u;
|
||||||
|
SPI1.CTLR1.B.SPE = SET;
|
||||||
|
}
|
||||||
|
uint8_t SpiBlocked::ReadWriteByte(const uint8_t data) {
|
||||||
|
while (SPI1.STATR.B.TXE == RESET);
|
||||||
|
SPI1.DATAR.B.DATAR = data;
|
||||||
|
while (SPI1.STATR.B.RXNE == RESET);
|
||||||
|
return SPI1.DATAR.B.DATAR;
|
||||||
|
}
|
||||||
|
void SpiBlocked::ChipSelect(const bool on) {
|
||||||
|
if (on) GPIOA.BSHR.B.BR4 = SET;
|
||||||
|
else GPIOA.BSHR.B.BS4 = SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
12
V203F6P6/gsm/spiblocked.h
Normal file
12
V203F6P6/gsm/spiblocked.h
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#ifndef SPIBLOCKED_H
|
||||||
|
#define SPIBLOCKED_H
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class SpiBlocked {
|
||||||
|
public:
|
||||||
|
explicit SpiBlocked () noexcept;
|
||||||
|
uint8_t ReadWriteByte (const uint8_t data);
|
||||||
|
void ChipSelect (const bool on);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SPIBLOCKED_H
|
22
V203F6P6/gsm/wrap.c
Normal file
22
V203F6P6/gsm/wrap.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
/* Funkce z newlib, použité ve zdrojácích.
|
||||||
|
* Velmi zjednodušeno.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int quot, rem;
|
||||||
|
} div_t;
|
||||||
|
typedef __SIZE_TYPE__ size_t;
|
||||||
|
div_t div (int numerator, int denominator) {
|
||||||
|
const div_t result = { numerator / denominator, numerator % denominator };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void * memset(void * s, int c, size_t n) {
|
||||||
|
char * p = (char*) s;
|
||||||
|
for (unsigned i=0u; i<n; i++) p [i] = c;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
void * memcpy(void * dest, const void * src, size_t n) {
|
||||||
|
char * d = (char*) dest;
|
||||||
|
const char * s = (const char*) src;
|
||||||
|
for (unsigned i=0u; i<n; i++) d [i] = s [i];
|
||||||
|
return dest;
|
||||||
|
}
|
Loading…
Reference in a new issue