diff --git a/.gitignore b/.gitignore index 40b6e41cf..81fa4defb 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ test qtpro5 .DS_Store .qt +win32x +qrc_* +install_manifest.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index eb9be42bb..2c7e1c4b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ set(DS_DESCRIPTION "A GUI for instruments of DreamSourceLab") set(DS_VERSION_MAJOR 1) set(DS_VERSION_MINOR 2) -set(DS_VERSION_MICRO 1) +set(DS_VERSION_MICRO 2) set(DS_VERSION_STRING ${DS_VERSION_MAJOR}.${DS_VERSION_MINOR}.${DS_VERSION_MICRO} ) configure_file ( diff --git a/DSView/config.h b/DSView/config.h index 063d4fb46..3b0403610 100644 --- a/DSView/config.h +++ b/DSView/config.h @@ -29,7 +29,7 @@ /* DSView version information */ #define DS_VERSION_MAJOR 1 #define DS_VERSION_MINOR 2 -#define DS_VERSION_MICRO 1 -#define DS_VERSION_STRING "1.2.1" +#define DS_VERSION_MICRO 2 +#define DS_VERSION_STRING "1.2.2" #endif diff --git a/DSView/pv/dialogs/storeprogress.cpp b/DSView/pv/dialogs/storeprogress.cpp index f05ad8615..ad3cb450d 100644 --- a/DSView/pv/dialogs/storeprogress.cpp +++ b/DSView/pv/dialogs/storeprogress.cpp @@ -49,6 +49,7 @@ StoreProgress::StoreProgress(SigSession *session, QWidget *parent) : _isExport = false; _done = false; + _isBusy = false; QGridLayout *grid = new QGridLayout(); _grid = grid; @@ -133,6 +134,9 @@ void StoreProgress::accept() return; } + if (_isBusy) + return; + _progress.setVisible(true); _fileLab->setVisible(false); _fileLab->setVisible(false); @@ -157,7 +161,8 @@ void StoreProgress::accept() //start done if (_isExport){ if (_store_session.export_start()){ - QTimer::singleShot(100, this, SLOT(timeout())); + _isBusy = true; + QTimer::singleShot(100, this, SLOT(timeout())); } else{ save_done(); @@ -167,7 +172,8 @@ void StoreProgress::accept() } else{ if (_store_session.save_start()){ - QTimer::singleShot(100, this, SLOT(timeout())); + _isBusy = true; + QTimer::singleShot(100, this, SLOT(timeout())); } else{ save_done(); diff --git a/DSView/pv/dialogs/storeprogress.h b/DSView/pv/dialogs/storeprogress.h index 051185123..a519135b8 100644 --- a/DSView/pv/dialogs/storeprogress.h +++ b/DSView/pv/dialogs/storeprogress.h @@ -84,6 +84,7 @@ private slots: QPushButton *_openButton; QGridLayout *_grid; QWidget *_space; + bool _isBusy; }; } // dialogs diff --git a/DSView/pv/mainwindow.cpp b/DSView/pv/mainwindow.cpp index d251b14f3..562084941 100644 --- a/DSView/pv/mainwindow.cpp +++ b/DSView/pv/mainwindow.cpp @@ -96,6 +96,7 @@ #include "utility/encoding.h" #include "utility/path.h" #include "log.h" +#include "mainframe.h" #define BASE_SESSION_VERSION 2 @@ -247,8 +248,8 @@ void MainWindow::setup_ui() connect(&_event, SIGNAL(show_error(QString)), this, SLOT(on_show_error(QString))); connect(&_event, SIGNAL(signals_changed()), this, SLOT(on_signals_changed())); connect(&_event, SIGNAL(receive_trigger(quint64)), this, SLOT(on_receive_trigger(quint64))); - connect(&_event, SIGNAL(frame_ended()), this, SLOT(on_frame_ended())); - connect(&_event, SIGNAL(frame_began()), this, SLOT(on_frame_began())); + connect(&_event, SIGNAL(frame_ended()), this, SLOT(on_frame_ended()), Qt::DirectConnection); + connect(&_event, SIGNAL(frame_began()), this, SLOT(on_frame_began()), Qt::DirectConnection); connect(&_event, SIGNAL(decode_done()), this, SLOT(on_decode_done())); connect(&_event, SIGNAL(data_updated()), this, SLOT(on_data_updated())); connect(&_event, SIGNAL(cur_snap_samplerate_changed()), this, SLOT(on_cur_snap_samplerate_changed())); @@ -673,24 +674,6 @@ void MainWindow::on_session_error() title = tr("Malloc Error"); details = tr("Memory is not enough for this sample!\nPlease reduce the sample depth!"); break; - case SigSession::Test_data_err: - _session->set_repeating(false); - _session->stop_capture(); - _sampling_bar->set_sampling(false); - _session->capture_state_changed(SigSession::Stopped); - title = tr("Data Error"); - error_pattern = _session->get_error_pattern(); - for(int i = 0; i < 16; i++) { - if (error_pattern & 0x01) - ch_status += "X "; - else - ch_status += " "; - ch_status += (i > 9 ? " " : ""); - error_pattern >>= 1; - } - details = tr("the received data are not consist with pre-defined test data!") + "\n" + - tr("0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15")+ "\n" + ch_status; - break; case SigSession::Pkt_data_err: title = tr("Packet Error"); details = tr("the content of received packet are not expected!"); @@ -888,14 +871,20 @@ void MainWindow::on_screenShot() QString default_name = app._userHistory.screenShotPath + "/" + APP_NAME + QDateTime::currentDateTime().toString("-yyMMdd-hhmmss"); #ifdef _WIN32 - int x = parentWidget()->pos().x(); - int y = parentWidget()->pos().y(); - int w = parentWidget()->frameGeometry().width(); - int h = parentWidget()->frameGeometry().height(); - QDesktopWidget *desktop = QApplication::desktop(); - QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(desktop->winId(), x, y, w, h); + int x = parentWidget()->pos().x(); + int y = parentWidget()->pos().y(); + int w = parentWidget()->frameGeometry().width(); + int h = parentWidget()->frameGeometry().height(); + QDesktopWidget *desktop = QApplication::desktop(); + QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(desktop->winId(), x, y, w, h); +#elif __APPLE__ + int x = parentWidget()->pos().x() + MainFrame::Margin; + int y = parentWidget()->pos().y() + MainFrame::Margin; + int w = parentWidget()->geometry().width() - MainFrame::Margin * 2; + int h = parentWidget()->geometry().height() - MainFrame::Margin * 2; + QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(winId(), x, y, w, h); #else - QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(winId()); + QPixmap pixmap = QGuiApplication::primaryScreen()->grabWindow(winId()); #endif QString format = "png"; @@ -1326,6 +1315,13 @@ bool MainWindow::eventFilter(QObject *object, QEvent *event) SigSession *_session = _control->GetSession(); const auto &sigs = _session->get_signals(); QKeyEvent *ke = (QKeyEvent *) event; + int modifier = ke->modifiers(); + if(modifier & Qt::ControlModifier || + modifier & Qt::ShiftModifier || + modifier & Qt::AltModifier) + { + return true; + } switch(ke->key()) { case Qt::Key_S: on_run_stop(); diff --git a/DSView/pv/sigsession.cpp b/DSView/pv/sigsession.cpp index 5659f41ee..60f2de807 100644 --- a/DSView/pv/sigsession.cpp +++ b/DSView/pv/sigsession.cpp @@ -981,12 +981,6 @@ void SigSession::feed_in_logic(const sr_datafeed_logic &logic) return; } - if (logic.data_error == 1) { - _error = Test_data_err; - _error_pattern = logic.error_pattern; - _callback->session_error(); - } - if (_logic_data->snapshot()->last_ended()) { _logic_data->snapshot()->first_payload(logic, _dev_inst->get_sample_limit(), _dev_inst->dev_inst()->channels); // @todo Putting this here means that only listeners querying diff --git a/DSView/pv/utility/path.cpp b/DSView/pv/utility/path.cpp index 44dcc2b7e..7ca423224 100644 --- a/DSView/pv/utility/path.cpp +++ b/DSView/pv/utility/path.cpp @@ -22,6 +22,8 @@ #include "path.h" #ifdef _WIN32 #include +#include "../log.h" +#include #endif namespace pv{ @@ -45,16 +47,22 @@ namespace path{ std::string ToUnicodePath(QString path) { std::string str; - + #ifdef _WIN32 QTextCodec *codec = QTextCodec::codecForName("System"); - QByteArray str_tmp = codec->fromUnicode(path); - str = str_tmp.data(); + if (codec != NULL){ + QByteArray str_tmp = codec->fromUnicode(path); + str = str_tmp.data(); + } + else{ + dsv_err("Error: can't get \"System\" page code"); + str = path.toUtf8().data(); + } #else - str = path.toUtf8().data(); + str = path.toUtf8().data(); #endif return str; } } -} \ No newline at end of file +} diff --git a/DSView/pv/view/dsosignal.cpp b/DSView/pv/view/dsosignal.cpp index 5b37e8db6..6096f1b05 100644 --- a/DSView/pv/view/dsosignal.cpp +++ b/DSView/pv/view/dsosignal.cpp @@ -890,7 +890,12 @@ void DsoSignal::paint_mid(QPainter &p, int left, int right, QColor fore, QColor const uint32_t count = (index == 0) ? status.ch0_cyc_cnt : status.ch1_cyc_cnt; const bool plevel = (index == 0) ? status.ch0_plevel : status.ch1_plevel; const bool startXORend = (index == 0) ? (status.ch0_cyc_llen == 0) : (status.ch1_cyc_llen == 0); - const uint16_t total_channels = g_slist_length(_dev_inst->dev_inst()->channels); + uint16_t total_channels = g_slist_length(_dev_inst->dev_inst()->channels); + + if (total_channels == 1 && _dev_inst->is_file()){ + total_channels++; + } + const double tfactor = (total_channels / enabled_channels) * SR_GHZ(1) * 1.0 / samplerate; double samples = (index == 0) ? status.ch0_cyc_tlen : status.ch1_cyc_tlen; diff --git a/DSView/res/DSLogicPlus-pgl12.bin b/DSView/res/DSLogicPlus-pgl12.bin new file mode 100644 index 000000000..7ce73fdad Binary files /dev/null and b/DSView/res/DSLogicPlus-pgl12.bin differ diff --git a/DSView/res/DSLogicU2Basic-pgl12.bin b/DSView/res/DSLogicU2Basic-pgl12.bin new file mode 100644 index 000000000..7dfbd18b1 Binary files /dev/null and b/DSView/res/DSLogicU2Basic-pgl12.bin differ diff --git a/NEWS25 b/NEWS25 index 20d80cf9b..9467fd81e 100644 --- a/NEWS25 +++ b/NEWS25 @@ -1,3 +1,23 @@ +v1.2.2 -- (2023-01-11) +---------- + (通用) + *增加快捷键对ctrl/shift/alt的识别 + *修复保存文件过程中多次点击崩溃的问题 + *修复macOS下截图崩溃的问题 + *改进CSV文件的保存精度 + + (逻辑分析仪) + *支持新的硬件和固件版本 + *清理0:UART协议的outputs申明 + *增加CAN解码器对CANFD的支持 + *修复某些解码器的wait错误 + *修复QI解码器的错误 + *修复SPDIF解码器对不完整帧的解码 + *增加USB PD协议的消息类型支持 + + (示波器) + *修复不同通道数的dsl文件载入后测量值显示问题 + 1.2.1 -- (2022-08-27) ---------- (通用) diff --git a/NEWS31 b/NEWS31 index deb0d0b97..eb1653918 100644 --- a/NEWS31 +++ b/NEWS31 @@ -1,3 +1,23 @@ +v1.2.2 -- (2023-01-11) +---------- + --common + * Add shortcut key recognition of ctrl/shift/alt + * Fix multiple clicks crash during file saving + * Fix screenshot crash under macOS + * Improve accuracy of CSV file + + --for logic analyzer + * Support new hardware and firmware versions + * Clean up 0: UART protocol outputs statement + * Add CAN decoder support for CANFD + * Fix wait error for some decoders + * Fix QI decoder bugs + * Fix SPDIF decoder error for incomplete frames + * Add message type support for USB PD decoder + + --for oscilloscope + * Fix measure error of DSL files with different channel number + 1.2.1 -- (2022-08-27) ----------------- --common diff --git a/libsigrok4DSL/hardware/DSL/command.h b/libsigrok4DSL/hardware/DSL/command.h index a56476383..4311f32b3 100644 --- a/libsigrok4DSL/hardware/DSL/command.h +++ b/libsigrok4DSL/hardware/DSL/command.h @@ -49,6 +49,8 @@ #define bmWR_WORDWIDE (1 << 0) #define VTH_ADDR 0x78 +#define SEC_DATA_ADDR 0x75 +#define SEC_CTRL_ADDR 0x73 #define CTR1_ADDR 0x71 #define CTR0_ADDR 0x70 #define COMB_ADDR 0x68 @@ -56,6 +58,14 @@ #define ADCC_ADDR 0x48 #define HDL_VERSION_ADDR 0x04 +#define bmSECU_READY (1 << 3) +#define bmSECU_PASS (1 << 4) +#define SECU_STEPS 8 +#define SECU_START 0x0513 +#define SECU_CHECK 0x0219 +#define SECU_EEP_ADDR 0x3C00 +#define SECU_TRY_CNT 8 + #define EI2C_CTR_OFF 0x2 #define EI2C_RXR_OFF 0x3 #define EI2C_SR_OFF 0x4 diff --git a/libsigrok4DSL/hardware/DSL/dsl.c b/libsigrok4DSL/hardware/DSL/dsl.c index f10909003..1f904f458 100644 --- a/libsigrok4DSL/hardware/DSL/dsl.c +++ b/libsigrok4DSL/hardware/DSL/dsl.c @@ -1920,6 +1920,16 @@ SR_PRIV int dsl_dev_open(struct sr_dev_driver *di, struct sr_dev_inst *sdi, gboo } } + // check security + uint16_t encryption[SECU_STEPS]; + ret = dsl_wr_reg(sdi, CTR0_ADDR, bmNONE); // dessert clear + if (dsl_rd_nvm(sdi, (unsigned char *)encryption, SECU_EEP_ADDR, SECU_STEPS*2) != SR_OK) { + sr_err("Read EEPROM content failed!"); + return SR_ERR; + } + ret = dsl_secuCheck(sdi, encryption, SECU_STEPS); + if (ret != SR_OK) + sr_err("Security check failed!"); return SR_OK; } @@ -2471,3 +2481,103 @@ SR_PRIV int dsl_start_transfers(const struct sr_dev_inst *sdi) return SR_OK; } + +/* + * security low level operations + */ +SR_PRIV int dsl_secuReset(const struct sr_dev_inst *sdi) +{ + if (dsl_wr_reg(sdi, SEC_CTRL_ADDR, 0) != SR_OK) goto Err; + if (dsl_wr_reg(sdi, SEC_CTRL_ADDR + 1, 0) != SR_OK) goto Err; + g_usleep(10*1000); + if (dsl_wr_reg(sdi, SEC_CTRL_ADDR, 1) != SR_OK) goto Err; + if (dsl_wr_reg(sdi, SEC_CTRL_ADDR + 1, 0) != SR_OK) goto Err; + + return SR_OK; +Err: + sr_err("Sent dsl_wr_reg(SEC_XXX_ADDR) command failed."); + return SR_ERR; +} + +SR_PRIV int dsl_secuWrite(const struct sr_dev_inst *sdi, uint16_t cmd, uint16_t din) +{ + if (dsl_wr_reg(sdi, SEC_DATA_ADDR, din) != SR_OK) goto Err; + if (dsl_wr_reg(sdi, SEC_DATA_ADDR + 1, (din >> 8)) != SR_OK) goto Err; + if (dsl_wr_reg(sdi, SEC_CTRL_ADDR, cmd) != SR_OK) goto Err; + if (dsl_wr_reg(sdi, SEC_CTRL_ADDR + 1, (cmd >> 8)) != SR_OK) goto Err; + + return SR_OK; +Err: + sr_err("Sent dsl_wr_reg(SEC_XXX_ADDR) command failed."); + return SR_ERR; +} + +SR_PRIV gboolean dsl_isSecuReady(const struct sr_dev_inst *sdi) +{ + uint8_t temp; + if (dsl_rd_reg(sdi, SEC_CTRL_ADDR, &temp) != SR_OK) goto Err; + + if (temp & bmSECU_READY) + return TRUE; + else + return FALSE; +Err: + sr_err("Sent dsl_rd_reg(SEC_XXX_ADDR) command failed."); + return FALSE; +} + +SR_PRIV gboolean dsl_isSecuPass(const struct sr_dev_inst *sdi) +{ + uint8_t temp; + if (dsl_rd_reg(sdi, SEC_CTRL_ADDR, &temp) != SR_OK) goto Err; + + if (temp & bmSECU_PASS) + return TRUE; + else + return FALSE; +Err: + sr_err("Sent dsl_rd_reg(SEC_XXX_ADDR) command failed."); + return FALSE; +} + +SR_PRIV uint16_t dsl_secuRead(const struct sr_dev_inst *sdi) +{ + uint16_t sec; + if (dsl_rd_reg(sdi, SEC_DATA_ADDR + 1, (uint8_t*)&sec) != SR_OK) goto Err; + sec <<= 8; + if (dsl_rd_reg(sdi, SEC_DATA_ADDR, (uint8_t*)&sec) != SR_OK) goto Err; + + return sec; +Err: + sr_err("Sent dsl_rd_reg(SEC_XXX_ADDR) command failed."); + return 0; +} + + +/* + * security API interface + */ +SR_PRIV int dsl_secuCheck(const struct sr_dev_inst *sdi, uint16_t* encryption, int steps) +{ + int tryCnt = SECU_TRY_CNT; + + dsl_secuReset(sdi); + if (dsl_isSecuPass(sdi)) + return SR_ERR; + dsl_secuWrite(sdi, SECU_START, 0); + while(steps--) { + if (dsl_isSecuPass(sdi)) + return SR_ERR; + while(!dsl_isSecuReady(sdi)) { + if (tryCnt-- == 0) { + sr_err("Get security ready failed."); + return SR_ERR; + } + } + if (dsl_secuRead(sdi) != 0) + return SR_ERR; + dsl_secuWrite(sdi, SECU_CHECK, encryption[steps]); + } + + return SR_OK; +} \ No newline at end of file diff --git a/libsigrok4DSL/hardware/DSL/dsl.h b/libsigrok4DSL/hardware/DSL/dsl.h index 0581c025e..badad3985 100644 --- a/libsigrok4DSL/hardware/DSL/dsl.h +++ b/libsigrok4DSL/hardware/DSL/dsl.h @@ -87,6 +87,8 @@ #define CAPS_FEATURE_LA_CH32 (1 << 11) // auto tunning vgain #define CAPS_FEATURE_AUTO_VGAIN (1 << 12) +// max 2.5v fpga threshold +#define CAPS_FEATURE_MAX25_VTH (1 << 13) /* end */ @@ -744,6 +746,61 @@ static const struct DSL_profile supported_DSLogic[] = { SR_GHZ(1)} }, + {0x2A0E, 0x0030, LIBUSB_SPEED_HIGH, "DreamSourceLab", "DSLogic PLus", NULL, + "DSLogicPlus.fw", + "DSLogicPlus-pgl12.bin", + "DSLogicPlus-pgl12.bin", + {CAPS_MODE_LOGIC, + CAPS_FEATURE_VTH | CAPS_FEATURE_BUF | CAPS_FEATURE_MAX25_VTH, + (1 << DSL_STREAM20x16) | (1 << DSL_STREAM25x12) | (1 << DSL_STREAM50x6) | (1 << DSL_STREAM100x3) | + (1 << DSL_BUFFER100x16) | (1 << DSL_BUFFER200x8) | (1 << DSL_BUFFER400x4), + 16, + SR_MB(256), + 0, + DSL_BUFFER100x16, + 0, + samplerates400, + 0, + DSL_STREAM20x16, + SR_MHZ(1), + SR_Mn(1), + 0, + 0, + 0, + 0, + 0, + SR_MHZ(200), + SR_MHZ(400)} + }, + + {0x2A0E, 0x0031, LIBUSB_SPEED_HIGH, "DreamSourceLab", "DSLogic U2Basic", NULL, + "DSLogicU2Basic.fw", + "DSLogicU2Basic-pgl12.bin", + "DSLogicU2Basic-pgl12.bin", + {CAPS_MODE_LOGIC, + CAPS_FEATURE_VTH | CAPS_FEATURE_BUF | CAPS_FEATURE_MAX25_VTH, + (1 << DSL_STREAM20x16) | (1 << DSL_STREAM25x12) | (1 << DSL_STREAM50x6) | (1 << DSL_STREAM100x3) | + (1 << DSL_BUFFER100x16), + 16, + SR_MB(64), + 0, + DSL_BUFFER100x16, + 0, + samplerates100, + 0, + DSL_STREAM20x16, + SR_MHZ(1), + SR_Mn(1), + 0, + 0, + 0, + 0, + 0, + SR_MHZ(200), + SR_MHZ(400)} + }, + + { 0, 0, LIBUSB_SPEED_UNKNOWN, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}} }; @@ -1364,4 +1421,6 @@ SR_PRIV unsigned int dsl_get_timeout(const struct sr_dev_inst *sdi); SR_PRIV int dsl_start_transfers(const struct sr_dev_inst *sdi); SR_PRIV int dsl_header_size(const struct DSL_context *devc); +SR_PRIV int dsl_secuCheck(const struct sr_dev_inst *sdi, uint16_t* encryption, int steps); + #endif diff --git a/libsigrok4DSL/hardware/DSL/dslogic.c b/libsigrok4DSL/hardware/DSL/dslogic.c index b2955fca6..20b940be3 100644 --- a/libsigrok4DSL/hardware/DSL/dslogic.c +++ b/libsigrok4DSL/hardware/DSL/dslogic.c @@ -1014,7 +1014,10 @@ static int config_set(int id, GVariant *data, struct sr_dev_inst *sdi, } } else if (id == SR_CONF_VTH) { devc->vth = g_variant_get_double(data); - ret = dsl_wr_reg(sdi, VTH_ADDR, (uint8_t)(devc->vth/5.0*255)); + if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_MAX25_VTH) + ret = dsl_wr_reg(sdi, VTH_ADDR, (uint8_t)(devc->vth/5.0*(2.5/3.3)*255)); + else + ret = dsl_wr_reg(sdi, VTH_ADDR, (uint8_t)(devc->vth/5.0*255)); } else if (id == SR_CONF_MAX_HEIGHT) { stropt = g_variant_get_string(data, NULL); for (i = 0; i < ARRAY_SIZE(maxHeights); i++) { @@ -1157,7 +1160,10 @@ static int dev_open(struct sr_dev_inst *sdi) if ((ret = dsl_dev_open(di, sdi, &fpga_done)) == SR_OK) { // set threshold - ret = dsl_wr_reg(sdi, VTH_ADDR, (uint8_t)(devc->vth/5.0*255)); + if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_MAX25_VTH) + ret = dsl_wr_reg(sdi, VTH_ADDR, (uint8_t)(devc->vth/5.0*(2.5/3.3)*255)); + else + ret = dsl_wr_reg(sdi, VTH_ADDR, (uint8_t)(devc->vth/5.0*255)); if (devc->profile->dev_caps.feature_caps & CAPS_FEATURE_ADF4360) { dsl_config_adc(sdi, adc_clk_init_500m); } diff --git a/libsigrok4DSL/output/csv.c b/libsigrok4DSL/output/csv.c index 28fccda19..0a562eaf1 100644 --- a/libsigrok4DSL/output/csv.c +++ b/libsigrok4DSL/output/csv.c @@ -240,7 +240,7 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p continue; } - g_string_append_printf(*out, "%0.10g", (ctx->index-1)*1.0/ctx->samplerate); + g_string_append_printf(*out, "%0.15g", (ctx->index-1)*1.0/ctx->samplerate); for (j = 0; j < ctx->num_enabled_channels; j++) { //idx = ctx->channel_index[j]; idx = j; diff --git a/libsigrokdecode4DSL/decoders/can/pd.py b/libsigrokdecode4DSL/decoders/can/pd.py index ceb79b744..5ee6241ab 100644 --- a/libsigrokdecode4DSL/decoders/can/pd.py +++ b/libsigrokdecode4DSL/decoders/can/pd.py @@ -2,7 +2,8 @@ ## This file is part of the libsigrokdecode project. ## ## Copyright (C) 2012-2013 Uwe Hermann -## Copyright (C) 2019 DreamSourceLab +## Copyright (C) 2019 Stephan Thiele +## Copyright (C) 2022 DreamSourceLab ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -18,11 +19,15 @@ ## along with this program; if not, see . ## +from common.srdhelper import bitpack_msb import sigrokdecode as srd class SamplerateError(Exception): pass +def dlc2len(dlc): + return [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64][dlc] + class Decoder(srd.Decoder): api_version = 3 id = 'can' @@ -31,13 +36,14 @@ class Decoder(srd.Decoder): desc = 'Field bus protocol for distributed realtime control.' license = 'gplv2+' inputs = ['logic'] - outputs = [] + outputs = ['can'] tags = ['Automotive'] channels = ( {'id': 'can_rx', 'name': 'CAN', 'desc': 'CAN bus line'}, ) options = ( - {'id': 'bitrate', 'desc': 'Bitrate (bits/s)', 'default': 1000000}, + {'id': 'nominal_bitrate', 'desc': 'Nominal bitrate (bits/s)', 'default': 1000000}, + {'id': 'fast_bitrate', 'desc': 'Fast bitrate (bits/s)', 'default': 2000000}, {'id': 'sample_point', 'desc': 'Sample point (%)', 'default': 70.0}, ) annotations = ( @@ -75,11 +81,22 @@ def reset(self): def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) + self.out_python = self.register(srd.OUTPUT_PYTHON) + + def set_bit_rate(self, bitrate): + self.bit_width = float(self.samplerate) / float(bitrate) + self.sample_point = (self.bit_width / 100.0) * self.options['sample_point'] + + def set_nominal_bitrate(self): + self.set_bit_rate(self.options['nominal_bitrate']) + + def set_fast_bitrate(self): + self.set_bit_rate(self.options['fast_bitrate']) def metadata(self, key, value): if key == srd.SRD_CONF_SAMPLERATE: self.samplerate = value - self.bit_width = float(self.samplerate) / float(self.options['bitrate']) + self.bit_width = float(self.samplerate) / float(self.options['nominal_bitrate']) self.sample_point = (self.bit_width / 100.0) * self.options['sample_point'] # Generic helper for CAN bit annotations. @@ -95,10 +112,17 @@ def putx(self, data): def put12(self, data): self.putg(self.ss_bit12, self.ss_bit12, data) + # Single-CAN-bit annotation using the samplenum of CAN bit 32. + def put32(self, data): + self.putg(self.ss_bit32, self.ss_bit32, data) + # Multi-CAN-bit annotation from self.ss_block to current samplenum. def putb(self, data): self.putg(self.ss_block, self.samplenum, data) + def putpy(self, data): + self.put(self.ss_packet, self.es_packet, self.out_python, data) + def reset_variables(self): self.state = 'IDLE' self.sof = self.frame_type = self.dlc = None @@ -108,7 +132,12 @@ def reset_variables(self): self.last_databit = 999 # Positive value that bitnum+x will never match self.ss_block = None self.ss_bit12 = None + self.ss_bit32 = None self.ss_databytebits = [] + self.frame_bytes = [] + self.rtr_type = None + self.fd = False + self.rtr = None # Poor man's clock synchronization. Use signal edges which change to # dominant state in rather simple ways. This naive approach is neither @@ -119,16 +148,12 @@ def dom_edge_seen(self, force = False): self.dom_edge_snum = self.samplenum self.dom_edge_bcount = self.curbit - def bit_sampled(self): - # EMPTY - pass - # Determine the position of the next desired bit's sample point. def get_sample_point(self, bitnum): samplenum = self.dom_edge_snum - samplenum += int(self.bit_width * (bitnum - self.dom_edge_bcount)) - samplenum += int(self.sample_point) - return samplenum + samplenum += self.bit_width * (bitnum - self.dom_edge_bcount) + samplenum += self.sample_point + return int(samplenum) def is_stuff_bit(self): # CAN uses NRZ encoding and bit stuffing. @@ -161,45 +186,67 @@ def decode_frame_end(self, can_rx, bitnum): # Remember start of CRC sequence (see below). if bitnum == (self.last_databit + 1): self.ss_block = self.samplenum + if self.fd: + if dlc2len(self.dlc) < 16: + self.crc_len = 27 # 17 + SBC + stuff bits + else: + self.crc_len = 32 # 21 + SBC + stuff bits + else: + self.crc_len = 15 + + # CRC sequence (15 bits, 17 bits or 21 bits) + elif bitnum == (self.last_databit + self.crc_len): + if self.fd: + if dlc2len(self.dlc) < 16: + crc_type = "CRC-17" + else: + crc_type = "CRC-21" + else: + crc_type = "CRC-15" - # CRC sequence (15 bits) - elif bitnum == (self.last_databit + 15): x = self.last_databit + 1 - crc_bits = self.bits[x:x + 15 + 1] - self.crc = int(''.join(str(d) for d in crc_bits), 2) - self.putb([11, ['CRC sequence: 0x%04x' % self.crc, - 'CRC: 0x%04x' % self.crc, 'CRC']]) + crc_bits = self.bits[x:x + self.crc_len + 1] + self.crc = bitpack_msb(crc_bits) + self.putb([11, ['%s sequence: 0x%04x' % (crc_type, self.crc), + '%s: 0x%04x' % (crc_type, self.crc), '%s' % crc_type]]) if not self.is_valid_crc(crc_bits): self.putb([16, ['CRC is invalid']]) # CRC delimiter bit (recessive) - elif bitnum == (self.last_databit + 16): + elif bitnum == (self.last_databit + self.crc_len + 1): self.putx([12, ['CRC delimiter: %d' % can_rx, 'CRC d: %d' % can_rx, 'CRC d']]) if can_rx != 1: self.putx([16, ['CRC delimiter must be a recessive bit']]) + if self.fd: + self.set_nominal_bitrate() + # ACK slot bit (dominant: ACK, recessive: NACK) - elif bitnum == (self.last_databit + 17): + elif bitnum == (self.last_databit + self.crc_len + 2): ack = 'ACK' if can_rx == 0 else 'NACK' self.putx([13, ['ACK slot: %s' % ack, 'ACK s: %s' % ack, 'ACK s']]) # ACK delimiter bit (recessive) - elif bitnum == (self.last_databit + 18): + elif bitnum == (self.last_databit + self.crc_len + 3): self.putx([14, ['ACK delimiter: %d' % can_rx, 'ACK d: %d' % can_rx, 'ACK d']]) if can_rx != 1: self.putx([16, ['ACK delimiter must be a recessive bit']]) # Remember start of EOF (see below). - elif bitnum == (self.last_databit + 19): + elif bitnum == (self.last_databit + self.crc_len + 4): self.ss_block = self.samplenum # End of frame (EOF), 7 recessive bits - elif bitnum == (self.last_databit + 25): + elif bitnum == (self.last_databit + self.crc_len + 10): self.putb([2, ['End of frame', 'EOF', 'E']]) if self.rawbits[-7:] != [1, 1, 1, 1, 1, 1, 1]: self.putb([16, ['End of frame (EOF) must be 7 recessive bits']]) + self.es_packet = self.samplenum + py_data = tuple([self.frame_type, self.fullid, self.rtr_type, + self.dlc, self.frame_bytes]) + self.putpy(py_data) self.reset_variables() return True @@ -208,43 +255,66 @@ def decode_frame_end(self, can_rx, bitnum): # Returns True if the frame ended (EOF), False otherwise. def decode_standard_frame(self, can_rx, bitnum): - # Bit 14: RB0 (reserved bit) - # Has to be sent dominant, but receivers should accept recessive too. + # Bit 14: FDF (Flexible data format) + # Has to be sent dominant when FD frame, has to be sent recessive + # when classic CAN frame. if bitnum == 14: - self.putx([7, ['Reserved bit 0: %d' % can_rx, - 'RB0: %d' % can_rx, 'RB0']]) + self.fd = True if can_rx else False + if self.fd: + self.putx([7, ['Flexible data format: %d' % can_rx, + 'FDF: %d' % can_rx, 'FDF']]) + else: + self.putx([7, ['Reserved bit 0: %d' % can_rx, + 'RB0: %d' % can_rx, 'RB0']]) + + if self.fd: + # Bit 12: Substitute remote request (SRR) bit + self.put12([8, ['Substitute remote request', 'SRR']]) + self.dlc_start = 18 + else: + # Bit 12: Remote transmission request (RTR) bit + # Data frame: dominant, remote frame: recessive + # Remote frames do not contain a data field. + rtr = 'remote' if self.bits[12] == 1 else 'data' + self.put12([8, ['Remote transmission request: %s frame' % rtr, + 'RTR: %s frame' % rtr, 'RTR']]) + self.rtr_type = rtr + self.dlc_start = 15 - # Bit 12: Remote transmission request (RTR) bit - # Data frame: dominant, remote frame: recessive - # Remote frames do not contain a data field. - rtr = 'remote' if self.bits[12] == 1 else 'data' - self.put12([8, ['Remote transmission request: %s frame' % rtr, - 'RTR: %s frame' % rtr, 'RTR']]) + if bitnum == 15 and self.fd: + self.putx([7, ['Reserved: %d' % can_rx, 'R0: %d' % can_rx, 'R0']]) + + if bitnum == 16 and self.fd: + self.putx([7, ['Bit rate switch: %d' % can_rx, 'BRS: %d' % can_rx, 'BRS']]) + + if bitnum == 17 and self.fd: + self.putx([7, ['Error state indicator: %d' % can_rx, 'ESI: %d' % can_rx, 'ESI']]) # Remember start of DLC (see below). - elif bitnum == 15: + elif bitnum == self.dlc_start: self.ss_block = self.samplenum # Bits 15-18: Data length code (DLC), in number of bytes (0-8). - elif bitnum == 18: - self.dlc = int(''.join(str(d) for d in self.bits[15:18 + 1]), 2) + elif bitnum == self.dlc_start + 3: + self.dlc = bitpack_msb(self.bits[self.dlc_start:self.dlc_start + 4]) self.putb([10, ['Data length code: %d' % self.dlc, 'DLC: %d' % self.dlc, 'DLC']]) - self.last_databit = 18 + (self.dlc * 8) - if self.dlc > 8: + self.last_databit = self.dlc_start + 3 + (dlc2len(self.dlc) * 8) + if self.dlc > 8 and not self.fd: self.putb([16, ['Data length code (DLC) > 8 is not allowed']]) # Remember all databyte bits, except the very last one. - elif bitnum in range(19, self.last_databit): + elif bitnum in range(self.dlc_start + 4, self.last_databit): self.ss_databytebits.append(self.samplenum) # Bits 19-X: Data field (0-8 bytes, depending on DLC) # The bits within a data byte are transferred MSB-first. elif bitnum == self.last_databit: self.ss_databytebits.append(self.samplenum) # Last databyte bit. - for i in range(self.dlc): - x = 18 + (8 * i) + 1 - b = int(''.join(str(d) for d in self.bits[x:x + 8]), 2) + for i in range(dlc2len(self.dlc)): + x = self.dlc_start + 4 + (8 * i) + b = bitpack_msb(self.bits[x:x + 8]) + self.frame_bytes.append(b) ss = self.ss_databytebits[i * 8] es = self.ss_databytebits[((i + 1) * 8) - 1] self.putg(ss, es, [0, ['Data byte %d: 0x%02x' % (i, b), @@ -262,15 +332,17 @@ def decode_extended_frame(self, can_rx, bitnum): # Remember start of EID (see below). if bitnum == 14: self.ss_block = self.samplenum + self.fd = False + self.dlc_start = 35 # Bits 14-31: Extended identifier (EID[17..0]) elif bitnum == 31: - self.eid = int(''.join(str(d) for d in self.bits[14:]), 2) + self.eid = bitpack_msb(self.bits[14:]) s = '%d (0x%x)' % (self.eid, self.eid) self.putb([4, ['Extended Identifier: %s' % s, 'Extended ID: %s' % s, 'Extended ID', 'EID']]) - self.fullid = self.id << 18 | self.eid + self.fullid = self.ident << 18 | self.eid s = '%d (0x%x)' % (self.fullid, self.fullid) self.putb([5, ['Full Identifier: %s' % s, 'Full ID: %s' % s, 'Full ID', 'FID']]) @@ -282,43 +354,67 @@ def decode_extended_frame(self, can_rx, bitnum): # Bit 32: Remote transmission request (RTR) bit # Data frame: dominant, remote frame: recessive # Remote frames do not contain a data field. + + # Remember start of RTR (see below). if bitnum == 32: - rtr = 'remote' if can_rx == 1 else 'data' - self.putx([8, ['Remote transmission request: %s frame' % rtr, - 'RTR: %s frame' % rtr, 'RTR']]) + self.ss_bit32 = self.samplenum + self.rtr = can_rx + + if not self.fd: + rtr = 'remote' if can_rx == 1 else 'data' + self.putx([8, ['Remote transmission request: %s frame' % rtr, + 'RTR: %s frame' % rtr, 'RTR']]) + self.rtr_type = rtr # Bit 33: RB1 (reserved bit) elif bitnum == 33: - self.putx([7, ['Reserved bit 1: %d' % can_rx, - 'RB1: %d' % can_rx, 'RB1']]) + self.fd = True if can_rx else False + if self.fd: + self.dlc_start = 37 + self.putx([7, ['Flexible data format: %d' % can_rx, + 'FDF: %d' % can_rx, 'FDF']]) + self.put32([7, ['Reserved bit 1: %d' % self.rtr, + 'RB1: %d' % self.rtr, 'RB1']]) + else: + self.putx([7, ['Reserved bit 1: %d' % can_rx, + 'RB1: %d' % can_rx, 'RB1']]) # Bit 34: RB0 (reserved bit) elif bitnum == 34: self.putx([7, ['Reserved bit 0: %d' % can_rx, 'RB0: %d' % can_rx, 'RB0']]) + elif bitnum == 35 and self.fd: + self.putx([7, ['Bit rate switch: %d' % can_rx, + 'BRS: %d' % can_rx, 'BRS']]) + + elif bitnum == 36 and self.fd: + self.putx([7, ['Error state indicator: %d' % can_rx, + 'ESI: %d' % can_rx, 'ESI']]) + # Remember start of DLC (see below). - elif bitnum == 35: + elif bitnum == self.dlc_start: self.ss_block = self.samplenum # Bits 35-38: Data length code (DLC), in number of bytes (0-8). - elif bitnum == 38: - self.dlc = int(''.join(str(d) for d in self.bits[35:38 + 1]), 2) + elif bitnum == self.dlc_start + 3: + self.dlc = bitpack_msb(self.bits[self.dlc_start:self.dlc_start + 4]) self.putb([10, ['Data length code: %d' % self.dlc, 'DLC: %d' % self.dlc, 'DLC']]) - self.last_databit = 38 + (self.dlc * 8) + self.last_databit = self.dlc_start + 3 + (dlc2len(self.dlc) * 8) # Remember all databyte bits, except the very last one. - elif bitnum in range(39, self.last_databit): + elif bitnum in range(self.dlc_start + 4, self.last_databit): self.ss_databytebits.append(self.samplenum) # Bits 39-X: Data field (0-8 bytes, depending on DLC) # The bits within a data byte are transferred MSB-first. elif bitnum == self.last_databit: self.ss_databytebits.append(self.samplenum) # Last databyte bit. - for i in range(self.dlc): - x = 38 + (8 * i) + 1 - b = int(''.join(str(d) for d in self.bits[x:x + 8]), 2) + for i in range(dlc2len(self.dlc)): + x = self.dlc_start + 4 + (8 * i) + b = bitpack_msb(self.bits[x:x + 8]) + self.frame_bytes.append(b) ss = self.ss_databytebits[i * 8] es = self.ss_databytebits[((i + 1) * 8) - 1] self.putg(ss, es, [0, ['Data byte %d: 0x%02x' % (i, b), @@ -337,6 +433,12 @@ def handle_bit(self, can_rx): # Get the index of the current CAN frame bit (without stuff bits). bitnum = len(self.bits) - 1 + if self.fd and can_rx: + if bitnum == 16 and self.frame_type == 'standard' \ + or bitnum == 35 and self.frame_type == 'extended': + self.dom_edge_seen(force=True) + self.set_fast_bitrate() + # If this is a stuff bit, remove it from self.bits and ignore it. if self.is_stuff_bit(): self.putx([15, [str(can_rx)]]) @@ -347,6 +449,7 @@ def handle_bit(self, can_rx): # Bit 0: Start of frame (SOF) bit if bitnum == 0: + self.ss_packet = self.samplenum self.putx([1, ['Start of frame', 'SOF', 'S']]) if can_rx != 0: self.putx([16, ['Start of frame (SOF) must be a dominant bit']]) @@ -358,10 +461,13 @@ def handle_bit(self, can_rx): # Bits 1-11: Identifier (ID[10..0]) # The bits ID[10..4] must NOT be all recessive. elif bitnum == 11: - self.id = int(''.join(str(d) for d in self.bits[1:]), 2) - s = '%d (0x%x)' % (self.id, self.id), + # BEWARE! Don't clobber the decoder's .id field which is + # part of its boiler plate! + self.ident = bitpack_msb(self.bits[1:]) + self.fullid = self.ident + s = '%d (0x%x)' % (self.ident, self.ident), self.putb([3, ['Identifier: %s' % s, 'ID: %s' % s, 'ID']]) - if (self.id & 0x7f0) == 0x7f0: + if (self.ident & 0x7f0) == 0x7f0: self.putb([16, ['Identifier bits 10..4 must not be all recessive']]) # RTR or SRR bit, depending on frame type (gets handled later). @@ -412,4 +518,3 @@ def decode(self): self.dom_edge_seen() if (self.matched & (0b1 << 0)): self.handle_bit(can_rx) - self.bit_sampled() diff --git a/libsigrokdecode4DSL/decoders/ieee488/pd.py b/libsigrokdecode4DSL/decoders/ieee488/pd.py index 5fb6fa886..35b22a3d9 100644 --- a/libsigrokdecode4DSL/decoders/ieee488/pd.py +++ b/libsigrokdecode4DSL/decoders/ieee488/pd.py @@ -620,7 +620,8 @@ def decode_serial(self, has_clk, has_data_1, has_atn, has_srq): # re-use 'iec' decoder logic. Turn ATN to positive logic for # easier processing. The data bits get handled during byte # accumulation. - pins = self.wait(step_wait_conds[step]) + (dio1,dio2,dio3,dio4,dio5,dio6,dio7,dio8,eoi,dav,nrfd,ndac,ifc,srq,atn,ren,clk)= self.wait(step_wait_conds[step]) + pins = (dio1,dio2,dio3,dio4,dio5,dio6,dio7,dio8,eoi,dav,nrfd,ndac,ifc,srq,atn,ren,clk) data, clk = pins[PIN_DATA], pins[PIN_CLK] atn, = self.invert_pins([pins[PIN_ATN]]) diff --git a/libsigrokdecode4DSL/decoders/qi/pd.py b/libsigrokdecode4DSL/decoders/qi/pd.py index b750d9cec..9e7c972a8 100644 --- a/libsigrokdecode4DSL/decoders/qi/pd.py +++ b/libsigrokdecode4DSL/decoders/qi/pd.py @@ -136,7 +136,7 @@ def process_packet(self): 'CS: %d' % self.packet[1], 'CS']) elif self.packet[0] == 0x06: # Power Control Hold-off self.putp(['Power Control Hold-off: %dms' % self.packet[1], - 'PCH: %d' % self.packet[1]], 'PCH') + 'PCH: %d' % self.packet[1], 'PCH']) elif self.packet[0] == 0x51: # Configuration powerclass = (self.packet[1] & 0xc0) >> 7 maxpower = self.packet[1] & 0x3f diff --git a/libsigrokdecode4DSL/decoders/sle44xx/pd.py b/libsigrokdecode4DSL/decoders/sle44xx/pd.py index 92842b3b1..3bdab06ee 100644 --- a/libsigrokdecode4DSL/decoders/sle44xx/pd.py +++ b/libsigrokdecode4DSL/decoders/sle44xx/pd.py @@ -492,8 +492,7 @@ def decode(self): is_outgoing = self.state == 'OUT' is_processing = self.state == 'PROC' - pins = self.wait(conditions) - io = pins[Pin.IO] + (rst,clk,io) = self.wait(conditions) # Handle RESET conditions, including an optional CLK pulse # while RST is asserted. diff --git a/libsigrokdecode4DSL/decoders/spdif/pd.py b/libsigrokdecode4DSL/decoders/spdif/pd.py index 532bf8257..d1fdcb24b 100644 --- a/libsigrokdecode4DSL/decoders/spdif/pd.py +++ b/libsigrokdecode4DSL/decoders/spdif/pd.py @@ -2,6 +2,7 @@ ## This file is part of the libsigrokdecode project. ## ## Copyright (C) 2014 Guenther Wenninger +## Copyright (C) 2022 DreamSourceLab ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -33,7 +34,7 @@ class Decoder(srd.Decoder): outputs = [] tags = ['Audio', 'PC'] channels = ( - {'id': 'data', 'name': 'Data', 'desc': 'Data line'}, + {'id': 'data', 'name': 'Data', 'desc': 'Data line', 'idn':'dec_spdif_chan_data'}, ) annotations = ( ('bitrate', 'Bitrate / baudrate'), @@ -79,6 +80,11 @@ def reset(self): self.first_one = True self.subframe = [] + + self.temp_pulse_width = [] + self.temp_samplenum = [] + self.firstpramble = True + def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) @@ -98,47 +104,219 @@ def get_pulse_type(self): return 1 def find_first_pulse_width(self): + self.temp_pulse_width.append(self.pulse_width) + self.temp_samplenum.append(self.samplenum) if self.pulse_width != 0: self.clocks.append(self.pulse_width) self.state = 'GET SECOND PULSE WIDTH' - + def find_second_pulse_width(self): + self.temp_pulse_width.append(self.pulse_width) + self.temp_samplenum.append(self.samplenum) if self.pulse_width > (self.clocks[0] * 1.3) or \ self.pulse_width < (self.clocks[0] * 0.7): self.clocks.append(self.pulse_width) self.state = 'GET THIRD PULSE WIDTH' def find_third_pulse_width(self): - if not ((self.pulse_width > (self.clocks[0] * 1.3) or \ - self.pulse_width < (self.clocks[0] * 0.7)) \ - and (self.pulse_width > (self.clocks[1] * 1.3) or \ - self.pulse_width < (self.clocks[1] * 0.7))): + self.temp_pulse_width.append(self.pulse_width) + self.temp_samplenum.append(self.samplenum) + + if ((self.pulse_width <= (self.clocks[0] * 1.3) and self.pulse_width >= (self.clocks[0] * 0.7)) or \ + (self.pulse_width <= (self.clocks[1] * 1.3) and self.pulse_width >= (self.clocks[1] * 0.7))): return self.clocks.append(self.pulse_width) self.clocks.sort() self.range1 = (self.clocks[0] + self.clocks[1]) / 2 self.range2 = (self.clocks[1] + self.clocks[2]) / 2 + spdif_bitrate = int(self.samplerate / (self.clocks[2] / 1.5)) self.ss_edge = 0 - self.puty([0, ['Signal Bitrate: %d Mbit/s (=> %d kHz)' % \ + self.putx(0,self.temp_samplenum[0]-24,[0, ['Signal Bitrate: %d Mbit/s (=> %d kHz)' % \ (spdif_bitrate, (spdif_bitrate/ (2 * 32)))]]) - clock_period_nsec = 1000000000 / spdif_bitrate self.last_preamble = self.samplenum - # We are done recovering the clock, now let's decode the data stream. + is_preamble_status = True + while len(self.decode_re_get_pulse_type())>0: + if is_preamble_status == True: + if self.decode_recheck_preablm() == 0: + return + else: + is_preamble_status = False + else: + if self.decode_recheck_stream() == 0: + return + else: + is_preamble_status = True self.state = 'DECODE STREAM' + + def decode_re_get_pulse_type(self): + pulse_type =[] + for temp_pulse in self.temp_pulse_width: + if self.range1 == 0 or self.range2 == 0: + return pulse_type + if temp_pulse >= self.range2: + pulse_type.append(2) + elif temp_pulse >= self.range1: + pulse_type.append(0) + else : + pulse_type.append(1) + return pulse_type + + def decode_recheck_preablm(self): + if self.decode_re_get_pulse_type() == -1: + return -1 + + pulse_type = self.decode_re_get_pulse_type() + temp_preamble = [] + preamble_is_ok = 0 + preamble_state = -1 + + while len(pulse_type)>0: + temp_samnum = self.temp_samplenum.pop(0) + temp_pul_type = pulse_type.pop(0) + temp_pul_width = self.temp_pulse_width.pop(0) + if preamble_state == -1 and temp_pul_type == 2: + temp_preamble.append(temp_pul_type) + preamble_state = 0 + self.ss_edge = temp_samnum - temp_pul_width - 1 + elif preamble_state == 0: + temp_preamble.append(temp_pul_type) + preamble_state = 1 + elif preamble_state == 1: + temp_preamble.append(temp_pul_type) + preamble_state = 2 + elif preamble_state == 2: + temp_preamble.append(temp_pul_type) + if temp_preamble == [2, 0, 1, 0]: + self.putx(self.ss_edge,temp_samnum,[1, ['Preamble W', 'W']]) + self.seen_preamble = True + elif temp_preamble == [2, 2, 1, 1]: + self.putx(self.ss_edge,temp_samnum,[1, ['Preamble M', 'M']]) + self.seen_preamble = True + elif temp_preamble == [2, 1, 1, 2]: + self.putx(self.ss_edge,temp_samnum,[1, ['Preamble B', 'B']]) + self.seen_preamble = True + else: + self.putx(self.ss_edge,temp_samnum,[1, ['Unknown Preamble', 'Unknown Prea.', 'U']]) + preamble_state = -1 + preamble_is_ok = 1 + temp_preamble = [] + + self.bitcount = 0 + self.first_one = True + self.last_preamble = temp_samnum + break + + if preamble_is_ok == 1: + if len(pulse_type) == 0: + self.state = 'DECODE STREAM' + return 0 + else: + return 1 + else: + self.state = 'DECODE PREAMBLE' + self.preamble = temp_preamble.copy() + if preamble_state == -1: + self.preamble_state = 0 + else: + self.preamble_state = preamble_state + return 0 + + def decode_recheck_stream(self): + if self.decode_re_get_pulse_type() == -1: + return -1 + + pulse_type = self.decode_re_get_pulse_type() + subframe = [] + first_one = True + subframe_is_ok = 0 + bitcount = 0 + + while len(pulse_type)>0: + samnum = self.temp_samplenum.pop(0) + pul_type = pulse_type.pop(0) + pul_width = self.temp_pulse_width.pop(0) + if pul_type == 1 and first_one: + first_one = False + subframe.append([pul_type,samnum - \ + pul_width -1,samnum]) + elif pul_type == 1 and not first_one: + subframe[-1][2] = samnum + self.putx(subframe[-1][1],samnum, [2, ['1']]) + bitcount += 1 + first_one = True + else: + subframe.append([pul_type,samnum - \ + pul_width -1,samnum]) + self.putx(samnum - pul_width - 1, + samnum,[2,['0']]) + bitcount += 1 + + if bitcount == 28: + aux_audio_data = subframe[0:4] + sam, sam_rot = '', '' + for a in aux_audio_data: + sam = sam + str(a[0]) + sam_rot = str(a[0]) + sam_rot + sample = subframe[4:24] + for s in sample: + sam = sam + str(s[0]) + sam_rot = str(s[0]) + sam_rot + validity = subframe[24:25] + subcode_data = subframe[25:26] + channel_status = subframe[26:27] + parity = subframe[27:28] + + self.putx(aux_audio_data[0][1], aux_audio_data[3][2], \ + [3, ['Aux 0x%x' % int(sam, 2), '0x%x' % int(sam, 2)]]) + self.putx(sample[0][1], sample[19][2], \ + [3, ['Sample 0x%x' % int(sam, 2), '0x%x' % int(sam, 2)]]) + self.putx(aux_audio_data[0][1], sample[19][2], \ + [4, ['Audio 0x%x' % int(sam_rot, 2), '0x%x' % int(sam_rot, 2)]]) + if validity[0][0] == 0: + self.putx(validity[0][1], validity[0][2], [5, ['V']]) + else: + self.putx(validity[0][1], validity[0][2], [5, ['E']]) + self.putx(subcode_data[0][1], subcode_data[0][2], + [6, ['S: %d' % subcode_data[0][0]]]) + self.putx(channel_status[0][1], channel_status[0][2], + [7, ['C: %d' % channel_status[0][0]]]) + self.putx(parity[0][1], parity[0][2], [8, ['P: %d' % parity[0][0]]]) + + subframe = [] + self.seen_preamble = False + bitcount = 0 + subframe_is_ok = 1 + break + + if subframe_is_ok == 1: + if len(pulse_type) == 0: + self.state = 'DECODE STREAM' + return 0 + else: + return 1 + else: + self.state = 'DECODE STREAM' + self.subframe = subframe.copy() + self.bitcount = bitcount + self.first_one =first_one + return 0 + + def decode_stream(self): pulse = self.get_pulse_type() - + if not self.seen_preamble: # This is probably the start of a preamble, decode it. if pulse == 2: self.preamble.append(self.get_pulse_type()) + self.preamble_state == 0 self.state = 'DECODE PREAMBLE' self.ss_edge = self.samplenum - self.pulse_width - 1 return @@ -195,6 +373,7 @@ def decode_stream(self): self.seen_preamble = False self.bitcount = 0 + #Unknown Preamble def decode_preamble(self): if self.preamble_state == 0: self.preamble.append(self.get_pulse_type()) @@ -208,14 +387,16 @@ def decode_preamble(self): self.state = 'DECODE STREAM' if self.preamble == [2, 0, 1, 0]: self.puty([1, ['Preamble W', 'W']]) + self.seen_preamble = True elif self.preamble == [2, 2, 1, 1]: self.puty([1, ['Preamble M', 'M']]) + self.seen_preamble = True elif self.preamble == [2, 1, 1, 2]: self.puty([1, ['Preamble B', 'B']]) + self.seen_preamble = True else: self.puty([1, ['Unknown Preamble', 'Unknown Prea.', 'U']]) self.preamble = [] - self.seen_preamble = True self.bitcount = 0 self.first_one = True @@ -227,6 +408,7 @@ def decode(self): # Throw away first detected edge as it might be mangled data. self.wait({0: 'e'}) + self.samplenum_prev_edge = self.samplenum while True: # Wait for any edge (rising or falling).