added feature to help debugging control signals
authorPurdea Andrei <andrei@purdea.ro>
Tue, 16 Feb 2021 01:47:48 +0000 (03:47 +0200)
committerPurdea Andrei <andrei@purdea.ro>
Tue, 16 Feb 2021 01:47:48 +0000 (03:47 +0200)
12 files changed:
keyboards/xwhatsit/matrix.c
keyboards/xwhatsit/matrix_manipulate.h
keyboards/xwhatsit/util/util/columntester.cpp
keyboards/xwhatsit/util/util/columntester.h
keyboards/xwhatsit/util/util/columntester.ui
keyboards/xwhatsit/util/util/device.cpp
keyboards/xwhatsit/util/util/device.h
keyboards/xwhatsit/util/util/hidthread.cpp
keyboards/xwhatsit/util/util/hidthread.h
keyboards/xwhatsit/util/util/mainwindow.cpp
keyboards/xwhatsit/util_comm.c
keyboards/xwhatsit/util_comm.h

index e1714dd..70a380a 100644 (file)
@@ -141,18 +141,25 @@ void shift_select_nothing(void)
     writePin(CAPSENSE_SHIFT_STCP, 0);
 }
 
-void shift_data(uint32_t data)
+void shift_data(uint32_t data, int data_idle, int shcp_idle, int stcp_idle)
 {
     int i;
+    writePin(CAPSENSE_SHIFT_SHCP, 0);
+    writePin(CAPSENSE_SHIFT_STCP, 0);
     for (i=SHIFT_BITS-1; i>=0; i--)
     {
         writePin(CAPSENSE_SHIFT_DIN, (data >> (SHIFT_BITS - 1)) & 1);
         writePin(CAPSENSE_SHIFT_SHCP, 1);
-        writePin(CAPSENSE_SHIFT_SHCP, 0);
+        if (!((i == 0) && (shcp_idle))) {
+            writePin(CAPSENSE_SHIFT_SHCP, 0);
+        }
         data <<= 1;
     }
     writePin(CAPSENSE_SHIFT_STCP, 1);
-    writePin(CAPSENSE_SHIFT_STCP, 0);
+    if (!stcp_idle) {
+        writePin(CAPSENSE_SHIFT_STCP, 0);
+    }
+    writePin(CAPSENSE_SHIFT_DIN, !!data_idle);
 }
 
 void shift_select_col_no_strobe(uint8_t col)
index 52c7de4..98de0c7 100644 (file)
@@ -27,7 +27,7 @@ void matrix_scan_raw(matrix_row_t current_matrix[]);
 extern uint16_t cal_thresholds[CAPSENSE_CAL_BINS];
 extern matrix_row_t assigned_to_threshold[CAPSENSE_CAL_BINS][MATRIX_ROWS];
 uint16_t measure_middle_keymap_coords(uint8_t col, uint8_t row, uint8_t time, uint8_t reps);
-void shift_data(uint32_t data);
+void shift_data(uint32_t data, int data_idle, int shcp_idle, int stcp_idle);
 void dac_write_threshold(uint16_t value);
 uint8_t test_single(uint8_t col, uint16_t time, uint8_t *interference_ptr);
 
index fe62434..1ec2e16 100644 (file)
@@ -36,9 +36,14 @@ ColumnTester::ColumnTester(HidThread &thread, std::string path, QWidget *parent)
         button->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
         button->setMinimumSize(20, 0);
         button->setCheckable(true);
+        button->setStyleSheet(":checked {background-color: #c0FFc0; color:black }");
         ui->horizontalLayout->addWidget(button);
         connect(button, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
     }
+    connect(ui->pushButton_data, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
+    connect(ui->pushButton_shcp, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
+    connect(ui->pushButton_stcp, SIGNAL(clicked()), this, SLOT(onButtonClicked()));
+    connect(&thread, &HidThread::reportControlReadback, this, &ColumnTester::onReportControlState);
     this->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
             this, SLOT(ShowContextMenu(const QPoint &)));
@@ -72,5 +77,26 @@ void ColumnTester::onButtonClicked()
             data |= 1 << i;
         }
     }
-    thread.shiftData(path, data);
+    thread.shiftData(path, data,
+                     ui->pushButton_data->isChecked(),
+                     ui->pushButton_shcp->isChecked(),
+                     ui->pushButton_stcp->isChecked());
+}
+
+void ColumnTester::onReportControlState(std::vector<uint8_t> readback)
+{
+    const bool enabled = readback.size() != 0;
+    ui->pushButton_data->setEnabled(enabled);
+    ui->pushButton_shcp->setEnabled(enabled);
+    ui->pushButton_stcp->setEnabled(enabled);
+    ui->label_control_set->setEnabled(enabled);
+    ui->label_control_readback->setEnabled(enabled);
+    if (enabled) {
+        if (readback[0]) ui->frame_data->setStyleSheet("background-color:#c0FFc0");
+        else ui->frame_data->setStyleSheet("background-color:");
+        if (readback[1]) ui->frame_shcp->setStyleSheet("background-color:#c0FFc0");
+        else ui->frame_shcp->setStyleSheet("background-color:");
+        if (readback[2]) ui->frame_stcp->setStyleSheet("background-color:#c0FFc0");
+        else ui->frame_stcp->setStyleSheet("background-color:");
+    }
 }
index 995f837..f98d033 100644 (file)
@@ -38,6 +38,7 @@ public:
 private slots:
     void onButtonClicked();
     void ShowContextMenu(const QPoint &pos);
+    void onReportControlState(std::vector<uint8_t>);
 
 private:
     Ui::ColumnTester *ui;
index c58845b..50d0884 100644 (file)
@@ -9,12 +9,12 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>807</width>
-    <height>196</height>
+    <width>664</width>
+    <height>395</height>
    </rect>
   </property>
   <property name="sizePolicy">
-   <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+   <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
     <horstretch>0</horstretch>
     <verstretch>0</verstretch>
    </sizepolicy>
@@ -38,7 +38,7 @@
    <item>
     <widget class="QLabel" name="label">
      <property name="sizePolicy">
-      <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+      <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
        <horstretch>0</horstretch>
        <verstretch>0</verstretch>
       </sizepolicy>
@@ -50,7 +50,7 @@
       </size>
      </property>
      <property name="text">
-      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;*NOTE1: The column tester is a debugging feature that allows you to set Low/High static output on each column pin. Pressed means logic high. This feature is most useful in conjunction with a voltmeter, to check for functional shift registers, and no broken or shorted column traces.&lt;/p&gt;&lt;p&gt;*NOTE2: These are physical columns, so if the keyboard skips some columns those are still listed here&lt;/p&gt;&lt;p&gt;*NOTE3: Normal keyboard input is disabled while this window is open.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;*NOTE1: The column tester is a debugging feature that allows you to set Low/High static output on each column pin. Pressed means logic high. This feature is most useful in conjunction with a voltmeter, to check for functional shift registers, and no broken or shorted column traces.&lt;/p&gt;&lt;p&gt;*NOTE2: These are physical columns, so if the keyboard skips some columns those are still listed here&lt;/p&gt;&lt;p&gt;*NOTE3: Column numbers here are not dependent on the keyboard layout. Column 1 is always the first bit of the first shift register in the chain.&lt;/p&gt;&lt;p&gt;*NOTE4: If readback differs from the set state of the control signals, then you might have a short on your control signals.&lt;/p&gt;&lt;p&gt;*NOTE5: Normal keyboard input is disabled while this window is open.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
      </property>
      <property name="scaledContents">
       <bool>false</bool>
     </widget>
    </item>
    <item>
-    <layout class="QHBoxLayout" name="horizontalLayout"/>
+    <widget class="QLabel" name="label_2">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>Columns:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+    </layout>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_control_set">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>Idle Control Signal States:</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QPushButton" name="pushButton_data">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="styleSheet">
+        <string notr="true">:checked {background-color: #c0FFc0; color:black}</string>
+       </property>
+       <property name="text">
+        <string>SER/DS/MOSI/SR_DS
+(Data to shift register)</string>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pushButton_shcp">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="styleSheet">
+        <string notr="true">:checked {background-color: #c0FFc0; color:black}</string>
+       </property>
+       <property name="text">
+        <string>SHCP/SRCLK/CLOCK/SR_SHCP
+(Shifting clock to shift register)</string>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="pushButton_stcp">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="styleSheet">
+        <string notr="true">:checked {background-color: #c0FFc0; color:black}</string>
+       </property>
+       <property name="text">
+        <string>STCP/RCLK/LOADCOL/SR_STCP
+(Storage clock for shift register)</string>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QLabel" name="label_control_readback">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>Idle Control Signal State Readback (only updated when you change something above):</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_3">
+     <item>
+      <widget class="QFrame" name="frame_data">
+       <property name="minimumSize">
+        <size>
+         <width>0</width>
+         <height>10</height>
+        </size>
+       </property>
+       <property name="styleSheet">
+        <string notr="true"/>
+       </property>
+       <property name="frameShape">
+        <enum>QFrame::StyledPanel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Raised</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QFrame" name="frame_shcp">
+       <property name="frameShape">
+        <enum>QFrame::StyledPanel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Raised</enum>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QFrame" name="frame_stcp">
+       <property name="frameShape">
+        <enum>QFrame::StyledPanel</enum>
+       </property>
+       <property name="frameShadow">
+        <enum>QFrame::Raised</enum>
+       </property>
+      </widget>
+     </item>
+    </layout>
    </item>
   </layout>
  </widget>
index e34c8f9..a3cc72b 100644 (file)
@@ -242,6 +242,53 @@ void Device::shiftData(uint32_t shdata)
     }
 }
 
+std::vector<uint8_t> Device::shiftDataExt(uint32_t shdata, bool data_idle, bool shcp_idle, bool stcp_idle)
+{
+    uint8_t data[33];
+    {
+        QMutexLocker locker(&mutex);
+        if (xwhatsit_original_firmware)
+        {
+            throw std::runtime_error("This doesn't work with xwhatsit original firmware");
+        }
+
+        data[0] = 0;
+        memcpy(data + 1, magic, sizeof(magic));
+        data[2+1] = UTIL_COMM_SHIFT_DATA_EXT;
+        data[3+1] = shdata & 0xff;
+        data[4+1] = (shdata >> 8) & 0xff;
+        data[5+1] = (shdata >> 16) & 0xff;
+        data[6+1] = (shdata >> 24) & 0xff;
+        data[7+1] = (uint8_t)data_idle;
+        data[8+1] = (uint8_t)shcp_idle;
+        data[9+1] = (uint8_t)stcp_idle;
+        if (-1==hid_write(device, data, sizeof(data)))
+        {
+            printf("hid error: %ls\n", hid_error(device));
+            throw std::runtime_error("hid_write failed to shift data");
+        }
+        if ((sizeof(data)-1)!=hid_read_timeout(device, data, sizeof(data)-1, 1000))
+        {
+            printf("hid error: %ls\n", hid_error(device));
+            throw std::runtime_error("hid_read failed while shifting data");
+        }
+        if ((data[0] != magic[0]) || (data[1] != magic[1]))
+        {
+            throw std::runtime_error("hid_read failed while shifting data -- no magic returned");
+        }
+    }
+    std::vector<uint8_t> ret;
+    if (data[2] != UTIL_COMM_RESPONSE_OK)
+    {
+        shiftData(shdata);
+        return ret;
+    }
+    ret.push_back(data[3]);
+    ret.push_back(data[4]);
+    ret.push_back(data[5]);
+    return ret;
+}
+
 void Device::disableKeyboard()
 {
     QMutexLocker locker(&mutex);
index a24cba6..7019274 100644 (file)
@@ -39,6 +39,7 @@ public:
     void assertVersionIsAtLeast(uint8_t major, uint8_t mid, uint16_t minor);
     void eraseEeprom();
     void shiftData(uint32_t shdata);
+    std::vector<uint8_t> shiftDataExt(uint32_t shdata, bool data_idle, bool shcp_idle, bool stcp_idle);
     std::vector<std::vector<uint8_t>> getThresholds();
     std::vector<uint8_t> getKeyState();
     std::vector<uint8_t> getKeyboardDetails();
index 9d66144..f400719 100644 (file)
@@ -102,10 +102,13 @@ void HidThread::closeMonitoredDevice()
     condition.wakeOne();
 }
 
-void HidThread::shiftData(std::string path, uint32_t shdata)
+void HidThread::shiftData(std::string path, uint32_t shdata, bool data_idle, bool shcp_idle, bool stcp_idle)
 {
     QMutexLocker locker(&mutex);
     this->shift_data = shdata;
+    this->shift_data_idle = data_idle;
+    this->shift_shcp_idle = shcp_idle;
+    this->shift_stcp_idle = stcp_idle;
     this->shift_data_path = path;
     condition.wakeOne();
 }
@@ -161,6 +164,7 @@ void HidThread::run()
         mutex.lock();
         bool l_keep_scanning, l_abort, nothing_to_do, l_autoenter_mode, l_close_monitored_device, l_set_dac;
         uint32_t l_shift_data;
+        bool l_shift_data_idle, l_shift_shcp_idle, l_shift_stcp_idle;
         std::string l_enter_bootloader_path, l_monitor_path, l_erase_eeprom_path, l_signal_level_path, l_shift_data_path, l_enable_keyboard_path, l_monitor_row_state_path;
         uint16_t l_set_dac_value;
         do {
@@ -174,6 +178,9 @@ void HidThread::run()
             l_erase_eeprom_path = this->erase_eeprom_path;
             l_shift_data_path = shift_data_path;
             l_shift_data = shift_data;
+            l_shift_data_idle = shift_data_idle;
+            l_shift_shcp_idle = shift_shcp_idle;
+            l_shift_stcp_idle = shift_stcp_idle;
             l_enable_keyboard_path = enable_keyboard_path;
             l_set_dac = set_dac;
             l_set_dac_value = set_dac_value;
@@ -218,7 +225,7 @@ void HidThread::run()
                 QScopedPointer<Device> dev(comm.open(l_shift_data_path));
                 dev.data()->disableKeyboard();
                 dev.data()->assertVersionIsAtLeast(2, 0, 3);
-                dev.data()->shiftData(l_shift_data);
+                emit reportControlReadback(dev.data()->shiftDataExt(l_shift_data, l_shift_data_idle, l_shift_shcp_idle, l_shift_stcp_idle));
             } catch (const std::runtime_error &e1) {
                 emit reportError(e1.what());
             }
index c4ffa57..9f2066e 100644 (file)
@@ -40,7 +40,7 @@ public:
     void signalLevel(std::string path);
     void eraseEeprom(std::string path);
     void closeMonitoredDevice();
-    void shiftData(std::string path, uint32_t shdata);
+    void shiftData(std::string path, uint32_t shdata, bool data_idle, bool shcp_idle, bool stcp_idle);
     void enableKeyboard(std::string path);
     void setDacValue(uint16_t value);
     Device *connectToDevice(std::string path);
@@ -55,6 +55,7 @@ signals:
     void reportMonitorError(std::string error_message);
     void reportSignalLevel(std::vector<uint16_t>);
     void reportRowsAndMaxDac(uint8_t rows, uint16_t max_dac);
+    void reportControlReadback(std::vector<uint8_t>);
 
 protected:
     void run() override;
@@ -65,6 +66,9 @@ private:
     bool autoenter_mode;
     bool close_monitored_device;
     uint32_t shift_data;
+    bool shift_data_idle;
+    bool shift_shcp_idle;
+    bool shift_stcp_idle;
     std::string shift_data_path;
     std::string enter_bootloader_path;
     std::string monitor_path;
index 46eb01c..9c8ac97 100644 (file)
@@ -187,11 +187,11 @@ void MainWindow::on_columnTesterButton_clicked()
     ColumnTester *ctw = new ColumnTester(thread, path, this);
     ctw->setAttribute(Qt::WA_DeleteOnClose);
     bool previousScanning = thread.setScanning(false);
-    thread.shiftData(path, 0);
+    thread.shiftData(path, 0, 0, 0 ,0);
     this->setEnabled(false);
     ctw->setEnabled(true);
     ctw->exec();
-    thread.shiftData(path, 0);
+    thread.shiftData(path, 0, 0, 0, 0);
     this->setEnabled(true);
     thread.enableKeyboard(path);
     thread.setScanning(previousScanning);
index cf30479..fd6db37 100644 (file)
@@ -180,13 +180,26 @@ void raw_hid_receive(uint8_t *data, uint8_t length) {
                 break;
             }
         case UTIL_COMM_SHIFT_DATA:
+        case UTIL_COMM_SHIFT_DATA_EXT:
             {
                 response[2] = UTIL_COMM_RESPONSE_OK;
                 uint32_t shdata = (((uint32_t)(data[3])) << 0) |
                                 (((uint32_t)(data[4])) << 8) |
                                 (((uint32_t)(data[5])) << 16) |
                                 (((uint32_t)(data[6])) << 24);
-                shift_data(shdata);
+                int data_idle = 0;
+                int shcp_idle = 0;
+                int stcp_idle = 0;
+                if (data[2] == UTIL_COMM_SHIFT_DATA_EXT)
+                {
+                    data_idle = data[7];
+                    shcp_idle = data[8];
+                    stcp_idle = data[9];
+                }
+                shift_data(shdata, data_idle, shcp_idle, stcp_idle);
+                response[3] = readPin(CAPSENSE_SHIFT_DIN);
+                response[4] = readPin(CAPSENSE_SHIFT_SHCP);
+                response[5] = readPin(CAPSENSE_SHIFT_STCP);
                 break;
             }
         case UTIL_COMM_SET_DAC_VALUE:
index 1a9931d..fd9e74e 100644 (file)
@@ -38,6 +38,7 @@ enum command {
     UTIL_COMM_SHIFT_DATA,
     UTIL_COMM_SET_DAC_VALUE,
     UTIL_COMM_GET_ROW_STATE,
+    UTIL_COMM_SHIFT_DATA_EXT,
 };
 
 enum response {