-
Notifications
You must be signed in to change notification settings - Fork 12
/
as5x47.c
executable file
·115 lines (99 loc) · 2.73 KB
/
as5x47.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "as5x47.h"
#include "ch.h"
#include "hal.h"
#include "stm32f4xx_conf.h"
#include "comm_usb.h"
#include "hw_conf.h"
static void spicb(SPIDriver *spip);
static bool inTransaction = false;
static uint8_t rx[2];
static uint8_t tx[2];
static uint16_t lastRawPosition = 0;
static const SPIConfig encoderSPI =
{
spicb,
GPIOA,
GPIOA_LRCK,
0
};
CH_IRQ_HANDLER(TIM4_IRQHandler) {
chSysLockFromISR();
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) {
// as5x47_update_raw_position();
palClearPad(GPIOA, GPIOA_LRCK);
// Clear the IT pending bit
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
chSysUnlockFromISR();
}
void as5x47_init(void)
{
palSetPadMode(ENCODER_SCK_GPIO, ENCODER_SCK_PIN, PAL_MODE_ALTERNATE(5) |
PAL_STM32_OSPEED_HIGHEST); /* SCK. */
palSetPadMode(ENCODER_MISO_GPIO, ENCODER_MISO_PIN, PAL_MODE_ALTERNATE(5) |
PAL_STM32_OSPEED_HIGHEST); /* MISO.*/
palSetPadMode(ENCODER_MOSI_GPIO, ENCODER_MOSI_PIN, PAL_MODE_ALTERNATE(5) |
PAL_STM32_OSPEED_HIGHEST); /* MOSI.*/
palSetPadMode(ENCODER_NSS_GPIO, ENCODER_NSS_PIN, PAL_MODE_OUTPUT_PUSHPULL |
PAL_STM32_OSPEED_HIGHEST);
palSetPad(ENCODER_NSS_GPIO, ENCODER_NSS_PIN);
spiStart(&SPID1, &encoderSPI);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
// Time Base configuration
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = ((168000000 / 2 / 20000) - 1);
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
nvicEnableVector(TIM4_IRQn, 6);
// Enable overflow interrupt
//TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
// Enable timers
TIM_Cmd(TIM4, ENABLE);
}
float as5x47_get_angle(void)
{
as5x47_update_raw_position();
float raw = as5x47_get_raw_position() % 8192;
return 360.0 * raw / 8192.0;
}
void as5x47_update_raw_position(void)
{
spiSelectI(&SPID1);
tx[0] = 0x3F | (1 << 6);
tx[1] = 0xFF;
spiStartSendI(&SPID1, 2, tx);
inTransaction = true;
}
uint16_t as5x47_get_raw_position(void)
{
return lastRawPosition;
}
float as5x47_get_last_angle(void)
{
return 360.0 * (as5x47_get_raw_position() % 8192) / 8192.0;
}
static void spicb(SPIDriver *spip) {
chSysLockFromISR();
spiUnselectI(spip);
if (inTransaction)
{
int i = 0;
for(i = 0; i < 20; i++)
{
__asm__("NOP");
}
spiSelectI(spip);
tx[0] = 0;
tx[1] = 0;
spiStartExchangeI(spip, 2, tx, rx);
inTransaction = false;
}
else
{
lastRawPosition = (uint16_t)(((rx[0] << 8) | rx[1]) & 0x3FFF);
}
chSysUnlockFromISR();
}