From 7a02a41fc8acc542dd14736840ed15313bf0fbfe Mon Sep 17 00:00:00 2001 From: Kizarm Date: Fri, 8 Nov 2024 20:56:19 +0100 Subject: [PATCH] prepare channel --- V203/usb/ch32v203/spiclass.cpp | 104 +++++++++++++++++++++++++ V203/usb/ch32v203/spiclass.h | 21 +++++ V203/usb/scope/firmware/Makefile | 2 +- V203/usb/scope/firmware/samplering.cpp | 7 +- V203/usb/scope/firmware/samplering.h | 5 +- V203/usb/scope/firmware/structures.h | 30 ++++++- V203/usb/scope/software/datasource.cpp | 31 +++++++- V203/usb/scope/software/datasource.h | 1 + V203/usb/scope/software/mainwindow.cpp | 20 +++++ V203/usb/scope/software/mainwindow.h | 2 + V203/usb/scope/software/mainwindow.ui | 41 ++++++---- 11 files changed, 242 insertions(+), 22 deletions(-) create mode 100644 V203/usb/ch32v203/spiclass.cpp create mode 100644 V203/usb/ch32v203/spiclass.h diff --git a/V203/usb/ch32v203/spiclass.cpp b/V203/usb/ch32v203/spiclass.cpp new file mode 100644 index 0000000..1d864e0 --- /dev/null +++ b/V203/usb/ch32v203/spiclass.cpp @@ -0,0 +1,104 @@ +#include "system.h" +#include "spiclass.h" +typedef __SIZE_TYPE__ size_t; + +enum SPICLK : uint32_t { + FPCLK_2 = 0u, // 72 MHz + FPCLK_4, // 72 MHz + FPCLK_8, // 36 MHz + FPCLK_16, // 18 MHz + FPCLK_32, // 9 MHz + FPCLK_64, // 4.5 MHz + FPCLK_128, // 2.25 MHz + FPCLK_256, // 1.125 MHz +}; + +static SpiClass * pSpiInstance = nullptr; +extern "C" { + [[gnu::interrupt]] extern void SPI1_IRQHandler (); + extern void * memcpy (void * dest, const void * src, size_t n); +}; +void SPI1_IRQHandler () { + if (pSpiInstance) pSpiInstance->irq(); +} +static void InitPins () noexcept { + // PA4 - NSS (software), PA5 - SCK, PA6 - MISO, PA7 - MOSI + GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> uint32_t { + r.B.MODE4 = 3u; // 50 MHz + r.B.CNF4 = 0u; // gen push - pull + r.B.MODE5 = 3u; // 50 MHz + r.B.CNF5 = 3u; // alt push - pull + + r.B.MODE6 = 0u; // input mode + r.B.CNF6 = 1u; // floating + r.B.MODE7 = 3u; // 50 MHz + r.B.CNF7 = 3u; // alt push - pull + return r.R; + }); + // AFIO - default +} +void SpiClass::irq() { + if (SPI1.STATR.B.RXNE) { + buffer [index++] = SPI1.DATAR.R; + if (index == total) { + complete = true; + index = 0u; + select (true); + return; + } + // tady by mělo být už odesláno + SPI1.DATAR.R = buffer [index]; + } +} + +SpiClass::SpiClass() noexcept : index(0u), total(0u), complete (false) { + pSpiInstance = this; + 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(); + select (true); + SPI1.CTLR1.modify([](SPI1_Type::CTLR1_DEF & r) -> uint32_t { + r.B.CPHA = SET; + r.B.CPOL = SET; + r.B.MSTR = SET; + r.B.DFF = RESET; // 8 bit + r.B.SSM = SET; + r.B.SSI = SET; + r.B.LSBFIRST = RESET; + r.B.BR = FPCLK_64; // 4.5 MHz + return r.R; + }); + SPI1.CTLR2.modify([](SPI1_Type::CTLR2_DEF & r) -> uint32_t { + r.B.SSOE = SET; + r.B.RXNEIE = SET; + return r.R; + }); + NVIC.EnableIRQ(SPI1_IRQn); + SPI1.CTLR1.B.SPE = SET; +} +void SpiClass::select (const bool set) const noexcept { + if (set) GPIOA.BSHR.B.BS4 = SET; + else GPIOA.BSHR.B.BR4 = SET; +} + +bool SpiClass::send (const char * data, const unsigned int len) { + if (!complete) return false; + select (false); + complete = false; + index = 0u; + total = len > SPIBUFLEN ? SPIBUFLEN : len; + memcpy (buffer, data, total); + SPI1.DATAR.R = buffer [index]; + + return true; +} +char * SpiClass::received (unsigned int & count) { + if (complete) count = total; + else count = 0; + return buffer; +} + diff --git a/V203/usb/ch32v203/spiclass.h b/V203/usb/ch32v203/spiclass.h new file mode 100644 index 0000000..8b6c80b --- /dev/null +++ b/V203/usb/ch32v203/spiclass.h @@ -0,0 +1,21 @@ +#ifndef SPICLASS_H +#define SPICLASS_H + +/** + */ +static constexpr unsigned SPIBUFLEN = 8u; + +class SpiClass { + volatile unsigned index; + unsigned total; + volatile bool complete; + char buffer [SPIBUFLEN]; + public: + explicit SpiClass () noexcept; + void irq (); + void select (const bool set) const noexcept; + bool send (const char * data, const unsigned len); + char * received (unsigned & count); +}; + +#endif // SPICLASS_H diff --git a/V203/usb/scope/firmware/Makefile b/V203/usb/scope/firmware/Makefile index 81cc043..3b5399e 100644 --- a/V203/usb/scope/firmware/Makefile +++ b/V203/usb/scope/firmware/Makefile @@ -17,7 +17,7 @@ DEL = rm -f # zdrojaky OBJS = main.o hack.o -OBJS += usb_desc.o cdc_class.o adcscope.o samplering.o +OBJS += usb_desc.o cdc_class.o spiclass.o adcscope.o samplering.o include $(TARGET)/$(TOOL).mk BOBJS = $(addprefix $(BLD),$(OBJS)) diff --git a/V203/usb/scope/firmware/samplering.cpp b/V203/usb/scope/firmware/samplering.cpp index 28085de..a8e490a 100644 --- a/V203/usb/scope/firmware/samplering.cpp +++ b/V203/usb/scope/firmware/samplering.cpp @@ -56,7 +56,7 @@ void SampleRing::SendSettings() { const unsigned max = 64; char buf [max]; unsigned idx = 0; - AllSettings as (m_settings, m_time_base_order); + AllSettings as (m_settings, m_time_base_order, voltage); buf [idx++] = '!'; for (unsigned n=0u; n (header.bits.destinat); switch (dest) { case DEST_CHA: + voltage.a = header.bits.cmd_value; + spi.send (voltage.common, 1); + break; case DEST_CHB: + voltage.b = header.bits.cmd_value; + spi.send (voltage.common, 1); break; case DEST_BASE: m_time_base_order = header.bits.cmd_value; diff --git a/V203/usb/scope/firmware/samplering.h b/V203/usb/scope/firmware/samplering.h index da2e77c..7043b88 100644 --- a/V203/usb/scope/firmware/samplering.h +++ b/V203/usb/scope/firmware/samplering.h @@ -3,6 +3,7 @@ #include #include "structures.h" #include "baselayer.h" +#include "spiclass.h" static constexpr unsigned RING_BIT = 10; static constexpr unsigned RING_LEN = 1u << RING_BIT; @@ -18,6 +19,8 @@ enum RCVD_STATUS { }; class SampleRing : public BaseLayer { + SpiClass spi; + ChannelVoltage voltage; [[gnu::aligned(4)]]DATA_BLOCK ring_buffer [RING_LEN]; TrigerSettings m_settings; volatile unsigned m_head, m_tail; @@ -32,7 +35,7 @@ class SampleRing : public BaseLayer { unsigned rcvd_counter; RCVD_STATUS rcvd_status; public: - explicit SampleRing () noexcept : BaseLayer(), m_settings(), m_head(0), m_tail(0), m_lenght(0), + explicit SampleRing () noexcept : BaseLayer(), spi(), voltage(), m_settings(), m_head(0), m_tail(0), m_lenght(0), m_old_triger(false), m_trigered(false), m_finished(false), m_mode (TIME_BASE_TRIGERED), o_mode (TIME_BASE_TRIGERED), m_time_base_order(6u), rcvd_counter(0u), rcvd_status (RCVD_IDLE) {}; diff --git a/V203/usb/scope/firmware/structures.h b/V203/usb/scope/firmware/structures.h index 221b600..ef17e83 100644 --- a/V203/usb/scope/firmware/structures.h +++ b/V203/usb/scope/firmware/structures.h @@ -27,22 +27,48 @@ struct TrigerSettings { explicit TrigerSettings () noexcept : value(0x80u), offset(100u), mode(TRIGER_MODE_AUTO), channel(V1_VSENSE), rising(false) {} }; static_assert (sizeof(TrigerSettings) == 10, "TrigerSettings error"); +enum VOLTAGE_SCALE { + S100mV = 0b0011, // 1:1 x10 + S200mV = 0b0111, // 1:1 x5 + S500mV = 0b1011, // 1:1 x2 + + S1V = 0b0000, // 1:10 x10 + S2V = 0b0100, // 1:10 x5 + S5V = 0b1000, // 1:10 x2 + + S10V = 0b0001, // 1:100x10 + S20V = 0b0101, // 1:100x5 + S50V = 0b1001, // 1:100x2 +}; +union ChannelVoltage { + struct { + uint8_t a : 4; + uint8_t b : 4; + }; + uint8_t value; + char common [1]; + explicit ChannelVoltage () noexcept : value (0u) {} +}; +static_assert (sizeof(ChannelVoltage) == 1, "ChannelVoltage error"); union AllSettings { struct _x { TrigerSettings trg; uint16_t tim; + uint8_t asc,bsc; } part; uint8_t common [sizeof (_x)]; - explicit AllSettings (const TrigerSettings & ts, const unsigned n) noexcept { + explicit AllSettings (const TrigerSettings & ts, const unsigned n, const ChannelVoltage chv) noexcept { part.trg.value = ts.value; part.trg.offset = ts.offset; part.trg.mode = ts.mode; part.trg.channel = ts.channel; part.trg.rising = ts.rising; part.tim = n; + part.asc = chv.a; + part.bsc = chv.b; } }; -static_assert (sizeof(AllSettings) == 12, "TrigerSettings error"); +static_assert (sizeof(AllSettings) == 14, "TrigerSettings error"); union SendHeader { struct s_bits { uint16_t pack_len : 15; diff --git a/V203/usb/scope/software/datasource.cpp b/V203/usb/scope/software/datasource.cpp index 3d10f70..afaf019 100644 --- a/V203/usb/scope/software/datasource.cpp +++ b/V203/usb/scope/software/datasource.cpp @@ -2,6 +2,11 @@ #include "helpers.h" static constexpr unsigned DATASIZE = 0x2000; +static const uint8_t VoltageRangeTable [] = { + S100mV, S200mV, S500mV, + S1V, S2V, S5V, + S10V, S20V, S50V, +}; DataSource::DataSource(QObject * p) : QObject (p), usart (QString("/dev/serial/by-id/usb-Kizarm_Labs._USB_Osciloscope_00001-if00")), @@ -88,10 +93,18 @@ static uint8_t from_hex (const char * ptr) { } return result; } +static uint8_t find_index (uint8_t n) { + unsigned m = sizeof (VoltageRangeTable); + for (unsigned i=0u; i> 1; int k = 0; for (int n=0; n= sizeof (VoltageRangeTable) ? (sizeof (VoltageRangeTable) - 1u) : n; + uint8_t v = VoltageRangeTable [k]; + RcvdHeader hdr; + hdr.common = 0u; + hdr.bits.destinat = ch == 0 ? DEST_CHA : DEST_CHB; + hdr.bits.cmd_value = v; + const unsigned len = 64; + char buffer [len]; + int r = snprintf(buffer, len, "$%04X\r\n", (int) hdr.common); + buffer [r] = '\0'; + usart.write (buffer, r); + qDebug ("%d:%s", r, strip_eol(buffer)); +} diff --git a/V203/usb/scope/software/datasource.h b/V203/usb/scope/software/datasource.h index dc1383b..f2cdb98 100644 --- a/V203/usb/scope/software/datasource.h +++ b/V203/usb/scope/software/datasource.h @@ -35,6 +35,7 @@ class DataSource : public QObject { void SendTrigerEdge (int n); void SendTrigerChan (int n); void SendBaseRange (int n); + void SendVoltage (int ch, int n); void Start (); public slots: void read_data (); diff --git a/V203/usb/scope/software/mainwindow.cpp b/V203/usb/scope/software/mainwindow.cpp index b2bac4d..d5996ca 100644 --- a/V203/usb/scope/software/mainwindow.cpp +++ b/V203/usb/scope/software/mainwindow.cpp @@ -25,6 +25,11 @@ static const char * TimeBaseTexts [] = { "1ms", "2ms", "5ms", "10ms", "20ms", "50ms", "100ms", "200ms", "500ms", "1s", }; +static const char * VoltageScaleTexts [] = { + "100mV","200mV","500mV", + "1V", "2V", "5V", + "10V","20V","50V", +}; MainWindow::MainWindow (QWidget * parent) : QMainWindow (parent), firmware(parent) { @@ -37,6 +42,8 @@ MainWindow::MainWindow (QWidget * parent) for (auto & e: TrigerEdgeTexts) ui->comboRissing ->addItem(QString(e)); for (auto & e: TrigerSelectTexts) ui->comboValue ->addItem(QString(e)); for (auto & e: TimeBaseTexts) ui->comboTimeRange->addItem(QString(e)); + for (auto & e: VoltageScaleTexts) ui->comboVA ->addItem(QString(e)); + for (auto & e: VoltageScaleTexts) ui->comboVB ->addItem(QString(e)); setWindowTitle ("Scope"); setWindowIcon (QIcon(":ico")); @@ -60,6 +67,8 @@ MainWindow::MainWindow (QWidget * parent) connect (ui->comboValue, SIGNAL(activated(int)), this, SLOT(TriggerValues (int))); connect (ui->comboTimeRange, SIGNAL(activated(int)), this, SLOT(TimeBaseRange (int))); + connect (ui->comboVA, SIGNAL(activated(int)), this, SLOT(SendVoltageA (int))); + connect (ui->comboVB, SIGNAL(activated(int)), this, SLOT(SendVoltageB (int))); ui->comboTimeRange->setCurrentIndex(6); ui->buttonStart->setEnabled(false); } @@ -70,10 +79,14 @@ void MainWindow::SetSelections(AllSettings as) { printf("offset : %d\n", as.part.trg.offset); printf("value : %d\n", as.part.trg.value); printf("tim bas : %d\n", as.part.tim); + printf("CHA : %d\n", as.part.asc); + printf("CHB : %d\n", as.part.bsc); ui->comboChannel ->setCurrentIndex(as.part.trg.channel); ui->comboMode ->setCurrentIndex(as.part.trg.mode); ui->comboRissing ->setCurrentIndex(as.part.trg.rising ? 1 : 0); ui->comboTimeRange->setCurrentIndex(as.part.tim); + ui->comboVA ->setCurrentIndex(as.part.asc); + ui->comboVB ->setCurrentIndex(as.part.bsc); ui->Display->TimeBaseRange(as.part.tim); } @@ -90,6 +103,13 @@ void MainWindow::MarkerChanged(bool b) { void MainWindow::TriggerValues (int n) { ui->Display->TriggerValues(n); } +void MainWindow::SendVoltageA(int n) { + firmware.SendVoltage (0,n); +} +void MainWindow::SendVoltageB(int n) { + firmware.SendVoltage (1,n); +} + void MainWindow::SendTrigerMode (int n) { if (n == TRIGER_MODE_SINGLE) ui->buttonStart->setEnabled(true); else ui->buttonStart->setEnabled(false); diff --git a/V203/usb/scope/software/mainwindow.h b/V203/usb/scope/software/mainwindow.h index ac9d0de..e124078 100644 --- a/V203/usb/scope/software/mainwindow.h +++ b/V203/usb/scope/software/mainwindow.h @@ -14,6 +14,8 @@ public: ~MainWindow (); protected: public slots: + void SendVoltageA (int n); + void SendVoltageB (int n); void SendTrigerMode (int n); void SendTrigerEdge (int n); void SendTrigerChan (int n); diff --git a/V203/usb/scope/software/mainwindow.ui b/V203/usb/scope/software/mainwindow.ui index c3b8536..4cf2d4b 100644 --- a/V203/usb/scope/software/mainwindow.ui +++ b/V203/usb/scope/software/mainwindow.ui @@ -14,22 +14,7 @@ MainWindow - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - + @@ -44,6 +29,30 @@ + + + + Channel A + + + + + + + + + + + + Channel B + + + + + + + +