2424#include "hw.h"
2525#include "mc_interface.h"
2626#include "utils.h"
27+ #include "timer.h"
2728#include <math.h>
2829
2930// Defines
3233#define AD2S1205_SAMPLE_RATE_HZ 20000 //25MHz max spi clk
3334#define MT6816_SAMPLE_RATE_HZ 20000
3435#define MT6816_NO_MAGNET_ERROR_MASK 0x0002
36+ #define BISSC_SAMPLE_RATE_HZ 10000
3537#define SINCOS_SAMPLE_RATE_HZ 20000
3638#define SINCOS_MIN_AMPLITUDE 1.0 // sqrt(sin^2 + cos^2) has to be larger than this
3739#define SINCOS_MAX_AMPLITUDE 1.65 // sqrt(sin^2 + cos^2) has to be smaller than this
3840
39- #if (AS5047_USE_HW_SPI_PINS ) || (MT6816_USE_HW_SPI_PINS ) || (AD2S1205_USE_HW_SPI_PINS )
41+ #if (AS5047_USE_HW_SPI_PINS ) || (MT6816_USE_HW_SPI_PINS ) || (AD2S1205_USE_HW_SPI_PINS ) || ( BISSC_USE_HW_SPI_PINS )
4042#ifdef HW_SPI_DEV
4143#define SPI_SW_MISO_GPIO HW_SPI_PORT_MISO
4244#define SPI_SW_MISO_PIN HW_SPI_PIN_MISO
7577#define SPI_SW_CS_PIN HW_HALL_ENC_PIN3
7678#endif
7779
80+ // Add this to move from Thread to NVIC process to schedule encoder
81+ #define BISSC_ISR_IMPL
82+
7883// Private types
7984typedef enum {
8085 ENCODER_MODE_NONE = 0 ,
@@ -83,7 +88,8 @@ typedef enum {
8388 RESOLVER_MODE_AD2S1205 ,
8489 ENCODER_MODE_SINCOS ,
8590 ENCODER_MODE_TS5700N8501 ,
86- ENCODER_MODE_MT6816_SPI
91+ ENCODER_MODE_MT6816_SPI ,
92+ ENCODER_MODE_BISSC_SPI
8793} encoder_mode ;
8894
8995// Private variables
@@ -116,6 +122,20 @@ static uint32_t sincos_signal_above_max_error_cnt = 0;
116122static float sincos_signal_low_error_rate = 0.0 ;
117123static float sincos_signal_above_max_error_rate = 0.0 ;
118124
125+ #ifndef BISSC_ISR_IMPL
126+ static THD_FUNCTION (bissc_thread , arg ) ;
127+ static THD_WORKING_AREA (bissc_thread_wa , 512 ) ;
128+ static thread_t * bissc_tp ;
129+ static volatile bool bissc_stop_now = true;
130+ static volatile bool bissc_thread_is_running = false;
131+ #endif
132+ static uint8_t tableCRC6n [64 ] = {0 };
133+ static const uint8_t POLY = 0x43 ;
134+ static volatile uint8_t decod_buf [8 ] = {0 };
135+ static volatile float delay_between_2biss_c ;
136+ void computeBisscData (SPIDriver * spip );
137+
138+
119139static SerialConfig TS5700N8501_uart_cfg = {
120140 2500000 ,
121141 0 ,
@@ -141,6 +161,13 @@ static const SPIConfig mt6816_spi_cfg = {
141161 SPI_SW_CS_GPIO ,
142162 SPI_SW_CS_PIN ,
143163 SPI_BaudRatePrescaler_4 | SPI_CR1_CPOL | SPI_CR1_CPHA | SPI_DATASIZE_16BIT };
164+
165+ static const SPIConfig bissc_spi_cfg = {
166+ & computeBisscData ,
167+ SPI_SW_CS_GPIO ,
168+ SPI_SW_CS_PIN ,
169+ SPI_BaudRatePrescaler_32 | SPI_CR1_CPOL | SPI_CR1_CPHA };
170+
144171#endif
145172
146173static THD_FUNCTION (ts5700n8501_thread , arg ) ;
@@ -250,6 +277,10 @@ void encoder_ts57n8501_reset_multiturn(void) {
250277 ts5700n8501_reset_multiturn = true;
251278}
252279
280+ float encode_bissc_get_time_between_reads (void ) {
281+ return delay_between_2biss_c ;
282+ }
283+
253284void encoder_deinit (void ) {
254285 nvicDisableVector (HW_ENC_EXTI_CH );
255286 nvicDisableVector (HW_ENC_TIM_ISR_CH );
@@ -280,6 +311,16 @@ void encoder_deinit(void) {
280311#endif
281312 }
282313
314+ #ifndef BISSC_ISR_IMPL
315+ if (mode == ENCODER_MODE_BISSC_SPI ) {
316+ chEvtSignalI (bissc_tp , (eventmask_t ) 1 );
317+ bissc_stop_now = true;
318+ while (bissc_thread_is_running ) {
319+ chThdSleepMilliseconds (1 );
320+ }
321+ }
322+ #endif
323+
283324 index_found = false;
284325 mode = ENCODER_MODE_NONE ;
285326 last_enc_angle = 0.0 ;
@@ -413,6 +454,71 @@ void encoder_init_mt6816_spi(void) {
413454#endif
414455}
415456
457+ void encoder_init_bissc_spi (uint32_t counts ) {
458+ #ifdef HW_SPI_DEV
459+
460+ mode = ENCODER_MODE_BISSC_SPI ;
461+ index_found = true;
462+ spi_error_rate = 0.0 ;
463+ enc_counts = counts ;
464+
465+ palSetPadMode (SPI_SW_SCK_GPIO , SPI_SW_SCK_PIN , PAL_MODE_ALTERNATE (5 ) | PAL_STM32_OSPEED_HIGHEST );
466+ palSetPadMode (SPI_SW_MISO_GPIO , SPI_SW_MISO_PIN , PAL_MODE_ALTERNATE (5 ) | PAL_STM32_OSPEED_HIGHEST );
467+ palSetPadMode (SPI_SW_MOSI_GPIO , SPI_SW_MOSI_PIN , PAL_MODE_ALTERNATE (5 ) | PAL_STM32_OSPEED_HIGHEST );
468+ palSetPadMode (SPI_SW_CS_GPIO , SPI_SW_CS_PIN , PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST );
469+
470+ //Start driver with BissC SPI settings
471+ spiInit ();
472+ spiStart (& HW_SPI_DEV , & bissc_spi_cfg );
473+
474+ //Init CRC table
475+ for (int i = 0 ; i < 64 ; i ++ ){
476+ int crc = i ;
477+
478+ for (int j = 0 ; j < 6 ; j ++ ){
479+ if (crc & 0x20 ){
480+ crc <<= 1 ;
481+ crc ^= POLY ;
482+ } else {
483+ crc <<= 1 ;
484+ }
485+ }
486+ tableCRC6n [i ] = crc ;
487+ }
488+
489+ #ifdef BISSC_ISR_IMPL
490+
491+ // Enable timer clock
492+ HW_ENC_TIM_CLK_EN ();
493+
494+ // Time Base configuration
495+ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
496+ TIM_TimeBaseStructure .TIM_Prescaler = 0 ;
497+ TIM_TimeBaseStructure .TIM_CounterMode = TIM_CounterMode_Up ;
498+ TIM_TimeBaseStructure .TIM_Period = ((168000000 / 2 / BISSC_SAMPLE_RATE_HZ ) - 1 );
499+ TIM_TimeBaseStructure .TIM_ClockDivision = 0 ;
500+ TIM_TimeBaseStructure .TIM_RepetitionCounter = 0 ;
501+ TIM_TimeBaseInit (HW_ENC_TIM , & TIM_TimeBaseStructure );
502+
503+ // Enable overflow interrupt
504+ TIM_ITConfig (HW_ENC_TIM , TIM_IT_Update , ENABLE );
505+
506+ // Enable timer
507+ TIM_Cmd (HW_ENC_TIM , ENABLE );
508+
509+ nvicEnableVector (HW_ENC_TIM_ISR_CH , 6 );
510+ #else
511+ bissc_thread_is_running = true;
512+ bissc_stop_now = false;
513+
514+ chThdCreateStatic (bissc_thread_wa , sizeof (bissc_thread_wa ),
515+ NORMALPRIO - 10 , bissc_thread , NULL );
516+ #endif
517+
518+
519+ #endif
520+ }
521+
416522void encoder_init_ad2s1205_spi (void ) {
417523 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
418524
@@ -524,6 +630,7 @@ float encoder_read_deg(void) {
524630 case ENCODER_MODE_MT6816_SPI :
525631 case RESOLVER_MODE_AD2S1205 :
526632 case ENCODER_MODE_TS5700N8501 :
633+ case ENCODER_MODE_BISSC_SPI :
527634 angle = last_enc_angle ;
528635 break ;
529636
@@ -848,6 +955,15 @@ void encoder_tim_isr(void) {
848955 UTILS_LP_FAST (spi_error_rate , 1.0 , 1. /MT6816_SAMPLE_RATE_HZ );
849956 }
850957 }
958+ #ifdef BISSC_ISR_IMPL
959+ if (mode == ENCODER_MODE_BISSC_SPI ) {
960+ if (HW_SPI_DEV .state == SPI_READY ) {
961+ spiSelectI (& HW_SPI_DEV );
962+ spiStartReceiveI (& HW_SPI_DEV , 8 , (void * )decod_buf );
963+ }
964+ }
965+ #endif
966+
851967#endif
852968
853969 if (mode == RESOLVER_MODE_AD2S1205 ) {
@@ -1164,3 +1280,97 @@ static THD_FUNCTION(ts5700n8501_thread, arg) {
11641280 }
11651281}
11661282
1283+
1284+ void computeBisscData (SPIDriver * spip ) {
1285+
1286+ spiUnselectI (spip );
1287+
1288+ int lenghtDataBit = enc_counts ;
1289+
1290+ uint64_t rxData64 ;
1291+ rxData64 = (uint64_t )decod_buf [0 ] << 56 ;
1292+ rxData64 |= (uint64_t )decod_buf [1 ] << 48 ;
1293+ rxData64 |= (uint64_t )decod_buf [2 ] << 40 ;
1294+ rxData64 |= (uint64_t )decod_buf [3 ] << 32 ;
1295+ rxData64 |= (uint64_t )decod_buf [4 ] << 24 ;
1296+ rxData64 |= (uint64_t )decod_buf [5 ] << 16 ;
1297+ rxData64 |= (uint64_t )decod_buf [6 ] << 8 ;
1298+ rxData64 |= (uint64_t )decod_buf [7 ];
1299+
1300+ // sample of rxData64
1301+ // like this 1100000000000000100001100111010000000101110111100000000000000000
1302+ rxData64 <<= __builtin_clzll (rxData64 ); // slice rxData to have a value starting with 1
1303+ rxData64 &= 0x3FFFFFFFFFFFFFFF ; // remove the 2 first bit
1304+
1305+ // remove the first 1, count how many digit stay in buffer after removing the 0, if there is more than 32 digits,
1306+ // keep only 32st (on the left)
1307+ // 32 because the format is : (1+1+lenghtDataBit+1+1+6) - Align bitstream to left (Startbit, CDS, 22-bit Position, Error, Warning, CRC)
1308+ int nbBit = log2 (rxData64 )+ 1 ;
1309+ if ( nbBit >= ( lenghtDataBit + 10 ) ) {
1310+ rxData64 >>= nbBit - ( lenghtDataBit + 10 );
1311+ }
1312+
1313+ uint8_t crcRx = rxData64 & 0x3F ; //extract last 6-bit digits to get CRC
1314+ uint32_t dataRx = (rxData64 >> 6 ) & ((1 <<(lenghtDataBit + 2 )) - 1 ); //Shift out CRC, AND with 24-bit mask to get raw data (position, error, warning)
1315+ spi_val = (dataRx >> 2 ) & ((1 <<lenghtDataBit ) - 1 ); //Shift out error and warning, AND with 22-bit mask to get position
1316+
1317+ uint8_t crc = 0 ; //CRC seed is 0b000000
1318+ crc = ((dataRx >> 30 ) & 0x03 );
1319+ crc = tableCRC6n [((dataRx >> 24 ) & 0x3F ) ^ crc ];
1320+ crc = tableCRC6n [((dataRx >> 18 ) & 0x3F ) ^ crc ];
1321+ crc = tableCRC6n [((dataRx >> 12 ) & 0x3F ) ^ crc ];
1322+ crc = tableCRC6n [((dataRx >> 6 ) & 0x3F ) ^ crc ];
1323+ crc = tableCRC6n [((dataRx >> 0 ) & 0x3F ) ^ crc ];
1324+ crc = 0x3F & ~crc ; //CRC is output inverted
1325+
1326+ if (crc != crcRx )
1327+ {
1328+ ++ spi_error_cnt ;
1329+ UTILS_LP_FAST (spi_error_rate , 1.0 , 1. /BISSC_SAMPLE_RATE_HZ );
1330+ } else {
1331+ last_enc_angle = ((float )spi_val * 360.0 ) / ((1 <<lenghtDataBit ) - 1 );
1332+ UTILS_LP_FAST (spi_error_rate , 0.0 , 1. /BISSC_SAMPLE_RATE_HZ );
1333+ }
1334+
1335+ #ifndef BISSC_ISR_IMPL
1336+ chEvtSignalI (bissc_tp , (eventmask_t ) 1 );
1337+ #endif
1338+
1339+ }
1340+
1341+ #ifndef BISSC_ISR_IMPL
1342+
1343+ static THD_FUNCTION (bissc_thread , arg ) {
1344+ (void )arg ;
1345+
1346+ chRegSetThreadName ("BISSC Read" );
1347+
1348+ bissc_tp = chThdGetSelfX ();
1349+ int end_bissc_time = timer_time_now ();
1350+
1351+
1352+
1353+ for (;;) {
1354+ // Check if it is time to stop.
1355+ if (bissc_stop_now ) {
1356+ bissc_thread_is_running = false;
1357+ return ;
1358+ }
1359+
1360+ delay_between_2biss_c = timer_seconds_elapsed_since (end_bissc_time );
1361+
1362+ // Call the spi incoming message in DMA, on return, the result is decoded
1363+ // by the computeBisscData callBack
1364+ spiSelectI (& HW_SPI_DEV );
1365+ spiStartReceiveI (& HW_SPI_DEV , 8 , (void * )decod_buf );
1366+
1367+ chEvtWaitAny ((eventmask_t ) 1 );
1368+ end_bissc_time = timer_time_now ();
1369+
1370+ chThdSleepMicroseconds (10 );
1371+
1372+ }
1373+
1374+ }
1375+
1376+ #endif
0 commit comments