Compare commits
4 commits
e79f5facff
...
64aeaf99ed
Author | SHA1 | Date | |
---|---|---|---|
|
64aeaf99ed | ||
|
7a02a41fc8 | ||
|
df6193040f | ||
|
afd7795f8e |
16 changed files with 314 additions and 27 deletions
104
V203/usb/ch32v203/spiclass.cpp
Normal file
104
V203/usb/ch32v203/spiclass.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
|
21
V203/usb/ch32v203/spiclass.h
Normal file
21
V203/usb/ch32v203/spiclass.h
Normal file
|
@ -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
|
|
@ -85,6 +85,22 @@
|
||||||
<option value="4">Time base zoom</option>
|
<option value="4">Time base zoom</option>
|
||||||
</select></div>
|
</select></div>
|
||||||
</fieldset></td>
|
</fieldset></td>
|
||||||
|
<td><fieldset>
|
||||||
|
<legend>Channel A</legend>
|
||||||
|
<div><select id="setcha" name="setcha">
|
||||||
|
<option value="0">100mV</option><option value="1">200mV</option><option value="2">500mV</option>
|
||||||
|
<option value="3">1V</option><option value="4">2V</option><option value="5">5V</option>
|
||||||
|
<option value="6">10V</option><option value="7">20V</option><option value="8">50V</option>
|
||||||
|
</select></div>
|
||||||
|
</fieldset></td>
|
||||||
|
<td><fieldset>
|
||||||
|
<legend>Channel B</legend>
|
||||||
|
<div><select id="setchb" name="setchb">
|
||||||
|
<option value="0">100mV</option><option value="1">200mV</option><option value="2">500mV</option>
|
||||||
|
<option value="3">1V</option><option value="4">2V</option><option value="5">5V</option>
|
||||||
|
<option value="6">10V</option><option value="7">20V</option><option value="8">50V</option>
|
||||||
|
</select></div>
|
||||||
|
</fieldset></td>
|
||||||
<td><input type="button" class="start" id="Start" value="Start" onclick="Start();" disabled></td>
|
<td><input type="button" class="start" id="Start" value="Start" onclick="Start();" disabled></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -7,6 +7,8 @@ const MarkerVolt = document.getElementById ('volt');
|
||||||
|
|
||||||
const TimeBase = document.getElementById ('time_base');
|
const TimeBase = document.getElementById ('time_base');
|
||||||
const MoveElem = document.getElementById ('move');
|
const MoveElem = document.getElementById ('move');
|
||||||
|
const VoltChA = document.getElementById ('setcha');
|
||||||
|
const VoltChB = document.getElementById ('setchb');
|
||||||
const StartBut = document.getElementById ('Start');
|
const StartBut = document.getElementById ('Start');
|
||||||
const ConnectBut = document.getElementById ('Connect');
|
const ConnectBut = document.getElementById ('Connect');
|
||||||
const Connected = document.getElementById ('Connected');
|
const Connected = document.getElementById ('Connected');
|
||||||
|
@ -61,6 +63,7 @@ function initWebSocket() {
|
||||||
console.log (stored);
|
console.log (stored);
|
||||||
if (stored) {
|
if (stored) {
|
||||||
gMark = JSON.parse (stored);
|
gMark = JSON.parse (stored);
|
||||||
|
if (gMark.type === 'volt') MarkerVolt.checked = true;
|
||||||
}
|
}
|
||||||
connected = true;
|
connected = true;
|
||||||
};
|
};
|
||||||
|
@ -94,6 +97,8 @@ function RefreshSettings (obj) {
|
||||||
document.getElementById('trigger_mode').value = obj.mode;
|
document.getElementById('trigger_mode').value = obj.mode;
|
||||||
document.getElementById('trigger_edge').value = obj.rising;
|
document.getElementById('trigger_edge').value = obj.rising;
|
||||||
document.getElementById('time_base' ).value = obj.tim;
|
document.getElementById('time_base' ).value = obj.tim;
|
||||||
|
document.getElementById('setcha' ).value = obj.cha;
|
||||||
|
document.getElementById('setchb' ).value = obj.chb;
|
||||||
gTC.x = obj.offset; gTC.y = obj.value;
|
gTC.x = obj.offset; gTC.y = obj.value;
|
||||||
PrepareBG();
|
PrepareBG();
|
||||||
DrawAll ();
|
DrawAll ();
|
||||||
|
@ -288,6 +293,14 @@ MoveElem.onchange = (event) => {
|
||||||
gItemToMove = e.value;
|
gItemToMove = e.value;
|
||||||
console.log(e);
|
console.log(e);
|
||||||
};
|
};
|
||||||
|
VoltChA.onchange = (event) => {
|
||||||
|
const e = { type : "cha_set", value : parseInt(event.target.value, 10) };
|
||||||
|
SendEvent (e);
|
||||||
|
};
|
||||||
|
VoltChB.onchange = (event) => {
|
||||||
|
const e = { type : "chb_set", value : parseInt(event.target.value, 10) };
|
||||||
|
SendEvent (e);
|
||||||
|
};
|
||||||
MarkerTime.onclick = (event) => {
|
MarkerTime.onclick = (event) => {
|
||||||
console.log ('time_mark');
|
console.log ('time_mark');
|
||||||
gMark.type = 'time';
|
gMark.type = 'time';
|
||||||
|
|
|
@ -17,7 +17,7 @@ DEL = rm -f
|
||||||
|
|
||||||
# zdrojaky
|
# zdrojaky
|
||||||
OBJS = main.o hack.o
|
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
|
include $(TARGET)/$(TOOL).mk
|
||||||
BOBJS = $(addprefix $(BLD),$(OBJS))
|
BOBJS = $(addprefix $(BLD),$(OBJS))
|
||||||
|
|
|
@ -56,7 +56,7 @@ void SampleRing::SendSettings() {
|
||||||
const unsigned max = 64;
|
const unsigned max = 64;
|
||||||
char buf [max];
|
char buf [max];
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
AllSettings as (m_settings, m_time_base_order);
|
AllSettings as (m_settings, m_time_base_order, voltage);
|
||||||
buf [idx++] = '!';
|
buf [idx++] = '!';
|
||||||
for (unsigned n=0u; n<sizeof(as); n++) {
|
for (unsigned n=0u; n<sizeof(as); n++) {
|
||||||
const uint8_t c = as.common[n];
|
const uint8_t c = as.common[n];
|
||||||
|
@ -75,7 +75,12 @@ void SampleRing::CommandPass(const unsigned int cmd) {
|
||||||
const DESTINATION dest = static_cast<DESTINATION> (header.bits.destinat);
|
const DESTINATION dest = static_cast<DESTINATION> (header.bits.destinat);
|
||||||
switch (dest) {
|
switch (dest) {
|
||||||
case DEST_CHA:
|
case DEST_CHA:
|
||||||
|
voltage.a = header.bits.cmd_value;
|
||||||
|
spi.send (voltage.common, 1);
|
||||||
|
break;
|
||||||
case DEST_CHB:
|
case DEST_CHB:
|
||||||
|
voltage.b = header.bits.cmd_value;
|
||||||
|
spi.send (voltage.common, 1);
|
||||||
break;
|
break;
|
||||||
case DEST_BASE:
|
case DEST_BASE:
|
||||||
m_time_base_order = header.bits.cmd_value;
|
m_time_base_order = header.bits.cmd_value;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "structures.h"
|
#include "structures.h"
|
||||||
#include "baselayer.h"
|
#include "baselayer.h"
|
||||||
|
#include "spiclass.h"
|
||||||
|
|
||||||
static constexpr unsigned RING_BIT = 10;
|
static constexpr unsigned RING_BIT = 10;
|
||||||
static constexpr unsigned RING_LEN = 1u << RING_BIT;
|
static constexpr unsigned RING_LEN = 1u << RING_BIT;
|
||||||
|
@ -18,6 +19,8 @@ enum RCVD_STATUS {
|
||||||
};
|
};
|
||||||
|
|
||||||
class SampleRing : public BaseLayer {
|
class SampleRing : public BaseLayer {
|
||||||
|
SpiClass spi;
|
||||||
|
ChannelVoltage voltage;
|
||||||
[[gnu::aligned(4)]]DATA_BLOCK ring_buffer [RING_LEN];
|
[[gnu::aligned(4)]]DATA_BLOCK ring_buffer [RING_LEN];
|
||||||
TrigerSettings m_settings;
|
TrigerSettings m_settings;
|
||||||
volatile unsigned m_head, m_tail;
|
volatile unsigned m_head, m_tail;
|
||||||
|
@ -32,7 +35,7 @@ class SampleRing : public BaseLayer {
|
||||||
unsigned rcvd_counter;
|
unsigned rcvd_counter;
|
||||||
RCVD_STATUS rcvd_status;
|
RCVD_STATUS rcvd_status;
|
||||||
public:
|
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_old_triger(false), m_trigered(false), m_finished(false),
|
||||||
m_mode (TIME_BASE_TRIGERED), o_mode (TIME_BASE_TRIGERED), m_time_base_order(6u),
|
m_mode (TIME_BASE_TRIGERED), o_mode (TIME_BASE_TRIGERED), m_time_base_order(6u),
|
||||||
rcvd_counter(0u), rcvd_status (RCVD_IDLE) {};
|
rcvd_counter(0u), rcvd_status (RCVD_IDLE) {};
|
||||||
|
|
|
@ -27,22 +27,48 @@ struct TrigerSettings {
|
||||||
explicit TrigerSettings () noexcept : value(0x80u), offset(100u), mode(TRIGER_MODE_AUTO), channel(V1_VSENSE), rising(false) {}
|
explicit TrigerSettings () noexcept : value(0x80u), offset(100u), mode(TRIGER_MODE_AUTO), channel(V1_VSENSE), rising(false) {}
|
||||||
};
|
};
|
||||||
static_assert (sizeof(TrigerSettings) == 10, "TrigerSettings error");
|
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 {
|
union AllSettings {
|
||||||
struct _x {
|
struct _x {
|
||||||
TrigerSettings trg;
|
TrigerSettings trg;
|
||||||
uint16_t tim;
|
uint16_t tim;
|
||||||
|
uint8_t asc,bsc;
|
||||||
} part;
|
} part;
|
||||||
uint8_t common [sizeof (_x)];
|
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.value = ts.value;
|
||||||
part.trg.offset = ts.offset;
|
part.trg.offset = ts.offset;
|
||||||
part.trg.mode = ts.mode;
|
part.trg.mode = ts.mode;
|
||||||
part.trg.channel = ts.channel;
|
part.trg.channel = ts.channel;
|
||||||
part.trg.rising = ts.rising;
|
part.trg.rising = ts.rising;
|
||||||
part.tim = n;
|
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 {
|
union SendHeader {
|
||||||
struct s_bits {
|
struct s_bits {
|
||||||
uint16_t pack_len : 15;
|
uint16_t pack_len : 15;
|
||||||
|
|
|
@ -2,9 +2,8 @@ PR = ../bin/wserver
|
||||||
CC = g++
|
CC = g++
|
||||||
AS = as
|
AS = as
|
||||||
CFLAGS = -Wall -Os
|
CFLAGS = -Wall -Os
|
||||||
CFLAGS+= -I$(HOME)/local/include
|
|
||||||
MFLAGS = -o $(PR)
|
MFLAGS = -o $(PR)
|
||||||
LFLAGS = -L$(HOME)/local/lib -lseasocks -lz -lpthread
|
LFLAGS = -lseasocks -lz -lpthread
|
||||||
|
|
||||||
all: $(PR)
|
all: $(PR)
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,23 @@ using json = nlohmann::json;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace seasocks;
|
using namespace seasocks;
|
||||||
|
|
||||||
|
static const uint8_t VoltageRangeTable [] = {
|
||||||
|
S100mV, S200mV, S500mV,
|
||||||
|
S1V, S2V, S5V,
|
||||||
|
S10V, S20V, S50V,
|
||||||
|
};
|
||||||
|
static uint8_t find_index (uint8_t n) {
|
||||||
|
unsigned m = sizeof (VoltageRangeTable);
|
||||||
|
for (unsigned i=0u; i<m; i++) {
|
||||||
|
if (n == VoltageRangeTable [i]) return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
static string channels_to_json (const vector<int> & a, const vector<int> & b) {
|
static string channels_to_json (const vector<int> & a, const vector<int> & b) {
|
||||||
json msg;
|
json msg;
|
||||||
msg["a"] = a;
|
msg["a"] = a;
|
||||||
msg["b"] = b;
|
msg["b"] = b;
|
||||||
return to_string(msg);
|
return msg.dump();
|
||||||
}
|
}
|
||||||
bool WsClient::start() {
|
bool WsClient::start() {
|
||||||
cout << "Client Start\n";
|
cout << "Client Start\n";
|
||||||
|
@ -146,13 +158,18 @@ static uint8_t from_hex (const char * ptr) {
|
||||||
void WsClient::parse_reply(const char * data, const int len) {
|
void WsClient::parse_reply(const char * data, const int len) {
|
||||||
printf("(%d):%s\n", len, data);
|
printf("(%d):%s\n", len, data);
|
||||||
TrigerSettings ts;
|
TrigerSettings ts;
|
||||||
AllSettings as (ts, 0);
|
ChannelVoltage cv;
|
||||||
|
AllSettings as (ts, 0, cv);
|
||||||
const int bl = len >> 1;
|
const int bl = len >> 1;
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (int n=0; n<bl; n++) {
|
for (int n=0; n<bl; n++) {
|
||||||
as.common [n] = from_hex (data + k);
|
as.common [n] = from_hex (data + k);
|
||||||
k += 2;
|
k += 2;
|
||||||
}
|
}
|
||||||
|
as.part.asc = find_index(as.part.asc);
|
||||||
|
as.part.bsc = find_index(as.part.bsc);
|
||||||
|
// ulož zpět, synchronizace serveru
|
||||||
|
memcpy (&trigerSettings, &as.part.trg, sizeof(TrigerSettings));
|
||||||
json msg;
|
json msg;
|
||||||
msg["channel"] = as.part.trg.channel;
|
msg["channel"] = as.part.trg.channel;
|
||||||
msg["mode"] = as.part.trg.mode;
|
msg["mode"] = as.part.trg.mode;
|
||||||
|
@ -160,7 +177,9 @@ void WsClient::parse_reply(const char * data, const int len) {
|
||||||
msg["offset"] = as.part.trg.offset;
|
msg["offset"] = as.part.trg.offset;
|
||||||
msg["value"] = as.part.trg.value;
|
msg["value"] = as.part.trg.value;
|
||||||
msg["tim"] = as.part.tim;
|
msg["tim"] = as.part.tim;
|
||||||
string s = to_string (msg);
|
msg["cha"] = as.part.asc;
|
||||||
|
msg["chb"] = as.part.bsc;
|
||||||
|
string s = msg.dump ();
|
||||||
cout << s << endl;
|
cout << s << endl;
|
||||||
ws->send(s);
|
ws->send(s);
|
||||||
}
|
}
|
||||||
|
@ -233,12 +252,30 @@ void WsClient::send(const char * data) {
|
||||||
SettingChanged(1);
|
SettingChanged(1);
|
||||||
} else if (type == "tim_bas") {
|
} else if (type == "tim_bas") {
|
||||||
SendBaseRange(value);
|
SendBaseRange(value);
|
||||||
|
} else if (type == "cha_set") {
|
||||||
|
SendVoltage(0, VoltageRangeTable[value]);
|
||||||
|
} else if (type == "chb_set") {
|
||||||
|
SendVoltage(1, VoltageRangeTable[value]);
|
||||||
} else if (type == "start") {
|
} else if (type == "start") {
|
||||||
Start ();
|
Start ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// cout << "type=" << type << ", value=" << value << endl;
|
// cout << "type=" << type << ", value=" << value << endl;
|
||||||
}
|
}
|
||||||
|
void WsClient::SendVoltage(int ch, int n) {
|
||||||
|
const int k = (unsigned) 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';
|
||||||
|
write (buffer, r);
|
||||||
|
}
|
||||||
|
|
||||||
void WsClient::SendTrigerChan(int n) {
|
void WsClient::SendTrigerChan(int n) {
|
||||||
trigerSettings.channel = static_cast<ADC_CHANNELS> (n);
|
trigerSettings.channel = static_cast<ADC_CHANNELS> (n);
|
||||||
send_trig_mode();
|
send_trig_mode();
|
||||||
|
|
|
@ -51,6 +51,8 @@ class WsClient {
|
||||||
void SendTrigerChan (int n);
|
void SendTrigerChan (int n);
|
||||||
void SendBaseRange (int n);
|
void SendBaseRange (int n);
|
||||||
void SettingChanged (int n);
|
void SettingChanged (int n);
|
||||||
|
void SendVoltage (int ch, int n);
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void send_trig_mode ();
|
void send_trig_mode ();
|
||||||
int write (const char * data, const int len);
|
int write (const char * data, const int len);
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
|
||||||
static constexpr unsigned DATASIZE = 0x2000;
|
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),
|
DataSource::DataSource(QObject * p) : QObject (p),
|
||||||
usart (QString("/dev/serial/by-id/usb-Kizarm_Labs._USB_Osciloscope_00001-if00")),
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
static uint8_t find_index (uint8_t n) {
|
||||||
|
unsigned m = sizeof (VoltageRangeTable);
|
||||||
|
for (unsigned i=0u; i<m; i++) {
|
||||||
|
if (n == VoltageRangeTable [i]) return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
void DataSource::parse_reply(const char * data, const int len) {
|
void DataSource::parse_reply(const char * data, const int len) {
|
||||||
printf("(%d):%s\n", len, data);
|
printf("(%d):%s\n", len, data);
|
||||||
TrigerSettings ts;
|
TrigerSettings ts;
|
||||||
AllSettings as (ts, 0);
|
ChannelVoltage cv;
|
||||||
|
AllSettings as (ts, 0, cv);
|
||||||
const int bl = len >> 1;
|
const int bl = len >> 1;
|
||||||
int k = 0;
|
int k = 0;
|
||||||
for (int n=0; n<bl; n++) {
|
for (int n=0; n<bl; n++) {
|
||||||
|
@ -103,6 +116,8 @@ void DataSource::parse_reply(const char * data, const int len) {
|
||||||
trigerSettings.rising = as.part.trg.rising;
|
trigerSettings.rising = as.part.trg.rising;
|
||||||
trigerSettings.offset = as.part.trg.offset;
|
trigerSettings.offset = as.part.trg.offset;
|
||||||
trigerSettings.value = as.part.trg.value;
|
trigerSettings.value = as.part.trg.value;
|
||||||
|
as.part.asc = find_index (as.part.asc); // reverse bits
|
||||||
|
as.part.bsc = find_index (as.part.bsc);
|
||||||
emit SettingReceived (as);
|
emit SettingReceived (as);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,6 +230,20 @@ void DataSource::SendBaseRange (int n) {
|
||||||
usart.write (buffer, r);
|
usart.write (buffer, r);
|
||||||
qDebug ("%d:%s", r, strip_eol(buffer));
|
qDebug ("%d:%s", r, strip_eol(buffer));
|
||||||
}
|
}
|
||||||
|
void DataSource::SendVoltage(int ch, int n) {
|
||||||
|
const int k = (unsigned) 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ class DataSource : public QObject {
|
||||||
void SendTrigerEdge (int n);
|
void SendTrigerEdge (int n);
|
||||||
void SendTrigerChan (int n);
|
void SendTrigerChan (int n);
|
||||||
void SendBaseRange (int n);
|
void SendBaseRange (int n);
|
||||||
|
void SendVoltage (int ch, int n);
|
||||||
void Start ();
|
void Start ();
|
||||||
public slots:
|
public slots:
|
||||||
void read_data ();
|
void read_data ();
|
||||||
|
|
|
@ -25,6 +25,11 @@ static const char * TimeBaseTexts [] = {
|
||||||
"1ms", "2ms", "5ms", "10ms", "20ms", "50ms", "100ms", "200ms",
|
"1ms", "2ms", "5ms", "10ms", "20ms", "50ms", "100ms", "200ms",
|
||||||
"500ms", "1s",
|
"500ms", "1s",
|
||||||
};
|
};
|
||||||
|
static const char * VoltageScaleTexts [] = {
|
||||||
|
"100mV","200mV","500mV",
|
||||||
|
"1V", "2V", "5V",
|
||||||
|
"10V","20V","50V",
|
||||||
|
};
|
||||||
|
|
||||||
MainWindow::MainWindow (QWidget * parent)
|
MainWindow::MainWindow (QWidget * parent)
|
||||||
: QMainWindow (parent), firmware(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: TrigerEdgeTexts) ui->comboRissing ->addItem(QString(e));
|
||||||
for (auto & e: TrigerSelectTexts) ui->comboValue ->addItem(QString(e));
|
for (auto & e: TrigerSelectTexts) ui->comboValue ->addItem(QString(e));
|
||||||
for (auto & e: TimeBaseTexts) ui->comboTimeRange->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");
|
setWindowTitle ("Scope");
|
||||||
setWindowIcon (QIcon(":ico"));
|
setWindowIcon (QIcon(":ico"));
|
||||||
|
@ -60,6 +67,8 @@ MainWindow::MainWindow (QWidget * parent)
|
||||||
connect (ui->comboValue, SIGNAL(activated(int)), this, SLOT(TriggerValues (int)));
|
connect (ui->comboValue, SIGNAL(activated(int)), this, SLOT(TriggerValues (int)));
|
||||||
connect (ui->comboTimeRange, SIGNAL(activated(int)), this, SLOT(TimeBaseRange (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->comboTimeRange->setCurrentIndex(6);
|
||||||
ui->buttonStart->setEnabled(false);
|
ui->buttonStart->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
@ -70,10 +79,14 @@ void MainWindow::SetSelections(AllSettings as) {
|
||||||
printf("offset : %d\n", as.part.trg.offset);
|
printf("offset : %d\n", as.part.trg.offset);
|
||||||
printf("value : %d\n", as.part.trg.value);
|
printf("value : %d\n", as.part.trg.value);
|
||||||
printf("tim bas : %d\n", as.part.tim);
|
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->comboChannel ->setCurrentIndex(as.part.trg.channel);
|
||||||
ui->comboMode ->setCurrentIndex(as.part.trg.mode);
|
ui->comboMode ->setCurrentIndex(as.part.trg.mode);
|
||||||
ui->comboRissing ->setCurrentIndex(as.part.trg.rising ? 1 : 0);
|
ui->comboRissing ->setCurrentIndex(as.part.trg.rising ? 1 : 0);
|
||||||
ui->comboTimeRange->setCurrentIndex(as.part.tim);
|
ui->comboTimeRange->setCurrentIndex(as.part.tim);
|
||||||
|
ui->comboVA ->setCurrentIndex(as.part.asc);
|
||||||
|
ui->comboVB ->setCurrentIndex(as.part.bsc);
|
||||||
ui->Display->TimeBaseRange(as.part.tim);
|
ui->Display->TimeBaseRange(as.part.tim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +103,13 @@ void MainWindow::MarkerChanged(bool b) {
|
||||||
void MainWindow::TriggerValues (int n) {
|
void MainWindow::TriggerValues (int n) {
|
||||||
ui->Display->TriggerValues(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) {
|
void MainWindow::SendTrigerMode (int n) {
|
||||||
if (n == TRIGER_MODE_SINGLE) ui->buttonStart->setEnabled(true);
|
if (n == TRIGER_MODE_SINGLE) ui->buttonStart->setEnabled(true);
|
||||||
else ui->buttonStart->setEnabled(false);
|
else ui->buttonStart->setEnabled(false);
|
||||||
|
|
|
@ -14,6 +14,8 @@ public:
|
||||||
~MainWindow ();
|
~MainWindow ();
|
||||||
protected:
|
protected:
|
||||||
public slots:
|
public slots:
|
||||||
|
void SendVoltageA (int n);
|
||||||
|
void SendVoltageB (int n);
|
||||||
void SendTrigerMode (int n);
|
void SendTrigerMode (int n);
|
||||||
void SendTrigerEdge (int n);
|
void SendTrigerEdge (int n);
|
||||||
void SendTrigerChan (int n);
|
void SendTrigerChan (int n);
|
||||||
|
|
|
@ -14,22 +14,7 @@
|
||||||
<string>MainWindow</string>
|
<string>MainWindow</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralwidget">
|
<widget class="QWidget" name="centralwidget">
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
<layout class="QGridLayout" name="gridLayout_6">
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -44,6 +29,30 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="ChannelA">
|
||||||
|
<property name="title">
|
||||||
|
<string>Channel A</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QComboBox" name="comboVA"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="ChannelB">
|
||||||
|
<property name="title">
|
||||||
|
<string>Channel B</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_5">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QComboBox" name="comboVB"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupTriger">
|
<widget class="QGroupBox" name="groupTriger">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
|
Loading…
Reference in a new issue