Open FFBoard
Open source force feedback firmware
MtEncoderSPI.cpp
Go to the documentation of this file.
1/*
2 * MtEncoderSPI.cpp
3 *
4 * Created on: 02.11.2021
5 * Author: Yannick
6 */
7
8#include "MtEncoderSPI.h"
9#include "constants.h"
10#ifdef MTENCODERSPI
11bool MtEncoderSPI::inUse = false;
12
14 .name = "MT6825 SPI3" ,
15 .id=CLSID_ENCODER_MTSPI,
16 };
18 return info;
19}
20
21MtEncoderSPI::MtEncoderSPI() : SPIDevice(ENCODER_SPI_PORT,ENCODER_SPI_PORT.getFreeCsPins()[0]), CommandHandler("mtenc",CLSID_ENCODER_MTSPI,0),cpp_freertos::Thread("MTENC",256,42) {
23 this->spiConfig.peripheral.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; // 4 = 10MHz 8 = 5MHz
24 this->spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_MSB;
25 this->spiConfig.peripheral.CLKPhase = SPI_PHASE_2EDGE;
26 this->spiConfig.peripheral.CLKPolarity = SPI_POLARITY_HIGH;
27 this->spiConfig.cspol = true;
28
31
33 registerCommand("cs", MtEncoderSPI_commands::cspin, "CS pin",CMDFLAG_GET | CMDFLAG_SET);
34 registerCommand("pos", MtEncoderSPI_commands::pos, "Position",CMDFLAG_GET | CMDFLAG_SET);
35 registerCommand("errors", MtEncoderSPI_commands::errors, "Parity error count",CMDFLAG_GET);
36 this->Start();
37}
38
40 MtEncoderSPI::inUse = false;
42}
43
45 uint16_t conf_int = Flash_ReadDefault(ADR_MTENC_CONF1, 0);
46 offset = Flash_ReadDefault(ADR_MTENC_OFS, 0) << 2;
47 uint8_t cspin = conf_int & 0xF;
49}
50
52 uint16_t conf_int = this->cspin & 0xF;
53 Flash_Write(ADR_MTENC_CONF1, conf_int);
54 Flash_Write(ADR_MTENC_OFS, offset >> 2);
55}
56
57
59 while(true){
60 requestNewDataSem.Take(); // Wait until a position is requested
61 //spiPort.receive_DMA(spi_buf, bytes, this); // Receive next frame
63 this->WaitForNotification(); // Wait until DMA is finished
65
66 if(curAngleInt-lastAngleInt > 0x20000){ // Underflowed
67 rotations--;
68 }
69 else if(lastAngleInt-curAngleInt > 0x20000){ // Overflowed
70 rotations++;
71 }
73
74 curPos = rotations * getCpr() + curAngleInt; // Update position
75 }else{
76 errors++;
77 }
79 updateInProgress = false;
80 }
81}
82
83void MtEncoderSPI::setCsPin(uint8_t cspin){
85 this->cspin = std::min<uint8_t>(spiPort.getCsPins().size(), cspin);
86 this->spiConfig.cs = *spiPort.getCsPin(this->cspin);
87 initSPI();
89}
90
93
96}
97
101uint8_t MtEncoderSPI::readSpi(uint8_t addr){
102
103 uint8_t txbuf[2] = {(uint8_t)(addr | MAGNTEK_READ),0};
104 uint8_t rxbuf[2] = {0,0};
105 spiPort.transmitReceive(txbuf, rxbuf, 2, this,100);
106
107 return rxbuf[1];
108}
109
110void MtEncoderSPI::writeSpi(uint8_t addr,uint8_t data){
111 uint8_t txbuf[2] = {addr,data};
112 spiPort.transmit(txbuf, 2, this,100);
113}
114
115void MtEncoderSPI::setPos(int32_t pos){
116 offset = curPos - pos;
117}
118
119
121
124 //updateAngleStatusCb();
126 }
127}
128
129
134
135 uint8_t txbufNew[4] = {0x03 | MAGNTEK_READ,0,0,0};
136 memcpy(this->txbuf,txbufNew,4);
137
139
140
141}
142
144 uint32_t angle17_10 = rxbuf[1];
145 uint32_t angle9_4 = rxbuf[2];
146 uint32_t angle3_0 = rxbuf[3];
147
148 // Parity check byte 2
149 uint8_t pc1 = angle17_10 ^ angle17_10 >> 1;
150 pc1 = pc1 ^ pc1 >> 2;
151 pc1 = pc1 ^ pc1 >> 4;
152
153 uint8_t pc1_2 = angle9_4 ^ angle9_4 >> 1;
154 pc1_2 = pc1_2 ^ pc1_2 >> 2;
155 pc1_2 = pc1_2 ^ pc1_2 >> 4;
156
157 // Parity check byte 1
158 angle3_0 = angle3_0 >> 2; // shift 2
159 uint8_t pc2 = (angle3_0) ^ (angle3_0) >> 1;
160 pc2 = pc2 ^ pc2 >> 2;
161 pc2 = pc2 ^ pc2 >> 4;
162
163 nomag = (angle9_4 & 0x02) >> 1;
164 overspeed = (angle3_0 & 0x04) >> 2;
165 angle9_4 = (angle9_4 & 0xFC) >> 2;
166 angle3_0 = angle3_0 >> 2;//(angle3_0 & 0xF0) >> 4;
167
168
169 bool parity_ok = !(pc2 & 1) && ((pc1 & 1) == (pc1_2 & 1));
170
171 curAngleInt = (angle17_10 << 10) | (angle9_4 << 4) | (angle3_0);
172
173
174 this->updateInProgress = false;
175
176 return parity_ok; // ok if both bytes have even parity
177}
178
180
181 return getPosAbs() - offset;
182}
183
185 if(updateInProgress){ // If a transfer is still in progress return the last result
186 return curPos;
187 }
188 updateInProgress = true;
189 requestNewDataSem.Give(); // Start transfer
190 waitForUpdateSem.Take(10); // Wait a bit
191
192 return curPos;
193}
194
196 return 262144;
197}
198
199
200
201CommandStatus MtEncoderSPI::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
202 switch(static_cast<MtEncoderSPI_commands>(cmd.cmdId)){
204 if(cmd.type==CMDtype::get){
205 replies.emplace_back(this->cspin+1);
206 }else if(cmd.type==CMDtype::set){
207 this->setCsPin(cmd.val-1);
208 }else{
209 return CommandStatus::ERR;
210 }
211 break;
212
214 if(cmd.type==CMDtype::get){
215 replies.emplace_back(getPos());
216 }else if(cmd.type==CMDtype::set){
217 this->setPos(cmd.val);
218 }else{
219 return CommandStatus::ERR;
220 }
221 break;
223 replies.emplace_back(errors);
224 break;
225 default:
227 }
228
229 return CommandStatus::OK;
230}
231
232#endif
CommandStatus
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
int32_t getPos() override
virtual ~MtEncoderSPI()
bool updateInProgress
Definition: MtEncoderSPI.h:70
uint8_t rxbuf[4]
Definition: MtEncoderSPI.h:75
uint32_t getCpr() override
cpp_freertos::BinarySemaphore requestNewDataSem
Definition: MtEncoderSPI.h:77
void saveFlash() override
static bool inUse
Definition: MtEncoderSPI.h:29
cpp_freertos::BinarySemaphore waitForUpdateSem
Definition: MtEncoderSPI.h:78
int32_t getPosAbs() override
uint8_t cspin
Definition: MtEncoderSPI.h:69
void setPos(int32_t pos)
int32_t curPos
Definition: MtEncoderSPI.h:66
void writeSpi(uint8_t addr, uint8_t data)
int32_t curAngleInt
Definition: MtEncoderSPI.h:65
const ClassIdentifier getInfo()
Command handlers always have class infos. Works well with ChoosableClass.
void restoreFlash() override
uint32_t errors
Definition: MtEncoderSPI.h:71
void updateAngleStatus()
int32_t rotations
Definition: MtEncoderSPI.h:67
int32_t lastAngleInt
Definition: MtEncoderSPI.h:64
void spiTxRxCompleted(SPIPort *port)
int32_t offset
Definition: MtEncoderSPI.h:68
uint8_t txbuf[4]
Definition: MtEncoderSPI.h:74
uint8_t readSpi(uint8_t addr)
bool updateAngleStatusCb()
void setCsPin(uint8_t cspin)
static ClassIdentifier info
Definition: MtEncoderSPI.h:30
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
uint8_t rxbuf_t[4]
Definition: MtEncoderSPI.h:76
Definition: SPI.h:100
SPIPort & spiPort
Definition: SPI.h:124
SPIConfig spiConfig
Definition: SPI.h:125
Definition: SPI.h:43
void transmitReceive(const uint8_t *txbuf, uint8_t *rxbuf, uint16_t size, SPIDevice *device, uint16_t timeout)
Definition: SPI.cpp:176
std::vector< OutputPin > & getCsPins()
Definition: SPI.cpp:61
void takeSemaphore()
Definition: SPI.cpp:186
bool reserveCsPin(OutputPin pin)
Definition: SPI.cpp:25
void transmitReceive_DMA(const uint8_t *txbuf, uint8_t *rxbuf, uint16_t size, SPIDevice *device)
Definition: SPI.cpp:103
void transmit(const uint8_t *buf, uint16_t size, SPIDevice *device, uint16_t timeout)
Definition: SPI.cpp:158
OutputPin * getCsPin(uint16_t idx)
Definition: SPI.cpp:65
void configurePort(SPI_InitTypeDef *config)
Definition: SPI.cpp:72
void giveSemaphore()
Definition: SPI.cpp:199
bool freeCsPin(OutputPin pin)
Definition: SPI.cpp:37
bool Take(TickType_t Timeout=portMAX_DELAY)
Definition: csemaphore.cpp:46
uint32_t WaitForNotification(TickType_t Timeout=portMAX_DELAY)
Definition: thread.hpp:246
static struct @612 data
TVal Flash_ReadDefault(uint16_t adr, TVal def)
Definition: flash_helpers.h:36
bool Flash_Write(uint16_t adr, uint16_t dat)
static void * memcpy(void *dst, const void *src, size_t n)
Definition: ringbuffer.c:8
const char * name
uint32_t cmdId
SPI_InitTypeDef peripheral
Definition: SPI.h:38
OutputPin cs
Definition: SPI.h:34
bool cspol
CSPOL=true === active low.
Definition: SPI.h:37