mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -05:00
Deep redesign: Better support for FCD dongles #8: removed old FCD plugin
This commit is contained in:
parent
a2a9c45210
commit
0345969124
@ -1,55 +0,0 @@
|
|||||||
project(fcd)
|
|
||||||
|
|
||||||
set(fcd_SOURCES
|
|
||||||
fcdgui.cpp
|
|
||||||
fcdinput.cpp
|
|
||||||
fcdplugin.cpp
|
|
||||||
fcdserializer.cpp
|
|
||||||
fcdthread.cpp
|
|
||||||
hid-libusb.c
|
|
||||||
)
|
|
||||||
|
|
||||||
set(fcd_HEADERS
|
|
||||||
fcdgui.h
|
|
||||||
fcdinput.h
|
|
||||||
fcdplugin.h
|
|
||||||
fcdserializer.h
|
|
||||||
fcdthread.h
|
|
||||||
qthid.h
|
|
||||||
hid-libusb.h
|
|
||||||
hidapi.h
|
|
||||||
)
|
|
||||||
|
|
||||||
set(fcd_FORMS
|
|
||||||
fcdgui.ui
|
|
||||||
)
|
|
||||||
|
|
||||||
include_directories(
|
|
||||||
.
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
${CMAKE_SOURCE_DIR}/include
|
|
||||||
${CMAKE_SOURCE_DIR}/include-gpl
|
|
||||||
)
|
|
||||||
|
|
||||||
#include(${QT_USE_FILE})
|
|
||||||
add_definitions(${QT_DEFINITIONS})
|
|
||||||
add_definitions(-DQT_PLUGIN)
|
|
||||||
add_definitions(-DQT_SHARED)
|
|
||||||
|
|
||||||
#qt4_wrap_cpp(fcd_HEADERS_MOC ${fcd_HEADERS})
|
|
||||||
qt5_wrap_ui(fcd_FORMS_HEADERS ${fcd_FORMS})
|
|
||||||
|
|
||||||
add_library(inputfcd SHARED
|
|
||||||
${fcd_SOURCES}
|
|
||||||
${fcd_HEADERS_MOC}
|
|
||||||
${fcd_FORMS_HEADERS}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(inputfcd
|
|
||||||
${QT_LIBRARIES}
|
|
||||||
${LIBUSB_LIBRARIES}
|
|
||||||
asound
|
|
||||||
sdrbase
|
|
||||||
)
|
|
||||||
|
|
||||||
qt5_use_modules(inputfcd Core Widgets OpenGL Multimedia)
|
|
@ -1,88 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
* This file is part of Qthid.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Howard Long, G6LVB
|
|
||||||
* CopyRight (C) 2011 Alexandru Csete, OZ9AEC
|
|
||||||
* Mario Lorenz, DL5MLO
|
|
||||||
*
|
|
||||||
* Qthid is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Qthid is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Qthid. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#ifndef FCD_H
|
|
||||||
#define FCD_H 1
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef FCD
|
|
||||||
#define EXTERN
|
|
||||||
#define ASSIGN (x) =x
|
|
||||||
#else
|
|
||||||
#define EXTERN extern
|
|
||||||
#define ASSIGN(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define FCD_API_EXPORT __declspec(dllexport)
|
|
||||||
#define FCD_API_CALL _stdcall
|
|
||||||
#else
|
|
||||||
#define FCD_API_EXPORT
|
|
||||||
#define FCD_API_CALL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief FCD mode enumeration. */
|
|
||||||
typedef enum {
|
|
||||||
FCD_MODE_NONE, /*!< No FCD detected. */
|
|
||||||
FCD_MODE_DEAD,
|
|
||||||
FCD_MODE_BL, /*!< FCD present in bootloader mode. */
|
|
||||||
FCD_MODE_APP /*!< FCD present in aplpication mode. */
|
|
||||||
} FCD_MODE_ENUM; // The current mode of the FCD: none inserted, in bootloader mode or in normal application mode
|
|
||||||
|
|
||||||
/** \brief FCD capabilities that depend on both hardware and firmware. */
|
|
||||||
typedef struct {
|
|
||||||
unsigned char hasBiasT; /*!< Whether FCD has hardware bias tee (1=yes, 0=no) */
|
|
||||||
unsigned char hasCellBlock; /*!< Whether FCD has cellular blocking. */
|
|
||||||
} FCD_CAPS_STRUCT;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Application functions */
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdGetMode(void);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdGetFwVerStr(char *str);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdGetCaps(FCD_CAPS_STRUCT *fcd_caps);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdGetCapsStr(char *caps_str);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppReset(void);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppSetFreqkHz(int nFreq);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppSetFreq(int nFreq);
|
|
||||||
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppSetParam(uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppGetParam(uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len);
|
|
||||||
|
|
||||||
|
|
||||||
/* Bootloader functions */
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdBlReset(void);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdBlErase(void);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdBlWriteFirmware(char *pc, int64_t n64Size);
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdBlVerifyFirmware(char *pc, int64_t n64Size);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // FCD_H
|
|
@ -1,149 +0,0 @@
|
|||||||
#include "fcdgui.h"
|
|
||||||
#include "ui_fcdgui.h"
|
|
||||||
#include "plugin/pluginapi.h"
|
|
||||||
#include "gui/colormapper.h"
|
|
||||||
#include "dsp/dspengine.h"
|
|
||||||
|
|
||||||
FCDGui::FCDGui(PluginAPI* pluginAPI, QWidget* parent) :
|
|
||||||
QWidget(parent),
|
|
||||||
ui(new Ui::FCDGui),
|
|
||||||
m_pluginAPI(pluginAPI),
|
|
||||||
m_settings(),
|
|
||||||
m_sampleSource(NULL)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
|
||||||
ui->centerFrequency->setValueRange(7, 64000U, 1700000U);
|
|
||||||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
|
||||||
displaySettings();
|
|
||||||
|
|
||||||
m_sampleSource = new FCDInput();
|
|
||||||
DSPEngine::instance()->setSource(m_sampleSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
FCDGui::~FCDGui()
|
|
||||||
{
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::destroy()
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::setName(const QString& name)
|
|
||||||
{
|
|
||||||
setObjectName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString FCDGui::getName() const
|
|
||||||
{
|
|
||||||
return objectName();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::resetToDefaults()
|
|
||||||
{
|
|
||||||
m_settings.resetToDefaults();
|
|
||||||
displaySettings();
|
|
||||||
sendSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray FCDGui::serialize() const
|
|
||||||
{
|
|
||||||
return m_settings.serialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FCDGui::deserialize(const QByteArray& data)
|
|
||||||
{
|
|
||||||
if(m_settings.deserialize(data))
|
|
||||||
{
|
|
||||||
displaySettings();
|
|
||||||
sendSettings();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resetToDefaults();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FCDGui::handleMessage(const Message& message)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::displaySettings()
|
|
||||||
{
|
|
||||||
ui->centerFrequency->setValue(m_settings.centerFrequency / 1000);
|
|
||||||
ui->checkBoxR->setChecked(m_settings.range);
|
|
||||||
ui->checkBoxG->setChecked(m_settings.gain);
|
|
||||||
ui->checkBoxB->setChecked(m_settings.bias);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::sendSettings()
|
|
||||||
{
|
|
||||||
if(!m_updateTimer.isActive())
|
|
||||||
m_updateTimer.start(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::on_centerFrequency_changed(quint64 value)
|
|
||||||
{
|
|
||||||
m_settings.centerFrequency = value * 1000;
|
|
||||||
sendSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::updateHardware()
|
|
||||||
{
|
|
||||||
FCDInput::MsgConfigureFCD* message = FCDInput::MsgConfigureFCD::create(m_settings);
|
|
||||||
m_sampleSource->getInputMessageQueue()->push(message);
|
|
||||||
m_updateTimer.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::on_checkBoxR_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (state == Qt::Checked) // FIXME: this is for the Pro+ version only!
|
|
||||||
{
|
|
||||||
ui->centerFrequency->setValueRange(7, 150U, 240000U);
|
|
||||||
ui->centerFrequency->setValue(7000);
|
|
||||||
m_settings.centerFrequency = 7000 * 1000;
|
|
||||||
m_settings.range = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui->centerFrequency->setValueRange(7, 64000U, 1900000U);
|
|
||||||
ui->centerFrequency->setValue(435000);
|
|
||||||
m_settings.centerFrequency = 435000 * 1000;
|
|
||||||
m_settings.range = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::on_checkBoxG_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (state == Qt::Checked)
|
|
||||||
{
|
|
||||||
m_settings.gain = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_settings.gain = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDGui::on_checkBoxB_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (state == Qt::Checked)
|
|
||||||
{
|
|
||||||
m_settings.bias = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_settings.bias = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sendSettings();
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
#ifndef INCLUDE_FCDGUI_H
|
|
||||||
#define INCLUDE_FCDGUI_H
|
|
||||||
|
|
||||||
#include <QTimer>
|
|
||||||
#include "plugin/plugingui.h"
|
|
||||||
#include "fcdinput.h"
|
|
||||||
|
|
||||||
class PluginAPI;
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class FCDGui;
|
|
||||||
}
|
|
||||||
|
|
||||||
class FCDGui : public QWidget, public PluginGUI {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FCDGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
|
||||||
virtual ~FCDGui();
|
|
||||||
void destroy();
|
|
||||||
|
|
||||||
void setName(const QString& name);
|
|
||||||
QString getName() const;
|
|
||||||
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::FCDGui* ui;
|
|
||||||
|
|
||||||
PluginAPI* m_pluginAPI;
|
|
||||||
FCDInput::Settings m_settings;
|
|
||||||
QTimer m_updateTimer;
|
|
||||||
std::vector<int> m_gains;
|
|
||||||
SampleSource* m_sampleSource;
|
|
||||||
|
|
||||||
void displaySettings();
|
|
||||||
void sendSettings();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void on_centerFrequency_changed(quint64 value);
|
|
||||||
void on_checkBoxR_stateChanged(int state);
|
|
||||||
void on_checkBoxG_stateChanged(int state);
|
|
||||||
void on_checkBoxB_stateChanged(int state);
|
|
||||||
void updateHardware();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_FCDGUI_H
|
|
@ -1,144 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>FCDGui</class>
|
|
||||||
<widget class="QWidget" name="FCDGui">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>132</width>
|
|
||||||
<height>119</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>FunCubeDongle</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="ValueDial" name="centerFrequency" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>32</width>
|
|
||||||
<height>16</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<family>Monospace</family>
|
|
||||||
<pointsize>20</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="focusPolicy">
|
|
||||||
<enum>Qt::StrongFocus</enum>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Tuner center frequency in kHz</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="horizontalSpacer_2">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_4">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayoutR">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="checkBoxR">
|
|
||||||
<property name="text">
|
|
||||||
<string>Low Range</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayoutG">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="checkBoxG">
|
|
||||||
<property name="text">
|
|
||||||
<string>LNA Gain</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="checkBoxB">
|
|
||||||
<property name="text">
|
|
||||||
<string>Bias T</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>ValueDial</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>gui/valuedial.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
@ -1,305 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
* This file is part of Qthid.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Howard Long, G6LVB
|
|
||||||
* CopyRight (C) 2011 Alexandru Csete, OZ9AEC
|
|
||||||
* Mario Lorenz, DL5MLO
|
|
||||||
*
|
|
||||||
* Qthid is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Qthid is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Qthid. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
***************************************************************************/
|
|
||||||
#ifndef FCDHIDCMD_H
|
|
||||||
#define FCD_HID_CMD_H 1
|
|
||||||
|
|
||||||
|
|
||||||
/* Commands applicable in bootloader mode */
|
|
||||||
#define FCD_CMD_BL_QUERY 1 /*!< Returns string with "FCDAPP version". */
|
|
||||||
#define FCD_CMD_BL_RESET 8 /*!< Reset to application mode. */
|
|
||||||
#define FCD_CMD_BL_ERASE 24 /*!< Erase firmware from FCD flash. */
|
|
||||||
#define FCD_CMD_BL_SET_BYTE_ADDR 25 /*!< TBD */
|
|
||||||
#define FCD_CMD_BL_GET_BYTE_ADDR_RANGE 26 /*!< Get address range. */
|
|
||||||
#define FCD_CMD_BL_WRITE_FLASH_BLOCK 27 /*!< Write flash block. */
|
|
||||||
#define FCD_CMD_BL_READ_FLASH_BLOCK 28 /*!< Read flash block. */
|
|
||||||
|
|
||||||
/* Commands applicable in application mode */
|
|
||||||
#define FCD_CMD_APP_SET_FREQ_KHZ 100 /*!< Send with 3 byte unsigned little endian frequency in kHz. */
|
|
||||||
#define FCD_CMD_APP_SET_FREQ_HZ 101 /*!< Send with 4 byte unsigned little endian frequency in Hz, returns with actual frequency set in Hz */
|
|
||||||
#define FCD_CMD_APP_GET_FREQ_HZ 102 /*!< Returns 4 byte unsigned little endian frequency in Hz. */
|
|
||||||
|
|
||||||
#define FCD_CMD_APP_GET_IF_RSSI 104 /*!< Supposed to return 1 byte unsigned IF RSSI (-35dBm=0, -10dBm=70) but it is not functional. */
|
|
||||||
#define FCD_CMD_APP_GET_PLL_LOCK 105 /*!< Returns 1 bit, true if locked. */
|
|
||||||
|
|
||||||
#define FCD_CMD_APP_SET_DC_CORR 106 /*!< Send with 2 byte unsigned I DC correction followed by 2 byte unsigned Q DC correction. 32768 is the default centre value. */
|
|
||||||
#define FCD_CMD_APP_GET_DC_CORR 107 /*!< Returns 2 byte unsigned I DC correction followed by 2 byte unsigned Q DC correction. 32768 is the default centre value. */
|
|
||||||
#define FCD_CMD_APP_SET_IQ_CORR 108 /*!< Send with 2 byte signed phase correction followed by 2 byte unsigned gain correction. 0 is the default centre value for phase correction, 32768 is the default centre value for gain. */
|
|
||||||
#define FCD_CMD_APP_GET_IQ_CORR 109 /*!< Returns 2 byte signed phase correction followed by 2 byte unsigned gain correction. 0 is the default centre value for phase correction, 32768 is the default centre value for gain. */
|
|
||||||
|
|
||||||
#define FCD_CMD_APP_SET_LNA_GAIN 110 /*!< Send a 1 byte value, see enums for reference. */
|
|
||||||
#define FCD_CMD_APP_SET_LNA_ENHANCE 111
|
|
||||||
#define FCD_CMD_APP_SET_BAND 112
|
|
||||||
#define FCD_CMD_APP_SET_RF_FILTER 113
|
|
||||||
#define FCD_CMD_APP_SET_MIXER_GAIN 114
|
|
||||||
#define FCD_CMD_APP_SET_BIAS_CURRENT 115
|
|
||||||
#define FCD_CMD_APP_SET_MIXER_FILTER 116
|
|
||||||
#define FCD_CMD_APP_SET_IF_GAIN1 117
|
|
||||||
#define FCD_CMD_APP_SET_IF_GAIN_MODE 118
|
|
||||||
#define FCD_CMD_APP_SET_IF_RC_FILTER 119
|
|
||||||
#define FCD_CMD_APP_SET_IF_GAIN2 120
|
|
||||||
#define FCD_CMD_APP_SET_IF_GAIN3 121
|
|
||||||
#define FCD_CMD_APP_SET_IF_FILTER 122
|
|
||||||
#define FCD_CMD_APP_SET_IF_GAIN4 123
|
|
||||||
#define FCD_CMD_APP_SET_IF_GAIN5 124
|
|
||||||
#define FCD_CMD_APP_SET_IF_GAIN6 125
|
|
||||||
#define FCD_CMD_APP_SET_BIAS_TEE 126 /*!< Bias T for ext LNA. Send with one byte: 1=ON, 0=OFF. */
|
|
||||||
|
|
||||||
#define FCD_CMD_APP_GET_LNA_GAIN 150 // Retrieve a 1 byte value, see enums for reference
|
|
||||||
#define FCD_CMD_APP_GET_LNA_ENHANCE 151
|
|
||||||
#define FCD_CMD_APP_GET_BAND 152
|
|
||||||
#define FCD_CMD_APP_GET_RF_FILTER 153
|
|
||||||
#define FCD_CMD_APP_GET_MIXER_GAIN 154
|
|
||||||
#define FCD_CMD_APP_GET_BIAS_CURRENT 155
|
|
||||||
#define FCD_CMD_APP_GET_MIXER_FILTER 156
|
|
||||||
#define FCD_CMD_APP_GET_IF_GAIN1 157
|
|
||||||
#define FCD_CMD_APP_GET_IF_GAIN_MODE 158
|
|
||||||
#define FCD_CMD_APP_GET_IF_RC_FILTER 159
|
|
||||||
#define FCD_CMD_APP_GET_IF_GAIN2 160
|
|
||||||
#define FCD_CMD_APP_GET_IF_GAIN3 161
|
|
||||||
#define FCD_CMD_APP_GET_IF_FILTER 162
|
|
||||||
#define FCD_CMD_APP_GET_IF_GAIN4 163
|
|
||||||
#define FCD_CMD_APP_GET_IF_GAIN5 164
|
|
||||||
#define FCD_CMD_APP_GET_IF_GAIN6 165
|
|
||||||
#define FCD_CMD_APP_GET_BIAS_TEE 166 /*!< Bias T. 1=ON, 0=OFF. */
|
|
||||||
|
|
||||||
#define FCD_CMD_APP_SEND_I2C_BYTE 200
|
|
||||||
#define FCD_CMD_APP_RECV_I2C_BYTE 201
|
|
||||||
|
|
||||||
#define FCD_CMD_APP_RESET 255 // Reset to bootloader
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TLGE_N5_0DB=0,
|
|
||||||
TLGE_N2_5DB=1,
|
|
||||||
TLGE_P0_0DB=4,
|
|
||||||
TLGE_P2_5DB=5,
|
|
||||||
TLGE_P5_0DB=6,
|
|
||||||
TLGE_P7_5DB=7,
|
|
||||||
TLGE_P10_0DB=8,
|
|
||||||
TLGE_P12_5DB=9,
|
|
||||||
TLGE_P15_0DB=10,
|
|
||||||
TLGE_P17_5DB=11,
|
|
||||||
TLGE_P20_0DB=12,
|
|
||||||
TLGE_P25_0DB=13,
|
|
||||||
TLGE_P30_0DB=14
|
|
||||||
} TUNER_LNA_GAIN_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TLEE_OFF=0,
|
|
||||||
TLEE_0=1,
|
|
||||||
TLEE_1=3,
|
|
||||||
TLEE_2=5,
|
|
||||||
TLEE_3=7
|
|
||||||
} TUNER_LNA_ENHANCE_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TBE_VHF2,
|
|
||||||
TBE_VHF3,
|
|
||||||
TBE_UHF,
|
|
||||||
TBE_LBAND
|
|
||||||
} TUNER_BAND_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
// Band 0, VHF II
|
|
||||||
TRFE_LPF268MHZ=0,
|
|
||||||
TRFE_LPF299MHZ=8,
|
|
||||||
// Band 1, VHF III
|
|
||||||
TRFE_LPF509MHZ=0,
|
|
||||||
TRFE_LPF656MHZ=8,
|
|
||||||
// Band 2, UHF
|
|
||||||
TRFE_BPF360MHZ=0,
|
|
||||||
TRFE_BPF380MHZ=1,
|
|
||||||
TRFE_BPF405MHZ=2,
|
|
||||||
TRFE_BPF425MHZ=3,
|
|
||||||
TRFE_BPF450MHZ=4,
|
|
||||||
TRFE_BPF475MHZ=5,
|
|
||||||
TRFE_BPF505MHZ=6,
|
|
||||||
TRFE_BPF540MHZ=7,
|
|
||||||
TRFE_BPF575MHZ=8,
|
|
||||||
TRFE_BPF615MHZ=9,
|
|
||||||
TRFE_BPF670MHZ=10,
|
|
||||||
TRFE_BPF720MHZ=11,
|
|
||||||
TRFE_BPF760MHZ=12,
|
|
||||||
TRFE_BPF840MHZ=13,
|
|
||||||
TRFE_BPF890MHZ=14,
|
|
||||||
TRFE_BPF970MHZ=15,
|
|
||||||
// Band 2, L band
|
|
||||||
TRFE_BPF1300MHZ=0,
|
|
||||||
TRFE_BPF1320MHZ=1,
|
|
||||||
TRFE_BPF1360MHZ=2,
|
|
||||||
TRFE_BPF1410MHZ=3,
|
|
||||||
TRFE_BPF1445MHZ=4,
|
|
||||||
TRFE_BPF1460MHZ=5,
|
|
||||||
TRFE_BPF1490MHZ=6,
|
|
||||||
TRFE_BPF1530MHZ=7,
|
|
||||||
TRFE_BPF1560MHZ=8,
|
|
||||||
TRFE_BPF1590MHZ=9,
|
|
||||||
TRFE_BPF1640MHZ=10,
|
|
||||||
TRFE_BPF1660MHZ=11,
|
|
||||||
TRFE_BPF1680MHZ=12,
|
|
||||||
TRFE_BPF1700MHZ=13,
|
|
||||||
TRFE_BPF1720MHZ=14,
|
|
||||||
TRFE_BPF1750MHZ=15
|
|
||||||
} TUNER_RF_FILTER_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TMGE_P4_0DB=0,
|
|
||||||
TMGE_P12_0DB=1
|
|
||||||
} TUNER_MIXER_GAIN_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TBCE_LBAND=0,
|
|
||||||
TBCE_1=1,
|
|
||||||
TBCE_2=2,
|
|
||||||
TBCE_VUBAND=3
|
|
||||||
} TUNER_BIAS_CURRENT_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TMFE_27_0MHZ=0,
|
|
||||||
TMFE_4_6MHZ=8,
|
|
||||||
TMFE_4_2MHZ=9,
|
|
||||||
TMFE_3_8MHZ=10,
|
|
||||||
TMFE_3_4MHZ=11,
|
|
||||||
TMFE_3_0MHZ=12,
|
|
||||||
TMFE_2_7MHZ=13,
|
|
||||||
TMFE_2_3MHZ=14,
|
|
||||||
TMFE_1_9MHZ=15
|
|
||||||
} TUNER_MIXER_FILTER_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIG1E_N3_0DB=0,
|
|
||||||
TIG1E_P6_0DB=1
|
|
||||||
} TUNER_IF_GAIN1_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIGME_LINEARITY=0,
|
|
||||||
TIGME_SENSITIVITY=1
|
|
||||||
} TUNER_IF_GAIN_MODE_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIRFE_21_4MHZ=0,
|
|
||||||
TIRFE_21_0MHZ=1,
|
|
||||||
TIRFE_17_6MHZ=2,
|
|
||||||
TIRFE_14_7MHZ=3,
|
|
||||||
TIRFE_12_4MHZ=4,
|
|
||||||
TIRFE_10_6MHZ=5,
|
|
||||||
TIRFE_9_0MHZ=6,
|
|
||||||
TIRFE_7_7MHZ=7,
|
|
||||||
TIRFE_6_4MHZ=8,
|
|
||||||
TIRFE_5_3MHZ=9,
|
|
||||||
TIRFE_4_4MHZ=10,
|
|
||||||
TIRFE_3_4MHZ=11,
|
|
||||||
TIRFE_2_6MHZ=12,
|
|
||||||
TIRFE_1_8MHZ=13,
|
|
||||||
TIRFE_1_2MHZ=14,
|
|
||||||
TIRFE_1_0MHZ=15
|
|
||||||
} TUNER_IF_RC_FILTER_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIG2E_P0_0DB=0,
|
|
||||||
TIG2E_P3_0DB=1,
|
|
||||||
TIG2E_P6_0DB=2,
|
|
||||||
TIG2E_P9_0DB=3
|
|
||||||
} TUNER_IF_GAIN2_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIG3E_P0_0DB=0,
|
|
||||||
TIG3E_P3_0DB=1,
|
|
||||||
TIG3E_P6_0DB=2,
|
|
||||||
TIG3E_P9_0DB=3
|
|
||||||
} TUNER_IF_GAIN3_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIG4E_P0_0DB=0,
|
|
||||||
TIG4E_P1_0DB=1,
|
|
||||||
TIG4E_P2_0DB=2
|
|
||||||
} TUNER_IF_GAIN4_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIFE_5_50MHZ=0,
|
|
||||||
TIFE_5_30MHZ=1,
|
|
||||||
TIFE_5_00MHZ=2,
|
|
||||||
TIFE_4_80MHZ=3,
|
|
||||||
TIFE_4_60MHZ=4,
|
|
||||||
TIFE_4_40MHZ=5,
|
|
||||||
TIFE_4_30MHZ=6,
|
|
||||||
TIFE_4_10MHZ=7,
|
|
||||||
TIFE_3_90MHZ=8,
|
|
||||||
TIFE_3_80MHZ=9,
|
|
||||||
TIFE_3_70MHZ=10,
|
|
||||||
TIFE_3_60MHZ=11,
|
|
||||||
TIFE_3_40MHZ=12,
|
|
||||||
TIFE_3_30MHZ=13,
|
|
||||||
TIFE_3_20MHZ=14,
|
|
||||||
TIFE_3_10MHZ=15,
|
|
||||||
TIFE_3_00MHZ=16,
|
|
||||||
TIFE_2_95MHZ=17,
|
|
||||||
TIFE_2_90MHZ=18,
|
|
||||||
TIFE_2_80MHZ=19,
|
|
||||||
TIFE_2_75MHZ=20,
|
|
||||||
TIFE_2_70MHZ=21,
|
|
||||||
TIFE_2_60MHZ=22,
|
|
||||||
TIFE_2_55MHZ=23,
|
|
||||||
TIFE_2_50MHZ=24,
|
|
||||||
TIFE_2_45MHZ=25,
|
|
||||||
TIFE_2_40MHZ=26,
|
|
||||||
TIFE_2_30MHZ=27,
|
|
||||||
TIFE_2_28MHZ=28,
|
|
||||||
TIFE_2_24MHZ=29,
|
|
||||||
TIFE_2_20MHZ=30,
|
|
||||||
TIFE_2_15MHZ=31
|
|
||||||
} TUNER_IF_FILTER_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIG5E_P3_0DB=0,
|
|
||||||
TIG5E_P6_0DB=1,
|
|
||||||
TIG5E_P9_0DB=2,
|
|
||||||
TIG5E_P12_0DB=3,
|
|
||||||
TIG5E_P15_0DB=4
|
|
||||||
} TUNER_IF_GAIN5_ENUM;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
TIG6E_P3_0DB=0,
|
|
||||||
TIG6E_P6_0DB=1,
|
|
||||||
TIG6E_P9_0DB=2,
|
|
||||||
TIG6E_P12_0DB=3,
|
|
||||||
TIG6E_P15_0DB=4
|
|
||||||
} TUNER_IF_GAIN6_ENUM;
|
|
||||||
|
|
||||||
|
|
||||||
#endif // FCDHIDCMD_H
|
|
@ -1,248 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
|
||||||
// written by Christian Daniel //
|
|
||||||
// //
|
|
||||||
// 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 //
|
|
||||||
// the Free Software Foundation as version 3 of the License, or //
|
|
||||||
// //
|
|
||||||
// This program is distributed in the hope that it will be useful, //
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
||||||
// GNU General Public License V3 for more details. //
|
|
||||||
// //
|
|
||||||
// You should have received a copy of the GNU General Public License //
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// FIXME: FCD is handled very badly!
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <string.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "fcdinput.h"
|
|
||||||
#include "fcdthread.h"
|
|
||||||
#include "fcdgui.h"
|
|
||||||
#include "qthid.h"
|
|
||||||
#include "dsp/dspcommands.h"
|
|
||||||
#include "fcdserializer.h"
|
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(FCDInput::MsgConfigureFCD, Message)
|
|
||||||
//MESSAGE_CLASS_DEFINITION(FCDInput::MsgReportFCD, Message)
|
|
||||||
|
|
||||||
FCDInput::Settings::Settings() :
|
|
||||||
centerFrequency(435000000),
|
|
||||||
range(0),
|
|
||||||
gain(0),
|
|
||||||
bias(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDInput::Settings::resetToDefaults()
|
|
||||||
{
|
|
||||||
centerFrequency = 435000000;
|
|
||||||
range = 0;
|
|
||||||
gain = 0;
|
|
||||||
bias = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray FCDInput::Settings::serialize() const
|
|
||||||
{
|
|
||||||
FCDSerializer::FCDData data;
|
|
||||||
|
|
||||||
data.m_data.m_lnaGain = gain;
|
|
||||||
data.m_data.m_frequency = centerFrequency;
|
|
||||||
data.m_range = range;
|
|
||||||
data.m_bias = bias;
|
|
||||||
|
|
||||||
QByteArray byteArray;
|
|
||||||
|
|
||||||
FCDSerializer::writeSerializedData(data, byteArray);
|
|
||||||
|
|
||||||
return byteArray;
|
|
||||||
|
|
||||||
/*
|
|
||||||
SimpleSerializer s(1);
|
|
||||||
s.writeU64(1, centerFrequency);
|
|
||||||
s.writeS32(2, range);
|
|
||||||
s.writeS32(3, gain);
|
|
||||||
s.writeS32(4, bias);
|
|
||||||
return s.final();*/
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FCDInput::Settings::deserialize(const QByteArray& serializedData)
|
|
||||||
{
|
|
||||||
FCDSerializer::FCDData data;
|
|
||||||
|
|
||||||
bool valid = FCDSerializer::readSerializedData(serializedData, data);
|
|
||||||
|
|
||||||
gain = data.m_data.m_lnaGain;
|
|
||||||
centerFrequency = data.m_data.m_frequency;
|
|
||||||
range = data.m_range;
|
|
||||||
bias = data.m_bias;
|
|
||||||
|
|
||||||
return valid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
SimpleDeserializer d(data);
|
|
||||||
|
|
||||||
if (d.isValid() && d.getVersion() == 1)
|
|
||||||
{
|
|
||||||
d.readU64(1, ¢erFrequency, 435000000);
|
|
||||||
d.readS32(2, &range, 0);
|
|
||||||
d.readS32(3, &gain, 0);
|
|
||||||
d.readS32(4, &bias, 0);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetToDefaults();
|
|
||||||
return true;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
FCDInput::FCDInput() :
|
|
||||||
m_settings(),
|
|
||||||
m_FCDThread(0),
|
|
||||||
m_deviceDescription()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FCDInput::~FCDInput()
|
|
||||||
{
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FCDInput::init(const Message& cmd)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FCDInput::start(int device)
|
|
||||||
{
|
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
|
||||||
|
|
||||||
if (m_FCDThread)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apply settings before streaming to avoid bus contention;
|
|
||||||
* there is very little spare bandwidth on a full speed USB device.
|
|
||||||
* Failure is harmless if no device is found */
|
|
||||||
|
|
||||||
applySettings(m_settings, true);
|
|
||||||
|
|
||||||
if(!m_sampleFifo.setSize(96000*4))
|
|
||||||
{
|
|
||||||
qCritical("Could not allocate SampleFifo");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_FCDThread = new FCDThread(&m_sampleFifo)) == NULL)
|
|
||||||
{
|
|
||||||
qFatal("out of memory");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug("FCDInput::start");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDInput::stop()
|
|
||||||
{
|
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
|
||||||
|
|
||||||
if (m_FCDThread)
|
|
||||||
{
|
|
||||||
m_FCDThread->stopWork();
|
|
||||||
// wait for thread to quit ?
|
|
||||||
delete m_FCDThread;
|
|
||||||
m_FCDThread = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_deviceDescription.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString& FCDInput::getDeviceDescription() const
|
|
||||||
{
|
|
||||||
return m_deviceDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FCDInput::getSampleRate() const
|
|
||||||
{
|
|
||||||
return 192000;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 FCDInput::getCenterFrequency() const
|
|
||||||
{
|
|
||||||
return m_settings.centerFrequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FCDInput::handleMessage(const Message& message)
|
|
||||||
{
|
|
||||||
if(MsgConfigureFCD::match(message))
|
|
||||||
{
|
|
||||||
qDebug() << "FCDInput::handleMessage: MsgConfigureFCD";
|
|
||||||
MsgConfigureFCD& conf = (MsgConfigureFCD&) message;
|
|
||||||
applySettings(conf.getSettings(), false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDInput::applySettings(const Settings& settings, bool force)
|
|
||||||
{
|
|
||||||
bool signalChange = false;
|
|
||||||
|
|
||||||
if ((m_settings.centerFrequency != settings.centerFrequency) || force)
|
|
||||||
{
|
|
||||||
qDebug() << "FCDInput::applySettings: fc: " << settings.centerFrequency;
|
|
||||||
m_settings.centerFrequency = settings.centerFrequency;
|
|
||||||
set_center_freq((double) m_settings.centerFrequency);
|
|
||||||
signalChange = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_settings.gain != settings.gain) || force)
|
|
||||||
{
|
|
||||||
set_lna_gain(settings.gain > 0);
|
|
||||||
m_settings.gain = settings.gain;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((m_settings.bias != settings.bias) || force)
|
|
||||||
{
|
|
||||||
set_bias_t(settings.bias > 0);
|
|
||||||
m_settings.bias = settings.bias;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signalChange)
|
|
||||||
{
|
|
||||||
DSPSignalNotification *notif = new DSPSignalNotification(192000, m_settings.centerFrequency);
|
|
||||||
getOutputMessageQueue()->push(notif);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDInput::set_center_freq(double freq)
|
|
||||||
{
|
|
||||||
if (fcdAppSetFreq(freq) == FCD_MODE_NONE)
|
|
||||||
{
|
|
||||||
qDebug("No FCD HID found for frquency change");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDInput::set_bias_t(bool on)
|
|
||||||
{
|
|
||||||
quint8 cmd = on ? 1 : 0;
|
|
||||||
|
|
||||||
fcdAppSetParam(FCD_CMD_APP_SET_BIAS_TEE, &cmd, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDInput::set_lna_gain(bool on)
|
|
||||||
{
|
|
||||||
quint8 cmd = on ? 1 : 0;
|
|
||||||
|
|
||||||
fcdAppSetParam(FCD_CMD_APP_SET_LNA_GAIN, &cmd, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
|
||||||
// written by Christian Daniel //
|
|
||||||
// //
|
|
||||||
// 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 //
|
|
||||||
// the Free Software Foundation as version 3 of the License, or //
|
|
||||||
// //
|
|
||||||
// This program is distributed in the hope that it will be useful, //
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
||||||
// GNU General Public License V3 for more details. //
|
|
||||||
// //
|
|
||||||
// You should have received a copy of the GNU General Public License //
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef INCLUDE_FCDINPUT_H
|
|
||||||
#define INCLUDE_FCDINPUT_H
|
|
||||||
|
|
||||||
#include "dsp/samplesource.h"
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
struct fcd_buffer {
|
|
||||||
void *start;
|
|
||||||
std::size_t length;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FCDThread;
|
|
||||||
|
|
||||||
class FCDInput : public SampleSource {
|
|
||||||
public:
|
|
||||||
struct Settings {
|
|
||||||
Settings();
|
|
||||||
quint64 centerFrequency;
|
|
||||||
qint32 range;
|
|
||||||
qint32 gain;
|
|
||||||
qint32 bias;
|
|
||||||
void resetToDefaults();
|
|
||||||
QByteArray serialize() const;
|
|
||||||
bool deserialize(const QByteArray& data);
|
|
||||||
};
|
|
||||||
|
|
||||||
class MsgConfigureFCD : public Message {
|
|
||||||
MESSAGE_CLASS_DECLARATION
|
|
||||||
|
|
||||||
public:
|
|
||||||
const Settings& getSettings() const { return m_settings; }
|
|
||||||
|
|
||||||
static MsgConfigureFCD* create(const Settings& settings)
|
|
||||||
{
|
|
||||||
return new MsgConfigureFCD(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Settings m_settings;
|
|
||||||
|
|
||||||
MsgConfigureFCD(const Settings& settings) :
|
|
||||||
Message(),
|
|
||||||
m_settings(settings)
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
FCDInput();
|
|
||||||
virtual ~FCDInput();
|
|
||||||
|
|
||||||
virtual bool init(const Message& cmd);
|
|
||||||
virtual bool start(int device);
|
|
||||||
virtual void stop();
|
|
||||||
|
|
||||||
virtual const QString& getDeviceDescription() const;
|
|
||||||
virtual int getSampleRate() const;
|
|
||||||
virtual quint64 getCenterFrequency() const;
|
|
||||||
|
|
||||||
virtual bool handleMessage(const Message& message);
|
|
||||||
|
|
||||||
void set_center_freq(double freq);
|
|
||||||
void set_bias_t(bool on);
|
|
||||||
void set_lna_gain(bool on);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void applySettings(const Settings& settings, bool force);
|
|
||||||
|
|
||||||
QMutex m_mutex;
|
|
||||||
Settings m_settings;
|
|
||||||
FCDThread* m_FCDThread;
|
|
||||||
QString m_deviceDescription;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_FCD_H
|
|
@ -1,55 +0,0 @@
|
|||||||
#include <QtPlugin>
|
|
||||||
#include <QAction>
|
|
||||||
#include "plugin/pluginapi.h"
|
|
||||||
#include "util/simpleserializer.h"
|
|
||||||
#include "fcdplugin.h"
|
|
||||||
#include "fcdgui.h"
|
|
||||||
|
|
||||||
const PluginDescriptor FCDPlugin::m_pluginDescriptor = {
|
|
||||||
QString("FunCube Input"),
|
|
||||||
QString("V20"),
|
|
||||||
QString("(c) John Greb"),
|
|
||||||
QString("http://funcubedongle.com"),
|
|
||||||
true,
|
|
||||||
QString("github.com/hexameron/rtl-sdrangelove")
|
|
||||||
};
|
|
||||||
|
|
||||||
FCDPlugin::FCDPlugin(QObject* parent) :
|
|
||||||
QObject(parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const PluginDescriptor& FCDPlugin::getPluginDescriptor() const
|
|
||||||
{
|
|
||||||
return m_pluginDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDPlugin::initPlugin(PluginAPI* pluginAPI)
|
|
||||||
{
|
|
||||||
m_pluginAPI = pluginAPI;
|
|
||||||
|
|
||||||
m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.fcd", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginInterface::SampleSourceDevices FCDPlugin::enumSampleSources()
|
|
||||||
{
|
|
||||||
SampleSourceDevices result;
|
|
||||||
|
|
||||||
QString displayedName(QString("Funcube Dongle #1"));
|
|
||||||
SimpleSerializer s(1);
|
|
||||||
s.writeS32(1, 0);
|
|
||||||
result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.fcd", s.final()));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginGUI* FCDPlugin::createSampleSourcePluginGUI(const QString& sourceName, const QByteArray& address)
|
|
||||||
{
|
|
||||||
if(sourceName == "org.osmocom.sdr.samplesource.fcd") {
|
|
||||||
FCDGui* gui = new FCDGui(m_pluginAPI);
|
|
||||||
m_pluginAPI->setInputGUI(gui);
|
|
||||||
return gui;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
#ifndef INCLUDE_FCDPLUGIN_H
|
|
||||||
#define INCLUDE_FCDPLUGIN_H
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include "plugin/plugininterface.h"
|
|
||||||
|
|
||||||
class FCDPlugin : public QObject, public PluginInterface {
|
|
||||||
Q_OBJECT
|
|
||||||
Q_INTERFACES(PluginInterface)
|
|
||||||
Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.fcd")
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FCDPlugin(QObject* parent = NULL);
|
|
||||||
|
|
||||||
const PluginDescriptor& getPluginDescriptor() const;
|
|
||||||
void initPlugin(PluginAPI* pluginAPI);
|
|
||||||
|
|
||||||
SampleSourceDevices enumSampleSources();
|
|
||||||
PluginGUI* createSampleSourcePluginGUI(const QString& sourceName, const QByteArray& address);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static const PluginDescriptor m_pluginDescriptor;
|
|
||||||
|
|
||||||
PluginAPI* m_pluginAPI;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // INCLUDE_FCDPLUGIN_H
|
|
@ -1,68 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
|
||||||
// //
|
|
||||||
// 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 //
|
|
||||||
// the Free Software Foundation as version 3 of the License, or //
|
|
||||||
// //
|
|
||||||
// This program is distributed in the hope that it will be useful, //
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
||||||
// GNU General Public License V3 for more details. //
|
|
||||||
// //
|
|
||||||
// You should have received a copy of the GNU General Public License //
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include "fcdserializer.h"
|
|
||||||
|
|
||||||
void FCDSerializer::writeSerializedData(const FCDData& data, QByteArray& serializedData)
|
|
||||||
{
|
|
||||||
QByteArray sampleSourceSerialized;
|
|
||||||
SampleSourceSerializer::writeSerializedData(data.m_data, sampleSourceSerialized);
|
|
||||||
|
|
||||||
SimpleSerializer s(1);
|
|
||||||
|
|
||||||
s.writeBlob(1, sampleSourceSerialized);
|
|
||||||
s.writeS32(2, data.m_bias);
|
|
||||||
s.writeS32(3, data.m_range);
|
|
||||||
|
|
||||||
serializedData = s.final();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FCDSerializer::readSerializedData(const QByteArray& serializedData, FCDData& data)
|
|
||||||
{
|
|
||||||
bool valid = SampleSourceSerializer::readSerializedData(serializedData, data.m_data);
|
|
||||||
|
|
||||||
QByteArray sampleSourceSerialized;
|
|
||||||
|
|
||||||
SimpleDeserializer d(serializedData);
|
|
||||||
|
|
||||||
if (!d.isValid())
|
|
||||||
{
|
|
||||||
setDefaults(data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d.getVersion() == SampleSourceSerializer::getSerializerVersion())
|
|
||||||
{
|
|
||||||
int intval;
|
|
||||||
|
|
||||||
d.readBlob(1, &sampleSourceSerialized);
|
|
||||||
d.readS32(2, &data.m_bias);
|
|
||||||
d.readS32(3, &data.m_range);
|
|
||||||
|
|
||||||
return SampleSourceSerializer::readSerializedData(sampleSourceSerialized, data.m_data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setDefaults(data);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDSerializer::setDefaults(FCDData& data)
|
|
||||||
{
|
|
||||||
data.m_range = 0;
|
|
||||||
data.m_bias = 0;
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
|
||||||
// //
|
|
||||||
// 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 //
|
|
||||||
// the Free Software Foundation as version 3 of the License, or //
|
|
||||||
// //
|
|
||||||
// This program is distributed in the hope that it will be useful, //
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
||||||
// GNU General Public License V3 for more details. //
|
|
||||||
// //
|
|
||||||
// You should have received a copy of the GNU General Public License //
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_
|
|
||||||
#define PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_
|
|
||||||
|
|
||||||
#include "util/samplesourceserializer.h"
|
|
||||||
|
|
||||||
class FCDSerializer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
struct FCDData
|
|
||||||
{
|
|
||||||
SampleSourceSerializer::Data m_data;
|
|
||||||
qint32 m_bias;
|
|
||||||
qint32 m_range;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void writeSerializedData(const FCDData& data, QByteArray& serializedData);
|
|
||||||
static bool readSerializedData(const QByteArray& serializedData, FCDData& data);
|
|
||||||
static void setDefaults(FCDData& data);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_ */
|
|
@ -1,141 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
|
||||||
// written by Christian Daniel //
|
|
||||||
// //
|
|
||||||
// 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 //
|
|
||||||
// the Free Software Foundation as version 3 of the License, or //
|
|
||||||
// //
|
|
||||||
// This program is distributed in the hope that it will be useful, //
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
||||||
// GNU General Public License V3 for more details. //
|
|
||||||
// //
|
|
||||||
// You should have received a copy of the GNU General Public License //
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include "fcdthread.h"
|
|
||||||
#include "dsp/samplefifo.h"
|
|
||||||
|
|
||||||
FCDThread::FCDThread(SampleFifo* sampleFifo, QObject* parent) :
|
|
||||||
QThread(parent),
|
|
||||||
fcd_handle(NULL),
|
|
||||||
m_running(false),
|
|
||||||
m_convertBuffer(FCD_BLOCKSIZE),
|
|
||||||
m_sampleFifo(sampleFifo)
|
|
||||||
{
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
|
|
||||||
FCDThread::~FCDThread()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDThread::stopWork()
|
|
||||||
{
|
|
||||||
m_running = false;
|
|
||||||
wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDThread::run()
|
|
||||||
{
|
|
||||||
if ( !OpenSource("hw:CARD=V20") ) // FIXME: pro is V10 pro+ is V20. Make it an option
|
|
||||||
return;
|
|
||||||
// TODO: fallback to original fcd
|
|
||||||
|
|
||||||
m_running = true;
|
|
||||||
while(m_running) {
|
|
||||||
if ( work(FCD_BLOCKSIZE) < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CloseSource();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FCDThread::OpenSource(const char* cardname)
|
|
||||||
{
|
|
||||||
bool fail = false;
|
|
||||||
snd_pcm_hw_params_t* params;
|
|
||||||
//fcd_rate = FCDPP_RATE;
|
|
||||||
//fcd_channels =2;
|
|
||||||
//fcd_format = SND_PCM_SFMT_U16_LE;
|
|
||||||
snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE;
|
|
||||||
|
|
||||||
if (fcd_handle)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0)
|
|
||||||
{
|
|
||||||
qCritical("FCDThread::OpenSource: cannot open %s", cardname);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
snd_pcm_hw_params_alloca(¶ms);
|
|
||||||
|
|
||||||
if (snd_pcm_hw_params_any(fcd_handle, params) < 0)
|
|
||||||
{
|
|
||||||
qCritical("FCDThread::OpenSource: snd_pcm_hw_params_any failed");
|
|
||||||
fail = true;
|
|
||||||
}
|
|
||||||
else if (snd_pcm_hw_params(fcd_handle, params) < 0)
|
|
||||||
{
|
|
||||||
qCritical("FCDThread::OpenSource: snd_pcm_hw_params failed");
|
|
||||||
fail = true;
|
|
||||||
// TODO: check actual samplerate, may be crippled firmware
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (snd_pcm_start(fcd_handle) < 0)
|
|
||||||
{
|
|
||||||
qCritical("FCDThread::OpenSource: snd_pcm_start failed");
|
|
||||||
fail = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fail)
|
|
||||||
{
|
|
||||||
qCritical("Funcube Dongle stream start failed");
|
|
||||||
snd_pcm_close( fcd_handle );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
qDebug("Funcube stream started");
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDThread::CloseSource()
|
|
||||||
{
|
|
||||||
if (fcd_handle)
|
|
||||||
{
|
|
||||||
snd_pcm_close( fcd_handle );
|
|
||||||
}
|
|
||||||
|
|
||||||
fcd_handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int FCDThread::work(int n_items)
|
|
||||||
{
|
|
||||||
int l;
|
|
||||||
SampleVector::iterator it;
|
|
||||||
void *out;
|
|
||||||
|
|
||||||
it = m_convertBuffer.begin();
|
|
||||||
out = (void *)&it[0];
|
|
||||||
l = snd_pcm_mmap_readi(fcd_handle, out, (snd_pcm_uframes_t)n_items);
|
|
||||||
if (l > 0)
|
|
||||||
m_sampleFifo->write(it, it + l);
|
|
||||||
if (l == -EPIPE) {
|
|
||||||
qDebug("FCD: Overrun detected");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
|
||||||
// written by Christian Daniel //
|
|
||||||
// //
|
|
||||||
// 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 //
|
|
||||||
// the Free Software Foundation as version 3 of the License, or //
|
|
||||||
// //
|
|
||||||
// This program is distributed in the hope that it will be useful, //
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
||||||
// GNU General Public License V3 for more details. //
|
|
||||||
// //
|
|
||||||
// You should have received a copy of the GNU General Public License //
|
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
#ifndef INCLUDE_FCDTHREAD_H
|
|
||||||
#define INCLUDE_FCDTHREAD_H
|
|
||||||
|
|
||||||
#include <QThread>
|
|
||||||
#include <QMutex>
|
|
||||||
#include <QWaitCondition>
|
|
||||||
#include "dsp/samplefifo.h"
|
|
||||||
#include "dsp/inthalfbandfilter.h"
|
|
||||||
#include <alsa/asoundlib.h>
|
|
||||||
|
|
||||||
#define FCDPP_RATE 192000 // FIXME: The Pro / Pro+ switch should be handled better than this!
|
|
||||||
#define FCD_BLOCKSIZE (1<<11)
|
|
||||||
|
|
||||||
class FCDThread : public QThread {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
FCDThread(SampleFifo* sampleFifo, QObject* parent = NULL);
|
|
||||||
~FCDThread();
|
|
||||||
|
|
||||||
void stopWork();
|
|
||||||
bool OpenSource(const char *filename);
|
|
||||||
void CloseSource();
|
|
||||||
int work(int n_items);
|
|
||||||
private:
|
|
||||||
snd_pcm_format_t fcd_format;
|
|
||||||
snd_pcm_t* fcd_handle;
|
|
||||||
|
|
||||||
QMutex m_startWaitMutex;
|
|
||||||
QWaitCondition m_startWaiter;
|
|
||||||
bool m_running;
|
|
||||||
|
|
||||||
SampleVector m_convertBuffer;
|
|
||||||
SampleFifo* m_sampleFifo;
|
|
||||||
|
|
||||||
void run();
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif // INCLUDE_FCDTHREAD_H
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,387 +0,0 @@
|
|||||||
/*******************************************************
|
|
||||||
HIDAPI - Multi-Platform library for
|
|
||||||
communication with HID devices.
|
|
||||||
|
|
||||||
Alan Ott
|
|
||||||
Signal 11 Software
|
|
||||||
|
|
||||||
8/22/2009
|
|
||||||
|
|
||||||
Copyright 2009, All Rights Reserved.
|
|
||||||
|
|
||||||
At the discretion of the user of this library,
|
|
||||||
this software may be licensed under the terms of the
|
|
||||||
GNU General Public License v3, a BSD-Style license, or the
|
|
||||||
original HIDAPI license as outlined in the LICENSE.txt,
|
|
||||||
LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt
|
|
||||||
files located at the root of the source distribution.
|
|
||||||
These files may also be found in the public source
|
|
||||||
code repository located at:
|
|
||||||
http://github.com/signal11/hidapi .
|
|
||||||
********************************************************/
|
|
||||||
|
|
||||||
/** @file
|
|
||||||
* @defgroup API hidapi API
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef HIDAPI_H__
|
|
||||||
#define HIDAPI_H__
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define HID_API_EXPORT __declspec(dllexport)
|
|
||||||
#define HID_API_CALL
|
|
||||||
#else
|
|
||||||
#define HID_API_EXPORT /**< API export macro */
|
|
||||||
#define HID_API_CALL /**< API call macro */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
struct hid_device_;
|
|
||||||
typedef struct hid_device_ hid_device; /**< opaque hidapi structure */
|
|
||||||
|
|
||||||
/** hidapi info structure */
|
|
||||||
struct hid_device_info {
|
|
||||||
/** Platform-specific device path */
|
|
||||||
char *path;
|
|
||||||
/** Device Vendor ID */
|
|
||||||
unsigned short vendor_id;
|
|
||||||
/** Device Product ID */
|
|
||||||
unsigned short product_id;
|
|
||||||
/** Serial Number */
|
|
||||||
wchar_t *serial_number;
|
|
||||||
/** Device Release Number in binary-coded decimal,
|
|
||||||
also known as Device Version Number */
|
|
||||||
unsigned short release_number;
|
|
||||||
/** Manufacturer String */
|
|
||||||
wchar_t *manufacturer_string;
|
|
||||||
/** Product string */
|
|
||||||
wchar_t *product_string;
|
|
||||||
/** Usage Page for this Device/Interface
|
|
||||||
(Windows/Mac only). */
|
|
||||||
unsigned short usage_page;
|
|
||||||
/** Usage for this Device/Interface
|
|
||||||
(Windows/Mac only).*/
|
|
||||||
unsigned short usage;
|
|
||||||
/** The USB interface which this logical device
|
|
||||||
represents. Valid on both Linux implementations
|
|
||||||
in all cases, and valid on the Windows implementation
|
|
||||||
only if the device contains more than one interface. */
|
|
||||||
int interface_number;
|
|
||||||
|
|
||||||
/** Pointer to the next device */
|
|
||||||
struct hid_device_info *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @brief Initialize the HIDAPI library.
|
|
||||||
|
|
||||||
This function initializes the HIDAPI library. Calling it is not
|
|
||||||
strictly necessary, as it will be called automatically by
|
|
||||||
hid_enumerate() and any of the hid_open_*() functions if it is
|
|
||||||
needed. This function should be called at the beginning of
|
|
||||||
execution however, if there is a chance of HIDAPI handles
|
|
||||||
being opened by different threads simultaneously.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns 0 on success and -1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_init(void);
|
|
||||||
|
|
||||||
/** @brief Finalize the HIDAPI library.
|
|
||||||
|
|
||||||
This function frees all of the static data associated with
|
|
||||||
HIDAPI. It should be called at the end of execution to avoid
|
|
||||||
memory leaks.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns 0 on success and -1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_exit(void);
|
|
||||||
|
|
||||||
/** @brief Enumerate the HID Devices.
|
|
||||||
|
|
||||||
This function returns a linked list of all the HID devices
|
|
||||||
attached to the system which match vendor_id and product_id.
|
|
||||||
If @p vendor_id is set to 0 then any vendor matches.
|
|
||||||
If @p product_id is set to 0 then any product matches.
|
|
||||||
If @p vendor_id and @p product_id are both set to 0, then
|
|
||||||
all HID devices will be returned.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param vendor_id The Vendor ID (VID) of the types of device
|
|
||||||
to open.
|
|
||||||
@param product_id The Product ID (PID) of the types of
|
|
||||||
device to open.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns a pointer to a linked list of type
|
|
||||||
struct #hid_device, containing information about the HID devices
|
|
||||||
attached to the system, or NULL in the case of failure. Free
|
|
||||||
this linked list by calling hid_free_enumeration().
|
|
||||||
*/
|
|
||||||
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id);
|
|
||||||
|
|
||||||
/** @brief Free an enumeration Linked List
|
|
||||||
|
|
||||||
This function frees a linked list created by hid_enumerate().
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param devs Pointer to a list of struct_device returned from
|
|
||||||
hid_enumerate().
|
|
||||||
*/
|
|
||||||
void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs);
|
|
||||||
|
|
||||||
/** @brief Open a HID device using a Vendor ID (VID), Product ID
|
|
||||||
(PID) and optionally a serial number.
|
|
||||||
|
|
||||||
If @p serial_number is NULL, the first device with the
|
|
||||||
specified VID and PID is opened.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param vendor_id The Vendor ID (VID) of the device to open.
|
|
||||||
@param product_id The Product ID (PID) of the device to open.
|
|
||||||
@param serial_number The Serial Number of the device to open
|
|
||||||
(Optionally NULL).
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns a pointer to a #hid_device object on
|
|
||||||
success or NULL on failure.
|
|
||||||
*/
|
|
||||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
|
|
||||||
|
|
||||||
/** @brief Open a HID device by its path name.
|
|
||||||
|
|
||||||
The path name be determined by calling hid_enumerate(), or a
|
|
||||||
platform-specific path name can be used (eg: /dev/hidraw0 on
|
|
||||||
Linux).
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param path The path name of the device to open
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns a pointer to a #hid_device object on
|
|
||||||
success or NULL on failure.
|
|
||||||
*/
|
|
||||||
HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path);
|
|
||||||
|
|
||||||
/** @brief Write an Output report to a HID device.
|
|
||||||
|
|
||||||
The first byte of @p data[] must contain the Report ID. For
|
|
||||||
devices which only support a single report, this must be set
|
|
||||||
to 0x0. The remaining bytes contain the report data. Since
|
|
||||||
the Report ID is mandatory, calls to hid_write() will always
|
|
||||||
contain one more byte than the report contains. For example,
|
|
||||||
if a hid report is 16 bytes long, 17 bytes must be passed to
|
|
||||||
hid_write(), the Report ID (or 0x0, for devices with a
|
|
||||||
single report), followed by the report data (16 bytes). In
|
|
||||||
this example, the length passed in would be 17.
|
|
||||||
|
|
||||||
hid_write() will send the data on the first OUT endpoint, if
|
|
||||||
one exists. If it does not, it will send the data through
|
|
||||||
the Control Endpoint (Endpoint 0).
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param data The data to send, including the report number as
|
|
||||||
the first byte.
|
|
||||||
@param length The length in bytes of the data to send.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns the actual number of bytes written and
|
|
||||||
-1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length);
|
|
||||||
|
|
||||||
/** @brief Read an Input report from a HID device with timeout.
|
|
||||||
|
|
||||||
Input reports are returned
|
|
||||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
|
||||||
contain the Report number if the device uses numbered reports.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param data A buffer to put the read data into.
|
|
||||||
@param length The number of bytes to read. For devices with
|
|
||||||
multiple reports, make sure to read an extra byte for
|
|
||||||
the report number.
|
|
||||||
@param milliseconds timeout in milliseconds or -1 for blocking wait.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns the actual number of bytes read and
|
|
||||||
-1 on error. If no packet was available to be read within
|
|
||||||
the timeout period, this function returns 0.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds);
|
|
||||||
|
|
||||||
/** @brief Read an Input report from a HID device.
|
|
||||||
|
|
||||||
Input reports are returned
|
|
||||||
to the host through the INTERRUPT IN endpoint. The first byte will
|
|
||||||
contain the Report number if the device uses numbered reports.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param data A buffer to put the read data into.
|
|
||||||
@param length The number of bytes to read. For devices with
|
|
||||||
multiple reports, make sure to read an extra byte for
|
|
||||||
the report number.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns the actual number of bytes read and
|
|
||||||
-1 on error. If no packet was available to be read and
|
|
||||||
the handle is in non-blocking mode, this function returns 0.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length);
|
|
||||||
|
|
||||||
/** @brief Set the device handle to be non-blocking.
|
|
||||||
|
|
||||||
In non-blocking mode calls to hid_read() will return
|
|
||||||
immediately with a value of 0 if there is no data to be
|
|
||||||
read. In blocking mode, hid_read() will wait (block) until
|
|
||||||
there is data to read before returning.
|
|
||||||
|
|
||||||
Nonblocking can be turned on and off at any time.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param nonblock enable or not the nonblocking reads
|
|
||||||
- 1 to enable nonblocking
|
|
||||||
- 0 to disable nonblocking.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns 0 on success and -1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock);
|
|
||||||
|
|
||||||
/** @brief Send a Feature report to the device.
|
|
||||||
|
|
||||||
Feature reports are sent over the Control endpoint as a
|
|
||||||
Set_Report transfer. The first byte of @p data[] must
|
|
||||||
contain the Report ID. For devices which only support a
|
|
||||||
single report, this must be set to 0x0. The remaining bytes
|
|
||||||
contain the report data. Since the Report ID is mandatory,
|
|
||||||
calls to hid_send_feature_report() will always contain one
|
|
||||||
more byte than the report contains. For example, if a hid
|
|
||||||
report is 16 bytes long, 17 bytes must be passed to
|
|
||||||
hid_send_feature_report(): the Report ID (or 0x0, for
|
|
||||||
devices which do not use numbered reports), followed by the
|
|
||||||
report data (16 bytes). In this example, the length passed
|
|
||||||
in would be 17.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param data The data to send, including the report number as
|
|
||||||
the first byte.
|
|
||||||
@param length The length in bytes of the data to send, including
|
|
||||||
the report number.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns the actual number of bytes written and
|
|
||||||
-1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length);
|
|
||||||
|
|
||||||
/** @brief Get a feature report from a HID device.
|
|
||||||
|
|
||||||
Make sure to set the first byte of @p data[] to the Report
|
|
||||||
ID of the report to be read. Make sure to allow space for
|
|
||||||
this extra byte in @p data[].
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param data A buffer to put the read data into, including
|
|
||||||
the Report ID. Set the first byte of @p data[] to the
|
|
||||||
Report ID of the report to be read.
|
|
||||||
@param length The number of bytes to read, including an
|
|
||||||
extra byte for the report ID. The buffer can be longer
|
|
||||||
than the actual report.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns the number of bytes read and
|
|
||||||
-1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length);
|
|
||||||
|
|
||||||
/** @brief Close a HID device.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
*/
|
|
||||||
void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device);
|
|
||||||
|
|
||||||
/** @brief Get The Manufacturer String from a HID device.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param string A wide string buffer to put the data into.
|
|
||||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns 0 on success and -1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen);
|
|
||||||
|
|
||||||
/** @brief Get The Product String from a HID device.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param string A wide string buffer to put the data into.
|
|
||||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns 0 on success and -1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen);
|
|
||||||
|
|
||||||
/** @brief Get The Serial Number String from a HID device.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param string A wide string buffer to put the data into.
|
|
||||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns 0 on success and -1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen);
|
|
||||||
|
|
||||||
/** @brief Get a string from a HID device, based on its string index.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
@param string_index The index of the string to get.
|
|
||||||
@param string A wide string buffer to put the data into.
|
|
||||||
@param maxlen The length of the buffer in multiples of wchar_t.
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns 0 on success and -1 on error.
|
|
||||||
*/
|
|
||||||
int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen);
|
|
||||||
|
|
||||||
/** @brief Get a string describing the last error which occurred.
|
|
||||||
|
|
||||||
@ingroup API
|
|
||||||
@param device A device handle returned from hid_open().
|
|
||||||
|
|
||||||
@returns
|
|
||||||
This function returns a string containing the last error
|
|
||||||
which occurred or NULL if none has occurred.
|
|
||||||
*/
|
|
||||||
HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,913 +0,0 @@
|
|||||||
/***************************************************************************
|
|
||||||
* This file is part of Qthid.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010 Howard Long, G6LVB
|
|
||||||
* CopyRight (C) 2011 Alexandru Csete, OZ9AEC
|
|
||||||
* Mario Lorenz, DL5MLO
|
|
||||||
*
|
|
||||||
* Qthid is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Qthid is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Qthid. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
***************************************************************************/
|
|
||||||
|
|
||||||
#define FCD
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "hidapi.h"
|
|
||||||
#include "fcd.h"
|
|
||||||
#include "fcdhidcmd.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define TRUE true
|
|
||||||
#define FALSE false
|
|
||||||
typedef bool BOOL;
|
|
||||||
|
|
||||||
|
|
||||||
#define FCDPP // FIXME: the Pro / Pro+ switch should be handled better than this!
|
|
||||||
const unsigned short _usVID=0x04D8; /*!< USB vendor ID. */
|
|
||||||
#ifdef FCDPP
|
|
||||||
const unsigned short _usPID=0xFB31; /*!< USB product ID. */
|
|
||||||
#else
|
|
||||||
const unsigned short _usPID=0xFB56; /*!< USB product ID. */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int whichdongle=0;
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Open FCD device.
|
|
||||||
* \return Pointer to the FCD HID device or NULL if none found
|
|
||||||
*
|
|
||||||
* This function looks for FCD devices connected to the computer and
|
|
||||||
* opens the first one found.
|
|
||||||
*/
|
|
||||||
static hid_device *fcdOpen(void)
|
|
||||||
{
|
|
||||||
struct hid_device_info *phdi=NULL;
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
char *pszPath=NULL;
|
|
||||||
|
|
||||||
phdi=hid_enumerate(_usVID,_usPID);
|
|
||||||
|
|
||||||
int which=whichdongle;
|
|
||||||
while (phdi && which) {
|
|
||||||
phdi=phdi->next;
|
|
||||||
which--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phdi==NULL)
|
|
||||||
{
|
|
||||||
return NULL; // No FCD device found
|
|
||||||
}
|
|
||||||
|
|
||||||
pszPath=strdup(phdi->path);
|
|
||||||
if (pszPath==NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hid_free_enumeration(phdi);
|
|
||||||
phdi=NULL;
|
|
||||||
|
|
||||||
if ((phd=hid_open_path(pszPath)) == NULL)
|
|
||||||
{
|
|
||||||
free(pszPath);
|
|
||||||
pszPath=NULL;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pszPath);
|
|
||||||
pszPath=NULL;
|
|
||||||
|
|
||||||
return phd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Close FCD HID device. */
|
|
||||||
static void fcdClose(hid_device *phd)
|
|
||||||
{
|
|
||||||
hid_close(phd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Get FCD mode.
|
|
||||||
* \return The current FCD mode.
|
|
||||||
* \sa FCD_MODE_ENUM
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdGetMode(void)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE;
|
|
||||||
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_DEAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a BL Query Command */
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_QUERY;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
/* first check status bytes then check which mode */
|
|
||||||
if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) {
|
|
||||||
|
|
||||||
/* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/
|
|
||||||
if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) {
|
|
||||||
fcd_mode = FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
/* In application mode we have "FCDAPP_18.06" where the number is the FW version */
|
|
||||||
else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) {
|
|
||||||
fcd_mode = FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
/* either no FCD or firmware less than 18f */
|
|
||||||
else {
|
|
||||||
fcd_mode = FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fcd_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Get FCD firmware version as string.
|
|
||||||
* \param str The returned vesion number as a 0 terminated string (must be pre-allocated)
|
|
||||||
* \return The current FCD mode.
|
|
||||||
* \sa FCD_MODE_ENUM
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdGetFwVerStr(char *str)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE;
|
|
||||||
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a BL Query Command */
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_QUERY;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
/* first check status bytes then check which mode */
|
|
||||||
if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) {
|
|
||||||
|
|
||||||
/* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/
|
|
||||||
if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) {
|
|
||||||
fcd_mode = FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
/* In application mode we have "FCDAPP_18.06" where the number is the FW version */
|
|
||||||
else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) {
|
|
||||||
strncpy(str, (char *)(aucBufIn+9), 5);
|
|
||||||
str[5] = 0;
|
|
||||||
fcd_mode = FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
/* either no FCD or firmware less than 18f */
|
|
||||||
else {
|
|
||||||
fcd_mode = FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fcd_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Get hardware and firmware dependent FCD capabilities.
|
|
||||||
* \param fcd_caps Pointer to an FCD_CAPS_STRUCT
|
|
||||||
* \return The current FCD mode.
|
|
||||||
*
|
|
||||||
* This function queries the FCD and extracts the hardware and firmware dependent
|
|
||||||
* capabilities. Currently these capabilities are:
|
|
||||||
* - Bias T (available since S/N TBD)
|
|
||||||
* - Cellular block (the certified version of the FCD)
|
|
||||||
* When the FCD is in application mode, the string returned by the query command is
|
|
||||||
* (starting at index 2):
|
|
||||||
* FCDAPP 18.08 Brd 1.0 No blk
|
|
||||||
* 1.0 means no bias tee, 1.1 means there is a bias tee
|
|
||||||
* 'No blk' means it is not cellular blocked.
|
|
||||||
*
|
|
||||||
* Ref: http://uk.groups.yahoo.com/group/FCDevelopment/message/303
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdGetCaps(FCD_CAPS_STRUCT *fcd_caps)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE;
|
|
||||||
|
|
||||||
/* clear output buffer */
|
|
||||||
fcd_caps->hasBiasT = 0;
|
|
||||||
fcd_caps->hasCellBlock = 0;
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a BL Query Command */
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_QUERY;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
/* first check status bytes then check which mode */
|
|
||||||
if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) {
|
|
||||||
|
|
||||||
/* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/
|
|
||||||
if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) {
|
|
||||||
fcd_mode = FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
/* In application mode we have "FCDAPP 18.08 Brd 1.0 No blk" (see API doc) */
|
|
||||||
else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) {
|
|
||||||
|
|
||||||
/* Bias T */
|
|
||||||
fcd_caps->hasBiasT = (aucBufIn[21] == '1') ? 1 : 0;
|
|
||||||
|
|
||||||
/* cellular block */
|
|
||||||
if (strncmp((char *)(aucBufIn+23), "No blk", 6) == 0) {
|
|
||||||
fcd_caps->hasCellBlock = 0;
|
|
||||||
} else {
|
|
||||||
fcd_caps->hasCellBlock = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fcd_mode = FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
/* either no FCD or firmware less than 18f */
|
|
||||||
else {
|
|
||||||
fcd_mode = FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fcd_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Get hardware and firmware dependent FCD capabilities as string.
|
|
||||||
* \param caps_str Pointer to a pre-allocated string buffer where the info will be copied.
|
|
||||||
* \return The current FCD mode.
|
|
||||||
*
|
|
||||||
* This function queries the FCD and copies the returned string into the caps_str parameter.
|
|
||||||
* THe return buffer must be at least 28 characters.
|
|
||||||
* When the FCD is in application mode, the string returned by the query command is
|
|
||||||
* (starting at index 2):
|
|
||||||
* FCDAPP 18.08 Brd 1.0 No blk
|
|
||||||
* 1.0 means no bias tee, 1.1 means there is a bias tee
|
|
||||||
* 'No blk' means it is not cellular blocked.
|
|
||||||
*
|
|
||||||
* Ref: http://uk.groups.yahoo.com/group/FCDevelopment/message/303
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdGetCapsStr(char *caps_str)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
FCD_MODE_ENUM fcd_mode = FCD_MODE_NONE;
|
|
||||||
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a BL Query Command */
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_QUERY;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
/* first check status bytes then check which mode */
|
|
||||||
if (aucBufIn[0]==FCD_CMD_BL_QUERY && aucBufIn[1]==1) {
|
|
||||||
|
|
||||||
/* In bootloader mode we have the string "FCDBL" starting at acBufIn[2] **/
|
|
||||||
if (strncmp((char *)(aucBufIn+2), "FCDBL", 5) == 0) {
|
|
||||||
fcd_mode = FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
/* In application mode we have "FCDAPP 18.08 Brd 1.0 No blk" (see API doc) */
|
|
||||||
else if (strncmp((char *)(aucBufIn+2), "FCDAPP", 6) == 0) {
|
|
||||||
|
|
||||||
strncpy(caps_str, (char *)(aucBufIn+2), 27);
|
|
||||||
caps_str[27] = 0;
|
|
||||||
|
|
||||||
fcd_mode = FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
/* either no FCD or firmware less than 18f */
|
|
||||||
else {
|
|
||||||
fcd_mode = FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fcd_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Reset FCD to bootloader mode.
|
|
||||||
* \return FCD_MODE_NONE
|
|
||||||
*
|
|
||||||
* This function is used to switch the FCD into bootloader mode in which
|
|
||||||
* various firmware operations can be performed.
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppReset(void)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
//unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send an App reset command
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_APP_RESET;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
|
|
||||||
/** FIXME: hid_read() will occasionally hang due to a pthread_cond_wait() never returning.
|
|
||||||
It seems that the read_callback() in hid-libusb.c will never receive any
|
|
||||||
data during the reconfiguration. Since the same logic works in the native
|
|
||||||
windows application, it could be a libusb thing. Anyhow, since the value
|
|
||||||
returned by this function is not used, we may as well just skip the hid_read()
|
|
||||||
and return FME_NONE.
|
|
||||||
Correct switch from APP to BL mode can be observed in /var/log/messages (linux)
|
|
||||||
(when in bootloader mode the device version includes 'BL')
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
memset(aucBufIn,0xCC,65); // Clear out the response buffer
|
|
||||||
hid_read(phd,aucBufIn,65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]==FCDCMDAPPRESET && aucBufIn[1]==1)
|
|
||||||
{
|
|
||||||
FCDClose(phd);
|
|
||||||
phd=NULL;
|
|
||||||
return FME_APP;
|
|
||||||
}
|
|
||||||
FCDClose(phd);
|
|
||||||
phd=NULL;
|
|
||||||
return FME_BL;
|
|
||||||
*/
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Set FCD frequency with kHz resolution.
|
|
||||||
* \param nFreq The new frequency in kHz.
|
|
||||||
* \return The FCD mode.
|
|
||||||
*
|
|
||||||
* This function sets the frequency of the FCD with 1 kHz resolution. The parameter
|
|
||||||
* nFreq must already contain any necessary frequency correction.
|
|
||||||
*
|
|
||||||
* \sa fcdAppSetFreq
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppSetFreqkHz(int nFreq)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send an App reset command
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_APP_SET_FREQ_KHZ;
|
|
||||||
aucBufOut[2] = (unsigned char)nFreq;
|
|
||||||
aucBufOut[3] = (unsigned char)(nFreq>>8);
|
|
||||||
aucBufOut[4] = (unsigned char)(nFreq>>16);
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]==FCD_CMD_APP_SET_FREQ_KHZ && aucBufIn[1]==1)
|
|
||||||
{
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Set FCD frequency with Hz resolution.
|
|
||||||
* \param nFreq The new frequency in Hz.
|
|
||||||
* \return The FCD mode.
|
|
||||||
*
|
|
||||||
* This function sets the frequency of the FCD with 1 Hz resolution. The parameter
|
|
||||||
* nFreq must already contain any necessary frequency correction.
|
|
||||||
*
|
|
||||||
* \sa fcdAppSetFreq
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppSetFreq(int nFreq)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send an App reset command
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_APP_SET_FREQ_HZ;
|
|
||||||
aucBufOut[2] = (unsigned char)nFreq;
|
|
||||||
aucBufOut[3] = (unsigned char)(nFreq>>8);
|
|
||||||
aucBufOut[4] = (unsigned char)(nFreq>>16);
|
|
||||||
aucBufOut[5] = (unsigned char)(nFreq>>24);
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]==FCD_CMD_APP_SET_FREQ_HZ && aucBufIn[1]==1)
|
|
||||||
{
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Reset FCD to application mode.
|
|
||||||
* \return FCD_MODE_NONE
|
|
||||||
*
|
|
||||||
* This function is used to switch the FCD from bootloader mode
|
|
||||||
* into application mode.
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdBlReset(void)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
// unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send an BL reset command
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_RESET;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
|
|
||||||
/** FIXME: hid_read() will hang due to a pthread_cond_wait() never returning.
|
|
||||||
It seems that the read_callback() in hid-libusb.c will never receive any
|
|
||||||
data during the reconfiguration. Since the same logic works in the native
|
|
||||||
windows application, it could be a libusb thing. Anyhow, since the value
|
|
||||||
returned by this function is not used, we may as well jsut skip the hid_read()
|
|
||||||
and return FME_NONE.
|
|
||||||
Correct switch from BL to APP mode can be observed in /var/log/messages (linux)
|
|
||||||
(when in bootloader mode the device version includes 'BL')
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
memset(aucBufIn,0xCC,65); // Clear out the response buffer
|
|
||||||
hid_read(phd,aucBufIn,65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]==FCDCMDBLRESET && aucBufIn[1]==1)
|
|
||||||
{
|
|
||||||
FCDClose(phd);
|
|
||||||
phd=NULL;
|
|
||||||
return FME_BL;
|
|
||||||
}
|
|
||||||
FCDClose(phd);
|
|
||||||
phd=NULL;
|
|
||||||
return FME_APP;
|
|
||||||
*/
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Erase firmware from FCD.
|
|
||||||
* \return The FCD mode
|
|
||||||
*
|
|
||||||
* This function deletes the firmware from the FCD. This is required
|
|
||||||
* before writing new firmware into the FCD.
|
|
||||||
*
|
|
||||||
* \sa fcdBlWriteFirmware
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdBlErase(void)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send an App reset command
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_ERASE;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]==FCD_CMD_BL_ERASE && aucBufIn[1]==1)
|
|
||||||
{
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Write new firmware into the FCD.
|
|
||||||
* \param pc Pointer to the new firmware data
|
|
||||||
* \param n64size The number of bytes in the data
|
|
||||||
* \return The FCD mode
|
|
||||||
*
|
|
||||||
* This function is used to upload new firmware into the FCD flash.
|
|
||||||
*
|
|
||||||
* \sa fcdBlErase
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdBlWriteFirmware(char *pc, int64_t n64Size)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
uint32_t u32AddrStart;
|
|
||||||
uint32_t u32AddrEnd;
|
|
||||||
uint32_t u32Addr;
|
|
||||||
BOOL bFinished=FALSE;
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd==NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the valid flash address range
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_GET_BYTE_ADDR_RANGE;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]!=FCD_CMD_BL_GET_BYTE_ADDR_RANGE || aucBufIn[1]!=1)
|
|
||||||
{
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32AddrStart=
|
|
||||||
aucBufIn[2]+
|
|
||||||
(((uint32_t)aucBufIn[3])<<8)+
|
|
||||||
(((uint32_t)aucBufIn[4])<<16)+
|
|
||||||
(((uint32_t)aucBufIn[5])<<24);
|
|
||||||
u32AddrEnd=
|
|
||||||
aucBufIn[6]+
|
|
||||||
(((uint32_t)aucBufIn[7])<<8)+
|
|
||||||
(((uint32_t)aucBufIn[8])<<16)+
|
|
||||||
(((uint32_t)aucBufIn[9])<<24);
|
|
||||||
|
|
||||||
// Set start address for flash
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_SET_BYTE_ADDR;
|
|
||||||
aucBufOut[2] = ((unsigned char)u32AddrStart);
|
|
||||||
aucBufOut[3] = ((unsigned char)(u32AddrStart>>8));
|
|
||||||
aucBufOut[4] = ((unsigned char)(u32AddrStart>>16));
|
|
||||||
aucBufOut[5] = ((unsigned char)(u32AddrStart>>24));
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]!=FCD_CMD_BL_SET_BYTE_ADDR || aucBufIn[1]!=1)
|
|
||||||
{
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write blocks
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_WRITE_FLASH_BLOCK;
|
|
||||||
for (u32Addr=u32AddrStart; u32Addr+47<u32AddrEnd && u32Addr+47<n64Size && !bFinished; u32Addr+=48)
|
|
||||||
{
|
|
||||||
memcpy(&aucBufOut[3], &pc[u32Addr], 48);
|
|
||||||
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]!=FCD_CMD_BL_WRITE_FLASH_BLOCK || aucBufIn[1]!=1)
|
|
||||||
{
|
|
||||||
bFinished = TRUE;
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Verify firmware in FCd flash.
|
|
||||||
* \param pc Pointer to firmware data to verify against.
|
|
||||||
* \param n64Size Size of the data in pc.
|
|
||||||
* \return The FCD_MODE_BL if verification was succesful.
|
|
||||||
*
|
|
||||||
* This function verifies the firmware currently in the FCd flash against the firmware
|
|
||||||
* image pointed to by pc. The function return FCD_MODE_BL if the verification is OK and
|
|
||||||
* FCD_MODE_APP otherwise.
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdBlVerifyFirmware(char *pc, int64_t n64Size)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
uint32_t u32AddrStart;
|
|
||||||
uint32_t u32AddrEnd;
|
|
||||||
uint32_t u32Addr;
|
|
||||||
BOOL bFinished=FALSE;
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd==NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the valid flash address range
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_GET_BYTE_ADDR_RANGE;
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]!=FCD_CMD_BL_GET_BYTE_ADDR_RANGE || aucBufIn[1]!=1)
|
|
||||||
{
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32AddrStart=
|
|
||||||
aucBufIn[2]+
|
|
||||||
(((uint32_t)aucBufIn[3])<<8)+
|
|
||||||
(((uint32_t)aucBufIn[4])<<16)+
|
|
||||||
(((uint32_t)aucBufIn[5])<<24);
|
|
||||||
|
|
||||||
u32AddrEnd=
|
|
||||||
aucBufIn[6]+
|
|
||||||
(((uint32_t)aucBufIn[7])<<8)+
|
|
||||||
(((uint32_t)aucBufIn[8])<<16)+
|
|
||||||
(((uint32_t)aucBufIn[9])<<24);
|
|
||||||
|
|
||||||
// Set start address for flash
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_SET_BYTE_ADDR;
|
|
||||||
aucBufOut[2] = ((unsigned char)u32AddrStart);
|
|
||||||
aucBufOut[3] = ((unsigned char)(u32AddrStart>>8));
|
|
||||||
aucBufOut[4] = ((unsigned char)(u32AddrStart>>16));
|
|
||||||
aucBufOut[5] = ((unsigned char)(u32AddrStart>>24));
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]!=FCD_CMD_BL_SET_BYTE_ADDR || aucBufIn[1]!=1)
|
|
||||||
{
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read blocks
|
|
||||||
aucBufOut[0] = 0; // Report ID, ignored
|
|
||||||
aucBufOut[1] = FCD_CMD_BL_READ_FLASH_BLOCK;
|
|
||||||
for (u32Addr=u32AddrStart; u32Addr+47<u32AddrEnd && u32Addr+47<n64Size && !bFinished; u32Addr+=48)
|
|
||||||
{
|
|
||||||
hid_write(phd, aucBufOut, 65);
|
|
||||||
memset(aucBufIn, 0xCC, 65); // Clear out the response buffer
|
|
||||||
hid_read(phd, aucBufIn, 65);
|
|
||||||
|
|
||||||
if (aucBufIn[0]!=FCD_CMD_BL_READ_FLASH_BLOCK || aucBufIn[1]!=1)
|
|
||||||
{
|
|
||||||
bFinished = TRUE;
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(&aucBufIn[2],&pc[u32Addr],48)!=0)
|
|
||||||
{
|
|
||||||
bFinished = TRUE;
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Write FCD parameter (e.g. gain or filter)
|
|
||||||
* \param u8Cmd The command byte / parameter ID, see FCD_CMD_APP_SET_*
|
|
||||||
* \param pu8Data The parameter value to be written
|
|
||||||
* \param u8len Length of pu8Data in bytes
|
|
||||||
* \return One of FCD_MODE_NONE, FCD_MODE_APP or FCD_MODE_BL (see description)
|
|
||||||
*
|
|
||||||
* This function can be used to set the value of a parameter in the FCD for which there is no
|
|
||||||
* high level API call. It gives access to the low level API of the FCD and the caller is expected
|
|
||||||
* to be aware of the various FCD commands, since they are required to be supplied as parameter
|
|
||||||
* to this function.
|
|
||||||
*
|
|
||||||
* The return value can be used to determine the success or failure of the command execution:
|
|
||||||
* - FCD_MODE_APP : Reply from FCD was as expected (nominal case).
|
|
||||||
* - FCD_MODE_BL : Reply from FCD was not as expected.
|
|
||||||
* - FCD_MODE_NONE : No FCD was found
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppSetParam(uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
aucBufOut[0]=0; // Report ID, ignored
|
|
||||||
aucBufOut[1]=u8Cmd;
|
|
||||||
memcpy(aucBufOut+2, pu8Data,u8len);
|
|
||||||
hid_write(phd,aucBufOut,65);
|
|
||||||
|
|
||||||
/* we must read after each write in order to empty FCD/HID buffer */
|
|
||||||
memset(aucBufIn,0xCC,65); // Clear out the response buffer
|
|
||||||
hid_read(phd,aucBufIn,65);
|
|
||||||
|
|
||||||
/* Check the response, if OK return FCD_MODE_APP */
|
|
||||||
if (aucBufIn[0]==u8Cmd && aucBufIn[1]==1) {
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Response did not contain the expected bytes */
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_BL;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** \brief Read FCD parameter (e.g. gain or filter)
|
|
||||||
* \param u8Cmd The command byte / parameter ID, see FCD_CMD_APP_GET_*
|
|
||||||
* \param pu8Data TPointer to buffer where the parameter value(s) will be written
|
|
||||||
* \param u8len Length of pu8Data in bytes
|
|
||||||
* \return One of FCD_MODE_NONE, FCD_MODE_APP or FCD_MODE_BL (see description)
|
|
||||||
*
|
|
||||||
* This function can be used to read the value of a parameter in the FCD for which there is no
|
|
||||||
* high level API call. It gives access to the low level API of the FCD and the caller is expected
|
|
||||||
* to be aware of the various FCD commands, since they are required to be supplied as parameter
|
|
||||||
* to this function.
|
|
||||||
*
|
|
||||||
* The return value can be used to determine the success or failure of the command execution:
|
|
||||||
* - FCD_MODE_APP : Reply from FCD was as expected (nominal case).
|
|
||||||
* - FCD_MODE_BL : Reply from FCD was not as expected.
|
|
||||||
* - FCD_MODE_NONE : No FCD was found
|
|
||||||
*/
|
|
||||||
EXTERN FCD_API_EXPORT FCD_API_CALL FCD_MODE_ENUM fcdAppGetParam(uint8_t u8Cmd, uint8_t *pu8Data, uint8_t u8len)
|
|
||||||
{
|
|
||||||
hid_device *phd=NULL;
|
|
||||||
unsigned char aucBufOut[65];
|
|
||||||
unsigned char aucBufIn[65];
|
|
||||||
|
|
||||||
phd = fcdOpen();
|
|
||||||
if (phd == NULL)
|
|
||||||
{
|
|
||||||
return FCD_MODE_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
aucBufOut[0]=0; // Report ID, ignored
|
|
||||||
aucBufOut[1]=u8Cmd;
|
|
||||||
hid_write(phd,aucBufOut,65);
|
|
||||||
|
|
||||||
memset(aucBufIn,0xCC,65); // Clear out the response buffer
|
|
||||||
hid_read(phd,aucBufIn,65);
|
|
||||||
/* Copy return data to output buffer (even if cmd exec failed) */
|
|
||||||
memcpy(pu8Data,aucBufIn+2,u8len);
|
|
||||||
|
|
||||||
/* Check status bytes in returned data */
|
|
||||||
if (aucBufIn[0]==u8Cmd && aucBufIn[1]==1) {
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_APP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Response did not contain the expected bytes */
|
|
||||||
fcdClose(phd);
|
|
||||||
phd = NULL;
|
|
||||||
|
|
||||||
return FCD_MODE_BL;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user