This commit is contained in:
Kizarm 2024-04-08 20:55:20 +02:00
parent de48701e8c
commit dfcba8ee41
13 changed files with 338 additions and 2 deletions

View file

@ -7,7 +7,7 @@ SIZE = $(PREFIX)size
DUMP = $(PREFIX)objdump
COPY = $(PREFIX)objcopy
OBJS += startup.o system.o
CFLAGS+= -Os
CFLAGS+= -Os -I/usr/include/newlib
CCPU = -march=rv32ec -mabi=ilp32e
MCPU = $(CCPU)
CFLAGS+= $(MCPU)

View file

@ -17,6 +17,7 @@ class PcmDma {
OneWay * src;
public:
explicit PcmDma () noexcept;
uint16_t * getBuff () { return buffer; };
void attach (OneWay & s) { src = & s; }
void send (const bool b) {
if (!src) return;

54
i2c/Makefile Normal file
View file

@ -0,0 +1,54 @@
# ch32v003
TARGET?= ch32v003
TOOL ?= gcc
PRJ = example
VPATH = . ./$(TARGET) ./common
BLD = ./build/
DFLAGS = -d
LFLAGS = -g
LDLIBS =
BFLAGS = --strip-unneeded
CFLAGS = -MMD -Wall -ggdb -fno-exceptions -ffunction-sections -fdata-sections
CFLAGS+= -I. -I./$(TARGET) -I./common -I/usr/include/newlib -DUSE_HSE=1
DEL = rm -f
# zdrojaky
OBJS = main.o i2cmaster.o usart.o print.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
$(COPY) $(BFLAGS) -O ihex $(PRJ).elf $(PRJ).hex
# 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 *.hex *.elf *.map *~
.PHONY: all clean

1
i2c/ch32v003 Symbolic link
View file

@ -0,0 +1 @@
../ch32v003/

1
i2c/common Symbolic link
View file

@ -0,0 +1 @@
../common/

85
i2c/i2cmaster.cpp Normal file
View file

@ -0,0 +1,85 @@
#include "system.h"
#include "i2cmaster.h"
#include "print.h"
I2CMaster::I2CMaster() noexcept {
RCC.APB1PCENR.B.I2C1EN = SET;
RCC.APB2PCENR.B.IOPCEN = SET;
// GPIO Alternate Config - default SCL/PC2, SDA/PC1
GPIOC.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> auto {
r.B.CNF1 = 3u;
r.B.MODE1 = 1u;
r.B.CNF2 = 3u;
r.B.MODE2 = 1u;
return r.R;
});
RCC.APB1PRSTR.B.I2C1RST = SET;
RCC.APB1PRSTR.B.I2C1RST = RESET;
I2C1.CTLR2.B.FREQ = 48u;
I2C1.CKCFGR.B.CCR = 480u;
I2C1.CTLR1.B.PE = SET;
}
bool I2CMaster::Send(const unsigned char addr, const unsigned char * data, const unsigned int len) {
bool result = false;
do {
if (! send_address(addr & ~1u)) break;
if (data == nullptr) { return stop_condition(); }
for (unsigned n=0u; n<len; n++) {
const unsigned char to_send = data [n];
if (! wait_for([]() -> bool { return I2C1.STAR1.B.TxE == RESET; })) break;
I2C1.DATAR.B.DATAR = to_send;
}
if (! wait_for([]() -> bool { return I2C1.STAR1.B.BTF == RESET; })) break;
result = true;
} while (false);
return result and stop_condition();
}
bool I2CMaster::Receive (const unsigned char addr, unsigned char * data, const unsigned int len) {
bool result = false;
do {
if (! send_address(addr | 1u)) break;
I2C1.CTLR1.B.ACK = SET;
for (unsigned n=0u; n<len-1; n++) {
if (! wait_for([]() -> bool { return I2C1.STAR1.B.RxNE == RESET; })) break;
data [n] = I2C1.DATAR.B.DATAR;
}
I2C1.CTLR1.B.ACK = RESET;
if (! wait_for([]() -> bool { return I2C1.STAR1.B.RxNE == RESET; })) break;
data [len-1] = I2C1.DATAR.B.DATAR;
result = true;
} while (false);
return result and stop_condition();
}
bool I2CMaster::send_address(const unsigned char addr) {
I2C1.CTLR1.B.START = SET;
if (! wait_for([]() -> bool { return I2C1.STAR1.B.SB == RESET; })) return false;
I2C1.DATAR.B.DATAR = addr;
if (! wait_for([]() -> bool { return I2C1.STAR1.B.ADDR == RESET; })) return false;
volatile unsigned x = I2C1.STAR2.R; (void) x;
return true;
}
bool I2CMaster::stop_condition() {
I2C1.CTLR1.B.STOP = SET;
return wait_for([]() -> bool { return I2C1.CTLR1.B.STOP == SET; });
}
void I2CMaster::FindActive(Print& print) {
const char * blank = " \r";
for (unsigned addr = 0u; addr < 0xFF; addr += 2u) {
print << "addr = " << (int) addr;
if (send_address(addr & ~1u)) {
print << " ... OK\r\n";
} else {
print << blank;
}
stop_condition();
}
print << blank;
}

28
i2c/i2cmaster.h Normal file
View file

@ -0,0 +1,28 @@
#ifndef I2CMASTER_H
#define I2CMASTER_H
class Print;
class I2CMaster {
public:
explicit I2CMaster () noexcept;
bool Send (const unsigned char addr, const unsigned char * data, const unsigned len);
bool Receive (const unsigned char addr, unsigned char * data, const unsigned len);
void FindActive (Print & print);
protected:
bool stop_condition ();
bool send_address (const unsigned char addr);
template<typename F> bool wait_for (F f, const unsigned timeout = 10000) {
volatile unsigned counter = 0u;
while (f()) {
counter += 1u;
if (counter > timeout) return false;
}
return true;
}
};
#endif // I2CMASTER_H

34
i2c/main.cpp Normal file
View file

@ -0,0 +1,34 @@
#include "i2cmaster.h"
#include "usart.h"
#include "print.h"
//////////////////////////////////////
void delay () {
volatile unsigned n = 5'000'000u;
while (n--);
}
static I2CMaster iic;
static Usart serial (115200);
static Print cout (DEC);
static const unsigned char addr = 0x90u;
static const unsigned char cmd1 [] = {1u, 6u};
static const unsigned char cmd2 [] = {0u};
int main () {
cout += serial;
delay();
iic.FindActive(cout);
iic.Send(addr, cmd1 , 2);
iic.Send(addr, cmd2 , 1);
for (;;) {
delay();
unsigned char buf [2];
if (iic.Receive (addr, buf, 2)) {
const char * d = buf [1] != 0 ? ".5" : ".0";
cout << "T = " << (int) buf [0] << d << EOL;
} else {
cout << "error\r\n";
}
}
return 0;
}

View file

@ -1,6 +1,7 @@
# ch32v003
TARGET?= ch32v003
#TARGET?= stm32f051
#TARGET?= linux
TOOL ?= gcc
#TOOL ?= clang
@ -14,7 +15,7 @@ LDLIBS =
BFLAGS = --strip-unneeded
CFLAGS = -MMD -Wall -ggdb -fno-exceptions -ffunction-sections -fdata-sections
CFLAGS+= -I. -I./common -I./$(TARGET) -I/usr/include/newlib -DHAVE_CONFIG=1
CFLAGS+= -I. -I./common -I./$(TARGET) -DHAVE_CONFIG=1
DEL = rm -f
# zdrojaky

12
midi/linux/gcc.mk Normal file
View file

@ -0,0 +1,12 @@
# Use gcc / binutils toolchain
PREFIX =
CC = $(PREFIX)gcc
CXX = $(PREFIX)g++
LD = $(PREFIX)g++
SIZE = $(PREFIX)size
DUMP = $(PREFIX)objdump
COPY = $(PREFIX)objcopy
CFLAGS+= -Os
LFLAGS+= -Wl,--Map=$(@:%.elf=%.map),--gc-sections
LDLIBS+= -lc -lpthread -lasound

37
midi/linux/gpio.h Normal file
View file

@ -0,0 +1,37 @@
#ifndef _GPIO_CLASS_H_
#define _GPIO_CLASS_H_
#include <stdint.h>
enum GPIO_MODE : uint32_t {
GPIO_Speed_In = 0u,
GPIO_Speed_10MHz = 1u,
GPIO_Speed_2MHz = 2u,
GPIO_Speed_50MHz = 3u,
};
enum GPIO_CNF : uint32_t {
GPIO_AI_PPO = 0u,
GPIO_FI_ODO = 1u << 2,
GPIO_UPDI_MPPO = 2u << 2,
GPIO_none_MPDO = 3u << 2,
};
enum GPIOPuPd_TypeDef {
GPIO_PuPd_NOPULL = 0x00,
GPIO_PuPd_UP = 0x01,
GPIO_PuPd_DOWN = 0x02
};
class GpioClass {
const uint32_t pin;
public:
explicit constexpr GpioClass (const uint32_t _pin, const uint32_t _mode = GPIO_AI_PPO) noexcept
: pin(_pin) {
}
void operator<< (const bool b) const {
}
operator bool () const {
return false;
}
void setPuPd (GPIOPuPd_TypeDef p) {
}
};
#endif // _GPIO_CLASS_H_

79
midi/linux/pcmdma.cpp Normal file
View file

@ -0,0 +1,79 @@
#include "pcmdma.h"
#include <pthread.h>
#include <alsa/asoundlib.h>
#include <signal.h>
struct Sample {
short l;
short r;
}__attribute__((packed));
static constexpr unsigned BufLen = FULL_LEN;
static const char *device = "default";
static snd_pcm_t *handle;
static int open_alsa_device (int channels, int srate) {
int err;
if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
printf("Playback open error: %s\n", snd_strerror(err));
return 0;
}
if ((err = snd_pcm_set_params(handle,
SND_PCM_FORMAT_S16_LE,
SND_PCM_ACCESS_RW_INTERLEAVED,
channels,
srate,
1,
500000)) < 0) { /* 0.5sec */
printf("Playback open error: %s\n", snd_strerror(err));
return 0;
}
return 1;
}
int alsa_write (const void * buf, int len) {
snd_pcm_sframes_t frames;
int err = 0;
frames = snd_pcm_writei(handle, buf, len);
if (frames < 0)
frames = snd_pcm_recover(handle, frames, 0);
if (frames < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
return 0;
}
if (frames > 0 && frames < (long)sizeof(buf))
printf("Short write (expected %i, wrote %li)\n", len, frames);
return len;
}
void sig_handler (int signum) {
printf(" - Received signal %d\n", signum);
::exit (0);
}
static constexpr int CC = MAXPWM / 2;
static pthread_t rc;
void * WriteHandler (void * data) {
printf ("Start thread\n");
PcmDma * pA = (PcmDma *) data;
Sample buf [BufLen];
uint16_t * pbuf = pA->getBuff();
for (;;) {
pA->send (false);
pA->send (true);
//printf ("pass\n");
for (unsigned i=0; i<BufLen; i++) {
const short s = (pbuf [i] - CC) * 32;
buf[i].l = s; buf[i].r = s;
}
alsa_write (buf, BufLen);
}
return NULL;
}
PcmDma::PcmDma() noexcept : pL(buffer), pH(buffer + HALF_LEN), src(nullptr) {
signal (SIGINT, sig_handler);
open_alsa_device(2, 24000);
pthread_create (&rc, NULL, WriteHandler, this);
}

View file

@ -10,6 +10,9 @@ static constexpr unsigned MAXPWM = 2000u;
#elif __arm__
#define LED_CFG GpioPortA,0
#define BUT_CFG GpioPortA,3,GPIO_Mode_IN
#elif __linux__
#define LED_CFG 0
#define BUT_CFG 3
#else
#error "bad target"
#endif