NV14 implementation partially merged with actual Flysky version.

This commit is contained in:
Jakub
2020-01-05 15:48:13 +01:00
parent b12e55b2b7
commit fef09a5f74
55 changed files with 2945 additions and 1613 deletions
+2 -1
View File
@@ -267,7 +267,8 @@ enum TelemetryProtocol
PROTOCOL_TELEMETRY_HITEC,
PROTOCOL_TELEMETRY_HOTT,
PROTOCOL_TELEMETRY_MULTIMODULE,
PROTOCOL_TELEMETRY_LAST=PROTOCOL_TELEMETRY_MULTIMODULE,
PROTOCOL_TELEMETRY_FLYSKY_NV14,
PROTOCOL_TELEMETRY_LAST=PROTOCOL_TELEMETRY_FLYSKY_NV14,
PROTOCOL_TELEMETRY_LUA
};
+23 -3
View File
@@ -463,16 +463,36 @@ PACK(struct ModuleData {
uint8_t spare2:1 SKIP;
int8_t refreshRate; // definition as framelength for ppm (* 5 + 225 = time in 1/10 ms)
} sbus);
NOBACKUP(PACK(struct {
NOBACKUP(struct {
uint8_t receivers; // 5 bits spare
char receiverName[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME];
}) pxx2);
#if defined(PCBFLYSKY)
} pxx2);
#if defined(AFHDS2)
NOBACKUP(struct {
uint8_t rx_id[4];
uint8_t mode;
uint8_t rx_freq[2];
} flysky);
#endif
#if defined(AFHDS3)
NOBACKUP(PACK(struct {
uint8_t bindPower:3;
uint8_t runPower:3;
uint8_t emi:1;
uint8_t spare:1;
uint8_t telemetry:1;
uint8_t mode:4;
uint8_t spare2:3;
uint16_t failsafeTimeout; //4
uint16_t rxFreq;
//one more free byte
bool isSbus() {
return (mode & 1);
}
bool isPWM() {
return mode < 2;
}
} afhds3));
#endif
} NAME(mod) FUNC(select_mod_type);
+1
View File
@@ -60,5 +60,6 @@
#define BARGRAPH2_COLOR COLOR(BARGRAPH2_COLOR_INDEX)
#define BARGRAPH_BGCOLOR COLOR(BARGRAPH_BGCOLOR_INDEX)
#define SCROLLBOX_COLOR COLOR(SCROLLBOX_COLOR_INDEX)
#define BATTERY_CHARGE_COLOR COLOR(BATTERY_CHARGE_COLOR_INDEX)
#endif // _COLORS_H_
+2 -1
View File
@@ -68,7 +68,8 @@ class FrskyTheme: public ThemeBase
lcdColorTable[OVERLAY_COLOR_INDEX] = BLACK;
lcdColorTable[BARGRAPH1_COLOR_INDEX] = RED;
lcdColorTable[BARGRAPH2_COLOR_INDEX] = RGB(167, 167, 167);
lcdColorTable[BARGRAPH_BGCOLOR_INDEX] = RGB(222, 222, 222);
lcdColorTable[BARGRAPH_BGCOLOR_INDEX] = RGB(222, 222, 222);;
lcdColorTable[BATTERY_CHARGE_COLOR_INDEX] = GREEN;
}
void loadMenuIcon(uint8_t index, const char * filename, uint32_t color=MENU_COLOR) const
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 for more details.
*/
#include "afhds2.h"
afhds2::afhds2() {
// TODO Auto-generated constructor stub
}
afhds2::~afhds2() {
// TODO Auto-generated destructor stub
}
+55
View File
@@ -0,0 +1,55 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 for more details.
*/
#ifndef PULSES_AFHDS2_H_
#define PULSES_AFHDS2_H_
#include <functional>
#include <map>
#include <list>
struct FlySkySerialPulsesData {
uint8_t pulses[64];
uint8_t * ptr;
uint8_t frame_index;
uint8_t crc;
uint8_t state;
uint8_t timeout;
uint8_t esc_state;
uint8_t telemetry[64];
uint8_t telemetry_index;
} __attribute__((__packed__));
enum AfhdsSpecialChars {
END = 0xC0, //Frame end
START = END,
ESC_END = 0xDC, //Escaped frame end - in case END occurs in fame then ESC ESC_END must be used
ESC = 0xDB, //Escaping character
ESC_ESC = 0xDD, //Escaping character in case ESC occurs in fame then ESC ESC_ESC must be used
};
class afhds2 {
public:
afhds2();
virtual ~afhds2();
};
#endif /* PULSES_AFHDS2_H_ */
+496
View File
@@ -0,0 +1,496 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 for more details.
*/
#include "afhds3.h"
#include "../debug.h"
#include "../definitions.h"
#define FAILSAFE_HOLD 1
#define FAILSAFE_CUSTOM 2
namespace afhds3 {
uint8_t ModuleModeToState [] = {
ModuleState::STATE_READY, //not defined
ModuleState::STATE_STANDBY, //MODULE_MODE_E::STANDBY
ModuleState::STATE_BINDING, //MODULE_MODE_E::BIND
ModuleState::STATE_UPDATING_RX, //MODULE_MODE_E::RX_UPDATE
ModuleState::STATE_SYNC_DONE, //MODULE_MODE_E::RUN
};
static const char* const moduleStateText[] = {
"",
"HW Error",
"Binding",
"Connecting",
"Connected",
"Standby",
"Waiting for update",
"Updating",
"Updating RX",
"Updating RX failed",
"Testing"
"Not ready",
"Ready",
"HW test"
};
const char* afhds3::getState() {
if(data->state <= ModuleState::STATE_READY) return moduleStateText[data->state];
return "Unknown";
}
void afhds3::putByte(uint8_t byte) {
this->putBytes(&byte, 1);
}
void afhds3::putBytes(uint8_t* data, int length) {
for (int i = 0; i < length; i++) {
uint8_t byte = data[i];
this->data->crc += byte;
if (END == byte) {
*this->data->ptr++ = ESC;
*this->data->ptr++ = ESC_END;
}
else if (ESC == byte) {
*this->data->ptr++ = ESC;
*this->data->ptr++ = ESC_ESC;
}
else {
*this->data->ptr++ = byte;
}
}
}
void afhds3::putHeader(COMMAND command, FRAME_TYPE frame) {
operationState = State::SENDING_COMMAND;
data->ptr = this->data->pulses;
data->crc = 0;
*data->ptr++ = END;
uint8_t buffer[] = { FrameAddress, data->frame_index, frame, command};
putBytes(buffer, 4);
}
void afhds3::putFooter() {
putByte(data->crc ^ 0xff);
*data->ptr++ = END;
data->frame_index++;
switch((FRAME_TYPE)data->pulses[3])
{
case FRAME_TYPE::REQUEST_GET_DATA:
case FRAME_TYPE::REQUEST_SET_EXPECT_ACK:
case FRAME_TYPE::REQUEST_SET_EXPECT_DATA:
operationState = State::AWAITING_RESPONSE;
break;
default:
operationState = State::IDLE;
}
}
void afhds3::putFrame(COMMAND command, FRAME_TYPE frame, uint8_t* data, uint8_t dataLength){
putHeader(command, frame);
if(dataLength > 0) putBytes(data, dataLength);
putFooter();
}
void afhds3::addToQueue(COMMAND command, FRAME_TYPE frameType, uint8_t* data, uint8_t dataLength) {
request* r = new request(command, frameType, data, dataLength);
commandQueue.push(r);
}
void afhds3::clearQueue() {
while(!commandQueue.empty()) {
request* r = commandQueue.front();
delete r;
commandQueue.pop();
}
}
bool checkCRC(const uint8_t* data, uint8_t size)
{
uint8_t crc = 0;
//skip start byte
for (uint8_t i = 1; i < size; i++) {
crc += data[i];
}
return (crc ^ 0xff) == data[size];
}
bool containsData(enum FRAME_TYPE frameType) {
return frameType == FRAME_TYPE::RESPONSE_DATA || frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA ||
frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK || frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA ||
frameType == FRAME_TYPE::REQUEST_SET_NO_RESP;
}
void afhds3::setState(uint8_t state) {
if(state == data->state) return;
uint8_t oldState = data->state;
data->state = state;
if(oldState == ModuleState::STATE_BINDING) {
if(operationCallback != nullptr) {
operationCallback(false);
operationCallback = nullptr;
}
}
}
void afhds3::parseData(uint8_t* rxBuffer, uint8_t rxBufferCount) {
if(!checkCRC(rxBuffer, rxBufferCount - 2)) {
TRACE("AFHDS3 [INVALID CRC]");
return;
}
AfhdsFrame* responseFrame = reinterpret_cast<AfhdsFrame*>(rxBuffer);
AfhdsFrame* requestFrame = reinterpret_cast<AfhdsFrame*>(data->pulses);
uint8_t oldState = data->state;
if(containsData((enum FRAME_TYPE)responseFrame->frameType)) {
switch(responseFrame->command)
{
case COMMAND::MODULE_READY:
TRACE("AFHDS3 [MODULE_READY] %02X", responseFrame->value);
setState(responseFrame->value == MODULE_STATUS_READY ? ModuleState::STATE_READY : ModuleState::STATE_NOT_READY);
if(data->state == ModuleState::STATE_READY && oldState != data->state) {
addToQueue(COMMAND::MODULE_VERSION, FRAME_TYPE::REQUEST_GET_DATA);
addToQueue(COMMAND::MODULE_POWER_STATUS, FRAME_TYPE::REQUEST_GET_DATA);
addToQueue(COMMAND::MODULE_GET_CONFIG, FRAME_TYPE::REQUEST_GET_DATA);
uint8_t mode = MODULE_MODE_E::RUN;
addToQueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &mode, 1);
//addToQueue(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA);
}
break;
case COMMAND::MODULE_GET_CONFIG:
std::memcpy((void*)cfg.buffer, &responseFrame->value, sizeof(cfg.buffer));
TRACE("AFHDS3 [MODULE_GET_CONFIG] telemetry %d", cfg.config.telemetry);
break;
case COMMAND::MODULE_VERSION:
std::memcpy((void*)&version, &responseFrame->value, sizeof(version));
TRACE("AFHDS3 [MODULE_VERSION] Product %d, HW %d, BOOT %d, FW %d", version.productNumber, version.hardwereVersion, version.bootloaderVersion, version.firmwareVersion);
break;
case COMMAND::MODULE_POWER_STATUS:
powerSource = (enum MODULE_POWER_SOURCE)responseFrame->value;
TRACE("AFHDS3 [MODULE_POWER_STATUS], %d", powerSource);
break;
case COMMAND::MODULE_STATE:
TRACE("AFHDS3 [MODULE_STATE] %02X", responseFrame->value);
setState(responseFrame->value);
break;
case COMMAND::MODULE_MODE:
TRACE("AFHDS3 [MODULE_MODE] %02X", responseFrame->value);
if(responseFrame->value != CMD_RESULT::SUCCESS) {
setState(ModuleState::STATE_NOT_READY);
}
else addToQueue(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA);
break;
case COMMAND::MODULE_SET_CONFIG:
if(responseFrame->value != CMD_RESULT::SUCCESS) {
setState(ModuleState::STATE_NOT_READY);
}
TRACE("AFHDS3 [MODULE_SET_CONFIG], %02X", responseFrame->value);
break;
case COMMAND::TELEMETRY_DATA:
uint8_t* telemetry = &responseFrame->value;
uint8_t length = telemetry[1];
uint8_t id = telemetry[2];
if(telemetry[0] == 0x22) {
if(length == 5) {
if(id == 0xFA) telemetry[2] = 0xF8; //remap to afhds3 snr
processSensor(telemetry + 2, 0xAA);
}
else if(length == 6 && id == FRM302_STATUS) {
//convert to ibus
uint16_t t = (uint16_t)(((int16_t)telemetry[4] *10) + 400);
uint8_t dataTemp[] = { ++id, telemetry[3], (uint8_t)(t & 0xFF), (uint8_t)(t >> 8)};
processSensor(dataTemp, 0xAA);
uint8_t dataVoltage[] = { ++id, telemetry[3], telemetry[5], telemetry[6] };
processSensor(dataVoltage, 0xAA);
}
else if(length == 7) processSensor(telemetry + 2, 0xAC);
}
break;
}
}
if(responseFrame->frameType == FRAME_TYPE::REQUEST_GET_DATA || responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_DATA)
{
TRACE("Command %02X NOT IMPLEMENTED!", responseFrame->command);
}
else if (responseFrame->frameType == FRAME_TYPE::REQUEST_SET_EXPECT_ACK) {
addToQueue((enum COMMAND)responseFrame->command, FRAME_TYPE::RESPONSE_ACK);
}
else if(responseFrame->frameType == FRAME_TYPE::RESPONSE_DATA || responseFrame->frameType == FRAME_TYPE::RESPONSE_ACK) {
if(operationState == State::AWAITING_RESPONSE /* && requestFrame->command == responseFrame->command*/) {
operationState = State::IDLE;
}
}
}
void afhds3::onDataReceived(uint8_t byte, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize) {
if (rxBufferCount == 0 && byte != AfhdsSpecialChars::START) {
TRACE("AFHDS3 [SKIP] %02X", byte);
data->esc_state = 0;
return;
}
if (byte == AfhdsSpecialChars::ESC) {
data->esc_state = rxBufferCount;
return;
}
if (rxBufferCount > 1 && byte == AfhdsSpecialChars::END) {
rxBuffer[rxBufferCount++] = byte;
parseData(rxBuffer, rxBufferCount);
rxBufferCount = 0;
return;
}
if (data->esc_state && byte == AfhdsSpecialChars::ESC_END) byte = AfhdsSpecialChars::END;
else if (data->esc_state && byte == AfhdsSpecialChars::ESC_ESC) byte = AfhdsSpecialChars::ESC;
//reset esc index
data->esc_state = 0;
if (rxBufferCount >= maxSize) {
TRACE("AFHDS3 [BUFFER OVERFLOW]");
rxBufferCount = 0;
}
rxBuffer[rxBufferCount++] = byte;
}
void afhds3::trace(const char* message) {
char buffer[256];
char *pos = buffer;
for (int i = 0; i < data->ptr - data->pulses; i++) {
pos += std::snprintf(pos, buffer + sizeof(buffer) - pos, "%02X ", data->pulses[i]);
}
(*pos) = 0;
TRACE("%s size = %d data %s", message, data->ptr - data->pulses, buffer);
}
void afhds3::setupPulses() {
//TRACE("%d state %d repeatCount %d", (int)operationState, this->data->state, repeatCount);
if(operationState == State::AWAITING_RESPONSE) {
if(repeatCount++ < 5) return; //re-send
else reset(false);
}
data->ptr = data->pulses;
repeatCount = 0;
if (operationState == State::UNKNOWN || data->state == ModuleState::STATE_NOT_READY) {
putFrame(COMMAND::MODULE_READY, FRAME_TYPE::REQUEST_GET_DATA);
return;
}
//check waiting commands
if(!commandQueue.empty()) {
request* r = commandQueue.front();
commandQueue.pop();
putFrame(r->command, r->frameType, r->payload, r->payloadSize);
trace("AFHDS3 [CMD QUEUE] data");
delete r;
return;
}
//config should be loaded already
if(syncSettings()) return;
switch(data->state) {
case ModuleState::STATE_READY:
reset();
break;
case ModuleState::STATE_HW_ERROR:
case ModuleState::STATE_BINDING:
case ModuleState::STATE_UPDATING_RX:
case ModuleState::STATE_UPDATING_WAIT:
case ModuleState::STATE_UPDATING_MOD:
case ModuleState::STATE_SYNC_RUNNING:
case ModuleState::STATE_HW_TEST:
if(idleCount++ % 100 == 0) putFrame(COMMAND::MODULE_STATE, FRAME_TYPE::REQUEST_GET_DATA);
break;
case ModuleState::STATE_SYNC_DONE:
if(cfg.config.telemetry && idleCount++ % 800 == 0) {
uint8_t failSafe[3+MAX_CHANNELS*2] = {0x60, 0x12};
uint8_t channels = setFailSafe((int16_t*)(failSafe + 3));
failSafe[2] = channels *2;
putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, failSafe, 3 + channels*2);
//trace("AFHDS3 [AFHDS3 SET FAILSAFE] data");
}
else sendChannelsData();
break;
}
}
bool afhds3::syncSettings() {
if (moduleData->afhds3.runPower != cfg.config.runPower) {
cfg.config.runPower = moduleData->afhds3.runPower;
uint8_t data[] = { 0x20, 0x13, 0x01, moduleData->afhds3.runPower };
TRACE("AFHDS3 SET TX POWER %d", moduleData->afhds3.runPower);
putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
return true;
}
if(moduleData->afhds3.rxFreq != cfg.config.pwmFreq) {
cfg.config.pwmFreq = moduleData->afhds3.rxFreq;
uint8_t data[] = {0x70, 0x17, 0x02, (uint8_t)(moduleData->afhds3.rxFreq & 0xFF), (uint8_t)(moduleData->afhds3.rxFreq >> 8)};
TRACE("AFHDS3 SET RX FREQ");
putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
return true;
}
PULSE_MODE modelPulseMode = moduleData->afhds3.isPWM() ? PULSE_MODE::PWM: PULSE_MODE::PPM_MODE;
if(modelPulseMode != cfg.config.pulseMode) {
cfg.config.pulseMode = modelPulseMode;
TRACE("AFHDS3 PWM/PPM %d", modelPulseMode);
uint8_t data[] = {0x70, 0x16, 0x01, (uint8_t)(modelPulseMode)};
putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
return true;
}
SERIAL_MODE modelSerialMode = moduleData->afhds3.isSbus() ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS;
if(modelSerialMode != cfg.config.serialMode) {
cfg.config.serialMode = modelSerialMode;
TRACE("AFHDS3 IBUS/SBUS %d", modelSerialMode);
uint8_t data[] = {0x70, 0x18, 0x01, (uint8_t)(modelSerialMode)};
putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
return true;
}
if(moduleData->afhds3.failsafeTimeout != cfg.config.failSafeTimout) {
moduleData->afhds3.failsafeTimeout = cfg.config.failSafeTimout;
uint8_t data[] = { 0x60, 0x12, 0x02, (uint8_t)(moduleData->afhds3.failsafeTimeout & 0xFF), (uint8_t)(moduleData->afhds3.failsafeTimeout >> 8) };
putFrame(COMMAND::SEND_COMMAND, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, data, sizeof(data));
TRACE("AFHDS3 TRACE FAILSAFE TMEOUT");
return true;
}
return false;
}
void afhds3::sendChannelsData() {
uint8_t channels_start = moduleData->channelsStart;
uint8_t channelsCount = 8 + moduleData->channelsCount;
uint8_t channels_last = channels_start + channelsCount;
uint8_t channels[2*((8 + moduleData->channelsCount) + 1)];
channels[0] = 0x01;
channels[1] = channelsCount;
for(uint8_t channel = channels_start; channel < channels_last; channel++) {
int16_t channelValue = convert(getChannelValue(channel));
*((int16_t*)(channels + (channel * 2) + 2)) = channelValue;
}
putFrame(COMMAND::CHANNELS_FAILSAFE_DATA, FRAME_TYPE::REQUEST_SET_NO_RESP, channels, sizeof(channels));
}
void afhds3::bind(bindCallback_t callback) {
operationCallback = callback;
TRACE("AFHDS3 [BIND]");
setModelData();
addToQueue(COMMAND::MODULE_SET_CONFIG, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, cfg.buffer, sizeof(cfg.buffer));
uint8_t cmd = MODULE_MODE_E::BIND;
addToQueue(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &cmd, 1);
}
void afhds3::range(bindCallback_t callback) {
TRACE("AFHDS3 [RANGE CHECK] NOT IMPLEMENTED");
}
void afhds3::cancel() {
if(operationCallback!=nullptr) operationCallback(false);
reset(false);
}
void afhds3::stop() {
TRACE("AFHDS3 STOP");
uint8_t cmd = MODULE_MODE_E::STANDBY;
putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &cmd, 1);
reset(true);
}
void afhds3::setToDefault() {
moduleData->afhds3.bindPower = BIND_POWER::MIN_0dbm;
moduleData->afhds3.runPower = RUN_POWER::PLUS_15bBm;
moduleData->afhds3.emi = EMI_STANDARD::FCC;
moduleData->afhds3.telemetry = TELEMETRY::TELEMETRY_ENABLED;
moduleData->afhds3.rxFreq = 50;
moduleData->afhds3.failsafeTimeout = 1000;
moduleData->channelsCount = 14 - 8;
moduleData->failsafeMode = FAILSAFE_HOLD;
//" PWM+i"" PWM+s"" PPM+i"" PPM+s"
moduleData->afhds3.mode = 0;
for (uint8_t channel = 0; channel < MAX_OUTPUT_CHANNELS; channel++) {
failsafeChannels[channel] = 0;
}
}
int16_t afhds3::convert(int channelValue) {
//pulseValue = limit<uint16_t>(0, 988 + ((channelValue + 1024) / 2), 0xfff);
//988 - 750 = 238
//238 * 20 = 4760
//2250 - 2012 = 238
//238 * 20 = 4760
// 988 ---- 2012
//-10240 ---- 10240
//-1024 ---- 1024
return limit<int16_t>(FAILSAFE_MIN, channelValue*10, FAILSAFE_MAX);
}
void afhds3::setModelData() {
cfg.config.bindPower = moduleData->afhds3.bindPower;
cfg.config.runPower = moduleData->afhds3.runPower;
cfg.config.emiStandard = moduleData->afhds3.emi;
cfg.config.telemetry = moduleData->afhds3.telemetry;
cfg.config.pwmFreq = moduleData->afhds3.rxFreq;
cfg.config.serialMode = moduleData->afhds3.isSbus() ? SERIAL_MODE::SBUS_MODE : SERIAL_MODE::IBUS;
cfg.config.pulseMode = moduleData->afhds3.isPWM() ? PULSE_MODE::PWM: PULSE_MODE::PPM_MODE;
cfg.config.channelCount = 8 + moduleData->channelsCount;
cfg.config.failSafeTimout = moduleData->afhds3.failsafeTimeout;
setFailSafe(cfg.config.failSafeMode);
}
uint8_t afhds3::setFailSafe(int16_t* target) {
int16_t pulseValue = 0;
uint8_t channels_start = moduleData->channelsStart;
uint8_t channels_last = channels_start + 8 + moduleData->channelsCount;;
for (uint8_t channel = channels_start; channel < channels_last; channel++) {
if (moduleData->failsafeMode == FAILSAFE_CUSTOM) pulseValue = convert(failsafeChannels[channel]);
else if (moduleData->failsafeMode == FAILSAFE_HOLD) pulseValue = FAILSAFE_KEEP_LAST;
else pulseValue = convert(getChannelValue(channel));
target[channel-channels_start] = pulseValue;
}
return (uint8_t)(channels_last - channels_start);
}
void afhds3::onModelSwitch() {
//uint8_t cmd = MODULE_MODE_E::STANDBY;
//putFrame(COMMAND::MODULE_MODE, FRAME_TYPE::REQUEST_SET_EXPECT_DATA, &cmd, 1);
//setModelData();
}
void afhds3::reset(bool resetFrameCount) {
TRACE("AFHDS3 RESET");
clearQueue();
repeatCount = 0;
idleCount = 0;
this->data->state = ModuleState::STATE_NOT_READY;
this->data->frame_index = 1;
this->data->timeout = 0;
this->data->esc_state = 0;
}
}
+335
View File
@@ -0,0 +1,335 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 for more details.
*/
#ifndef PULSES_AFHDS3_H_
#define PULSES_AFHDS3_H_
#include "afhds2.h"
#include "../datastructs.h"
#include <cstring>
#include <queue>
#define AFHDS3_BAUDRATE 1500000
namespace afhds3 {
typedef void (*bindCallback_t) (bool);
typedef void (*processSensor_t) (const uint8_t *, uint8_t);
typedef int32_t (*getChannelValue_t)(uint8_t);
enum DeviceAddress {
TRANSMITTER = 0x01, MODULE = 0x03,
};
enum FRAME_TYPE {
REQUEST_GET_DATA = 0x01, //Get data response: ACK + DATA
REQUEST_SET_EXPECT_DATA = 0x02, //Set data response: ACK + DATA
REQUEST_SET_EXPECT_ACK = 0x03, //Set data response: ACK
REQUEST_SET_NO_RESP = 0x05, //Set data response: none
RESPONSE_DATA = 0x10, //Response ACK + DATA
RESPONSE_ACK = 0x20, //Response ACK
NOT_USED = 0xff
};
enum COMMAND {
MODULE_READY = 0x01,
MODULE_STATE = 0x02,
MODULE_MODE = 0x03,
MODULE_SET_CONFIG = 0x04,
MODULE_GET_CONFIG = 0x06,
CHANNELS_FAILSAFE_DATA = 0x07,
TELEMETRY_DATA = 0x09,
SEND_COMMAND = 0x0C,
COMMAND_RESULT = 0x0D,
MODULE_POWER_STATUS = 0x0F,
MODULE_VERSION = 0x1F,
};
enum COMMAND_DIRECTION {
RADIO_TO_MODULE = 0, MODULE_TO_RADIO = 1
};
enum DATA_TYPE {
READY_DT, // 8 bytes 0x01 Not ready 0x02 Ready
STATE_DT, // See MODULE_STATE
MODE_DT,
MOD_CONFIG_DT,
CHANNELS_DT,
TELEMETRY_DT,
MODULE_POWER_DT,
MODULE_VERSION_DT,
EMPTY_DT,
};
//enum used by command response -> translate to ModuleState
enum MODULE_READY_E {
MODULE_STATUS_UNKNOWN = 0x00,
MODULE_STATUS_NOT_READY = 0x01,
MODULE_STATUS_READY = 0x02
};
enum ModuleState {
STATE_HW_ERROR = 0x01,
STATE_BINDING = 0x02,
STATE_SYNC_RUNNING = 0x03,
STATE_SYNC_DONE = 0x04,
STATE_STANDBY = 0x05,
STATE_UPDATING_WAIT = 0x06,
STATE_UPDATING_MOD = 0x07,
STATE_UPDATING_RX = 0x08,
STATE_UPDATING_RX_FAILED = 0x09,
STATE_RF_TESTING = 0x0a,
STATE_NOT_READY = 0x0b, //virtual
STATE_READY = 0x0c, //virtual
STATE_HW_TEST = 0xff,
};
//used for set command
enum MODULE_MODE_E {
STANDBY = 0x01,
BIND = 0x02, //after bind module will enter run mode
RUN = 0x03,
RX_UPDATE = 0x04, //after successful update module will enter standby mode, otherwise hw error will be raised
};
enum CMD_RESULT {
FAILURE = 0x01,
SUCCESS = 0x02,
};
#define MIN_FREQ 50
#define MAX_FREQ 400
#define MAX_CHANNELS 18
#define FAILSAFE_KEEP_LAST 0x8000
#define FAILSAFE_MIN -15000
#define FAILSAFE_MAX 15000
enum BIND_POWER {
MIN_16dBm = 0x00,
MIN_5dBm = 0x01,
MIN_0dbm = 0x02,
PLUS_5dBm = 0x03,
PLUS_14dBm = 0x04
};
enum RUN_POWER {
PLUS_15bBm = 0x00,
PLUS_20bBm = 0x01,
PLUS_27dbm = 0x02,
PLUS_30dBm = 0x03,
PLUS_33dBm = 0x04
};
enum EMI_STANDARD {
FCC = 0x00, CE = 0x01
};
enum TELEMETRY {
TELEMETRY_DISABLED = 0x00, TELEMETRY_ENABLED = 0x01
};
enum PULSE_MODE {
PWM = 0x00, PPM_MODE = 0x01,
};
enum SERIAL_MODE {
IBUS = 0x00, SBUS_MODE = 0x02
};
struct __attribute__ ((packed)) Config_s {
uint8_t bindPower;
uint8_t runPower;
uint8_t emiStandard;
uint8_t telemetry;
uint16_t pwmFreq;
uint8_t pulseMode;
uint8_t serialMode;
uint8_t channelCount;
uint16_t failSafeTimout;
int16_t failSafeMode[MAX_CHANNELS];
};
union Config_u {
Config_s config;
uint8_t buffer[sizeof(Config_s)];
};
enum CHANNELS_DATA_MODE {
CHANNELS = 0x01, FAIL_SAFE = 0x02,
};
struct __attribute__ ((packed)) ChannelsData {
uint8_t mode;
uint8_t channelsNumber;
int16_t data[MAX_CHANNELS];
};
union ChannelsData_u {
ChannelsData data;
uint8_t buffer[sizeof(ChannelsData)];
};
struct __attribute__ ((packed)) TelemetryData {
uint8_t sensorType;
uint8_t length;
uint8_t type;
uint8_t semsorID;
uint8_t data[8];
};
enum MODULE_POWER_SOURCE {
INTERNAL = 0x01, EXTERNAL = 0x02,
};
struct __attribute__ ((packed)) ModuleVersion {
uint32_t productNumber;
uint32_t hardwereVersion;
uint32_t bootloaderVersion;
uint32_t firmwareVersion;
uint32_t rfVersion;
};
union AfhdsFrameData {
uint8_t value;
Config_s Config;
ChannelsData Channels;
TelemetryData Telemetry;
ModuleVersion Version;
};
struct __attribute__ ((packed)) AfhdsFrame {
uint8_t startByte;
uint8_t address;
uint8_t frameNumber;
uint8_t frameType;
uint8_t command;
uint8_t value;
AfhdsFrameData* GetData() {
return reinterpret_cast<AfhdsFrameData*>(&value);
}
};
#define FRM302_STATUS 0x56
enum State {
UNKNOWN = 0,
SENDING_COMMAND,
AWAITING_RESPONSE,
IDLE
};
class request {
public:
request(COMMAND command, FRAME_TYPE frameType, const uint8_t* data = nullptr, uint8_t length = 0) {
this->command = command;
this->frameType = frameType;
if(data && length){
payload = new uint8_t[length];
std::memcpy(payload, data, length);
}
else payload = nullptr;
payloadSize = length;
}
~request() {
if(payload != nullptr) {
delete[] payload;
payload = nullptr;
}
}
enum COMMAND command;
enum FRAME_TYPE frameType;
uint8_t* payload;
uint8_t payloadSize;
};
class afhds3 {
public:
afhds3(FlySkySerialPulsesData* data, ModuleData* moduleData, int16_t* failsafeChannels, getChannelValue_t getChannelValue, processSensor_t processSensor) {
this->data = data;
this->moduleData = moduleData;
this->getChannelValue = getChannelValue;
this->processSensor = processSensor;
this->failsafeChannels = failsafeChannels;
reset();
}
virtual ~afhds3() {
clearQueue();
}
const uint32_t baudrate = AFHDS3_BAUDRATE;
const uint16_t parity = ((uint16_t)0x0000); //USART_Parity_No
const uint16_t stopBits = ((uint16_t)0x0000); //USART_StopBits_1
const uint16_t wordLength = ((uint16_t)0x0000); //USART_WordLength_8b
const uint16_t commandTimout = 5; //ms
void setupPulses();
void onDataReceived(uint8_t data, uint8_t* rxBuffer, uint8_t& rxBufferCount, uint8_t maxSize);
void reset(bool resetFrameCount = true);
void bind(bindCallback_t callback);
void range(bindCallback_t callback);
void cancel();
const char* getState();
void stop();
void setToDefault();
void setModelData();
private:
const uint8_t FrameAddress = DeviceAddress::TRANSMITTER | (DeviceAddress::MODULE << 4);
const uint16_t commandRepeatCount = 5;
void putByte(uint8_t byte);
void putBytes(uint8_t* data, int length);
void putHeader(COMMAND command, FRAME_TYPE frameType);
void putFooter();
void putFrame(COMMAND command, FRAME_TYPE frameType, uint8_t* data = nullptr, uint8_t dataLength = 0);
void addToQueue(COMMAND command, FRAME_TYPE frameType, uint8_t* data = nullptr, uint8_t dataLength = 0);
void parseData(uint8_t* rxBuffer, uint8_t rxBufferCount);
void setState(uint8_t state);
bool syncSettings();
void trace(const char* message);
uint8_t setFailSafe(int16_t* target);
int16_t convert(int channelValue);
void onModelSwitch();
void sendChannelsData();
void clearQueue();
//external data
FlySkySerialPulsesData* data;
ModuleData* moduleData;
int16_t* failsafeChannels;
int16_t* channelOutputs;
bindCallback_t operationCallback;
getChannelValue_t getChannelValue;
processSensor_t processSensor;
//missing ppm center!
//local config
Config_u cfg;
ModuleVersion version;
enum MODULE_POWER_SOURCE powerSource;
//buffer where the channels are
State operationState;
uint16_t repeatCount;
uint32_t idleCount;
std::queue<request*> commandQueue;
};
}
#endif /* PULSES_AFHDS3_H_ */
+94 -179
View File
@@ -21,49 +21,17 @@
*/
#include "opentx.h"
#define END 0xC0
#define ESC 0xDB
#define ESC_END 0xDC
#define ESC_ESC 0xDD
#include "flysky.h"
#define FRAME_TYPE_REQUEST_ACK 0x01
#define FRAME_TYPE_REQUEST_NACK 0x02
#define FRAME_TYPE_ANSWER 0x10
enum FlySkyModuleCommandID {
COMMAND_ID_NONE,
COMMAND_ID_RF_INIT,
COMMAND_ID_BIND,
COMMAND_ID_SET_RECEIVER_ID,
COMMAND_ID_RF_GET_CONFIG,
COMMAND_ID_SEND_CHANNEL_DATA,
COMMAND_ID_RX_SENSOR_DATA,
COMMAND_ID_SET_RX_PWM_PPM,
COMMAND_ID_SET_RX_SERVO_FREQ,
COMMAND_ID_GET_FIRMWARE_REV,
COMMAND_ID_SET_RX_IBUS_SBUS,
COMMAND_ID_SET_RX_IBUS_SERVO_EXT,
COMMAND_ID0C_UPDATE_RF_FIRMWARE = 0x0C,
COMMAND_ID0D_SET_TX_POWER = 0x0D,
COMMAND_ID_SET_RF_PROTOCOL,
COMMAND_ID_TEST_RANGE,
COMMAND_ID_TEST_RF_RESERVED,
COMMAND_ID20_UPDATE_RX_FIRMWARE = 0x20,
COMMAND_ID_LAST
};
#define IS_VALID_COMMAND_ID(id) ((id) < COMMAND_ID_LAST)
#ifndef custom_log
#define custom_log
#endif
enum DEBUG_RF_FRAME_PRINT_E {
FRAME_PRINT_OFF,// 0:OFF, 1:RF frame only, 2:TX frame only, 3:Both RF and TX frame
RF_FRAME_ONLY,
TX_FRAME_ONLY,
BOTH_FRAME_PRINT
};
#define DEBUG_RF_FRAME_PRINT FRAME_PRINT_OFF
#define FLYSKY_MODULE_TIMEOUT 155 /* ms */
#define NUM_OF_NV14_CHANNELS (14)
@@ -72,70 +40,6 @@ enum DEBUG_RF_FRAME_PRINT_E {
#define gRomData g_model.moduleData[INTERNAL_MODULE].flysky
#define SET_DIRTY() storageDirty(EE_MODEL)
enum FlySkySensorType_E {
FLYSKY_SENSOR_RX_VOLTAGE,
FLYSKY_SENSOR_RX_SIGNAL,
FLYSKY_SENSOR_RX_RSSI,
FLYSKY_SENSOR_RX_NOISE,
FLYSKY_SENSOR_RX_SNR,
FLYSKY_SENSOR_TEMP,
FLYSKY_SENSOR_EXT_VOLTAGE,
FLYSKY_SENSOR_MOTO_RPM,
FLYSKY_SENSOR_PRESURRE,
FLYSKY_SENSOR_GPS
};
enum FlySkyModuleState_E {
FLYSKY_MODULE_STATE_SET_TX_POWER,
FLYSKY_MODULE_STATE_INIT,
FLYSKY_MODULE_STATE_BIND,
FLYSKY_MODULE_STATE_SET_RECEIVER_ID,
FLYSKY_MODULE_STATE_SET_RX_PWM_PPM,
FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS,
FLYSKY_MODULE_STATE_SET_RX_FREQUENCY,
FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE,
FLYSKY_MODULE_STATE_UPDATE_RX_FIRMWARE,
FLYSKY_MODULE_STATE_UPDATE_HALL_FIRMWARE,
FLYSKY_MODULE_STATE_UPDATE_RF_PROTOCOL,
FLYSKY_MODULE_STATE_GET_RECEIVER_CONFIG,
FLYSKY_MODULE_STATE_GET_RX_FIRMWARE_INFO,
FLYSKY_MODULE_STATE_GET_RX_FW_VERSION,
FLYSKY_MODULE_STATE_GET_RF_FIRMWARE_INFO,
FLYSKY_MODULE_STATE_GET_RF_FW_VERSION,
FLYSKY_MODULE_STATE_IDLE,
FLYSKY_MODULE_STATE_DEFAULT,
};
enum FlySkyBindState_E {
BIND_LOW_POWER,
BIND_NORMAL_POWER,
BIND_EXIT,
};
enum FlySkyRxPulse_E {
FLYSKY_PWM,
FLYSKY_PPM
};
enum FlySkyRxPort_E {
FLYSKY_IBUS,
FLYSKY_SBUS
};
enum FlySkyFirmwareType_E {
FLYSKY_RX_FIRMWARE,
FLYSKY_RF_FIRMWARE
};
enum FlySkyChannelDataType_E {
FLYSKY_CHANNEL_DATA_NORMAL,
FLYSKY_CHANNEL_DATA_FAILSAFE
};
enum FlySkyPulseModeValue_E {
PWM_IBUS, PWM_SBUS,
PPM_IBUS, PPM_SBUS
};
#define GET_FLYSKY_PWM_PPM (gRomData.mode < 2 ? FLYSKY_PWM: FLYSKY_PPM)
#define GET_FLYSKY_IBUS_SBUS (gRomData.mode & 1 ? FLYSKY_SBUS: FLYSKY_IBUS)
@@ -197,7 +101,7 @@ typedef struct RX_INFO_S {
static rx_sensor_t rx_sensor_info;
static uint8_t tx_working_power = 90;
static uint8_t lastState = FLYSKY_MODULE_STATE_IDLE;
static rf_info_t rf_info = {
.id = {8, 8, 8, 8},
.bind_power = BIND_NORMAL_POWER,
@@ -474,15 +378,15 @@ void setFlySkyChannelData(int channel, int16_t servoValue)
void sendPulsesFrameByState(uint8_t port, uint8_t frameState)
{
modulePulsesData[port].flysky.state = frameState;
modulePulsesData[port].flysky.state_index = FLYSKY_MODULE_TIMEOUT;
intmodulePulsesData.flysky.state = frameState;
intmodulePulsesData.flysky.timeout = FLYSKY_MODULE_TIMEOUT;
//setupPulsesFlySky(port); // effect immediately
}
bool isRxBindingState(uint8_t port)
{
return moduleFlag[port] == MODULE_BIND;
return moduleState[port].mode == MODULE_MODE_BIND;
}
bool isFlySkyUsbDownload(void)
@@ -501,22 +405,24 @@ void onIntmoduleSetPower(bool isPowerOn)
INTERNAL_MODULE_OFF();
}
}
//REMOVED FROM OPENTX
void resetPulsesFlySky(uint8_t port);
void onIntmoduleBindReceiver(uint8_t port)
{
resetPulsesFlySky(port);
moduleFlag[port] = MODULE_BIND;
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_INIT;
moduleState[port].mode = MODULE_MODE_BIND;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT;
}
void onFlySkyReceiverPulseMode(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_SET_RX_PWM_PPM;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RX_PWM_PPM;
}
void onFlySkyReceiverPulsePort(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS;
}
void onIntmoduleReceiverSetFrequency(uint8_t port)
@@ -533,96 +439,105 @@ void onIntmoduleReceiverSetPulse(uint8_t port, uint8_t mode_and_port) // mode_an
void onFlySkyTransmitterPower(uint8_t port, uint8_t dBmValue)
{
tx_working_power = dBmValue;
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_SET_TX_POWER;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_TX_POWER;
}
void onFlySkyUpdateReceiverFirmwareStart(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_UPDATE_RX_FIRMWARE;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_UPDATE_RX_FIRMWARE;
}
void setFlyskyState(uint8_t port, uint8_t state) {
intmodulePulsesData.flysky.state = state;
}
void onIntmoduleUsbDownloadStart(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE;
}
void onFlySkyUsbDownloadStart(uint8_t fw_state)
{
rf_info.fw_state = fw_state;
}
void onFlySkyGetVersionInfoStart(uint8_t port, uint8_t isRfTransfer)
{
lastState = intmodulePulsesData.flysky.state;
if ( isRfTransfer != 0 )
setFlyskyState(port, FLYSKY_MODULE_STATE_GET_RF_FW_VERSION);
else setFlyskyState(port, FLYSKY_MODULE_STATE_GET_RX_FW_VERSION);
}
void onFlySkyUpdateTransmitterProtocol(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_UPDATE_RF_PROTOCOL;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_UPDATE_RF_PROTOCOL;
}
void onFlySkyGetReceiverFirmwareInfo(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_GET_RX_FIRMWARE_INFO;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_GET_RX_FIRMWARE_INFO;
}
void onFlySkyGetTransmitterFirmwareInfo(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_GET_RF_FIRMWARE_INFO;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_GET_RF_FIRMWARE_INFO;
}
void onFlySkyGetReceiverFirmwareVersion(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_GET_RX_FW_VERSION;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_GET_RX_FW_VERSION;
}
void onFlySkyGetTransmitterFirmwareVersion(uint8_t port)
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_GET_RF_FW_VERSION;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_GET_RF_FW_VERSION;
}
void initFlySkyArray(uint8_t port)
{
modulePulsesData[port].flysky.ptr = modulePulsesData[port].flysky.pulses;
modulePulsesData[port].flysky.crc = 0;
intmodulePulsesData.flysky.ptr = intmodulePulsesData.flysky.pulses;
intmodulePulsesData.flysky.crc = 0;
}
inline void putFlySkyByte(uint8_t port, uint8_t byte)
{
if (END == byte) {
*modulePulsesData[port].flysky.ptr++ = ESC;
*modulePulsesData[port].flysky.ptr++ = ESC_END;
*intmodulePulsesData.flysky.ptr++ = ESC;
*intmodulePulsesData.flysky.ptr++ = ESC_END;
}
else if (ESC == byte) {
*modulePulsesData[port].flysky.ptr++ = ESC;
*modulePulsesData[port].flysky.ptr++ = ESC_ESC;
*intmodulePulsesData.flysky.ptr++ = ESC;
*intmodulePulsesData.flysky.ptr++ = ESC_ESC;
}
else {
*modulePulsesData[port].flysky.ptr++ = byte;
*intmodulePulsesData.flysky.ptr++ = byte;
}
}
void putFlySkyFrameByte(uint8_t port, uint8_t byte)
{
modulePulsesData[port].flysky.crc += byte;
intmodulePulsesData.flysky.crc += byte;
putFlySkyByte(port, byte);
}
void putFlySkyFrameHead(uint8_t port)
{
*modulePulsesData[port].flysky.ptr++ = END;
*intmodulePulsesData.flysky.ptr++ = END;
}
void putFlySkyFrameIndex(uint8_t port)
{
putFlySkyFrameByte(port, modulePulsesData[port].flysky.frame_index);
putFlySkyFrameByte(port, intmodulePulsesData.flysky.frame_index);
}
void putFlySkyFrameCrc(uint8_t port)
{
putFlySkyByte(port, modulePulsesData[port].flysky.crc ^ 0xff);
putFlySkyByte(port, intmodulePulsesData.flysky.crc ^ 0xff);
}
void putFlySkyFrameTail(uint8_t port)
{
*modulePulsesData[port].flysky.ptr++ = END;
*intmodulePulsesData.flysky.ptr++ = END;
}
@@ -719,7 +634,7 @@ void putFlySkySendChannelData(uint8_t port)
uint8_t channels_count = min<unsigned int>(NUM_OF_NV14_CHANNELS, channels_start + 8 + g_model.moduleData[port].channelsCount);
putFlySkyFrameByte(port, channels_count);
for (uint8_t channel = channels_start; channel < channels_count; channel++) {
int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[channel];
int16_t failsafeValue = g_model.failsafeChannels[channel];
uint16_t pulseValue = limit<uint16_t>(900, 900 + ((2100 - 900) * (failsafeValue + 1024) / 2048), 2100);
putFlySkyFrameByte(port, pulseValue & 0xff);
putFlySkyFrameByte(port, pulseValue >> 8);
@@ -761,8 +676,8 @@ void putFlySkyUpdateRfProtocol(uint8_t port)
void incrFlySkyFrame(uint8_t port)
{
if (++modulePulsesData[port].flysky.frame_index == 0)
modulePulsesData[port].flysky.frame_index = 1;
if (++intmodulePulsesData.flysky.frame_index == 0)
intmodulePulsesData.flysky.frame_index = 1;
}
bool checkFlySkyFrameCrc(const uint8_t * ptr, uint8_t size)
@@ -792,7 +707,7 @@ bool checkFlySkyFrameCrc(const uint8_t * ptr, uint8_t size)
void parseFlySkyFeedbackFrame(uint8_t port)
{
const uint8_t * ptr = modulePulsesData[port].flysky.telemetry;
const uint8_t * ptr = intmodulePulsesData.flysky.telemetry;
if (*ptr++ != END)
return;
@@ -802,15 +717,15 @@ void parseFlySkyFeedbackFrame(uint8_t port)
uint8_t first_para = *ptr++;
uint8_t * p_data = NULL;
if (!checkFlySkyFrameCrc(modulePulsesData[port].flysky.telemetry + 1, modulePulsesData[port].flysky.telemetry_index - 2)) {
if (!checkFlySkyFrameCrc(intmodulePulsesData.flysky.telemetry + 1, intmodulePulsesData.flysky.telemetry_index - 2)) {
return;
}
switch (command_id) {
default:
if (moduleFlag[port] == MODULE_NORMAL_MODE
&& modulePulsesData[port].flysky.state >= FLYSKY_MODULE_STATE_IDLE) {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_DEFAULT;
if (moduleState[port].mode == MODULE_MODE_NORMAL
&& intmodulePulsesData.flysky.state >= FLYSKY_MODULE_STATE_IDLE) {
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_DEFAULT;
if (DEBUG_RF_FRAME_PRINT & RF_FRAME_ONLY) TRACE("State back to channel data");
}
break;
@@ -818,27 +733,27 @@ void parseFlySkyFeedbackFrame(uint8_t port)
case COMMAND_ID_RF_INIT: {
if (first_para == 0x01) { // action only RF ready
if (moduleFlag[port] == MODULE_BIND) {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_BIND;
if (moduleState[port].mode == MODULE_MODE_BIND) {
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_BIND;
incrFlySkyFrame(port);
}
/*else if (moduleFlag[port] == MODULE_RANGECHECK) {
/*else if (moduleState[port].mode == MODULE_MODE_RANGECHECK) {
}*/
if (modulePulsesData[port].flysky.state == FLYSKY_MODULE_STATE_INIT) {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_SET_RECEIVER_ID;
if (intmodulePulsesData.flysky.state == FLYSKY_MODULE_STATE_INIT) {
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RECEIVER_ID;
incrFlySkyFrame(port);
}
}
else modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_IDLE;
else intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_IDLE;
break;
}
case COMMAND_ID_BIND: {
if (frame_type != FRAME_TYPE_ANSWER) {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_IDLE;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_IDLE;
return;
}
g_model.header.modelId[port] = ptr[2];
@@ -850,11 +765,11 @@ void parseFlySkyFeedbackFrame(uint8_t port)
TRACE("New Rx ID: %02X %02X %02X %02X", gRomData.rx_id[0], gRomData.rx_id[1], gRomData.rx_id[2], gRomData.rx_id[3]);
SET_DIRTY();
resetPulsesFlySky(port);
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_INIT;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT;
break;
case COMMAND_ID_RF_GET_CONFIG:
modulePulsesData[port].flysky.frame_index = frame_number;
intmodulePulsesData.flysky.frame_index = frame_number;
sendPulsesFrameByState(port, FLYSKY_MODULE_STATE_GET_RECEIVER_CONFIG);
break;
}
@@ -883,46 +798,46 @@ void parseFlySkyFeedbackFrame(uint8_t port)
p_data[1] = *ptr++;
}
if (moduleFlag[port] == MODULE_RANGECHECK) {
moduleFlag[port] = MODULE_NORMAL_MODE;
if (moduleState[port].mode == MODULE_MODE_RANGECHECK) {
moduleState[port].mode = MODULE_MODE_NORMAL;
onFlySkyTransmitterPower(port, 0); // set power 0
break;
}
if (moduleFlag[port] == MODULE_NORMAL_MODE && modulePulsesData[port].flysky.state >= FLYSKY_MODULE_STATE_IDLE) {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_DEFAULT;
if (moduleState[port].mode == MODULE_MODE_NORMAL && intmodulePulsesData.flysky.state >= FLYSKY_MODULE_STATE_IDLE) {
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_DEFAULT;
}
break;
}
case COMMAND_ID_SET_RECEIVER_ID: {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_DEFAULT;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_DEFAULT;
return;
}
case COMMAND_ID0D_SET_TX_POWER: {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_INIT;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT;
break;
}
case COMMAND_ID_SET_RX_PWM_PPM: {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RX_IBUS_SBUS;
break;
}
case COMMAND_ID_SET_RX_IBUS_SBUS: {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_SET_RX_FREQUENCY;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_RX_FREQUENCY;
break;
}
case COMMAND_ID_SET_RX_SERVO_FREQ: {
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_DEFAULT;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_DEFAULT;
break;
}
case COMMAND_ID0C_UPDATE_RF_FIRMWARE: {
rf_info.fw_state = FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE;
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_IDLE;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_IDLE;
break;
}
}
@@ -946,7 +861,7 @@ void checkFlySkyFeedback(uint8_t port)
uint8_t byte;
while (intmoduleGetByte(&byte)) {
//if ( modulePulsesData[port].flysky.state == FLYSKY_MODULE_STATE_IDLE
//if ( intmodulePulsesData.flysky.state == FLYSKY_MODULE_STATE_IDLE
// && rf_info.fw_state == FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE )
{
Parse_Character(&rfProtocolRx, byte );
@@ -966,7 +881,7 @@ void checkFlySkyFeedback(uint8_t port)
if ( 0x01 == rfProtocolRx.length &&
( 0x05 == rfProtocolRx.data[0] || 0x06 == rfProtocolRx.data[0]) )
{
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_INIT;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT;
rf_info.fw_state = 0;
}
@@ -975,26 +890,26 @@ void checkFlySkyFeedback(uint8_t port)
//continue;
}
if (byte == END && modulePulsesData[port].flysky.telemetry_index > 0) {
if (byte == END && intmodulePulsesData.flysky.telemetry_index > 0) {
parseFlySkyFeedbackFrame(port);
modulePulsesData[port].flysky.telemetry_index = 0;
intmodulePulsesData.flysky.telemetry_index = 0;
}
else {
if (byte == ESC) {
modulePulsesData[port].flysky.esc_state = 1;
intmodulePulsesData.flysky.esc_state = 1;
}
else {
if (modulePulsesData[port].flysky.esc_state) {
modulePulsesData[port].flysky.esc_state = 0;
if (intmodulePulsesData.flysky.esc_state) {
intmodulePulsesData.flysky.esc_state = 0;
if (byte == ESC_END)
byte = END;
else if (byte == ESC_ESC)
byte = ESC;
}
modulePulsesData[port].flysky.telemetry[modulePulsesData[port].flysky.telemetry_index++] = byte;
if (modulePulsesData[port].flysky.telemetry_index >= sizeof(modulePulsesData[port].flysky.telemetry)) {
intmodulePulsesData.flysky.telemetry[intmodulePulsesData.flysky.telemetry_index++] = byte;
if (intmodulePulsesData.flysky.telemetry_index >= sizeof(intmodulePulsesData.flysky.telemetry)) {
// TODO buffer is full, log an error?
modulePulsesData[port].flysky.telemetry_index = 0;
intmodulePulsesData.flysky.telemetry_index = 0;
}
}
}
@@ -1004,11 +919,11 @@ void checkFlySkyFeedback(uint8_t port)
void resetPulsesFlySky(uint8_t port)
{
modulePulsesData[port].flysky.frame_index = 1;
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_SET_TX_POWER;
modulePulsesData[port].flysky.state_index = 0;
modulePulsesData[port].flysky.esc_state = 0;
moduleFlag[port] = MODULE_NORMAL_MODE;
intmodulePulsesData.flysky.frame_index = 1;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_SET_TX_POWER;
intmodulePulsesData.flysky.timeout = 0;
intmodulePulsesData.flysky.esc_state = 0;
moduleState[port].mode = MODULE_MODE_NORMAL;
uint16_t rx_freq = g_model.moduleData[port].flysky.rx_freq[0];
rx_freq += (g_model.moduleData[port].flysky.rx_freq[1] * 256);
if (50 > rx_freq || 400 < rx_freq) {
@@ -1026,13 +941,13 @@ void setupPulsesFlySky(uint8_t port)
putFlySkyFrameHead(port);
putFlySkyFrameIndex(port);
if (modulePulsesData[port].flysky.state < FLYSKY_MODULE_STATE_DEFAULT) {
if (intmodulePulsesData.flysky.state < FLYSKY_MODULE_STATE_DEFAULT) {
if (++modulePulsesData[port].flysky.state_index >= FLYSKY_MODULE_TIMEOUT / PXX_PERIOD_DURATION) {
if (++intmodulePulsesData.flysky.timeout >= FLYSKY_MODULE_TIMEOUT / 9) {
modulePulsesData[port].flysky.state_index = 0;
intmodulePulsesData.flysky.timeout = 0;
switch (modulePulsesData[port].flysky.state) {
switch (intmodulePulsesData.flysky.state) {
case FLYSKY_MODULE_STATE_INIT:
putFlySkyRfInit(port);
@@ -1048,7 +963,7 @@ void setupPulsesFlySky(uint8_t port)
case FLYSKY_MODULE_STATE_GET_RECEIVER_CONFIG:
putFlySkyGetReceiverConfig(port);
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_INIT;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT;
break;
case FLYSKY_MODULE_STATE_SET_TX_POWER:
@@ -1096,11 +1011,11 @@ void setupPulsesFlySky(uint8_t port)
break;
case FLYSKY_MODULE_STATE_IDLE:
modulePulsesData[port].pxx_uart.ptr = modulePulsesData[port].pxx_uart.pulses;
intmodulePulsesData.flysky.ptr = intmodulePulsesData.flysky.pulses;
return;
default:
modulePulsesData[port].flysky.state = FLYSKY_MODULE_STATE_INIT;
intmodulePulsesData.flysky.state = FLYSKY_MODULE_STATE_INIT;
initFlySkyArray(port);
if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) {
TRACE("State back to INIT\r\n");
@@ -1123,10 +1038,10 @@ void setupPulsesFlySky(uint8_t port)
if ((DEBUG_RF_FRAME_PRINT & TX_FRAME_ONLY)) {
/* print each command, except channel data by interval */
uint8_t * data = modulePulsesData[port].pxx_uart.pulses;
uint8_t * data = intmodulePulsesData.flysky.pulses;
if (data[3] != COMMAND_ID_SEND_CHANNEL_DATA || (set_loop_cnt++ % 100 == 0)) {
uint8_t size = modulePulsesData[port].pxx_uart.ptr - data;
TRACE_NOCRLF("TX(State%0d)%0dB:", modulePulsesData[port].flysky.state, size);
uint8_t size = intmodulePulsesData.flysky.ptr - data;
TRACE_NOCRLF("TX(State%0d)%0dB:", intmodulePulsesData.flysky.state, size);
for (int idx = 0; idx < size; idx++) {
TRACE_NOCRLF(" %02X", data[idx]);
}
+7 -1
View File
@@ -27,6 +27,7 @@
#include "pxx1.h"
#include "pxx2.h"
#include "multi.h"
#include "flysky.h"
#include "modules_helpers.h"
#include "ff.h"
@@ -272,7 +273,9 @@ union InternalModulePulsesData {
PwmPxx1Pulses pxx;
#endif
#endif
#if defined(AFHDS2)
FlySkySerialPulsesData flysky;
#endif
#if defined(PXX2)
Pxx2Pulses pxx2;
#endif
@@ -305,6 +308,9 @@ union ExternalModulePulsesData {
#if defined(DSM2) || defined(MULTIMODULE) || defined(SBUS)
Dsm2PulsesData dsm2;
#endif
#if defined(AFHDS3)
FlySkySerialPulsesData flysky;
#endif
PpmPulsesData<pulse_duration_t> ppm;
+28 -1
View File
@@ -13,6 +13,8 @@ option(PPM "PPM TX Module" ON)
option(DSM2 "DSM2 TX Module" ON)
option(SBUS "SBUS TX Module" ON)
option(CROSSFIRE "Crossfire TX Module" ON)
option(AFHDS2 "Support for AFHDS2" OFF)
option(AFHDS3 "Support for AFHDS3" OFF)
option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON)
option(DEBUG_INTERRUPTS "Count interrupts" OFF)
option(DEBUG_LATENCY "Debug latency" OFF)
@@ -147,7 +149,18 @@ endif()
if(MULTIMODULE)
add_definitions(-DMULTIMODULE)
set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/flysky_ibus.cpp telemetry/hitec.cpp telemetry/hott.cpp telemetry/multi.cpp io/multi_firmware_update.cpp)
set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/hitec.cpp telemetry/hott.cpp telemetry/multi.cpp io/multi_firmware_update.cpp)
endif()
if(MULTIMODULE OR AFHDS3)
set(SRC ${SRC} telemetry/flysky_ibus.cpp)
endif()
if(AFHDS2)
add_definitions(-DAFHDS2)
set(SRC ${SRC} telemetry/flysky_nv14.cpp)
endif()
if(AFHDS3)
add_definitions(-DAFHDS3)
endif()
if(CROSSFIRE)
@@ -236,3 +249,17 @@ if(SBUS)
sbus.cpp
)
endif()
if(AFHDS2)
set(PULSES_SRC
${PULSES_SRC}
afhds2.cpp
flysky.cpp
)
endif()
if(AFHDS3)
set(PULSES_SRC
${PULSES_SRC}
afhds3.cpp
)
endif()
@@ -102,7 +102,7 @@ if(PCB STREQUAL X7 OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES)
)
endif()
if(NOT (PCB STREQUAL X10 OR PCB STREQUAL X12S))
if(NOT (PCB STREQUAL X10 OR PCB STREQUAL X12S OR PCB STREQUAL NV14))
set(BOOTLOADER_SRC
${BOOTLOADER_SRC}
../../../../../targets/${TARGET_DIR}/i2c_driver.cpp
@@ -516,6 +516,6 @@ int main()
return 0;
}
#if defined(PCBHORUS)
#if defined(PCBHORUS) || defined(PCBNV14)
void *__dso_handle = nullptr;
#endif
@@ -167,11 +167,11 @@ uint32_t isFirmwareStart(const uint8_t * buffer)
return 0;
}
// First ISR pointer in FLASH
if ((block[1] & 0xFFF00000) != 0x08000000) {
if ((block[1] & 0xFFC00000) != 0x08000000) {//for nv14 firmware may start up to 0x81F ....
return 0;
}
// Second ISR pointer in FLASH
if ((block[2] & 0xFFF00000) != 0x08000000) {
if ((block[2] & 0xFFC00000) != 0x08000000) {
return 0;
}
#else
@@ -57,7 +57,6 @@
#define USBD_VID 0x0483
#define USBD_LANGID_STRING 0x409
#define USBD_MANUFACTURER_STRING "FrSky"
#define USBD_SERIALNUMBER_FS_STRING "00000000001B"
@@ -216,8 +215,10 @@ uint8_t * USBD_USR_ProductStrDescriptor( uint8_t speed , uint16_t *length)
* @param length : pointer to data length variable
* @retval pointer to descriptor buffer
*/
static const char USBD_MANUFACTURER_STRING[] = { USB_MANUFACTURER };
uint8_t * USBD_USR_ManufacturerStrDescriptor( uint8_t speed , uint16_t *length)
{
USBD_GetString ((uint8_t*)USBD_MANUFACTURER_STRING, USBD_StrDesc, length);
return USBD_StrDesc;
}
+25 -12
View File
@@ -1,13 +1,13 @@
option(DISK_CACHE "Enable SD card disk cache" YES)
option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" YES)
option(DISK_CACHE "Enable SD card disk cache" ON)
option(UNEXPECTED_SHUTDOWN "Enable the Unexpected Shutdown screen" ON)
option(FLYSKY_HALL_STICKS "sticks for FlySky hall sticks" ON)
option(FLYSKY_HALL_STICKS_REVERSE "Reverse sticks for FlySky hall sticks" OFF)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
set(CPU_TYPE STM32F4)
set(HSE_VALUE 12000000)
set(SDCARD YES)
set(SDCARD YES)
set(STORAGE SDCARD)
set(STORAGE_FORMAT BIN)
set(HAPTIC YES)
@@ -24,7 +24,7 @@ endif()
set(RAMBACKUP YES)
set(PPM_LIMITS_SYMETRICAL YES)
# for size report script
set(CPU_TYPE_FULL STM32F429BIT6)
set(CPU_TYPE_FULL STM32F429xI)
set(SIZE_TARGET_MEM_DEFINE "MEM_SIZE_SDRAM2=8192")
option(USB_SERIAL "Enable USB serial (CDC)" ON)
@@ -37,7 +37,6 @@ add_definitions(-DPCBNV14 -DPCBFLYSKY -DINTERNAL_MODULE_BAUDRATE=${PCB_RF_BAUD})
#add_definitions(-DSOFTWARE_VOLUME)
set(TARGET_SRC
${TARGET_SRC}
#../common/arm/stm32/audio_dac_driver.cpp
audio_spi_driver.cpp
adc_driver.cpp
)
@@ -64,11 +63,22 @@ add_definitions(-DSTM32F429_439xx -DSDRAM -DCOLORLCD -DLIBOPENUI -DHARDWARE_TOUC
add_definitions(-DEEPROM_VARIANT=0 -DAUDIO -DVOICE -DRTCLOCK)
add_definitions(-DGPS_USART_BAUDRATE=${INTERNAL_GPS_BAUDRATE})
add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
add_definitions(-DCROSSFIRE_NATIVE)
add_definitions(-DFLYSKY_HALL_STICKS_REVERSE)
add_definitions(-DHALL_STICKS)
#add_definitions(-DFLYSKY_AUTO_POWER_DOWN)
if(STICKS_DEAD_ZONE)
add_definitions(-DSTICK_DEAD_ZONE)
endif()
if(NOT UNEXPECTED_SHUTDOWN)
add_definitions(-DNO_UNEXPECTED_SHUTDOWN)
endif()
set(AFHDS2 ON)
set(AFHDS3 ON)
include_directories(${RADIO_SRC_DIR}/fonts/colorlcd gui/${GUI_DIR} gui/${GUI_DIR}/layouts)
file(GLOB THEMES_SRC RELATIVE ${RADIO_SRC_DIR}/gui/colorlcd ${RADIO_SRC_DIR}/gui/colorlcd/themes/*.cpp)
@@ -110,14 +120,15 @@ set(FIRMWARE_TARGET_SRC
if(BOOTLOADER)
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
../common/arm/loadboot.cpp
)
${FIRMWARE_TARGET_SRC}
../common/arm/loadboot.cpp
)
endif()
set(PULSES_SRC
${PULSES_SRC}
#flysky.cpp
set(SRC
${SRC}
io/frsky_firmware_update.cpp
io/multi_firmware_update.cpp
)
set(STM32LIB_SRC
@@ -126,6 +137,8 @@ set(STM32LIB_SRC
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_ltdc.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_tim.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma2d.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_exti.c
STM32F4xx_StdPeriph_Driver/src/stm32f4xx_syscfg.c
)
if(PYTHONINTERP_FOUND)
+22 -6
View File
@@ -23,7 +23,11 @@
#if defined(SIMU)
// not needed
#elif defined(PCBNV14)
const int8_t ana_direction[NUM_ANALOGS] = { 0 };
const int8_t ana_direction[NUM_ANALOGS] = { 0 /*STICK1*/, 0 /*STICK2*/, 0 /*STICK3*/, 0 /*STICK4*/,
0 /*POT1*/, 0 /*POT2*/, 0 /*SWA*/, 0 /*SWB*/,
0 /*SWC*/, -1 /*SWD*/, 0 /*SWE*/, -1 /*SWF*/,
0 /*SWH*/, 0 /*SWG*/,
0 /*TX_VOLTAGE*/ };
const uint8_t anas_mapping[NUM_ANALOGS] = { 0 /*STICK1*/, 1 /*STICK2*/, 2 /*STICK3*/, 3 /*STICK4*/,
4 /*POT1*/, 5 /*POT2*/, 6 /*SWA*/, 13 /*SWB*/,
7 /*SWC*/, 14 /*SWD*/, 8 /*SWE*/, 9 /*SWF*/,
@@ -64,13 +68,18 @@
#define FIRST_ANALOG_ADC 0
#define NUM_MAIN_ANALOGS_ADC 10
#define NUM_MAIN_ANALOGS_ADC_EXT (NUM_MAIN_ANALOGS - 10)
#elif defined(PCBNV14) && defined(HALL_STICKS)
#define FIRST_ANALOG_ADC 4
#define NUM_MAIN_ANALOGS_ADC 9
#else
#define FIRST_ANALOG_ADC 0
#define FIRST_SUB_ANALOG_ADC 0
#define NUM_MAIN_ANALOGS_ADC (SUB_ANALOG_POS)
#define NUM_SUB_ANALOGS_ADC (NUM_ANALOGS - SUB_ANALOG_POS)
#endif
#ifndef NUM_SUB_ANALOGS_ADC
#define NUM_SUB_ANALOGS_ADC 0
#endif
uint16_t adcValues[NUM_ANALOGS] __DMA;
void adcInit()
@@ -104,7 +113,7 @@ void adcInit()
ADC_MAIN->CR1 = ADC_CR1_SCAN;
ADC_MAIN->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC_MAIN->SQR1 = (NUM_MAIN_ANALOGS_ADC-1) << 20; // bits 23:20 = number of conversions
#if defined(PCBNV14)
#if NUM_SUB_ANALOGS_ADC > 0
ADC_SUB->CR1 = ADC_CR1_SCAN;
ADC_SUB->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
ADC_SUB->SQR1 = (NUM_SUB_ANALOGS_ADC-1) << 20; // bits 23:20 = number of conversions
@@ -138,11 +147,16 @@ void adcInit()
ADC_MAIN->SQR2 = (ADC_CHANNEL_SWE<<0) + (ADC_CHANNEL_SWF<<5) + (ADC_CHANNEL_LIBATT<<10) + (ADC_CHANNEL_DRYBATT<<15); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_SWA<<10) + (ADC_CHANNEL_SWB<<15) + (ADC_CHANNEL_SWC<<20) + (ADC_CHANNEL_SWD<<25); // conversions 1 to 6
#elif defined(PCBNV14)
#if !defined(HALL_STICKS)
ADC_MAIN->SQR1 |= (ADC_CHANNEL_BATT <<0 );
ADC_MAIN->SQR2 = (ADC_CHANNEL_SWA << 0) + (ADC_CHANNEL_SWC << 5) + (ADC_CHANNEL_SWE << 10) + (ADC_CHANNEL_SWF << 15) + (ADC_CHANNEL_SWG << 20) + (ADC_CHANNEL_SWH << 25); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
ADC_SUB->SQR3 = (ADC_CHANNEL_SWB<<0) + (ADC_CHANNEL_SWD<<5); // conversions 1 to 2
#else
ADC_MAIN->SQR2 = (ADC_CHANNEL_SWG << 0) + (ADC_CHANNEL_SWH << 5) + (ADC_CHANNEL_BATT << 10); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_SWA<<10) + (ADC_CHANNEL_SWC<<15) + (ADC_CHANNEL_SWE<<20) + (ADC_CHANNEL_SWF<<25); // conversions 1 to 6
ADC_SUB->SQR3 = (ADC_CHANNEL_SWB<<0) + (ADC_CHANNEL_SWD<<5); // conversions 1 to 2
#endif
#else
ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
@@ -159,7 +173,7 @@ void adcInit()
ADC_MAIN_DMA_Stream->NDTR = NUM_MAIN_ANALOGS_ADC;
ADC_MAIN_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
#if defined(PCBNV14)
#if NUM_SUB_ANALOGS > 0
ADC_SUB->SMPR1 = ADC_SAMPTIME + (ADC_SAMPTIME<<3) + (ADC_SAMPTIME<<6) + (ADC_SAMPTIME<<9) + (ADC_SAMPTIME<<12) + (ADC_SAMPTIME<<15) + (ADC_SAMPTIME<<18) + (ADC_SAMPTIME<<21) + (ADC_SAMPTIME<<24);
ADC_SUB->SMPR2 = ADC_SAMPTIME + (ADC_SAMPTIME<<3) + (ADC_SAMPTIME<<6) + (ADC_SAMPTIME<<9) + (ADC_SAMPTIME<<12) + (ADC_SAMPTIME<<15) + (ADC_SAMPTIME<<18) + (ADC_SAMPTIME<<21) + (ADC_SAMPTIME<<24) + (ADC_SAMPTIME<<27);
@@ -192,6 +206,8 @@ void adcInit()
sticksPwmInit();
}
#endif
//Avoid reading wrong values when the adcRead not be called.
adcRead();
}
void adcSingleRead()
@@ -201,7 +217,7 @@ void adcSingleRead()
ADC_MAIN_SET_DMA_FLAGS();
ADC_MAIN_DMA_Stream->CR |= DMA_SxCR_EN; // Enable DMA
ADC_MAIN->CR2 |= (uint32_t) ADC_CR2_SWSTART;
#if defined(PCBNV14)
#if NUM_SUB_ANALOGS_ADC > 0
ADC_SUB_DMA_Stream->CR &= ~DMA_SxCR_EN; // Disable DMA
ADC_SUB->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR);
ADC_SUB_SET_DMA_FLAGS();
+32 -25
View File
@@ -78,6 +78,8 @@
#define READ_DREQ() (GPIO_ReadInputDataBit(AUDIO_DREQ_GPIO, AUDIO_DREQ_GPIO_PIN))
bool isAudioOn = false;
void audioSpiInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
@@ -164,13 +166,10 @@ void audioSpiSetSpeed(uint8_t speed)
break;
}
AUDIO_SPI->CR1 |= 0x01 << 6;
//SPI_Cmd(AUDIO_SPI, ENABLE);
}
uint8_t audioSpiReadWriteByte(uint8_t value)
{
uint8_t ret = 0;
uint16_t time_out = 0x0FFF;
while (SPI_I2S_GetFlagStatus(AUDIO_SPI, SPI_I2S_FLAG_TXE) == RESET) {
if (--time_out == 0) {
@@ -199,10 +198,7 @@ uint8_t audioSpiReadWriteByte(uint8_t value)
break;
}
}
ret = SPI_I2S_ReceiveData(AUDIO_SPI);
return ret;
return SPI_I2S_ReceiveData(AUDIO_SPI);
}
uint8_t audioWaitDreq(int32_t delay_us)
@@ -321,7 +317,6 @@ uint8_t audioSoftReset(void)
audioSpiReadWriteByte(0X0);
delay_01us(100); // 10us
XDCS_HIGH();
return 1;
}
@@ -386,15 +381,8 @@ void Audio_Sine_Test(void)
uint32_t audioSpiWriteData(const uint8_t * buffer, uint32_t size)
{
int i = 55;
XDCS_LOW();
if (58 == i)
{
TRACE("\nbuffer = %d \r\n)", buffer);
}
uint32_t index = 0;
while (index < size && READ_DREQ() != 0) {
for (int i=0; i<MP3_BUFFER_SIZE && index<size; i++) {
@@ -426,7 +414,20 @@ void audioSendRiffHeader()
audioSpiWriteBuffer(RiffHeader, sizeof(RiffHeader));
}
#if defined(PCBNV14)
void audioOn()
{
if(isAudioOn) return;
GPIO_SetBits(AUDIO_SHUTDOWN_GPIO, AUDIO_SHUTDOWN_GPIO_PIN);
isAudioOn = true;
}
void audioOff()
{
if(!isAudioOn) return;
GPIO_ResetBits(AUDIO_SHUTDOWN_GPIO, AUDIO_SHUTDOWN_GPIO_PIN);
isAudioOn = false;
}
void audioShutdownInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
@@ -436,21 +437,26 @@ void audioShutdownInit()
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(AUDIO_SHUTDOWN_GPIO, &GPIO_InitStructure);
GPIO_SetBits(AUDIO_SHUTDOWN_GPIO, AUDIO_SHUTDOWN_GPIO_PIN); // we never RESET it, there is a 2s delay on STARTUP
audioOn();
}
#endif
void audioInit()
{
#if defined(PCBNV14)
audioShutdownInit();
// TODO X10 code missing
#endif
audioSpiInit();
/* Audio setting */
audioSpiSetSpeed(SPI_SPEED_64);
audioHardReset();
audioSoftReset();
audioSpiSetSpeed(SPI_SPEED_8);
delay_01us(10000);
audioSendRiffHeader();
audioOn();
delay_01us(10000);
}
uint8_t * currentBuffer = NULL;
uint8_t * currentBuffer = nullptr;
uint32_t currentSize = 0;
int16_t newVolume = -1;
@@ -461,13 +467,14 @@ void audioSetCurrentBuffer(const AudioBuffer * buffer)
currentSize = buffer->size * 2;
}
else {
currentBuffer = NULL;
currentBuffer = nullptr;
currentSize = 0;
}
}
void audioConsumeCurrentBuffer()
{
//return;
if (newVolume >= 0) {
uint8_t value = newVolume;
audioSpiWriteCmd(SPI_VOL, (value << 8) + value);
@@ -485,7 +492,7 @@ void audioConsumeCurrentBuffer()
currentSize -= written;
if (currentSize == 0) {
audioQueue.buffersFifo.freeNextFilledBuffer();
currentBuffer = NULL;
currentBuffer = nullptr;
currentSize = 0;
}
}
+26 -3
View File
@@ -43,9 +43,32 @@ void backlightInit()
BACKLIGHT_TIMER->BDTR |= TIM_BDTR_MOE;
}
uint8_t lastDutyCycle = 0;
void backlightEnable(uint8_t dutyCycle)
{
// TODO SET provided cycle - for now ensure backlight will be on
//BACKLIGHT_TIMER->CCR1 = dutyCycle;
BACKLIGHT_TIMER->CCR1 = BACKLIGHT_LEVEL_MAX;
BACKLIGHT_TIMER->CCR1 = dutyCycle;
if(!dutyCycle) {
//experimental to turn off LCD when no backlight
if(lcdOffFunction) lcdOffFunction();
}
else if(!lastDutyCycle) {
if(lcdOnFunction) lcdOnFunction();
else lcdInit();
}
lastDutyCycle = dutyCycle;
}
void lcdOff() {
backlightEnable(0);
}
void lcdOn(){
if(lcdOnFunction) lcdOnFunction();
else lcdInit();
backlightEnable(BACKLIGHT_LEVEL_MAX);
}
bool isBacklightEnabled() {
return lastDutyCycle != 0;
}
+150 -37
View File
@@ -21,8 +21,17 @@
#define __BATTERY_DRIVER_C__
#define BATTERY_W 140
#define BATTERY_H 320
#define BATTERY_TOP ((LCD_H - BATTERY_H)/2)
#define BATTERY_CONNECTOR_W 32
#define BATTERY_CONNECTOR_H 10
#define BATTERY_BORDER 4
#define BATTERY_W_INNER (BATTERY_W - 2*BATTERY_BORDER)
#define BATTERY_H_INNER (BATTERY_H - 2*BATTERY_BORDER)
#define BATTERY_TOP_INNER (BATTERY_TOP + BATTERY_BORDER)
void init_battery_charge()
void battery_charge_init()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = PWR_CHARGE_FINISHED_GPIO_PIN | PWR_CHARGING_GPIO_PIN;
@@ -34,51 +43,155 @@ void init_battery_charge()
GPIO_SetBits(PWR_CHARGING_GPIO, PWR_CHARGE_FINISHED_GPIO_PIN | PWR_CHARGING_GPIO_PIN);
}
#define CHARGE_SAMPLES 10
uint16_t get_battery_charge_state()
{
if (!READ_CHARGE_FINISHED_STATE())
{
return CHARGE_FINISHED;
}
else if (!READ_CHARGING_STATE())
{
return CHARGE_STARTED;
}
static uint16_t chargeSamples[CHARGE_SAMPLES] = {0};
static uint16_t chargeSampleIndex = 0;
uint16_t chargeState = CHARGE_UNKNOWN;
int maxSamples = CHARGE_SAMPLES;
#if !defined(SIMU)
bool isFinished = !READ_CHARGE_FINISHED_STATE();
bool isCharging = !READ_CHARGING_STATE();
//maxSamples = boardState == BOARD_POWER_OFF ? CHARGE_SAMPLES/2 : CHARGE_SAMPLES;
if(chargeSampleIndex >= maxSamples) chargeSampleIndex = 0;
uint16_t currentChargeState = isFinished ? CHARGE_FINISHED : isCharging ? CHARGE_STARTED : CHARGE_NONE;
chargeSamples[chargeSampleIndex++] = currentChargeState;
//TRACE("CHARGE sample %d value %d", chargeSampleIndex -1, currentChargeState);
#endif
uint8_t temp1 = 0, temp2 = 0, temp3 = 0;
for(int index = 0; index < maxSamples; index++) {
if(chargeSamples[index] == CHARGE_FINISHED)
{
temp1++;
}
else if(chargeSamples[index] == CHARGE_STARTED)
{
temp2++;
}
else
{
temp3++;
}
return CHARGE_NONE;
if(temp1>=temp2&& temp1>temp3)
{
chargeState = CHARGE_FINISHED;
}
else if(temp2>=temp1&& temp2>temp3)
{
chargeState = CHARGE_STARTED;
}
else
{
chargeState = CHARGE_NONE;
}
}
return chargeState;
}
void drawChargingInfo(uint16_t chargeState){
static int progress = 0;
const char* text = chargeState == CHARGE_STARTED ? STR_BATTERYCHARGING : STR_BATTERYFULL;
int h = 0;
LcdFlags color = 0;
if(CHARGE_STARTED == chargeState)
{
if(progress >= 100)
{
progress = 0;
}
else
{
progress+=25;
}
text = STR_BATTERYCHARGING;
h = ((BATTERY_H_INNER * progress) / 100);
color = ROUND|BATTERY_CHARGE_COLOR;
}
else if(CHARGE_FINISHED == chargeState)
{
text = STR_BATTERYFULL;
h = BATTERY_H_INNER;
color = ROUND|BATTERY_CHARGE_COLOR;
}
else
{
text = STR_BATTERYNONE;
h = BATTERY_H_INNER;
color = ROUND|TRIM_SHADOW_COLOR;
}
uint16_t getBatteryVoltage()
BACKLIGHT_ENABLE();
lcd->drawSizedText(LCD_W/2, LCD_H-50, text, strlen(text), CENTERED|MAINVIEW_PANES_COLOR);
lcd->drawFilledRect((LCD_W - BATTERY_W)/2, BATTERY_TOP, BATTERY_W, BATTERY_H, SOLID, ROUND|MAINVIEW_PANES_COLOR);
lcd->drawFilledRect((LCD_W - BATTERY_W_INNER)/2, BATTERY_TOP_INNER, BATTERY_W_INNER, BATTERY_H_INNER, SOLID, ROUND|TRIM_SHADOW_COLOR);
lcd->drawFilledRect((LCD_W - BATTERY_W_INNER)/2, BATTERY_TOP_INNER + BATTERY_H_INNER - h , BATTERY_W_INNER, h, SOLID, color);
lcd->drawFilledRect((LCD_W - BATTERY_CONNECTOR_W)/2, BATTERY_TOP-BATTERY_CONNECTOR_H , BATTERY_CONNECTOR_W, BATTERY_CONNECTOR_H, SOLID, MAINVIEW_PANES_COLOR);
}
#define CHARGE_INFO_DURATION 500
//this method should be called by timer interrupt or by GPIO interrupt
void handle_battery_charge(uint32_t last_press_time)
{
#if defined (SIMU)
return 350 + g_eeGeneral.txVoltageCalibration;
#else
int32_t t = getAnalogValue(TX_VOLTAGE) + g_eeGeneral.txVoltageCalibration;
#if !defined(SIMU)
static uint32_t updateTime = 0;
static uint16_t lastState = CHARGE_UNKNOWN;
static uint32_t info_until = 0;
static bool lcdInited = false;
t *= ( 3300 * 20);
t /= ( 4095 * 10);
t = ( t * 100 + 500 ) / 1000;
if(boardState != BOARD_POWER_OFF) return;
uint32_t now = get_tmr10ms();
uint16_t chargeState = get_battery_charge_state();
if(chargeState != CHARGE_UNKNOWN) {
return t;
if(lastState != chargeState) {
//avoid positive check when none and unknown
if(lastState + chargeState > 1) {
//charge state changed - last state known
info_until = now + (CHARGE_INFO_DURATION);
}
}
//power buttons pressed
else if(now - last_press_time < POWER_ON_DELAY) {
info_until = now + CHARGE_INFO_DURATION;
}
lastState = chargeState;
}
if(now > info_until) {
info_until = 0;
lcd->clear();
BACKLIGHT_DISABLE();
if(lcdInited) {
lcdOff();
}
return;
}
if(updateTime == 0 || ((get_tmr10ms() - updateTime) >= 50))
{
if(!lcdInited) {
backlightInit();
lcdInit();
lcdInited = true;
}
else {
lcdOn();
}
updateTime = get_tmr10ms();
lcdNextLayer();
lcd->clear();
drawChargingInfo(chargeState);
lcdRefresh();
}
#endif
}
uint16_t getBatteryVoltage()
{
int32_t instant_vbat = anaIn(TX_VOLTAGE); // using filtered ADC value on purpose
return (uint16_t)((instant_vbat * (1000 + g_eeGeneral.txVoltageCalibration)) / 2942);
}
+3 -18
View File
@@ -31,6 +31,7 @@
enum ChargeState
{
CHARGE_UNKNOWN,
CHARGE_NONE,
CHARGE_STARTED,
CHARGE_FINISHED
@@ -48,25 +49,9 @@ enum ChargeState
#define READ_CHARGE_FINISHED_STATE() GPIO_ReadInputDataBit( PWR_CHARGE_FINISHED_GPIO, PWR_CHARGE_FINISHED_GPIO_PIN )
#define READ_CHARGING_STATE() GPIO_ReadInputDataBit( PWR_CHARGING_GPIO, PWR_CHARGING_GPIO_PIN )
extern void init_battery_charge();
extern void battery_charge_init();
extern void handle_battery_charge(uint32_t last_press_time);
extern uint16_t get_battery_charge_state();
extern uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
#endif
+119 -73
View File
@@ -17,8 +17,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
#include "touch.h"
#if defined(__cplusplus) && !defined(SIMU)
extern "C" {
#endif
@@ -62,8 +63,6 @@ void init1msTimer()
NVIC_EnableIRQ(INTERRUPT_xMS_IRQn);
NVIC_SetPriority(INTERRUPT_xMS_IRQn, 7);
}
// TODO use the same than board_sky9x.cpp
void interrupt1ms()
{
static uint8_t pre_scale; // Used to get 10 Hz counter
@@ -74,7 +73,7 @@ void interrupt1ms()
debugCounter1ms++;
#endif
#if defined(HAPTIC)
#if defined(HAPTIC) && !defined(BOOT)
if (pre_scale == 5 || pre_scale == 10) {
DEBUG_TIMER_START(debugTimerHaptic);
HAPTIC_HEARTBEAT();
@@ -85,7 +84,7 @@ void interrupt1ms()
if (pre_scale == 10) {
pre_scale = 0;
#if !defined(SIMU)
hall_stick_loop();
if (boardState == BOARD_STARTED) hall_stick_loop();
#endif
DEBUG_TIMER_START(debugTimerPer10ms);
DEBUG_TIMER_SAMPLE(debugTimerPer10msPeriod);
@@ -96,18 +95,70 @@ void interrupt1ms()
DEBUG_TIMER_START(debugTimerRotEnc);
DEBUG_TIMER_STOP(debugTimerRotEnc);
}
#if !defined(BOOT)
extern "C" void INTERRUPT_xMS_IRQHandler()
{
INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF;
interrupt1ms();
DEBUG_INTERRUPT(INT_1MS);
}
#endif
#if defined(SEMIHOSTING)
extern "C" void initialise_monitor_handles();
#endif
void delay_self(int count)
{
for (int i = 50000; i > 0; i--)
{
for (; count > 0; count--);
}
}
#define RCC_AHB1PeriphMinimum (PWR_RCC_AHB1Periph |\
LCD_RCC_AHB1Periph |\
BACKLIGHT_RCC_AHB1Periph |\
SDRAM_RCC_AHB1Periph \
)
#define RCC_AHB1PeriphOther (SD_RCC_AHB1Periph |\
AUDIO_RCC_AHB1Periph |\
MONITOR_RCC_AHB1Periph |\
KEYS_RCC_AHB1Periph |\
ADC_RCC_AHB1Periph |\
AUX_SERIAL_RCC_AHB1Periph |\
TELEMETRY_RCC_AHB1Periph |\
TRAINER_RCC_AHB1Periph |\
AUDIO_RCC_AHB1Periph |\
HAPTIC_RCC_AHB1Periph |\
INTMODULE_RCC_AHB1Periph |\
INTMODULE_RCC_AHB1Periph|\
EXTMODULE_RCC_AHB1Periph\
)
#define RCC_AHB3PeriphMinimum (SDRAM_RCC_AHB3Periph)
#define RCC_APB1PeriphMinimum (INTERRUPT_xMS_RCC_APB1Periph |\
TIMER_2MHz_RCC_APB1Periph |\
BACKLIGHT_RCC_APB1Periph \
)
#define RCC_APB1PeriphOther (TELEMETRY_RCC_APB1Periph |\
TRAINER_RCC_APB1Periph |\
INTMODULE_RCC_APB1Periph |\
HALL_RCC_APB1Periph |\
EXTMODULE_RCC_APB1Periph |\
INTMODULE_RCC_APB1Periph |\
AUX_SERIAL_RCC_APB1Periph \
)
#define RCC_APB2PeriphMinimum (LCD_RCC_APB2Periph)
#define RCC_APB2PeriphOther (ADC_RCC_APB2Periph |\
HAPTIC_RCC_APB2Periph |\
AUX_SERIAL_RCC_APB2Periph |\
AUDIO_RCC_APB2Periph |\
EXTMODULE_RCC_APB2Periph \
)
void boardInit()
{
#if defined(SEMIHOSTING)
@@ -115,51 +166,15 @@ void boardInit()
#endif
#if !defined(SIMU)
RCC_AHB1PeriphClockCmd(PWR_RCC_AHB1Periph |
LCD_RCC_AHB1Periph |
BACKLIGHT_RCC_AHB1Periph |
SD_RCC_AHB1Periph |
SDRAM_RCC_AHB1Periph |
AUDIO_RCC_AHB1Periph |
MONITOR_RCC_AHB1Periph |
KEYS_RCC_AHB1Periph |
ADC_RCC_AHB1Periph |
AUX_SERIAL_RCC_AHB1Periph |
TELEMETRY_RCC_AHB1Periph |
TRAINER_RCC_AHB1Periph |
AUDIO_RCC_AHB1Periph |
HAPTIC_RCC_AHB1Periph |
INTMODULE_RCC_AHB1Periph |
HALL_RCC_AHB1Periph |
EXTMODULE_RCC_AHB1Periph,
ENABLE);
RCC_AHB3PeriphClockCmd(SDRAM_RCC_AHB3Periph,
ENABLE);
RCC_APB1PeriphClockCmd(INTERRUPT_xMS_RCC_APB1Periph |
TIMER_2MHz_RCC_APB1Periph |
TELEMETRY_RCC_APB1Periph |
TRAINER_RCC_APB1Periph |
INTMODULE_RCC_APB1Periph |
HALL_RCC_APB1Periph |
EXTMODULE_RCC_APB1Periph |
BACKLIGHT_RCC_APB1Periph,
ENABLE);
RCC_APB2PeriphClockCmd(LCD_RCC_APB2Periph |
ADC_RCC_APB2Periph |
HAPTIC_RCC_APB2Periph |
AUX_SERIAL_RCC_APB2Periph |
INTMODULE_RCC_APB2Periph |
AUDIO_RCC_APB2Periph |
EXTMODULE_RCC_APB2Periph,
ENABLE);
pwrInit();
RCC_AHB1PeriphClockCmd(RCC_AHB1PeriphMinimum | RCC_AHB1PeriphOther, ENABLE);
RCC_AHB3PeriphClockCmd(RCC_AHB3PeriphMinimum, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1PeriphMinimum | RCC_APB1PeriphOther, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2PeriphMinimum | RCC_APB2PeriphOther, ENABLE);
__enable_irq();
#endif
#if defined(DEBUG)
auxSerialInit(0, 0); // default serial mode (None if DEBUG nm ot defined)
auxSerialInit(0, 0); // default serial mode (None if DEBUG not defined)
#endif
__enable_irq();
@@ -167,52 +182,83 @@ void boardInit()
TRACE("\nNV14 board started :)");
delay_ms(10);
TRACE("RCC->CSR = %08x", RCC->CSR);
audioInit();
// we need to initialize g_FATFS_Obj here, because it is in .ram section (because of DMA access)
pwrInit();
extModuleInit();
battery_charge_init();
init2MhzTimer();
init1msTimer();
TouchInit();
uint32_t press_start = 0;
uint32_t press_end = 0;
if(UNEXPECTED_SHUTDOWN() || true) pwrOn();
while (boardState == BOARD_POWER_OFF)
{
uint32_t now = get_tmr10ms();
if (pwrPressed())
{
press_end = now;
if (press_start == 0) press_start = now;
if ((now - press_start) > POWER_ON_DELAY)
{
pwrOn();
break;
}
}
else {
uint32_t press_end_touch = press_end;
if(touchState.event == TE_UP)
{
touchState.event = TE_NONE;
press_end_touch = touchState.time;
}
press_start = 0;
handle_battery_charge(press_end_touch);
delay_ms(20);
press_end = 0;
}
}
keysInit();
audioInit();
// we need to initialize g_FATFS_Obj here, because it is in .ram section (because of DMA access)
// and this section is un-initialized
memset(&g_FATFS_Obj, 0, sizeof(g_FATFS_Obj));
init_battery_charge();
monitorInit();
keysInit();
adcInit();
backlightInit();
lcdInit();
#if defined(FLYSKY_HALL_STICKS)
hall_stick_init(FLYSKY_HALL_BAUDRATE);
#endif
init2MhzTimer();
init1msTimer();
usbInit();
hapticInit();
TouchInit();
boardState = BOARD_STARTED;
#if defined(DEBUG)
DBGMCU_APB1PeriphConfig(DBGMCU_IWDG_STOP|DBGMCU_TIM1_STOP|DBGMCU_TIM2_STOP|DBGMCU_TIM3_STOP|DBGMCU_TIM4_STOP|DBGMCU_TIM5_STOP|DBGMCU_TIM6_STOP|DBGMCU_TIM7_STOP|DBGMCU_TIM8_STOP|DBGMCU_TIM9_STOP|DBGMCU_TIM10_STOP|DBGMCU_TIM11_STOP|DBGMCU_TIM12_STOP|DBGMCU_TIM13_STOP|DBGMCU_TIM14_STOP, ENABLE);
#endif
#endif
}
void boardOff()
{
BACKLIGHT_DISABLE();
lcd->drawFilledRect(0, 0, LCD_WIDTH, LCD_HEIGHT, SOLID, HEADER_BGCOLOR);
lcdOff();
while (pwrPressed()) {
wdt_reset();
WDG_RESET();
}
SysTick->CTRL = 0; // turn off systick
pwrOff();
#if !defined (SIMU)
#if defined(HAPTIC) && !defined(BOOT)
haptic.event(AU_ERROR);
delay_ms(50);
#endif
while(1)
{
NVIC_SystemReset();
}
#endif
}
void init_intmodule_heartbeat()
{
}
+67 -22
View File
@@ -54,8 +54,8 @@
extern uint16_t sessionTimer;
#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE)
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_SET)
#define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
#define TRAINER_CONNECTED() (true)
PACK(typedef struct {
uint8_t pxx2Enabled:1;
@@ -95,7 +95,7 @@ uint32_t sdGetSpeed();
#define SD_IS_HC() (sdIsHC())
#define SD_GET_SPEED() (sdGetSpeed())
#define SD_GET_FREE_BLOCKNR() (sdGetFreeSectors())
#define SD_CARD_PRESENT() (true)
#define SD_CARD_PRESENT() (~SD_PRESENT_GPIO->IDR & SD_PRESENT_GPIO_PIN)
void sdInit();
void sdMount();
void sdDone();
@@ -133,8 +133,8 @@ void SDRAM_Init();
// Pulses driver
#define INTERNAL_MODULE_OFF() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
#define INTERNAL_MODULE_ON() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
#define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
void EXTERNAL_MODULE_ON();
void EXTERNAL_MODULE_OFF();
#define BLUETOOTH_MODULE_ON() GPIO_ResetBits(BLUETOOTH_ON_GPIO, BLUETOOTH_ON_GPIO_PIN)
#define BLUETOOTH_MODULE_OFF() GPIO_SetBits(BLUETOOTH_ON_GPIO, BLUETOOTH_ON_GPIO_PIN)
#define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET)
@@ -162,6 +162,17 @@ void stop_trainer_capture();
// Keys driver
enum EnumKeys
{
KEY_ENTER,
KEY_EXIT,
KEY_PGUP,
KEY_PGDN,
KEY_UP,
KEY_DOWN,
KEY_RIGHT,
KEY_LEFT,
KEY_TELEM,
KEY_MENU,
KEY_RADIO,
TRM_BASE,
TRM_LH_DWN = TRM_BASE,
TRM_LH_UP,
@@ -173,14 +184,32 @@ enum EnumKeys
TRM_RH_UP,
TRM_LS_DWN,
TRM_LS_UP,
TRM_RS_DWN,
TRM_RS_UP,
TRM_LAST = TRM_RS_UP,
TRM_LEFT_CLICK,
TRM_RIGHT_CLICK,
TRM_LAST = TRM_RIGHT_CLICK,
NUM_KEYS
};
#define IS_SHIFT_KEY(index) (false)
#define IS_SHIFT_PRESSED() (false)&é&é&é""
#define IS_SHIFT_PRESSED() (false)
enum VirtualKeys {
VKEY_MIN,
VKEY_MAX,
VKEY_INC,
VKEY_DEC,
VKEY_INC_LARGE,
VKEY_DEC_LARGE,
VKEY_DEFAULT,
};
enum LUATouchEvent {
TOUCH_DOWN = 1,
TOUCH_UP,
TOUCH_SLIDE_UP,
TOUCH_SLIDE_DOWN,
TOUCH_SLIDE_LEFT,
TOUCH_SLIDE_RIGHT,
};
enum EnumSwitches
{
@@ -228,6 +257,13 @@ enum EnumSwitchesPositions
};
#define STORAGE_NUM_SWITCHES_POSITIONS (STORAGE_NUM_SWITCHES * 3)
enum EnumPowerupState
{
BOARD_POWER_OFF = 0xCAFEDEAD,
BOARD_POWER_ON = 0xDEADBEEF,
BOARD_STARTED = 0xBAADF00D,
BOARD_REBOOT = 0xC00010FF,
};
void monitorInit();
void keysInit();
@@ -245,14 +281,15 @@ uint32_t readTrims();
#define DBLKEYS_PRESSED_LFT_DWN(in) (false)
// WDT driver
#define WDTO_500MS 500
extern uint32_t powerupReason;
extern uint32_t boardState;
#define SHUTDOWN_REQUEST 0xDEADBEEF
#define NO_SHUTDOWN_REQUEST ~SHUTDOWN_REQUEST
#define DIRTY_SHUTDOWN 0xCAFEDEAD
#define NORMAL_POWER_OFF ~DIRTY_SHUTDOWN
#define WDG_DURATION 500 /*ms*/
void watchdogInit(unsigned int duration);
#if defined(SIMU)
#define WAS_RESET_BY_WATCHDOG() (false)
@@ -336,10 +373,11 @@ void adcInit();
void adcRead();
uint16_t getAnalogValue(uint8_t index);
uint16_t getBatteryVoltage(); // returns current battery voltage in 10mV steps
uint16_t getBattery2Voltage(); // returns current battery voltage in 10mV steps
#define BATTERY_WARN 37 // 3.7V
#define BATTERY_WARN 36 // 3.6V
#define BATTERY_MIN 35 // 3.5V
#define BATTERY_MAX 43 // 4.3V
#define BATTERY_MAX 42 // 4.2V
#if defined(__cplusplus) && !defined(SIMU)
extern "C" {
@@ -347,20 +385,24 @@ extern "C" {
// Power driver
#define SOFT_PWR_CTRL
#define POWER_ON_DELAY 100 // 3s
void pwrInit();
void extModuleInit();
uint32_t pwrCheck();
#if defined(PCBFLYSKY)
uint32_t lowPowerCheck();
#endif
//TBD removed?!
uint8_t UsbModeSelect( uint32_t index );
void pwrOn();
void pwrSoftReboot();
void pwrOff();
void pwrResetHandler();
bool pwrPressed();
uint32_t pwrPressedDuration();
uint32_t pwrPressedDuration();;
#if defined(SIMU) || defined(NO_UNEXPECTED_SHUTDOWN)
#define UNEXPECTED_SHUTDOWN() (false)
#else
#define UNEXPECTED_SHUTDOWN() ((powerupReason == DIRTY_SHUTDOWN) || WAS_RESET_BY_WATCHDOG_OR_SOFTWARE())
#define UNEXPECTED_SHUTDOWN() (powerupReason == DIRTY_SHUTDOWN)
#endif
// LCD driver
@@ -377,7 +419,8 @@ void DMACopyBitmap(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x,
void DMACopyAlphaBitmap(uint16_t * dest, uint16_t destw, uint16_t desth, uint16_t x, uint16_t y, const uint16_t * src, uint16_t srcw, uint16_t srch, uint16_t srcx, uint16_t srcy, uint16_t w, uint16_t h);
void DMABitmapConvert(uint16_t * dest, const uint8_t * src, uint16_t w, uint16_t h, uint32_t format);
void lcdSetContrast();
#define lcdOff() backlightEnable(0) /* just disable the backlight */
void lcdOff();
void lcdOn();
#define lcdSetRefVolt(...)
#define lcdRefreshWait(...)
void lcdStoreBackupBuffer();
@@ -385,10 +428,12 @@ int lcdRestoreBackupBuffer();
// Backlight driver
void backlightInit();
#if defined(SIMU)
#if defined(SIMU) || !defined(__cplusplus)
#define backlightEnable(...)
#define isBacklightEnabled() (true)
#else
void backlightEnable(uint8_t dutyCycle);
void backlightEnable(uint8_t dutyCycle = 0);
bool isBacklightEnabled();
#endif
#define BACKLIGHT_LEVEL_MAX 100
@@ -396,12 +441,11 @@ void backlightEnable(uint8_t dutyCycle);
#define BACKLIGHT_ENABLE() backlightEnable(globalData.unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : BACKLIGHT_LEVEL_MAX-g_eeGeneral.backlightBright)
#define BACKLIGHT_DISABLE() backlightEnable(globalData.unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : ((g_eeGeneral.blOffBright == BACKLIGHT_LEVEL_MIN) && (g_eeGeneral.backlightMode != e_backlight_mode_off)) ? 0 : g_eeGeneral.blOffBright)
#define isBacklightEnabled() true
#if !defined(SIMU)
void usbJoystickUpdate();
#endif
#define USBD_MANUFACTURER_STRING "FlySky"
#define USB_NAME "FlySky NV14"
#define USB_MANUFACTURER 'F', 'l', 'y', 'S', 'k', 'y', ' ', ' ' /* 8 bytes */
#define USB_PRODUCT 'N', 'V', '1', '4', ' ', ' ', ' ', ' ' /* 8 Bytes */
@@ -419,6 +463,8 @@ void audioSpiSetSpeed(uint8_t speed);
uint8_t audioHardReset();
uint8_t audioSoftReset();
void audioSendRiffHeader();
void audioOn();
void audioOff();
#define SPI_SPEED_2 0
#define SPI_SPEED_4 1
@@ -490,5 +536,4 @@ extern AuxSerialRxFifo auxSerialRxFifo;
uint8_t touchPressed(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
#endif // _BOARD_H_
+52 -49
View File
@@ -1,11 +1,12 @@
#include "opentx.h"
#include "../../common/arm/stm32/bootloader/boot.h"
#include "../../common/arm/stm32/bootloader/bin_files.h"
#define SELECTED_COLOR (INVERS | DEFAULT_COLOR)
#include "bmp_plug_usb.lbm"
#include "bmp_usb_plugged.lbm"
#define DEFAULT_PADDING 28
#define DOUBLE_PADDING 56
#define MESSAGE_TOP (LCD_H - (2*DOUBLE_PADDING))
//#include "bmp_plug_usb.lbm"
//#include "bmp_usb_plugged.lbm"
const uint8_t LBM_FLASH[] = {
#include "icon_flash.lbm"
@@ -34,7 +35,7 @@ const uint8_t LBM_OK[] = {
void bootloaderInitScreen()
{
lcdColorTable[DEFAULT_COLOR_INDEX] = BLACK;
lcdColorTable[DEFAULT_BGCOLOR_INDEX] = WHITE;
lcdColorTable[DEFAULT_BGCOLOR_INDEX] = WHITE;
lcdColorTable[LINE_COLOR_INDEX] = RED;
lcdColorTable[BARGRAPH1_COLOR_INDEX] = RED;
lcdColorTable[BARGRAPH2_COLOR_INDEX] = RGB(73, 219, 62); // green
@@ -42,52 +43,54 @@ void bootloaderInitScreen()
backlightEnable(BACKLIGHT_LEVEL_MAX);
}
static void bootloaderDrawTitle(unsigned int x, const char* text)
static void bootloaderDrawTitle(const char* text)
{
lcdDrawText(x, 28, text);
lcdDrawSolidFilledRect(28, 56, 422, 2, DEFAULT_COLOR);
lcd->drawText(LCD_W/2, DEFAULT_PADDING, text, CENTERED | DEFAULT_COLOR);
lcd->drawSolidFilledRect(DEFAULT_PADDING, DOUBLE_PADDING, LCD_W - DOUBLE_PADDING, 2, DEFAULT_COLOR);
}
static void bootloaderDrawFooter()
{
lcdDrawSolidFilledRect(28, 234, 422, 2, DEFAULT_COLOR);
lcd->drawSolidFilledRect(DEFAULT_PADDING, LCD_H - (DOUBLE_PADDING + 4), LCD_W - DOUBLE_PADDING, 2, DEFAULT_COLOR);
}
void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
{
#if defined(COLORLCD)
lcdNextLayer();
#endif
// clear screen
lcdDrawSolidFilledRect(0, 0, LCD_W-1, LCD_H-1, DEFAULT_BGCOLOR);
lcd->drawSolidFilledRect(0, 0, LCD_W-1, LCD_H-1, DEFAULT_BGCOLOR);
int center = LCD_W/2;
if (st == ST_START) {
bootloaderDrawTitle(88, "HORUS BOOTLOADER");
bootloaderDrawTitle("NV14 BOOTLOADER");
lcdDrawBitmapPattern(90, 72, LBM_FLASH, DEFAULT_COLOR);
lcdDrawText(124, 75, "Write Firmware");
lcd->drawBitmapPattern(50, 72, LBM_FLASH, DEFAULT_COLOR);
lcd->drawText(84, 75, "Write Firmware");
lcdDrawBitmapPattern(90, 107, LBM_EXIT, DEFAULT_COLOR);
lcdDrawText(124, 110, "Exit");
lcd->drawBitmapPattern(50, 107, LBM_EXIT, DEFAULT_COLOR);
lcd->drawText(84, 110, "Exit");
lcdDrawSolidRect(119, (opt == 0) ? 72 : 107, 270, 26, 2, LINE_COLOR);
lcd->drawSolidRect(79, (opt == 0) ? 72 : 107, LCD_W - 79 - 28, 26, 2, LINE_COLOR);
lcd->drawBitmap(60, 166, &BMP_PLUG_USB);
lcdDrawText(195, 175, "Or plug in a USB cable");
lcdDrawText(195, 200, "for mass storage");
//lcd->drawBitmap(60, 166, &BMP_PLUG_USB);
lcd->drawText(center, 175, "Or plug in a USB cable", CENTERED | DEFAULT_COLOR);
lcd->drawText(center, 200, "for mass storage", CENTERED | DEFAULT_COLOR);
bootloaderDrawFooter();
lcdDrawText( 36, 242, "Current Firmware:");
lcdDrawText(200, 242, getOtherVersion(nullptr));
lcd->drawText(center, LCD_H - DOUBLE_PADDING, "Current Firmware:", CENTERED | DEFAULT_COLOR);
lcd->drawText(center, LCD_H - DEFAULT_PADDING, getOtherVersion(nullptr), CENTERED | DEFAULT_COLOR);
}
else if (st == ST_USB) {
lcd->drawBitmap(136, 98, &BMP_USB_PLUGGED);
lcdDrawText(195, 128, "USB Connected");
//lcd->drawBitmap(136, 98, &BMP_USB_PLUGGED);
lcd->drawText(center, 128, "USB Connected", CENTERED | DEFAULT_COLOR);
}
else if (st == ST_FILE_LIST || st == ST_DIR_CHECK || st == ST_FLASH_CHECK ||
st == ST_FLASHING || st == ST_FLASH_DONE) {
bootloaderDrawTitle(126, "SD>FIRMWARE");
lcdDrawBitmapPattern(87, 16, LBM_SD, DEFAULT_COLOR);
bootloaderDrawTitle("SD>FIRMWARE");
lcd->drawBitmapPattern(DEFAULT_PADDING, 16, LBM_SD, DEFAULT_COLOR);
if (st == ST_FLASHING || st == ST_FLASH_DONE) {
@@ -98,39 +101,39 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
opt = 100; // Completed > 100%
}
lcdDrawRect(70, 120, 340, 31, 2);
lcdDrawSolidFilledRect(74, 124, (332 * opt) / 100, 23, color);
lcd->drawRect(DEFAULT_PADDING, 120, LCD_W - DOUBLE_PADDING, 31, 2);
lcd->drawSolidFilledRect(DEFAULT_PADDING+4, 124, ((LCD_W - DOUBLE_PADDING - 8) * opt) / 100, 23, color);
}
else if (st == ST_DIR_CHECK) {
if (opt == FR_NO_PATH) {
lcdDrawText(90, 168, "Directory is missing");
lcd->drawText(20, MESSAGE_TOP, "Directory is missing");
}
else {
lcdDrawText(90, 168, "Directory is empty");
lcd->drawText(20, MESSAGE_TOP, "Directory is empty");
}
lcdDrawBitmapPattern(356, 158, LBM_ERROR, BARGRAPH1_COLOR);
lcd->drawBitmapPattern(LCD_W - DOUBLE_PADDING, MESSAGE_TOP-10, LBM_ERROR, BARGRAPH1_COLOR);
}
else if (st == ST_FLASH_CHECK) {
bootloaderDrawFilename(str, 0, true);
if (opt == FC_ERROR) {
lcdDrawText(94, 168, STR_INVALID_FIRMWARE);
lcdDrawBitmapPattern(356, 158, LBM_ERROR, BARGRAPH1_COLOR);
lcd->drawText(20, MESSAGE_TOP, STR_INVALID_FIRMWARE);
lcd->drawBitmapPattern(LCD_W - DOUBLE_PADDING, MESSAGE_TOP-10, LBM_ERROR, BARGRAPH1_COLOR);
}
else if (opt == FC_OK) {
VersionTag tag;
extractFirmwareVersion(&tag);
lcdDrawText(168, 158, "Version:", RIGHT);
lcdDrawText(174, 158, tag.version);
lcd->drawText(LCD_W/4 + DEFAULT_PADDING, MESSAGE_TOP, "Version:", RIGHT);
lcd->drawText(LCD_W/4 + 6 + DEFAULT_PADDING, MESSAGE_TOP, tag.version);
lcdDrawText(168, 178, "Radio:", RIGHT);
lcdDrawText(174, 178, tag.flavour);
lcd->drawText(LCD_W/4 + DEFAULT_PADDING, MESSAGE_TOP + DEFAULT_PADDING, "Radio:", RIGHT);
lcd->drawText(LCD_W/4 + 6 + DEFAULT_PADDING, MESSAGE_TOP + DEFAULT_PADDING, tag.flavour);
lcdDrawBitmapPattern(356, 158, LBM_OK, BARGRAPH2_COLOR);
lcd->drawBitmapPattern(LCD_W - DOUBLE_PADDING, MESSAGE_TOP-10, LBM_OK, BARGRAPH2_COLOR);
}
}
@@ -138,35 +141,35 @@ void bootloaderDrawScreen(BootloaderState st, int opt, const char* str)
if ( st != ST_DIR_CHECK && (st != ST_FLASH_CHECK || opt == FC_OK)) {
lcdDrawBitmapPattern(28, 242, LBM_FLASH, DEFAULT_COLOR);
lcd->drawBitmapPattern(DEFAULT_PADDING, LCD_H - DOUBLE_PADDING - 2, LBM_FLASH, DEFAULT_COLOR);
if (st == ST_FILE_LIST) {
lcdDrawText(56, 244, "[ENT] to select file");
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING, "[R TRIM] to select file");
}
else if (st == ST_FLASH_CHECK && opt == FC_OK) {
lcdDrawText(56, 244, "Hold [ENT] long to flash");
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING, "Hold [R TRIM] long to flash");
}
else if (st == ST_FLASHING) {
lcdDrawText(56, 244, "Writing Firmware ...");
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING, "Writing Firmware ...");
}
else if (st == ST_FLASH_DONE) {
lcdDrawText(56, 244, "Writing Completed");
lcd->drawText(DOUBLE_PADDING, LCD_H - DOUBLE_PADDING, "Writing Completed");
}
}
if (st != ST_FLASHING) {
lcdDrawBitmapPattern(305, 242, LBM_EXIT, DEFAULT_COLOR);
lcdDrawText(335, 244, "[RTN] to exit");
lcd->drawBitmapPattern(DEFAULT_PADDING, LCD_H - DEFAULT_PADDING - 2, LBM_EXIT, DEFAULT_COLOR);
lcd->drawText(DOUBLE_PADDING, LCD_H - DEFAULT_PADDING, "[L TRIM] to exit");
}
}
}
void bootloaderDrawFilename(const char* str, uint8_t line, bool selected)
{
lcdDrawBitmapPattern(94, 76 + (line * 25), LBM_FILE, DEFAULT_COLOR);
lcdDrawText(124, 75 + (line * 25), str);
lcd->drawBitmapPattern(DEFAULT_PADDING, 76 + (line * 25), LBM_FILE, DEFAULT_COLOR);
lcd->drawText(DEFAULT_PADDING + 30, 75 + (line * 25), str);
if (selected) {
lcdDrawSolidRect(119, 72 + (line * 25), 278, 26, 2, LINE_COLOR);
lcd->drawSolidRect(DEFAULT_PADDING + 25, 72 + (line * 25), LCD_W - (DEFAULT_PADDING + 25) - 28, 26, 2, LINE_COLOR);
}
}
+47 -50
View File
@@ -19,6 +19,49 @@
*/
#include "opentx.h"
//fix it
#if defined(EXTMODULE_USART)
ModuleFifo extmoduleFifo;
#endif
bool stopOnTxDone = false;
void extmoduleSendNextFrame();
void EXTERNAL_MODULE_ON()
{
GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
GPIO_ResetBits(EXTMODULE_PWR_FIX_GPIO, EXTMODULE_PWR_FIX_GPIO_PIN);
}
void EXTERNAL_MODULE_OFF()
{
GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
GPIO_SetBits(EXTMODULE_PWR_FIX_GPIO, EXTMODULE_PWR_FIX_GPIO_PIN);
}
void extModuleInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PWR_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
GPIO_Init(EXTMODULE_PWR_GPIO, &GPIO_InitStructure);
//for additional transistor to ensuring module is completely disabled
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
//pin must be pulled to V+ (voltage of board - VCC is not enough to fully close transistor)
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PWR_FIX_GPIO_PIN;
GPIO_SetBits(EXTMODULE_PWR_FIX_GPIO, EXTMODULE_PWR_FIX_GPIO_PIN);
GPIO_Init(EXTMODULE_PWR_FIX_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_INVERT_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(EXTMODULE_TX_INVERT_GPIO, &GPIO_InitStructure);
GPIO_SetBits(EXTMODULE_TX_INVERT_GPIO, EXTMODULE_TX_INVERT_GPIO_PIN);
}
void extmoduleStop()
{
@@ -89,27 +132,13 @@ void extmodulePpmStart()
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop timer
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
EXTMODULE_TIMER->ARR = 45000;
#if defined(PCBX10) || PCBREV >= 13
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
EXTMODULE_TIMER->EGR = 1; // Reloads register values now
EXTMODULE_TIMER->DIER = TIM_DIER_UDE; // Update DMA request
EXTMODULE_TIMER->CR1 = TIM_CR1_CEN; // Start timer
#elif defined(PCBNV14)
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; // PWM mode 1
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
EXTMODULE_TIMER->EGR = 1; // Reloads register values now
EXTMODULE_TIMER->DIER = TIM_DIER_UDE; // Update DMA request
EXTMODULE_TIMER->CR1 = TIM_CR1_CEN; // Start timer
#else
EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
EXTMODULE_TIMER->EGR = 1; // Reloads register values now
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Update DMA request
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN; // Start timer
#endif
extmoduleSendNextFrame();
@@ -143,28 +172,8 @@ void extmodulePxxStart()
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
EXTMODULE_TIMER->ARR = 18000;
#if defined(PCBX10) || PCBREV >= 13
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE;
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
EXTMODULE_TIMER->CCR3 = 18;
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high
EXTMODULE_TIMER->EGR = 1; // Restart
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
#elif defined(PCBNV14)
{
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE;
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
EXTMODULE_TIMER->CCR1 = 18;
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
EXTMODULE_TIMER->EGR = 1; // Restart
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
}
#else
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P | TIM_CCER_CC1NE | TIM_CCER_CC1NP; // TIM_CCER_CC1E | TIM_CCER_CC1P;
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1NE;
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
EXTMODULE_TIMER->CCR1 = 18;
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
@@ -172,7 +181,6 @@ void extmodulePxxStart()
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
#endif
extmoduleSendNextFrame();
@@ -201,16 +209,6 @@ void extmoduleDsm2Start()
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
EXTMODULE_TIMER->ARR = 44000; // 22mS
#if defined(PCBX10) || PCBREV >= 13
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3P;
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
EXTMODULE_TIMER->CCR3 = 0;
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high
EXTMODULE_TIMER->EGR = 1; // Restart
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
EXTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
#else
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC1P;
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
EXTMODULE_TIMER->CCR1 = 0;
@@ -219,7 +217,6 @@ void extmoduleDsm2Start()
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0;
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
#endif
extmoduleSendNextFrame();
+113 -30
View File
@@ -97,10 +97,17 @@
// ADC
#define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_DMA2)
#define ADC_RCC_APB2Periph (RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC3)
#if !defined(HALL_STICKS)
#define ADC_GPIO_PIN_STICK_LH GPIO_Pin_2 // PA.02
#define ADC_GPIO_PIN_STICK_LV GPIO_Pin_3 // PA.03
#define ADC_GPIO_PIN_STICK_RH GPIO_Pin_4 // PA.04
#define ADC_GPIO_PIN_STICK_RV GPIO_Pin_5 // PA.05
#else
#define ADC_GPIO_PIN_STICK_LH 0
#define ADC_GPIO_PIN_STICK_LV 0
#define ADC_GPIO_PIN_STICK_RH 0
#define ADC_GPIO_PIN_STICK_RV 0
#endif
#define ADC_GPIO_PIN_POT1 GPIO_Pin_6 // PA.06 VRA
#define ADC_GPIO_PIN_POT2 GPIO_Pin_4 // PC.04 VRB
#define ADC_GPIO_PIN_SWA GPIO_Pin_1 // PB.01
@@ -118,10 +125,12 @@
#define ADC_GPIOC_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5)
#define ADC_GPIOF_PINS (GPIO_Pin_8 | GPIO_Pin_10)
#if !defined(HALL_STICKS)
#define ADC_CHANNEL_STICK_LH ADC_Channel_2 // ADC123_IN2 -> ADC1_IN2
#define ADC_CHANNEL_STICK_LV ADC_Channel_3 // ADC123_IN3 -> ADC1_IN3
#define ADC_CHANNEL_STICK_RH ADC_Channel_4 // ADC12_IN4 -> ADC1_IN4
#define ADC_CHANNEL_STICK_RV ADC_Channel_5 // ADC12_IN5 -> ADC1_IN5
#endif
#define ADC_CHANNEL_POT1 ADC_Channel_6 // ADC12_IN6 -> ADC1_IN6
#define ADC_CHANNEL_POT2 ADC_Channel_14 // ADC12_IN14 -> ADC1_IN14
#define ADC_CHANNEL_SWA ADC_Channel_9 // ADC12_IN9 -> ADC1_IN9
@@ -193,6 +202,9 @@
#define AUX_SERIAL_RX_INVERT_GPIO GPIOI
#define AUX_SERIAL_RX_INVERT_GPIO_PIN GPIO_Pin_15 // PI.15
//used in BOOTLOADER
#define SERIAL_RCC_AHB1Periph 0
#define SERIAL_RCC_APB1Periph 0
// Telemetry
#define TELEMETRY_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_DMA1)
#define TELEMETRY_RCC_APB1Periph RCC_APB1Periph_USART2
@@ -252,6 +264,7 @@
// TODO TIM3, TIM8, TIM14, review the channel in backlight_driver.cpp according to the chosen timer
#define BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define BACKLIGHT_RCC_APB1Periph RCC_APB1Periph_TIM2
#define BACKLIGHT_RCC_APB2Periph 0
#define BACKLIGHT_GPIO GPIOA
#define BACKLIGHT_GPIO_PIN GPIO_Pin_15
#define BACKLIGHT_GPIO_PinSource GPIO_PinSource15
@@ -259,9 +272,16 @@
#define BACKLIGHT_GPIO_AF GPIO_AF_TIM2
#define BACKLIGHT_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
//used in BOOTLOADER
#define SERIAL_RCC_AHB1Periph 0
#define SERIAL_RCC_APB1Periph 0
#define ROTARY_ENCODER_RCC_APB1Periph 0
// SD card
#define SD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
#define SD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_DMA2)
#define SD_RCC_APB1Periph 0
#define SD_PRESENT_GPIO GPIOH
#define SD_PRESENT_GPIO_PIN GPIO_Pin_10 // PH.10
#define SD_SDIO_DMA_STREAM DMA2_Stream3
#define SD_SDIO_DMA_CHANNEL DMA_Channel_4
#define SD_SDIO_DMA_FLAG_FEIF DMA_FLAG_FEIF3
@@ -324,18 +344,18 @@
#define I2C_RCC_AHB1Periph 0
#define I2C_RCC_APB1Periph 0
// Haptic: TIM1_CH2
// Haptic: TIM1_CH1
#define HAPTIC_PWM
#define HAPTIC_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define HAPTIC_RCC_APB2Periph RCC_APB2ENR_TIM1EN
#define HAPTIC_GPIO GPIOA
#define HAPTIC_GPIO_PIN GPIO_Pin_9
#define HAPTIC_GPIO_PIN GPIO_Pin_8
#define HAPTIC_GPIO_TIMER TIM1
#define HAPTIC_GPIO_AF GPIO_AF_TIM1
#define HAPTIC_GPIO_PinSource GPIO_PinSource9
#define HAPTIC_TIMER_OUTPUT_ENABLE TIM_CCER_CC2E
#define HAPTIC_TIMER_MODE TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2
#define HAPTIC_TIMER_COMPARE_VALUE HAPTIC_GPIO_TIMER->CCR2
#define HAPTIC_GPIO_PinSource GPIO_PinSource8
#define HAPTIC_TIMER_OUTPUT_ENABLE TIM_CCER_CC1E | TIM_CCER_CC1NE;
#define HAPTIC_TIMER_MODE TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE
#define HAPTIC_TIMER_COMPARE_VALUE HAPTIC_GPIO_TIMER->CCR1
// Internal Module
#define HARDWARE_INTERNAL_MODULE
@@ -359,42 +379,73 @@
#define INTMODULE_TX_DMA_Stream_IRQn DMA1_Stream1_IRQn
#define INTMODULE_TX_DMA_Stream_IRQHandler DMA1_Stream1_IRQHandler
#define INTMODULE_TX_DMA_FLAG_TC DMA_IT_TCIF1
//TX new implementation
#define INTMODULE_DMA_STREAM DMA1_Stream1
#define INTMODULE_DMA_CHANNEL DMA_Channel_5
#define INTMODULE_GPIO INTMODULE_TX_GPIO
//#define INTMODULE_DMA_STREAM_IRQ INTMODULE_RX_DMA_Stream_IRQHandler
#define INTMODULE_DMA_STREAM_IRQ INTMODULE_TX_DMA_Stream_IRQn
#define INTMODULE_RCC_APB1Periph (RCC_APB1Periph_UART7)
#define INTMODULE_RCC_APB2Periph (RCC_APB2Periph_TIM1)
#define INTMODULE_TIMER TIM1
#define INTMODULE_TIMER_IRQn TIM1_CC_IRQn
#define INTMODULE_TIMER_IRQHandler TIM1_CC_IRQHandler
#define INTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
#define INTMODULE_RCC_APB1Periph (RCC_APB1Periph_UART7 | RCC_APB1Periph_TIM3)
#define INTMODULE_RCC_APB2Periph 0
#define INTMODULE_TIMER TIM3
#define INTMODULE_TIMER_IRQn TIM3_IRQn
#define INTMODULE_TIMER_IRQHandler TIM3_IRQHandler
#define INTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
// External Module
#define EXTMODULE
#define EXTMODULE_PULSES
#define EXTMODULE_PWR_GPIO GPIOD
#define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_11
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2)
#define EXTMODULE_PWR_FIX_GPIO GPIOA
#define EXTMODULE_PWR_FIX_GPIO_PIN GPIO_Pin_2 // PA.02
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_DMA2)
#define EXTMODULE_RCC_APB1Periph 0
#define EXTMODULE_RCC_APB2Periph RCC_APB2Periph_TIM8
#define EXTMODULE_RCC_APB2Periph (RCC_APB2Periph_TIM8 | RCC_APB2Periph_USART6)
#define EXTMODULE_TX_GPIO GPIOC
#define EXTMODULE_TX_GPIO_PIN GPIO_Pin_6 // PC.06
#define EXTMODULE_TX_GPIO_PinSource GPIO_PinSource6
#define EXTMODULE_TX_GPIO_AF GPIO_AF_TIM8
#define EXTMODULE_TX_GPIO_AF_USART GPIO_AF_USART6
#define EXTMODULE_RX_GPIO GPIOC
#define EXTMODULE_RX_GPIO_PIN GPIO_Pin_7 // PC.07
#define EXTMODULE_RX_GPIO_PinSource GPIO_PinSource7
#define EXTMODULE_RX_GPIO_AF_USART GPIO_AF_USART6
#define EXTMODULE_TIMER TIM8
#define EXTMODULE_TIMER_IRQn TIM8_CC_IRQn
#define EXTMODULE_TIMER_IRQHandler TIM8_CC_IRQHandler
#define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB1)
#define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
//USART
#define EXTMODULE_USART_TX_DMA_CHANNEL DMA_Channel_5
#define EXTMODULE_USART_TX_DMA_STREAM DMA2_Stream7
#define EXTMODULE_USART_TX_DMA_IRQn DMA2_Stream7_IRQn
#define EXTMODULE_USART_TX_DMA_IRQHandler DMA2_Stream7_IRQHandler
#define EXTMODULE_USART_TX_DMA_FLAG_TC DMA_IT_TCIF7
#define EXTMODULE_USART_RX_DMA_CHANNEL DMA_Channel_5
#define EXTMODULE_USART_RX_DMA_STREAM DMA2_Stream2
#define EXTMODULE_USART_RX_DMA_IRQn DMA2_Stream5_IRQn
#define EXTMODULE_USART_RX_DMA_IRQHandler DMA2_Stream5_IRQHandler
#define EXTMODULE_USART_RX_DMA_FLAG_TC DMA_IT_TCIF5
#define EXTMODULE_USART_IRQHandler USART6_IRQHandler
#define EXTMODULE_USART_IRQn USART6_IRQn
//TIMER
#define EXTMODULE_DMA_CHANNEL DMA_Channel_7
#define EXTMODULE_DMA_STREAM DMA2_Stream1
#define EXTMODULE_DMA_IRQn DMA2_Stream1_IRQn
#define EXTMODULE_DMA_IRQHandler DMA2_Stream1_IRQHandler
#define EXTMODULE_DMA_FLAG_TC DMA_IT_TCIF1
//#define EXTMODULE_USART USART6 // TODO
#define EXTMODULE_USART USART6
#define EXTMODULE_TX_INVERT_GPIO GPIOE
#define EXTMODULE_TX_INVERT_GPIO_PIN GPIO_Pin_3 // PE.03
#define EXTMODULE_RX_INVERT_GPIO GPIOI
#define EXTMODULE_RX_INVERT_GPIO_PIN GPIO_Pin_15 // PI.15
// Heartbeat (not used)
#define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
@@ -410,20 +461,52 @@
#define TRAINER_IN_GPIO_PinSource GPIO_PinSource12
#define TRAINER_OUT_GPIO_PIN GPIO_Pin_13 // PD.13
#define TRAINER_OUT_GPIO_PinSource GPIO_PinSource13
// #define TRAINER_DETECT_GPIO GPIOB
// #define TRAINER_DETECT_GPIO_PIN GPIO_Pin_4 // PB.04
#define TRAINER_TIMER TIM4
#define TRAINER_TIMER_IRQn TIM4_IRQn
#define TRAINER_GPIO_AF GPIO_AF_TIM4 // TIM4_CH1 (in) + TIM4_CH2 (out)
#define TRAINER_OUT_DMA DMA1
// #define TRAINER_OUT_DMA_CHANNEL DMA_Channel_2
// #define TRAINER_OUT_DMA_STREAM DMA1_Stream3
// #define TRAINER_OUT_DMA_IRQn DMA1_Stream3_IRQn
// #define TRAINER_OUT_DMA_IRQHandler DMA1_Stream3_IRQHandler
// #define TRAINER_OUT_DMA_FLAG_TC DMA_IT_TCIF3
#define TRAINER_EXTMODULE_TIMER_IRQn TIM4_IRQn
#define TRAINER_EXTMODULE_TIMER_IRQHandler TIM4_IRQHandler
#define TRAINER_EXTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#define TRAINER_TIMER_IRQn TIM4_IRQn
#define TRAINER_TIMER_IRQHandler TIM4_IRQHandler
#define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#define TRAINER_OUT_CCMR1 TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE;
#define TRAINER_IN_CCMR1 TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_CC1S_0;
#define TRAINER_OUT_COUNTER_REGISTER TRAINER_TIMER->CCR2
#define TRAINER_IN_COUNTER_REGISTER TRAINER_TIMER->CCR1
#define TRAINER_SETUP_REGISTER TRAINER_TIMER->CCR3
#define TRAINER_OUT_INTERRUPT_FLAG TIM_SR_CC1IF
#define TRAINER_OUT_INTERRUPT_ENABLE TIM_DIER_CC1IE
#define TRAINER_IN_INTERRUPT_ENABLE TIM_DIER_CC1IE
#define TRAINER_IN_INTERRUPT_FLAG TIM_SR_CC1IF
#define TRAINER_OUT_CCER TIM_CCER_CC2E
#define TRAINER_CCER_POLARYTY TIM_CCER_CC2P
#define TRAINER_IN_CCER TIM_CCER_CC1E
/*
#define TRAINER_MODULE_SBUS_GPIO EXTMODULE_USART_GPIO
#define TRAINER_MODULE_SBUS_GPIO_PIN EXTMODULE_RX_GPIO_PIN
#define TRAINER_MODULE_SBUS_GPIO_AF EXTMODULE_USART_GPIO_AF
#define TRAINER_MODULE_SBUS_USART EXTMODULE_USART
#define TRAINER_MODULE_SBUS_GPIO_PinSource EXTMODULE_RX_GPIO_PinSource
#define TRAINER_MODULE_SBUS_DMA_STREAM EXTMODULE_DMA_STREAM
#define TRAINER_MODULE_SBUS_DMA_CHANNEL EXTMODULE_DMA_CHANNEL
*/
/*
#define TRAINER_MODULE_CPPM_GPIO EXTMODULE_USART_GPIO
#define TRAINER_MODULE_CPPM_GPIO_PIN EXTMODULE_RX_GPIO_PIN
#define TRAINER_MODULE_CPPM_GPIO_PinSource EXTMODULE_RX_GPIO_PinSource
#define TRAINER_MODULE_CPPM_GPIO_AF GPIO_AF_TIM3
#define TRAINER_MODULE_CPPM_TIMER TIM3
#define TRAINER_MODULE_CPPM_COUNTER_REGISTER TRAINER_MODULE_CPPM_TIMER->CCR2
#define TRAINER_MODULE_CPPM_INTERRUPT_ENABLE TIM_DIER_CC2IE
#define TRAINER_MODULE_CPPM_INTERRUPT_FLAG TIM_SR_CC2IF
#define TRAINER_MODULE_CPPM_CCMR1 (TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_CC2S_0)
#define TRAINER_MODULE_CPPM_CCER TIM_CCER_CC2E
#define TRAINER_MODULE_CPPM_TIMER_IRQn TIM3_IRQn
#define TRAINER_MODULE_CPPM_TIMER_IRQHandler TIM3_IRQHandler
*/
// Xms Interrupt
#define INTERRUPT_xMS_RCC_APB1Periph RCC_APB1Periph_TIM14
+62 -55
View File
@@ -19,6 +19,7 @@
*/
#include "opentx.h"
#include "pulses/flysky.h"
DMAFifo<HALLSTICK_BUFF_SIZE> hallDMAFifo __DMA (HALL_DMA_Stream_RX);
Fifo<uint8_t, HALLSTICK_BUFF_SIZE> hallStickTxFifo;
@@ -27,9 +28,9 @@ unsigned char HallCmd[264] __DMA;
STRUCT_HALL HallProtocol = { 0 };
STRUCT_HALL HallProtocolTx = { 0 };
STRUCT_HALL_CHANNEL Channel;
STRUCT_STICK_CALIBRATION StickCallbration[4] = { {0, 0, 0} };
unsigned short HallChVal[4];
signed short hall_raw_values[FLYSKY_HALL_CHANNEL_COUNT];
STRUCT_STICK_CALIBRATION hall_calibration[FLYSKY_HALL_CHANNEL_COUNT] = { {0, 0, 0} };
unsigned short hall_adc_values[FLYSKY_HALL_CHANNEL_COUNT];
/* crc16 implementation according to CCITT standards */
const unsigned short CRC16Table[256]= {
@@ -92,14 +93,14 @@ uint16_t get_hall_adc_value(uint8_t ch)
#if defined(FLYSKY_HALL_STICKS_REVERSE)
ch = sticks_mapping[ch];
return MAX_ADC_CHANNEL_VALUE - HallChVal[ch];
return MAX_ADC_CHANNEL_VALUE - hall_adc_values[ch];
#else
if (ch < 2)
{
return MAX_ADC_CHANNEL_VALUE - HallChVal[ch];
return MAX_ADC_CHANNEL_VALUE - hall_adc_values[ch];
}
return HallChVal[ch];
return hall_adc_values[ch];
#endif
}
@@ -175,11 +176,10 @@ void hall_stick_init(uint32_t baudrate)
void HallSendBuffer(uint8_t * buffer, uint32_t count)
{
for(int idx = 0; buffer != HallCmd && idx < count; idx++)
for(uint32_t idx = 0; buffer != HallCmd && idx < count; idx++)
{
HallCmd[idx] = buffer[idx];
}
DMA_InitTypeDef DMA_InitStructure;
DMA_DeInit(HALL_DMA_Stream_TX);
DMA_InitStructure.DMA_Channel = HALL_DMA_Channel;
@@ -228,7 +228,7 @@ void reset_hall_stick( void )
{
unsigned short crc16 = 0xffff;
HallCmd[0] = 0x55;
HallCmd[0] = HALL_PROTOLO_HEAD;
HallCmd[1] = 0xD1;
HallCmd[2] = 0x01;
HallCmd[3] = 0x01;
@@ -245,7 +245,7 @@ void get_hall_config( void )
{
unsigned short crc16 = 0xffff;
HallCmd[0] = 0x55;
HallCmd[0] = HALL_PROTOLO_HEAD;
HallCmd[1] = 0xD1;
HallCmd[2] = 0x01;
HallCmd[3] = 0x00;
@@ -262,7 +262,7 @@ void get_hall_firmware_info()
{
unsigned short crc16 = 0xffff;
HallCmd[0] = 0x55;
HallCmd[0] = HALL_PROTOLO_HEAD;
HallCmd[1] = 0xA2;
HallCmd[2] = 0x00;
@@ -278,7 +278,7 @@ void hallStickUpdatefwEnd( void )
{
unsigned short crc16 = 0xffff;
HallCmd[0] = 0x55;
HallCmd[0] = HALL_PROTOLO_HEAD;
HallCmd[1] = 0xA2;
HallCmd[2] = 0x01;
HallCmd[3] = 0x07;
@@ -380,36 +380,36 @@ exit: parse_ps_state = 0;
return ;
}
#define ERROR_OFFSET 10
void convert_hall_to_adcVaule( void )
{
uint16_t value;
for ( uint8_t i = 0; i < 4; i++ )
for ( uint8_t channel = 0; channel < 4; channel++ )
{
if (Channel.channel[i] < StickCallbration[i].mid)
if (hall_raw_values[channel] < hall_calibration[channel].mid)
{
value = StickCallbration[i].mid - StickCallbration[i].min;
value = ( MIDDLE_ADC_CHANNLE_VALUE * (StickCallbration[i].mid - Channel.channel[i] ) ) / ( value );
value = hall_calibration[channel].mid - (hall_calibration[channel].min+ERROR_OFFSET);
value = ( MIDDLE_ADC_CHANNLE_VALUE * (hall_calibration[channel].mid - hall_raw_values[channel] ) ) / ( value );
if (value >= MIDDLE_ADC_CHANNLE_VALUE ) {
value = MIDDLE_ADC_CHANNLE_VALUE;
}
HallChVal[i] = MIDDLE_ADC_CHANNLE_VALUE - value;
hall_adc_values[channel] = MIDDLE_ADC_CHANNLE_VALUE - value;
}
else
{
value = StickCallbration[i].max - StickCallbration[i].mid;
value = (hall_calibration[channel].max - ERROR_OFFSET) - hall_calibration[channel].mid;
value = ( MIDDLE_ADC_CHANNLE_VALUE * (Channel.channel[i] - StickCallbration[i].mid ) ) / (value );
value = ( MIDDLE_ADC_CHANNLE_VALUE * (hall_raw_values[channel] - hall_calibration[channel].mid ) ) / (value );
if (value >= MIDDLE_ADC_CHANNLE_VALUE )
{
value = MIDDLE_ADC_CHANNLE_VALUE;
}
HallChVal[i] = MIDDLE_ADC_CHANNLE_VALUE + value + 1;
hall_adc_values[channel] = MIDDLE_ADC_CHANNLE_VALUE + value + 1;
}
}
}
@@ -494,7 +494,7 @@ void hallStick_GetTxDataFromUSB( void )
break;
case TRANSFER_DIR_HALLSTICK:
// onFlySkyUsbDownloadStart(TRANSFER_DIR_HALLSTICK);
onFlySkyUsbDownloadStart(TRANSFER_DIR_HALLSTICK);
if ( 0xA2 == HallProtocolTx.hallID.ID )
{
@@ -513,17 +513,23 @@ void hallStick_GetTxDataFromUSB( void )
break;
case TRANSFER_DIR_RFMODULE:
// onFlySkyUsbDownloadStart(TRANSFER_DIR_RFMODULE);
onFlySkyUsbDownloadStart(TRANSFER_DIR_RFMODULE);
if ( 0xAE == HallProtocolTx.hallID.ID && HallProtocolTx.length == 0 )
{ // 55 AE 00 D3 47
// onIntmoduleUsbDownloadStart(INTERNAL_MODULE);
{
setFlyskyState(INTERNAL_MODULE, FLYSKY_MODULE_STATE_UPDATE_RF_FIRMWARE);
break;
}
if ( 0x0D == HallProtocolTx.hallID.hall_Id.packetID && HallProtocolTx.data[0] == 1 )
{
onFlySkyGetVersionInfoStart(INTERNAL_MODULE, 1);
break;
}
//if ( isFlySkyUsbDownload() )
{
// intmoduleSendBufferDMA( pt, HallProtocolTx.length + 3 + 2 );
intmoduleSendBuffer( pt, HallProtocolTx.length + 3 + 2 );
}
break;
}
@@ -532,7 +538,7 @@ void hallStick_GetTxDataFromUSB( void )
if ( !usbPlugged() )
{
// onFlySkyUsbDownloadStart(0);
onFlySkyUsbDownloadStart(0);
}
}
@@ -540,19 +546,24 @@ void hallStick_GetTxDataFromUSB( void )
/* Run it in 1ms timer routine */
void hall_stick_loop(void)
{
unsigned char ch;
static unsigned int getCfgTime = get_tmr10ms();
uint32_t printf_log_now = 0;
static uint8_t count = 0;
static tmr10ms_t lastConfigTime = get_tmr10ms();
bool log = 0;
hallStick_GetTxDataFromUSB();
hallstick_send_by_state();
while( HallGetByte(&ch) )
if(count>10)
{
count = 0;
hallstick_send_by_state();
}
count++;
uint8_t byte;
while(HallGetByte(&byte))
{
HallProtocol.index++;
Parse_Character(&HallProtocol, ch );
Parse_Character(&HallProtocol, byte);
if ( HallProtocol.msg_OK )
{
@@ -562,46 +573,42 @@ void hall_stick_loop(void)
switch ( HallProtocol.hallID.hall_Id.receiverID )
{
case TRANSFER_DIR_TXMCU:
if ( 0x0e == HallProtocol.hallID.hall_Id.packetID )
{
memcpy(&StickCallbration, HallProtocol.data, sizeof(StickCallbration));
if(HallProtocol.hallID.hall_Id.packetID == HALL_RESP_TYPE_CALIB) {
memcpy(&hall_calibration, HallProtocol.data, sizeof(hall_calibration));
}
else if(HallProtocol.hallID.hall_Id.packetID == HALL_RESP_TYPE_VALUES) {
memcpy(hall_raw_values, HallProtocol.data, sizeof(hall_raw_values));
convert_hall_to_adcVaule();
}
else if ( 0x0c == HallProtocol.hallID.hall_Id.packetID )
{
memcpy(&Channel, HallProtocol.data, sizeof(Channel));
convert_hall_to_adcVaule();
}
break;
case TRANSFER_DIR_HOSTPC:
if ( 0x01 == HallProtocol.length &&
( 0x05 == HallProtocol.data[0] || 0x06 == HallProtocol.data[0]) )
if (HallProtocol.length == 0x01 && (HallProtocol.data[0] == 0x05 || HallProtocol.data[0] == 0x06) )
{
hallStickSendState = HALLSTICK_SEND_STATE_IDLE;
}
case TRANSFER_DIR_HALLSTICK:
HallProtocolCount++;
uint8_t *pt = (uint8_t*)&HallProtocol;
//HallProtocol.head = HALL_PROTOLO_HEAD;
//TRACE("HALL: %02X %02X %02X ...%04X", pt[0], pt[1], pt[2], HallProtocol.checkSum);
pt[HallProtocol.length + 3] = HallProtocol.checkSum & 0xFF;
pt[HallProtocol.length + 4] = HallProtocol.checkSum >> 8;
// usbDownloadTransmit( pt, HallProtocol.length + 5 );
usbDownloadTransmit( pt, HallProtocol.length + 5 );
break;
}
//printf_log_now = 1;
}
}
if ((get_tmr10ms() - getCfgTime) > 200)
//check periodically if calibration is correct
if (get_tmr10ms() - lastConfigTime > 200)
{
if ( (0 == StickCallbration[0].max) && (0 == StickCallbration[0].mid) && (0== StickCallbration[0].min) )
{
get_hall_config();
getCfgTime = get_tmr10ms();
//invalid calibration
if(hall_calibration[0].max - hall_calibration[0].min < 1024) {
TRACE("GET HALL CONFIG");
get_hall_config();
lastConfigTime = get_tmr10ms();
}
if ( printf_log_now != 0)
if (log)
{
TRACE_NOCRLF("Hall(%0d):", FLYSKY_HALL_BAUDRATE);
for (int idx = 0; idx < HallProtocol.length + 5; idx++)
+13 -15
View File
@@ -46,10 +46,6 @@
#define MIN_ADC_CHANNLE_VALUE ( 0 )
#define MIDDLE_ADC_CHANNLE_VALUE ( 2047 )
extern unsigned short HallChVal[FLYSKY_HALL_CHANNEL_COUNT];
typedef struct
{
signed short min;
@@ -62,25 +58,20 @@ typedef struct
STRUCT_STICK_CALIBRATION sticksCalibration[4];
unsigned char reststate;
unsigned short CRC16;
}STRUCT_STICK_CALIBRATION_PACK;
} STRUCT_STICK_CALIBRATION_PACK;
typedef struct
{
signed short channel[4];
}STRUCT_HALL_CHANNEL;
typedef struct
{
STRUCT_HALL_CHANNEL channel;
unsigned char stickState;
unsigned short CRC16;
}STRUCT_CHANNEL_PACK;
} STRUCT_CHANNEL_PACK;
typedef union
{
STRUCT_STICK_CALIBRATION_PACK channelPack;
STRUCT_CHANNEL_PACK sticksCalibrationPack;
}UNION_DATA;
} UNION_DATA;
typedef struct
{
@@ -103,14 +94,14 @@ typedef union
{
STRUCT_HALLID hall_Id;
unsigned char ID;
}STRUCT_ID;
} STRUCT_ID;
typedef union
{
STRUCT_HALLDATA halldat;
unsigned char buffer[30];
}UNION_HALLDATA;
} UNION_HALLDATA;
typedef struct
@@ -159,7 +150,9 @@ enum TRANSFER_DIR_E {
TRANSFER_DIR_RFMODULE,
};
#define HALL_PROTOLO_HEAD ( 0x55 )
#define HALL_PROTOLO_HEAD 0x55
#define HALL_RESP_TYPE_CALIB 0x0e
#define HALL_RESP_TYPE_VALUES 0x0c
#define HALL_SERIAL_USART UART4
#define HALL_SERIAL_GPIO GPIOA
@@ -192,6 +185,11 @@ enum TRANSFER_DIR_E {
/***************************************************************************************************
interface function
***************************************************************************************************/
extern unsigned short hall_adc_values[FLYSKY_HALL_CHANNEL_COUNT];
extern signed short hall_raw_values[FLYSKY_HALL_CHANNEL_COUNT];
extern STRUCT_STICK_CALIBRATION hall_calibration[FLYSKY_HALL_CHANNEL_COUNT];
extern void reset_hall_stick( void );
extern void get_hall_config( void );
extern void hall_stick_init(uint32_t baudrate);
+3 -4
View File
@@ -49,11 +49,10 @@ void hapticInit(void)
HAPTIC_GPIO_TIMER->PSC = (PERI2_FREQUENCY * TIMER_MULT_APB2) / 10000 - 1;
HAPTIC_GPIO_TIMER->CCMR1 = HAPTIC_TIMER_MODE; // PWM
HAPTIC_GPIO_TIMER->CCER = HAPTIC_TIMER_OUTPUT_ENABLE;
hapticOff();
HAPTIC_GPIO_TIMER->EGR = 0;
HAPTIC_GPIO_TIMER->CCR1 = 0;
HAPTIC_GPIO_TIMER->EGR = TIM_EGR_UG;
HAPTIC_GPIO_TIMER->CR1 = TIM_CR1_CEN; // counter enable
HAPTIC_GPIO_TIMER->BDTR |= TIM_BDTR_MOE;
}
void hapticDone(void)
+50 -14
View File
@@ -22,31 +22,67 @@
uint32_t readKeys()
{
return 0;
uint32_t result = 0;
bool getKeys = true;
#if defined(LUA)
getKeys = (luaState & INTERPRETER_RUNNING_STANDALONE_SCRIPT);
#endif
if (getKeys) {
if (TRIMS_GPIO_REG_LHL & TRIMS_GPIO_PIN_LHL)
result |= 1 << KEY_PGDN;
if (TRIMS_GPIO_REG_LHR & TRIMS_GPIO_PIN_LHR)
result |= 1 << KEY_PGUP;
if (TRIMS_GPIO_REG_LVD & TRIMS_GPIO_PIN_LVD)
result |= 1 << KEY_TELEM;
if (TRIMS_GPIO_REG_LVU & TRIMS_GPIO_PIN_LVU)
result |= 1 << KEY_MENU;
if (TRIMS_GPIO_REG_RVD & TRIMS_GPIO_PIN_RVD)
result |= 1 << KEY_DOWN;
if (TRIMS_GPIO_REG_RVU & TRIMS_GPIO_PIN_RVU)
result |= 1 << KEY_UP;
if (TRIMS_GPIO_REG_RHL & TRIMS_GPIO_PIN_RHL)
result |= 1 << KEY_LEFT;
if (TRIMS_GPIO_REG_RHR & TRIMS_GPIO_PIN_RHR)
result |= 1 << KEY_RIGHT;
if (TRIMS_GPIO_REG_RPRESS & TRIMS_GPIO_PIN_RPRESS)
result |= 1 << KEY_ENTER;
if (TRIMS_GPIO_REG_LPRESS & TRIMS_GPIO_PIN_LPRESS)
result |= 1 << KEY_EXIT;
}
return result;
}
uint32_t readTrims()
{
uint32_t result = 0;
bool getTrim = true;
#if defined(LUA)
if(luaState & INTERPRETER_RUNNING_STANDALONE_SCRIPT) {
getTrim = false;
}
#endif
if(!getTrim) return result;
if (TRIMS_GPIO_REG_LHL & TRIMS_GPIO_PIN_LHL)
result |= 0x01;
result |= 1 << (TRM_LH_DWN - TRM_BASE);
if (TRIMS_GPIO_REG_LHR & TRIMS_GPIO_PIN_LHR)
result |= 0x02;
result |= 1 << (TRM_LH_UP - TRM_BASE);
if (TRIMS_GPIO_REG_LVD & TRIMS_GPIO_PIN_LVD)
result |= 0x04;
result |= 1 << (TRM_LV_DWN - TRM_BASE);
if (TRIMS_GPIO_REG_LVU & TRIMS_GPIO_PIN_LVU)
result |= 0x08;
result |= 1 << (TRM_LV_UP - TRM_BASE);
if (TRIMS_GPIO_REG_RVD & TRIMS_GPIO_PIN_RVD)
result |= 0x10;
result |= 1 << (TRM_RV_DWN - TRM_BASE);
if (TRIMS_GPIO_REG_RVU & TRIMS_GPIO_PIN_RVU)
result |= 0x20;
result |= 1 << (TRM_RV_UP - TRM_BASE);
if (TRIMS_GPIO_REG_RHL & TRIMS_GPIO_PIN_RHL)
result |= 0x40;
result |= 1 << (TRM_RH_DWN - TRM_BASE);
if (TRIMS_GPIO_REG_RHR & TRIMS_GPIO_PIN_RHR)
result |= 0x80;
// TRACE("readTrims(): result=0x%02x", result);
result |= 1 << (TRM_RH_UP - TRM_BASE);
if (TRIMS_GPIO_REG_RPRESS & TRIMS_GPIO_PIN_RPRESS)
result |= 1 << (TRM_RIGHT_CLICK - TRM_BASE);
if (TRIMS_GPIO_REG_LPRESS & TRIMS_GPIO_PIN_LPRESS)
result |= 1 << (TRM_LEFT_CLICK - TRM_BASE);
return result;
}
@@ -68,13 +104,13 @@ void readKeysAndTrims()
uint8_t index = 0;
uint32_t in = readKeys();
uint32_t trims = readTrims();
for (i = 0; i < TRM_BASE; i++) {
keys[index++].input(in & (1 << i));
}
in = readTrims();
for (i = 1; i <= 1 << (TRM_LAST-TRM_BASE); i <<= 1) {
keys[index++].input(in & i);
keys[index++].input(trims & i);
}
}
File diff suppressed because it is too large Load Diff
+3 -6
View File
@@ -87,12 +87,9 @@ typedef unsigned int LcdReadIDFucPtr( void );
extern void GPIO_SetDirection( GPIO_TypeDef *GPIOx, unsigned char Pin, unsigned char IsInput );
extern void LCD_HX8357D_On( void );
extern void LCD_ILI9481_On( void );
extern void LCD_ILI9486_On( void );
extern void LCD_ILI9488_On( void );
extern void LCD_ST7796S_On( void );
extern lcdSpiInitFucPtr lcdInitFunction;
extern lcdSpiInitFucPtr lcdOffFunction;
extern lcdSpiInitFucPtr lcdOnFunction;
#define SET_IO_INPUT( PORT, PIN ) GPIO_SetDirection( PORT, PIN, 1 )
#define SET_IO_OUTPUT( PORT, PIN ) GPIO_SetDirection( PORT, PIN, 0 )
@@ -124,6 +124,8 @@ enum LcdColorIndex
BARGRAPH2_COLOR_INDEX,
BARGRAPH_BGCOLOR_INDEX,
SCROLLBOX_COLOR_INDEX,
BATTERY_CHARGE_COLOR_INDEX,
LCD_COLOR_COUNT,
TABLE_HEADER_BGCOLOR_INDEX,
+23 -57
View File
@@ -21,9 +21,8 @@
#include "pwr.h"
#include "board.h"
uint32_t shutdownRequest; // Stores intentional shutdown to avoid reboot loop
uint32_t shutdownReason; // Used for detecting unexpected reboots regardless of reason
uint32_t powerupReason __NOINIT; // Stores power up reason beyond initialization for emergency mode activation
uint32_t boardState __NOINIT;
void pwrInit()
{
@@ -41,11 +40,6 @@ void pwrInit()
//GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN;
//GPIO_Init(INTMODULE_PWR_GPIO, &GPIO_InitStructure);
//TODO move this elsewhere!
GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PWR_GPIO_PIN;
GPIO_Init(EXTMODULE_PWR_GPIO, &GPIO_InitStructure);
//Bluetooth
GPIO_SetBits(BLUETOOTH_ON_GPIO, BLUETOOTH_ON_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = BLUETOOTH_ON_GPIO_PIN;
@@ -55,38 +49,35 @@ void pwrInit()
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_Pin = PWR_SWITCH_GPIO_PIN;
GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
// Init SD-DETECT PIN
GPIO_ResetBits(SD_PRESENT_GPIO, SD_PRESENT_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = SD_PRESENT_GPIO_PIN;
GPIO_Init(SD_PRESENT_GPIO, &GPIO_InitStructure);
// TODO move this elsewhere! (plus SD DETECT on other boards)
// Init TRAINER DETECT PIN
// GPIO_InitStructure.GPIO_Pin = TRAINER_DETECT_GPIO_PIN;
// GPIO_Init(TRAINER_DETECT_GPIO, &GPIO_InitStructure);
//turn power off
GPIO_ResetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
//turn Bluetooth off
GPIO_ResetBits(PWR_GPIO, BLUETOOTH_ON_GPIO_PIN);
pwrOn();
boardState = BOARD_POWER_OFF;
}
void pwrOn()
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = PWR_ON_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(PWR_GPIO, &GPIO_InitStructure);
GPIO_SetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
shutdownRequest = NO_SHUTDOWN_REQUEST;
shutdownReason = DIRTY_SHUTDOWN;
boardState = BOARD_POWER_ON;
}
void pwrSoftReboot(){
boardState = BOARD_REBOOT;
NVIC_SystemReset();
}
void pwrOff()
{
// Shutdown the Haptic
hapticDone();
shutdownRequest = SHUTDOWN_REQUEST;
shutdownReason = NORMAL_POWER_OFF;
boardState = BOARD_POWER_OFF;
GPIO_ResetBits(PWR_GPIO, PWR_ON_GPIO_PIN);
}
@@ -97,36 +88,11 @@ bool pwrPressed()
void pwrResetHandler()
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOJEN;
// these two NOPs are needed (see STM32F errata sheet) before the peripheral
// register can be written after the peripheral clock was enabled
__ASM volatile ("nop");
__ASM volatile ("nop");
// We get here whether we are powering up normally, we had an unexpected reboot or we have just powered down normally.
// We want:
// - In the 2nd case, to power ON as soon as possible if an unexpected reboot happened
// (we get there running on remaining capacitor charge, soft power having been cut by the RESET).
// - In the 3rd case, NOT power on as that would prevent from turning the system off.
// - The 1st case does not need to be handled here, but will be as a result of the handling for the 3rd case, see below.
//
// shutdownRequest is used to handle the 3rd case. If we really powered down on purpose this will still be set to SHUTDOWN_REQUEST
// as we left it in pwrOff(). If however we had an unexpected reboot, it would be set to NO_SHUTDOWN_REQUEST as we set it in pwrOn().
// Any other value (e.g. resulting from data corruption) would also keep power on for safety, so this variable can NOT be used
// to detect an unexpected reboot (on a normal power on the contents of the variable are random).
//
// shutdownReason is used to differentiate between an unexpected reboot and a normal power on. We set it to DIRTY_SHUTDOWN in pwrOn()
// in anticipation of a potential reboot. Should there be one the value should be preserved and signal below that we rebooted unexpectedly.
// If it is NOT set to DIRTY_SHUTDOWN we likely had a normal boot and its contents are random. Due to the need to initialize it to detect a
// potential failure ASAP we cannot use it to determine in the firmware why we got there, it has to be buffered.
//
// powerupReason is there to cater for that, and is what is used in the firmware to decide whether we have to enter emergency mode.
// This variable needs to be in a RAM section that is not initialized or zeroed, since once we exit this pwrResetHandler() function the
// C runtime would otherwise overwrite it during program init.
// Only for X12, X10 power circuit causes inability to shut down on some samples.
if (WAS_RESET_BY_WATCHDOG_OR_SOFTWARE()) {
pwrOn();
if (boardState != BOARD_POWER_OFF) {
powerupReason = boardState != BOARD_REBOOT && WAS_RESET_BY_WATCHDOG_OR_SOFTWARE() ? DIRTY_SHUTDOWN : ~DIRTY_SHUTDOWN;
RCC->CSR |= RCC_CSR_RMVF; //clear all flags
}
else {
powerupReason = ~DIRTY_SHUTDOWN;
}
}
+5 -3
View File
@@ -20,7 +20,7 @@
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20030000; /* end of 192K RAM */
_estack = 0x2002FFF0; /* end of 192K RAM */
_heap_end = 0xC0800000; /* end of 8192K SDRAM */
/* Generate a link error if heap and stack don't fit into RAM */
@@ -35,7 +35,8 @@ MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 65520
NO_INIT (xrw) : ORIGIN = 0x1000FFF0, LENGTH = 16
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
SDRAM(xrw) : ORIGIN = 0xC0000000, LENGTH = 8192K
}
@@ -132,7 +133,8 @@ SECTIONS
.noinit (NOLOAD) :
{
*(.noinit)
} >CCM
} >NO_INIT
/* collect all uninitialized .ccm sections */
.ram (NOLOAD) :
+11 -3
View File
@@ -20,7 +20,6 @@
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x10010000; /* end of 64K CCM */
_heap_end = 0xC0800000; /* end of 8192K SDRAM */
/* Generate a link error if heap and stack don't fit into RAM */
@@ -35,11 +34,16 @@ MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 65520
NO_INIT (xrw) : ORIGIN = 0x1000FFF0, LENGTH = 16
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
SDRAM(xrw) : ORIGIN = 0xC0000000, LENGTH = 8192K
}
/* Main stack end */
_estack = 0x10000000 + LENGTH(CCM);
_main_stack_start = _estack - _Main_Stack_Size;
/* Define output sections */
SECTIONS
{
@@ -52,6 +56,9 @@ SECTIONS
CREATE_OBJECT_SYMBOLS
_stext = .; /* Provide the name for the start of this section */
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
@@ -135,7 +142,8 @@ SECTIONS
.noinit (NOLOAD) :
{
*(.noinit)
} >CCM
} >NO_INIT
/* collect all uninitialized .ccm sections */
.ram (NOLOAD) :
@@ -20,26 +20,28 @@
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x10010000; /* end of 64K CCM */
_heap_end = 0xC0800000; /* end of 8192K SDRAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Main_Stack_Size = 1024; /* required amount of stack for interrupt stack (Main stack) */
/* Main stack end */
_main_stack_start = _estack - _Main_Stack_Size;
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 65520
NO_INIT (xrw) : ORIGIN = 0x1000FFF0, LENGTH = 16
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
SDRAM(xrw) : ORIGIN = 0xC0000000, LENGTH = 8192K
}
/* Main stack end */
_estack = 0x10000000 + LENGTH(CCM);
_main_stack_start = _estack - _Main_Stack_Size;
/* Define output sections */
SECTIONS
{
@@ -138,7 +140,7 @@ SECTIONS
.noinit (NOLOAD) :
{
*(.noinit)
} >CCM
} >NO_INIT
/* collect all uninitialized .ccm sections */
.ram (NOLOAD) :
+32 -57
View File
@@ -24,7 +24,6 @@ void trainerSendNextFrame();
void init_trainer_ppm()
{
#if 0
GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_OUT_GPIO_PinSource, TRAINER_GPIO_AF);
GPIO_InitTypeDef GPIO_InitStructure;
@@ -38,8 +37,8 @@ void init_trainer_ppm()
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN;
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
TRAINER_TIMER->ARR = 45000;
TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2;
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P);
TRAINER_TIMER->CCR2 = GET_TRAINER_PPM_DELAY()*2;
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (GET_TRAINER_PPM_POLARITY() ? 0 : TIM_CCER_CC2P);
TRAINER_TIMER->CCMR1 = TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_0; // Force O/P high
TRAINER_TIMER->BDTR = TIM_BDTR_MOE;
TRAINER_TIMER->EGR = 1;
@@ -47,120 +46,96 @@ void init_trainer_ppm()
TRAINER_TIMER->CCMR1 = TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2PE; // PWM mode 1
TRAINER_TIMER->CR1 |= TIM_CR1_CEN;
setupPulsesPPMTrainer();
trainerSendNextFrame();
NVIC_EnableIRQ(TRAINER_OUT_DMA_IRQn);
NVIC_SetPriority(TRAINER_OUT_DMA_IRQn, 7);
NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
#endif
}
void stop_trainer_ppm()
{
#if 0
NVIC_DisableIRQ(TRAINER_OUT_DMA_IRQn);
NVIC_DisableIRQ(TRAINER_TIMER_IRQn);
TRAINER_OUT_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
TRAINER_TIMER->DIER = 0; // Stop Interrupt
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
#endif
}
void init_trainer_capture()
{
#if 0
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_IN_GPIO_PinSource, TRAINER_GPIO_AF);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = TRAINER_IN_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(TRAINER_GPIO, &GPIO_InitStructure);
GPIO_PinAFConfig(TRAINER_GPIO, TRAINER_IN_GPIO_PinSource, TRAINER_GPIO_AF);
TRAINER_TIMER->ARR = 0xFFFF;
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
TRAINER_TIMER->CR2 = 0;
TRAINER_TIMER->CCMR1 = TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_CC1S_0;
TRAINER_TIMER->CCER = TIM_CCER_CC1E;
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags
TRAINER_TIMER->CCMR1 = TRAINER_IN_CCMR1;
TRAINER_TIMER->CCER = TRAINER_IN_CCER;
TRAINER_TIMER->SR &= ~TIM_SR_CC3IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE;
TRAINER_TIMER->CR1 = TIM_CR1_CEN;
NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
#endif
}
void stop_trainer_capture()
{
#if 0
NVIC_DisableIRQ(TRAINER_TIMER_IRQn); // Stop Interrupt
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
TRAINER_TIMER->DIER = 0; // Stop Interrupt
#endif
}
short unsigned int* lastPulse = 0;
void trainerSendNextFrame()
{
#if 0
TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2;
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P);
TRAINER_TIMER->CCR1 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
setupPulsesPPMTrainer();
TRAINER_TIMER->CCR2 = GET_TRAINER_PPM_DELAY() * 2;
TRAINER_TIMER->CCER = TIM_CCER_CC2E | (GET_TRAINER_PPM_POLARITY() ? 0 : TIM_CCER_CC2P);
lastPulse = trainerPulsesData.ppm.ptr;
TRAINER_TIMER->CCR3 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
TRAINER_OUT_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
TRAINER_OUT_DMA_STREAM->CR |= TRAINER_OUT_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
TRAINER_OUT_DMA_STREAM->PAR = CONVERT_PTR_UINT(&TRAINER_TIMER->ARR);
TRAINER_OUT_DMA_STREAM->M0AR = CONVERT_PTR_UINT(trainerPulsesData.ppm.pulses);
TRAINER_OUT_DMA_STREAM->NDTR = trainerPulsesData.ppm.ptr - trainerPulsesData.ppm.pulses;
TRAINER_OUT_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
#endif
}
#if 0
extern "C" void TRAINER_OUT_DMA_IRQHandler()
{
if (!DMA_GetITStatus(TRAINER_OUT_DMA_STREAM, TRAINER_OUT_DMA_FLAG_TC))
return;
DMA_ClearITPendingBit(TRAINER_OUT_DMA_STREAM, TRAINER_OUT_DMA_FLAG_TC);
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; // Enable this interrupt
trainerPulsesData.ppm.ptr = trainerPulsesData.ppm.pulses;
TRAINER_TIMER->DIER |= TIM_DIER_UDE;
TRAINER_TIMER->SR &= ~TIM_SR_UIF; // Clear this flag
TRAINER_TIMER->DIER |= TIM_DIER_UIE; // Enable this interrupt
}
extern "C" void TRAINER_TIMER_IRQHandler()
{
DEBUG_INTERRUPT(INT_TRAINER);
uint16_t capture = 0;
bool doCapture = false;
// What mode? in or out?
if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) {
// capture mode on trainer jack
capture = TRAINER_TIMER->CCR1;
capture = TRAINER_IN_COUNTER_REGISTER;
if (TRAINER_CONNECTED() && currentTrainerMode == TRAINER_MODE_MASTER_TRAINER_JACK) {
doCapture = true;
}
}
if (doCapture) {
captureTrainerPulses(capture);
}
}
// PPM out compare interrupt
if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) {
if ((TRAINER_TIMER->DIER & TIM_DIER_CC3IE) && (TRAINER_TIMER->SR & TIM_SR_CC3IF)) {
// compare interrupt
TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt
TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
setupPulsesPPMTrainer();
TRAINER_TIMER->DIER &= ~TIM_DIER_CC3IE; // stop this interrupt
TRAINER_TIMER->SR &= ~TIM_SR_CC3IF; // Clear flag
trainerSendNextFrame();
}
if ((TRAINER_TIMER->DIER & TIM_DIER_UIE) && (TRAINER_TIMER->SR & TIM_SR_UIF)) {
TRAINER_TIMER->SR &= ~TIM_SR_UIF; // Clear flag
TRAINER_TIMER->ARR = *trainerPulsesData.ppm.ptr++;
if (trainerPulsesData.ppm.ptr == lastPulse) {
TRAINER_TIMER->SR &= ~TIM_SR_CC3IF; // Clear flag
TRAINER_TIMER->DIER |= TIM_DIER_CC3IE; // Enable this interrupt
}
}
}
#endif
+192
View File
@@ -0,0 +1,192 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 for more details.
*/
#include "opentx.h"
#define FLYSKY_FIXED_RX_VOLTAGE (uint8_t)(FLYSKY_SENSOR_RX_VOLTAGE + (uint8_t)0xA0)
#define MIN_SNR 8
#define MAX_SNR 45
#define FIXED_PRECISION 15
#define FIXED(val) (val << FIXED_PRECISION)
#define DECIMAL(val) (val >> FIXED_PRECISION)
#define R_DIV_G_MUL_10_Q15 UINT64_C(9591506)
#define INV_LOG2_E_Q1DOT31 UINT64_C(0x58b90bfc) // Inverse log base 2 of e
struct FlyskyNv14Sensor {
const uint16_t id;
const uint8_t subId;
const char * name;
const TelemetryUnit unit;
const uint8_t precision;
const uint8_t offset;
const uint8_t bytes;
const bool issigned;
};
union nv14SensorData {
uint8_t UINT8;
uint16_t UINT16;
int16_t INT16;
uint32_t UINT32;
};
const FlyskyNv14Sensor Nv14Sensor[]=
{
{FLYSKY_FIXED_RX_VOLTAGE, 0, STR_SENSOR_A3, UNIT_VOLTS, 2, 0, 2, false},
{FLYSKY_SENSOR_RX_SIGNAL, 0, STR_SENSOR_RX_QUALITY, UNIT_RAW, 0, 0, 2, false},
{FLYSKY_SENSOR_RX_RSSI, 0, STR_SENSOR_RSSI, UNIT_DB, 0, 0, 2, true,},
{FLYSKY_SENSOR_RX_NOISE, 0, STR_SENSOR_RX_NOISE, UNIT_DB, 0, 0, 2, true},
{FLYSKY_SENSOR_RX_SNR, 0, STR_SENSOR_RX_SNR, UNIT_DB, 0, 0, 2, false},
{FLYSKY_SENSOR_RX_SNR, 1, STR_SENSOR_RX_QUALITY, UNIT_PERCENT, 0, 0, 2, false},
{FLYSKY_SENSOR_TEMP, 0, STR_SENSOR_TEMP1, UNIT_CELSIUS, 1, 0, 2, true},
{FLYSKY_SENSOR_EXT_VOLTAGE,0, STR_SENSOR_A3, UNIT_VOLTS, 2, 0, 2, false},
{FLYSKY_SENSOR_MOTO_RPM, 0, STR_SENSOR_RPM, UNIT_RPMS, 0, 0, 2, false},
{FLYSKY_SENSOR_PRESURRE, 0, STR_SENSOR_PRES, UNIT_RAW, 1, 0, 2, false},
{FLYSKY_SENSOR_PRESURRE, 1, STR_SENSOR_ALT, UNIT_METERS, 0, 0, 2, true},
{FLYSKY_SENSOR_GPS, 1, STR_SENSOR_SATELLITES, UNIT_RAW, 0, 0, 1, false},
{FLYSKY_SENSOR_GPS, 2, STR_SENSOR_GPS, UNIT_GPS_LATITUDE, 0, 1, 4, true},
{FLYSKY_SENSOR_GPS, 3, STR_SENSOR_GPS, UNIT_GPS_LONGITUDE, 0, 5, 4, true},
{FLYSKY_SENSOR_GPS, 4, STR_SENSOR_ALT, UNIT_METERS, 0, 8, 2, true},
{FLYSKY_SENSOR_GPS, 5, STR_SENSOR_GSPD, UNIT_KMH, 1, 10, 2, false},
{FLYSKY_SENSOR_GPS, 6, STR_SENSOR_HDG, UNIT_DEGREE, 3, 12, 2, false},
};
FlyskyNv14Sensor defaultNv14Sensor = {0, 0, "UNKNOWN", UNIT_RAW, 0, 0, 2, false};
const signed short tAltitude[225]=
{
20558, 20357, 20158, 19962, 19768, 19576, 19387, 19200, 19015, 18831, 18650, 18471, 18294, 18119, 17946, 17774,
17604, 17436, 17269, 17105, 16941, 16780, 16619, 16461, 16304, 16148, 15993, 15841, 15689, 15539, 15390, 15242,
15096, 14950, 14806, 14664, 14522, 14381, 14242, 14104, 13966, 13830, 13695, 13561, 13428, 13296, 13165, 13035,
12906, 12777, 12650, 12524, 12398, 12273, 12150, 12027, 11904, 11783, 11663, 11543, 11424, 11306, 11189, 11072,
10956, 10841, 10726, 10613, 10500, 10387, 10276, 10165, 10054, 9945, 9836, 9727, 9620, 9512, 9406, 9300,
9195, 9090, 8986, 8882, 8779, 8677, 8575, 8474, 8373, 8273, 8173, 8074, 7975, 7877, 7779, 7682,
7585, 7489, 7394, 7298, 7204, 7109, 7015, 6922, 6829, 6737, 6645, 6553, 6462, 6371, 6281, 6191,
6102, 6012, 5924, 5836, 5748, 5660, 5573, 5487, 5400, 5314, 5229, 5144, 5059, 4974, 4890, 4807,
4723, 4640, 4557, 4475, 4393, 4312, 4230, 4149, 4069, 3988, 3908, 3829, 3749, 3670, 3591, 3513,
3435, 3357, 3280, 3202, 3125, 3049, 2972, 2896, 2821, 2745, 2670, 2595, 2520, 2446, 2372, 2298,
2224, 2151, 2078, 2005, 1933, 1861, 1789, 1717, 1645, 1574, 1503, 1432, 1362, 1292, 1222, 1152,
1082, 1013, 944, 875, 806, 738, 670, 602, 534, 467, 399, 332, 265, 199, 132, 66,
0, -66, -131, -197, -262, -327, -392, -456, -521, -585, -649, -713, -776, -840, -903, -966,
-1029,-1091, -1154, -1216, -1278, -1340, -1402, -1463, -1525, -1586, -1647, -1708, -1769, -1829, -1889, -1950,
-2010
};
signed short CalculateAltitude( unsigned int Pressure, unsigned int SeaLevelPressure )
{
unsigned int Index;
signed int Altitude1;
signed int Altitude2;
unsigned int Decimal;
unsigned long Ratio;
Ratio = ( ( ( unsigned long long ) Pressure << 16 ) + ( SeaLevelPressure / 2 ) ) / SeaLevelPressure;
if( Ratio < ( ( 1 << 16 ) * 250 / 1000 ) )// 0.250 inclusive
{
Ratio = ( 1 << 16 ) * 250 / 1000;
}
else if( Ratio > ( 1 << 16 ) * 1125 / 1000 - 1 ) // 1.125 non-inclusive
{
Ratio = ( 1 << 16 ) * 1125 / 1000 - 1;
}
Ratio -= ( 1 << 16 ) * 250 / 1000; // from 0.000 (inclusive) to 0.875 (non-inclusive)
Index = Ratio >> 8;
Decimal = Ratio & ( ( 1 << 8 ) - 1 );
Altitude1 = tAltitude[Index];
Altitude2 = Altitude1 - tAltitude[Index + 1];
Altitude1 = Altitude1 - ( Altitude2 * Decimal + ( 1 << 7 ) ) / ( 1 << 8 );
if( Altitude1 >= 0 )
{
return( ( Altitude1 + 1 ) / 2 );
}
else
{
return( ( Altitude1 - 1 ) / 2 );
}
}
const FlyskyNv14Sensor* getFlyskyNv14Sensor(uint16_t id, uint8_t subId)
{
for(unsigned index = 0; index < *(&Nv14Sensor + 1) - Nv14Sensor; index++ ){
if (Nv14Sensor[index].id == id && Nv14Sensor[index].subId == subId) {
return &Nv14Sensor[index];
}
}
return &defaultNv14Sensor;
}
void flySkyNv14SetDefault(int index, uint8_t id, uint8_t subId, uint8_t instance)
{
TelemetrySensor & telemetrySensor = g_model.telemetrySensors[index];
telemetrySensor.id = id;
telemetrySensor.subId = subId;
telemetrySensor.instance = instance;
const FlyskyNv14Sensor* sensor = getFlyskyNv14Sensor(id, subId);
telemetrySensor.init(sensor->name, sensor->unit, sensor->precision);
storageDirty(EE_MODEL);
}
int32_t GetSensorValueFlySkyNv14(const FlyskyNv14Sensor* sensor, const uint8_t * data){
int32_t value = 0;
const nv14SensorData* sensorData = reinterpret_cast<const nv14SensorData*>(data + sensor->offset);
if(sensor->bytes == 1) value = sensorData->UINT8;
else if(sensor->bytes == 2) value = sensor->issigned ? sensorData->INT16 : sensorData->UINT16;
else if(sensor->bytes == 4) value = sensorData->UINT32;
if(sensor->id == FLYSKY_SENSOR_RX_RSSI) {
if(value < -200) value = -200;
#if defined (PCBNV14)
if(!g_model.rssiAlarms.flysky_telemetry)
#endif
{
value += 200;
value /= 2;
}
telemetryData.rssi.set(value);
}
if(sensor->id == FLYSKY_SENSOR_PRESURRE && sensor->subId != 0){
value = CalculateAltitude(value, 101325);
value = (value+500)/1000;
}
return value;
}
void flySkyNv14ProcessTelemetryPacket(const uint8_t * ptr, uint8_t sensorID )
{
uint8_t instnace = *ptr++;
if(sensorID == FLYSKY_SENSOR_RX_VOLTAGE) sensorID = FLYSKY_FIXED_RX_VOLTAGE;
for (const FlyskyNv14Sensor sensor : Nv14Sensor) {
if (sensor.id == sensorID) {
int32_t value = GetSensorValueFlySkyNv14(&sensor, ptr);
setTelemetryValue(PROTOCOL_TELEMETRY_FLYSKY_NV14, sensor.id, sensor.subId, instnace, value, sensor.unit, sensor.precision);
}
}
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
}
+63
View File
@@ -0,0 +1,63 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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 for more details.
*/
#ifndef __FLYSKY_NV14_H__
#define __FLYSKY_NV14_H__
enum FlySkySensorType_E {
FLYSKY_SENSOR_RX_VOLTAGE,
FLYSKY_SENSOR_RX_SIGNAL,
FLYSKY_SENSOR_RX_RSSI,
FLYSKY_SENSOR_RX_NOISE,
FLYSKY_SENSOR_RX_SNR,
FLYSKY_SENSOR_TEMP,
FLYSKY_SENSOR_EXT_VOLTAGE,
FLYSKY_SENSOR_MOTO_RPM,
FLYSKY_SENSOR_PRESURRE,
FLYSKY_SENSOR_GPS
};
typedef struct FLYSKY_GPS_INFO_S {
uint8_t position_fix;
uint8_t satell_cnt;
uint8_t latitude[4];
uint8_t longtitude[4];
uint8_t altitude[4];
uint8_t g_speed[2];
uint8_t direction[2];
} gps_info_t;
typedef struct FLYSKY_SENSOR_DATA_S {
uint8_t sensor_type;
uint8_t sensor_id;
uint8_t voltage[2];
uint8_t signal;
uint8_t rssi[2];
uint8_t noise[2];
uint8_t snr[2];
uint8_t temp[2];
uint8_t ext_voltage[2];
uint8_t moto_rpm[2];
uint8_t pressure_value[2];
gps_info_t gps_info;
} rx_sensor_t;
void flySkyNv14SetDefault(int index, uint8_t id, uint8_t subId, uint8_t instance);
void flySkyNv14ProcessTelemetryPacket(const uint8_t * ptr, uint8_t SensorType );
#endif
+25
View File
@@ -60,6 +60,31 @@ void checkTrainerSettings()
init_trainer_capture();
}
}
#elif defined(PCBNV14)
void checkTrainerSettings()
{
uint8_t requiredTrainerMode = g_model.trainerData.mode;
if (requiredTrainerMode != currentTrainerMode) {
switch (currentTrainerMode) {
case TRAINER_MODE_MASTER_TRAINER_JACK:
stop_trainer_capture();
break;
case TRAINER_MODE_SLAVE:
stop_trainer_ppm();
break;
}
currentTrainerMode = requiredTrainerMode;
switch (requiredTrainerMode) {
case TRAINER_MODE_SLAVE:
init_trainer_ppm();
break;
case TRAINER_MODE_MASTER_TRAINER_JACK:
init_trainer_capture();
break;
}
}
}
#else
void checkTrainerSettings()
{
+3
View File
@@ -165,6 +165,9 @@ const char STR_BEEP_LENGTH[] = TR_BEEP_LENGTH;
const char STR_CONTRAST[] = TR_CONTRAST;
const char STR_ALARMS_LABEL[] = TR_ALARMS_LABEL;
const char STR_BATTERY_RANGE[] = TR_BATTERY_RANGE;
const char STR_BATTERYCHARGING[] = TR_BATTERYCHARGING;
const char STR_BATTERYFULL[] = TR_BATTERYFULL;
const char STR_BATTERYNONE[] = TR_BATTERYNONE;
const char STR_BATTERYWARNING[] = TR_BATTERYWARNING;
const char STR_INACTIVITYALARM[] = TR_INACTIVITYALARM;
const char STR_MEMORYWARNING[] = TR_MEMORYWARNING;
+3
View File
@@ -286,6 +286,9 @@ extern const char STR_GYRO_MAX[];
extern const char STR_CONTRAST[];
extern const char STR_ALARMS_LABEL[];
extern const char STR_BATTERY_RANGE[];
extern const char STR_BATTERYCHARGING[];
extern const char STR_BATTERYFULL[];
extern const char STR_BATTERYNONE[];
extern const char STR_BATTERYWARNING[];
extern const char STR_INACTIVITYALARM[];
extern const char STR_MEMORYWARNING[];
+3
View File
@@ -513,6 +513,9 @@
#define TR_CONTRAST "对比度"
#define TR_ALARMS_LABEL "警告"
#define TR_BATTERY_RANGE TR("Batt. range", "电压测量范围")
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING "低电压报警值"
#define TR_INACTIVITYALARM "长时间无操作"
#define TR_MEMORYWARNING "内存不足"
+3
View File
@@ -507,6 +507,9 @@
#define TR_CONTRAST "Kontrast LCD"
#define TR_ALARMS_LABEL "Alarmy"
#define TR_BATTERY_RANGE TR("Ukazatel bat.", "Ukazatel baterie")
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING "Vybitá bat."
#define TR_INACTIVITYALARM TR("Nečinnost", "Nečinnost rádia")
#define TR_MEMORYWARNING "Plná pamět'"
+3
View File
@@ -512,6 +512,9 @@
#define TR_CONTRAST "LCD-Kontrast"
#define TR_ALARMS_LABEL "Alarme"
#define TR_BATTERY_RANGE TR("Akku Bereich", "Akku Spannungsbereich") // Symbol Akku Ladezustand
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING TR("Akku Warnung", "Akkuspannungswarnung")
#define TR_INACTIVITYALARM TR("Inaktivität", "Inaktivität nach")
#define TR_MEMORYWARNING "Speicher voll"
+3
View File
@@ -510,6 +510,9 @@
#define TR_CONTRAST "Contrast"
#define TR_ALARMS_LABEL "Alarms"
#define TR_BATTERY_RANGE TR("Batt. range", "Battery meter range")
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING "Battery low"
#define TR_INACTIVITYALARM "Inactivity"
#define TR_MEMORYWARNING "Memory low"
+3
View File
@@ -532,6 +532,9 @@
#define TR_CONTRAST "Contraste"
#define TR_ALARMS_LABEL "Alarmas"
#define TR_BATTERY_RANGE TR("Rango bateria","Rango medidor Bater")
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING "Bateria Baja"
#define TR_INACTIVITYALARM "Inactividad"
#define TR_MEMORYWARNING "Memoria Baja"
+3
View File
@@ -524,6 +524,9 @@
#define TR_CONTRAST "Contrast"
#define TR_ALARMS_LABEL "Alarms"
#define TR_BATTERY_RANGE TR("Battery range","Battery meter range")
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING "Battery Low"
#define TR_INACTIVITYALARM "Inactivity"
#define TR_MEMORYWARNING "Memory Low"
+3
View File
@@ -530,6 +530,9 @@
#define TR_CONTRAST "Contraste"
#define TR_ALARMS_LABEL "Alarmes"
#define TR_BATTERY_RANGE "Plage batterie"
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING TR("Batterie", "Batterie faible")
#define TR_INACTIVITYALARM "Inactivité"
#define TR_MEMORYWARNING "Mémoire pleine"
+3
View File
@@ -535,6 +535,9 @@
#define TR_CONTRAST "Contrasto"
#define TR_ALARMS_LABEL "Allarmi"
#define TR_BATTERY_RANGE TR("Int. Batt.", "Intervallo batteria")
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING TR(INDENT "Avv. Batt.", INDENT "Avviso Batteria")
#define TR_INACTIVITYALARM INDENT "Inattività"
#define TR_MEMORYWARNING TR(INDENT "Avv. Mem.", INDENT "Avviso Memoria")
+3 -1
View File
@@ -512,7 +512,9 @@
#define TR_CONTRAST "LCD-Kontrast"
#define TR_ALARMS_LABEL "Alarm"
#define TR_BATTERY_RANGE TR("Accu Bereik", "Accu Spngs-Bereik") // Symbol Akku Ladezustand
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING "Accu laag"
#define TR_INACTIVITYALARM TR("Inactiviteit", "Inactiviteit na")
#define TR_MEMORYWARNING "Geheugen laag"
+3
View File
@@ -531,6 +531,9 @@
#define TR_CONTRAST "Kontrast"
#define TR_ALARMS_LABEL "Alarmy"
#define TR_BATTERY_RANGE TR("PokażPasBat.", "Pokaż pasek bateri")
#define TR_BATTERYCHARGING "Ładowanie..."
#define TR_BATTERYFULL "Bateria naładowana"
#define TR_BATTERYNONE "Brak!"
#define TR_BATTERYWARNING "Bateria rozładowana"
#define TR_INACTIVITYALARM "Alarm bezczynności"
#define TR_MEMORYWARNING "Pełna pamięć"
+3
View File
@@ -517,6 +517,9 @@
#define TR_CONTRAST "Contraste"
#define TR_ALARMS_LABEL "Alarmes"
#define TR_BATTERY_RANGE "Battery Range"
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING "Bateria Baixa"
#define TR_INACTIVITYALARM "Inactividade"
#define TR_MEMORYWARNING "Memoria Baixa"
+3
View File
@@ -533,6 +533,9 @@
#define TR_CONTRAST "Kontrast"
#define TR_ALARMS_LABEL "Alarm"
#define TR_BATTERY_RANGE "Batteri-MinMax"
#define TR_BATTERYCHARGING "Charging..."
#define TR_BATTERYFULL "Battery full"
#define TR_BATTERYNONE "None!"
#define TR_BATTERYWARNING "Batteri"
#define TR_INACTIVITYALARM "Inaktivitet"
#define TR_MEMORYWARNING "Lite Minne"