Open FFBoard
Open source force feedback firmware
ShifterAnalog.cpp
Go to the documentation of this file.
1/*
2 * ShifterAnalog.cpp
3 *
4 * Created on: 27.02.2020
5 * Author: Yannick
6 */
7
8#include <functional>
9
10#include "LocalButtons.h"
11#include "ShifterAnalog.h"
12#include "global_callbacks.h"
13#include "cpp_target_config.h"
14#include "AdcHandler.h"
15
17 .name = "Shifter Analog" ,
18 .id=CLSID_BTN_SHIFTER, // 3
19 };
21 return info;
22}
23
24ShifterAnalog::ShifterAnalog() : CommandHandler("shifter", CLSID_BTN_SHIFTER) {
25 uint8_t bits = AdcHandler::getAdcResolutionBits(&AIN_HADC);
26 bitshift = std::max(0,16-bits);
27
28 this->restoreFlash();
29 this->registerCommands();
30}
31
33
34}
35
38
39 registerCommand("mode", ShifterAnalog_commands::mode, "Shifter mode",CMDFLAG_GET|CMDFLAG_SET|CMDFLAG_INFOSTRING);
40 registerCommand("x12", ShifterAnalog_commands::x12, "X-threshold for 1&2 gears",CMDFLAG_GET|CMDFLAG_SET);
41 registerCommand("x56", ShifterAnalog_commands::x56, "X-threshold for 5&6 gears",CMDFLAG_GET|CMDFLAG_SET);
42 registerCommand("y135", ShifterAnalog_commands::y135, "Y-threshold for 1&3&5 gears",CMDFLAG_GET|CMDFLAG_SET);
43 registerCommand("y246", ShifterAnalog_commands::y246, "Y-threshold for 2&4&6 gears",CMDFLAG_GET|CMDFLAG_SET);
44 registerCommand("revbtn", ShifterAnalog_commands::revbtn, "Pin for R signal",CMDFLAG_GET|CMDFLAG_SET);
45 registerCommand("cspin", ShifterAnalog_commands::cspin, "CS pin for SPI modes",CMDFLAG_GET|CMDFLAG_SET);
46 registerCommand("xchan", ShifterAnalog_commands::xchan, "X signal analog pin",CMDFLAG_GET|CMDFLAG_SET);
47 registerCommand("ychan", ShifterAnalog_commands::ychan, "Y signal analog pin",CMDFLAG_GET|CMDFLAG_SET);
48 registerCommand("vals", ShifterAnalog_commands::vals, "Analog values",CMDFLAG_GET);
49 registerCommand("gear", ShifterAnalog_commands::gear, "Decoded gear",CMDFLAG_GET);
50}
51
53 uint8_t chans = 0;
54 volatile uint32_t* buf = getAnalogBuffer(&AIN_HADC,&chans);
55 x_val = buf[ADC_CHAN_FPIN+x_chan-1] << bitshift; // Make 16 bit
56 y_val = buf[ADC_CHAN_FPIN+y_chan-1] << bitshift;
57}
58
60 gear = 0;
61
62 switch (mode)
63 {
66 // Sequential mode
67 if(x_val < X_12){
68 gear = 1;
69 }else if(x_val > X_56){
70 gear = 2;
71 }
72 break;
75 // Calculate h shifter gears by thresholds
76 if(x_val < X_12){
77 if(y_val > Y_135)
78 gear=1; // 1st gear
79
80 if(y_val < Y_246)
81 gear=2; // 2nd gear
82
83 }else if(x_val > X_56){
84 if(y_val > Y_135)
85 gear=5; // 5th gear
86
87 if(y_val < Y_246)
88 gear=6; // 6th gear
89
90 }else{
91 if(y_val > Y_135)
92 gear=3; // 3rd gear
93
94 if(y_val < Y_246)
95 gear=4; // 4th gear
96 }
97
98 if(gear == 6 && reverseButtonState){
99 gear = 7; // Reverse
100 }
101 }
102}
103
106 reverseButtonState = g27ShifterButtonClient->getReverseButton();
107 } else {
109 }
110}
111
114 *buf = g27ShifterButtonClient->getUserButtons();
115 return g27ShifterButtonClient->numUserButtons;
116 }
117
118 return 0;
119}
120
121uint8_t ShifterAnalog::readButtons(uint64_t* buf){
122 updateAdc();
123
126
127 *buf = 0;
128 // User buttons go first so that switching between sequential and H-pattern
129 // doesn't affect user button assignments.
130 auto numUserButtons{getUserButtons(buf)};
131
132 if(gear > 0){
133 *buf |= 1 << (gear - 1 + numUserButtons);
134 }
135
136 return this->btnnum;
137}
138
140 constexpr int numSequentialButtons{2};
141 constexpr int numHPatternButtons{7};
142
143 switch(mode) {
145 return numSequentialButtons;
147 return numHPatternButtons;
149 return G27ShifterButtonClient::numUserButtons + numSequentialButtons;
151 return G27ShifterButtonClient::numUserButtons + numHPatternButtons;
152 default:
153 return 0;
154 }
155}
156
158 Flash_Write(ADR_SHIFTERANALOG_CONF, static_cast<uint8_t>(mode));
159 Flash_Write(ADR_SHIFTERANALOG_CONF_2, pack(x_chan, y_chan));
160 Flash_Write(ADR_SHIFTERANALOG_CONF_3, pack(reverseButtonNum, cs_pin_num));
161
162 Flash_Write(ADR_SHIFTERANALOG_X_12, X_12);
163 Flash_Write(ADR_SHIFTERANALOG_X_56, X_56);
164 Flash_Write(ADR_SHIFTERANALOG_Y_135, Y_135);
165 Flash_Write(ADR_SHIFTERANALOG_Y_246, Y_246);
166}
167
169 std::tie(x_chan, y_chan) = unpack(Flash_ReadDefault(ADR_SHIFTERANALOG_CONF_2, pack(x_chan, y_chan)));
170 std::tie(reverseButtonNum, cs_pin_num) = unpack(Flash_ReadDefault(ADR_SHIFTERANALOG_CONF_3, pack(reverseButtonNum, cs_pin_num)));
171
172 setMode(Flash_ReadDefault(ADR_SHIFTERANALOG_CONF, ShifterMode::G29_H));
173
174 X_12 = Flash_ReadDefault(ADR_SHIFTERANALOG_X_12, X_12);
175 X_56 = Flash_ReadDefault(ADR_SHIFTERANALOG_X_56, X_56);
176 Y_135 = Flash_ReadDefault(ADR_SHIFTERANALOG_Y_135, Y_135);
177 Y_246 = Flash_ReadDefault(ADR_SHIFTERANALOG_Y_246, Y_246);
178}
179
181 std::string reply;
182 for(uint8_t i = 0; i<mode_names.size();i++){
183 reply+= mode_names[i] + ":" + std::to_string(i) + "," + std::to_string(mode_uses_spi[i]) + "," + std::to_string(mode_uses_local_reverse[i]) + "\n";
184 }
185 return reply;
186}
187
189 return m == ShifterMode::G27_H || m == ShifterMode::G27_seq;
190}
191
193 if (g27ShifterButtonClient && !isG27Mode(newMode)) {
195 g27ShifterButtonClient = nullptr;
196 } else if (!g27ShifterButtonClient && isG27Mode(newMode)) {
197 g27ShifterButtonClient = std::make_unique<G27ShifterButtonClient>(external_spi.getFreeCsPins()[0]);
198 }
199
200 mode = newMode;
201 this->btnnum = getBtnNum(); // Update amount
202}
203
204void ShifterAnalog::setCSPin(uint8_t new_cs_pin_num) {
205 if (new_cs_pin_num == cs_pin_num) {
206 return;
207 }
208
209 cs_pin_num = new_cs_pin_num;
210
213 }
214}
215
216
217
218CommandStatus ShifterAnalog::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
219
220 switch(static_cast<ShifterAnalog_commands>(cmd.cmdId)){
222 if(cmd.type == CMDtype::set){
223 setMode((ShifterMode)cmd.val);
224 }else if(cmd.type == CMDtype::get){
225 replies.emplace_back((uint8_t)this->mode);
226 }else if(cmd.type == CMDtype::info){
227 replies.emplace_back(printModes());
228 }
229 break;
230
232 return handleGetSet(cmd, replies, X_12);
234 return handleGetSet(cmd, replies, X_56);
236 return handleGetSet(cmd, replies, Y_135);
238 return handleGetSet(cmd, replies, Y_246);
240 return handleGetSet(cmd, replies, reverseButtonNum);
242 return handleGetSet(cmd, replies, cs_pin_num);
244 return handleGetSet(cmd, replies, x_chan);
246 return handleGetSet(cmd, replies, y_chan);
248 if(cmd.type == CMDtype::get){
249 replies.emplace_back(x_val,y_val);
250 }else{
251 return CommandStatus::ERR;
252 }
253 break;
255 if(cmd.type == CMDtype::get){
256 replies.emplace_back(gear);
257 }else{
258 return CommandStatus::ERR;
259 }
260 break;
261
262 default:
264 }
265
266 return CommandStatus::OK;
267}
268
270 :SPIDevice(external_spi,csPin) {
271 spiConfig.peripheral.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
272 spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_LSB;
273 spiConfig.peripheral.CLKPhase = SPI_PHASE_1EDGE;
274 spiConfig.peripheral.CLKPolarity = SPI_POLARITY_LOW;
275
276}
277
278
280 external_spi.receive_DMA(reinterpret_cast<uint8_t*>(&buttonStates), sizeof(buttonStates),this);
281 return buttonStates & 0x02;
282}
283
285 return buttonStates >> 4;
286}
287
CommandStatus
static uint8_t getAdcResolutionBits(ADC_HandleTypeDef *hadc)
Definition: AdcHandler.cpp:26
uint16_t btnnum
Definition: ButtonSource.h:38
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
static CommandStatus handleGetSet(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value)
static bool readButton(int button_num)
Definition: LocalButtons.h:51
Definition: SPI.h:100
SPIConfig spiConfig
Definition: SPI.h:125
std::vector< OutputPin > & getFreeCsPins()
Definition: SPI.cpp:55
void receive_DMA(uint8_t *buf, uint16_t size, SPIDevice *device)
Definition: SPI.cpp:117
OutputPin * getCsPin(uint16_t idx)
Definition: SPI.cpp:65
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies) override
const std::array< std::string, number_of_modes > mode_names
Definition: ShifterAnalog.h:37
virtual ~ShifterAnalog()
std::unique_ptr< G27ShifterButtonClient > g27ShifterButtonClient
Definition: ShifterAnalog.h:94
uint16_t X_56
Definition: ShifterAnalog.h:83
uint16_t x_val
Definition: ShifterAnalog.h:87
uint16_t y_val
Definition: ShifterAnalog.h:88
static ClassIdentifier info
Definition: ShifterAnalog.h:45
void calculateGear()
uint8_t cs_pin_num
Definition: ShifterAnalog.h:79
uint8_t y_chan
Definition: ShifterAnalog.h:77
uint16_t Y_246
Definition: ShifterAnalog.h:85
uint8_t bitshift
Definition: ShifterAnalog.h:92
uint8_t reverseButtonNum
Definition: ShifterAnalog.h:78
int getUserButtons(uint64_t *buf)
void updateReverseState()
void saveFlash() override
uint16_t getBtnNum()
static constexpr std::array< bool, number_of_modes > mode_uses_local_reverse
Definition: ShifterAnalog.h:39
void registerCommands()
uint16_t X_12
Definition: ShifterAnalog.h:82
uint16_t Y_135
Definition: ShifterAnalog.h:84
void restoreFlash() override
std::string printModes()
uint8_t x_chan
Definition: ShifterAnalog.h:76
void setCSPin(uint8_t new_cs_pin_num)
static bool isG27Mode(ShifterMode m)
const ClassIdentifier getInfo()
uint8_t readButtons(uint64_t *buf) override
bool reverseButtonState
Definition: ShifterAnalog.h:89
ShifterMode mode
Definition: ShifterAnalog.h:74
void setMode(ShifterMode newMode)
static constexpr std::array< bool, number_of_modes > mode_uses_spi
Definition: ShifterAnalog.h:38
SPIPort external_spi
uint16_t pack(uint8_t hb, uint8_t lb)
Definition: flash_helpers.h:44
TVal Flash_ReadDefault(uint16_t adr, TVal def)
Definition: flash_helpers.h:36
std::tuple< uint8_t, uint8_t > unpack(uint16_t v)
Definition: flash_helpers.h:48
bool Flash_Write(uint16_t adr, uint16_t dat)
volatile uint32_t * getAnalogBuffer(ADC_HandleTypeDef *hadc, uint8_t *chans)
const char * name
uint32_t cmdId
SPI_InitTypeDef peripheral
Definition: SPI.h:38