Open FFBoard
Open source force feedback firmware
EncoderSSI.cpp
Go to the documentation of this file.
1/*
2 * EncoderSSI.cpp
3 *
4 * Created on: 22.02.23
5 * Author: Yannick
6 *
7 */
8
9#include "EncoderSSI.h"
10
11bool EncoderSSI::inUse = false;
13 .name = "SSI" ,
14 .id=CLSID_ENCODER_SSI
15};
16
18 return info;
19}
20
21
23 SPIDevice(ENCODER_SPI_PORT, ENCODER_SPI_PORT.getCsPins()[0]),
24 CommandHandler("ssienc",CLSID_ENCODER_SSI,0) {
25 EncoderSSI::inUse = true;
26
27
29 this->spiPort.takeExclusive(true);
30 configSPI();
32}
33
35 setPos(0);
36 EncoderSSI::inUse = false;
37 this->spiPort.takeExclusive(false);
38}
39
40
42 uint16_t buf;
43 if(Flash_Read(ADR_SSI_CONF1, &buf)){
44 this->lenghtDataBit = (buf & 0x1F)+1; // up to 32 bit. 5 bits
45 this->spiSpeed = ((buf >> 5) & 0x3);
46 setMode(static_cast<EncoderSSI_modes>((buf >> 8) & 0xF));
47 }
48 posOffset = Flash_ReadDefault(ADR_SSI_OFS, 0)<<std::max(0,(lenghtDataBit-16));
49
50}
51
53 uint16_t buf = std::max((this->lenghtDataBit-1),0) & 0x1F;
54 buf |= ((this->spiSpeed) & 0x3) << 5;
55 // 1 bit free
56 buf |= (((uint16_t)this->mode) & 0xf) << 8; // 4 bits
57 Flash_Write(ADR_SSI_CONF1, buf);
58 Flash_Write(ADR_SSI_OFS, posOffset >> std::max(0,(lenghtDataBit-16)));
59}
60
62
63 uint32_t prescale;
64 switch (spiSpeed) {
65 case 0 :
66 prescale = SPI_BAUDRATEPRESCALER_32;
67 break;
68 case 1 :
69 prescale = SPI_BAUDRATEPRESCALER_16;
70 break;
71 case 2 :
72 prescale = SPI_BAUDRATEPRESCALER_8;
73 break;
74 default :
75 prescale = SPI_BAUDRATEPRESCALER_32;
76 break;
77 }
78
79 SPIConfig* config = this->getSpiConfig();
80
81 config->peripheral.BaudRatePrescaler = prescale;
82 config->peripheral.FirstBit = SPI_FIRSTBIT_MSB;
83 config->peripheral.CLKPhase = SPI_PHASE_2EDGE;
84 config->peripheral.CLKPolarity = SPI_POLARITY_LOW;
85 config->peripheral.DataSize = SPI_DATASIZE_8BIT;
86 config->cspol = true;
87 this->setSpiConfig(*config);
88 this->spiPort.configurePort(&config->peripheral);
89
90}
91
93 return !EncoderSSI::inUse && ENCODER_SPI_PORT.hasFreePins();
94}
95
97 lastPos = pos;
98 newPos = 0;
99 switch(mode){
100
102 {
103 newPos = (uint16_t)(spi_buf[0] & 0x3F) << 8;
104 newPos |= spi_buf[1];
105 newPos >>= std::max(14-lenghtDataBit,0);
106 uint8_t parity = (spi_buf[0] >> 6) & 0x3;
107 for(uint8_t i = 0;i<7;i++){
108 parity ^= (newPos >> (2*i)) & 0x3;
109 }
110 if(parity){
111 newPos &= ((1<<lenghtDataBit) - 1);
112 pos = newPos - (1<<(lenghtDataBit-1));
113 }else{
114 errors++;
115 }
116
117 break;
118 }
119
120
122 {
123 for(uint8_t i = 0;i<bytes;i++){
124 newPos |= spi_buf[i] << bytes;
125 }
126 newPos &= ((1<<lenghtDataBit) - 1);
127 pos = newPos;
128 break;
129 }
130
131 }
132 // Handle overflow
133 if(pos-lastPos > 1<<(lenghtDataBit-1)){
134 mtpos--;
135 }else if(lastPos-pos > 1<<(lenghtDataBit-1)){
136 mtpos++;
137 }
138 waitData = false;
139}
140
142 //port->takeSemaphore();
143 waitData = true;
145}
146
149 //port->giveSemaphore();
150}
151
152
153
156}
157
158
160 if(!waitData){ // If a transfer is still in progress return the last result
161 spiPort.receive_DMA(spi_buf, transferlen, this); // Receive next frame
162
163 }
164 return pos + mtpos * getCpr();
165}
166
168 return getPosAbs()-posOffset;
169}
170
171void EncoderSSI::setPos(int32_t newpos){
172
173 posOffset = pos - newpos;
174}
175
176
177
179 return 1<<lenghtDataBit;
180}
181
184 registerCommand("bits", EncoderSSI_commands::bits, "Bits of resolution",CMDFLAG_GET|CMDFLAG_SET);
185 registerCommand("speed", EncoderSSI_commands::speed, "SPI speed preset 0-2",CMDFLAG_GET|CMDFLAG_SET | CMDFLAG_INFOSTRING);
186 registerCommand("errors", EncoderSSI_commands::errors, "Error count",CMDFLAG_GET);
187 registerCommand("mode", EncoderSSI_commands::mode, "SPI mode",CMDFLAG_INFOSTRING | CMDFLAG_GET | CMDFLAG_SET);
188}
189
192 transferlen = 2;
193 }else{
194 transferlen = ((lenghtDataBit-1) / 8)+1;
195 }
196 this->mode = mode;
197}
198
200 std::string reply;
201 uint8_t base = 5; // 32
202 for(uint8_t i = 0; i<3;i++){
203 uint32_t khz = spiPort.getBaseClk() / ((1 << (base - i)) * 1000);
204 reply+= std::to_string(khz) + "kHz:" + std::to_string(i)+"\n";
205 }
206 return reply;
207}
208
209CommandStatus EncoderSSI::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
210 switch(static_cast<EncoderSSI_commands>(cmd.cmdId)){
212 handleGetSet(cmd, replies, this->lenghtDataBit);
214 lenghtDataBit = std::min(std::max(lenghtDataBit,12),14); // Only 12b and 14b valid
215 }
216 break;
218 replies.emplace_back(errors);
219 break;
221 if(cmd.type == CMDtype::info){
222 replies.emplace_back(printSpeeds());
223 }else{
224 handleGetSet(cmd, replies, this->spiSpeed);
225 this->spiSpeed = clip(this->spiSpeed,0,2); // Limit from 0-2
226 if(cmd.type == CMDtype::set){
227 configSPI();
228 }
229 }
230 break;
232 if(cmd.type == CMDtype::set){
233 setMode(static_cast<EncoderSSI_modes>(cmd.val & 0xF));
234
235 }else if(cmd.type == CMDtype::get){
236 replies.emplace_back((uint8_t)this->mode);
237 }else if(cmd.type == CMDtype::info){
238 replies.emplace_back(printModes(this->mode_names));
239 }else{
240 return CommandStatus::ERR;
241 }
242 break;
243 default:
245 }
246 return CommandStatus::OK;
247
248}
CommandStatus
EncoderType
Definition: Encoder.h:27
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)
int32_t pos
Definition: EncoderSSI.h:77
static bool inUse
Definition: EncoderSSI.h:84
EncoderSSI_modes mode
Definition: EncoderSSI.h:73
static ClassIdentifier info
Definition: EncoderSSI.h:26
int32_t getPos()
Definition: EncoderSSI.cpp:167
void restoreFlash()
Definition: EncoderSSI.cpp:41
static constexpr std::array< const char *, 2 > mode_names
Definition: EncoderSSI.h:46
void endSpiTransfer(SPIPort *port)
Definition: EncoderSSI.cpp:147
int32_t getPosAbs()
Definition: EncoderSSI.cpp:159
void setPos(int32_t pos)
Definition: EncoderSSI.cpp:171
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
Definition: EncoderSSI.cpp:209
uint8_t transferlen
Definition: EncoderSSI.h:82
int32_t posOffset
Definition: EncoderSSI.h:77
uint32_t errors
Definition: EncoderSSI.h:72
int spiSpeed
Definition: EncoderSSI.h:71
int32_t mtpos
Definition: EncoderSSI.h:78
std::string printSpeeds()
Definition: EncoderSSI.cpp:199
void registerCommands()
Definition: EncoderSSI.cpp:182
const ClassIdentifier getInfo()
Command handlers always have class infos. Works well with ChoosableClass.
Definition: EncoderSSI.cpp:17
bool waitData
Definition: EncoderSSI.h:86
static bool isCreatable()
Definition: EncoderSSI.cpp:92
uint8_t spi_buf[bytes]
Definition: EncoderSSI.h:81
void configSPI()
Definition: EncoderSSI.cpp:61
int32_t newPos
Definition: EncoderSSI.h:77
void setMode(EncoderSSI_modes mode)
Definition: EncoderSSI.cpp:190
EncoderSSI_commands
Definition: EncoderSSI.h:44
static const uint8_t bytes
Definition: EncoderSSI.h:80
std::string printModes(const std::array< const char *, N > &names)
Definition: EncoderSSI.h:49
int32_t lastPos
Definition: EncoderSSI.h:77
int lenghtDataBit
Definition: EncoderSSI.h:70
void beginSpiTransfer(SPIPort *port)
Definition: EncoderSSI.cpp:141
uint32_t getCpr()
Definition: EncoderSSI.cpp:178
void spiRxCompleted(SPIPort *port) override
Definition: EncoderSSI.cpp:96
void saveFlash()
Definition: EncoderSSI.cpp:52
EncoderType getEncoderType()
Definition: EncoderSSI.cpp:154
virtual ~EncoderSSI()
Definition: EncoderSSI.cpp:34
Definition: SPI.h:100
SPIPort & spiPort
Definition: SPI.h:124
void assertChipSelect()
Definition: SPI.cpp:373
virtual SPIConfig * getSpiConfig()
Definition: SPI.h:120
void clearChipSelect()
Definition: SPI.cpp:377
virtual void setSpiConfig(SPIConfig config)
Definition: SPI.h:123
Definition: SPI.h:43
void takeExclusive(bool exclusive)
Definition: SPI.cpp:216
uint32_t getBaseClk()
Definition: SPI.cpp:227
void receive_DMA(uint8_t *buf, uint16_t size, SPIDevice *device)
Definition: SPI.cpp:117
void configurePort(SPI_InitTypeDef *config)
Definition: SPI.cpp:72
T clip(T v, C l, C h)
Definition: cppmain.h:58
TVal Flash_ReadDefault(uint16_t adr, TVal def)
Definition: flash_helpers.h:36
bool Flash_Write(uint16_t adr, uint16_t dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
const char * name
uint32_t cmdId
Definition: SPI.h:18
SPI_InitTypeDef peripheral
Definition: SPI.h:38
bool cspol
CSPOL=true === active low.
Definition: SPI.h:37