Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
#include "commands.h"
#include "hal.h"
#include "math.h"
#include "defines.h"
#include "angle.h"
#include "stm32f4xx_conf.h"
#include "hw/hw.h"
HAL_COMP(res);
HAL_PIN(pos);
HAL_PIN(amp);
HAL_PIN(quad);
HAL_PIN(poles);
HAL_PIN(min_amp);
HAL_PIN(vel); // TODO: vel rev, fb,cmd -> vel0,1 -> rev
HAL_PIN(sin);
HAL_PIN(cos);
HAL_PIN(enable);
HAL_PIN(error);
HAL_PIN(state);
HAL_PIN(phase); //phase adjust
HAL_PIN(res_mode); //resolver mode output, calculated form frequency
HAL_PIN(freq);
// TODO: in hal stop, reset adc dma
struct res_ctx_t {
int lastq; // last quadrant
int abspos; // multiturn position
};
static void nrt_init(void *ctx_ptr, hal_pin_inst_t *pin_ptr) {
// struct res_ctx_t *ctx = (struct res_ctx_t *)ctx_ptr;
struct res_pin_ctx_t *pins = (struct res_pin_ctx_t *)pin_ptr;
PIN(poles) = 1.0;
PIN(phase) = 0.85;
PIN(min_amp) = 0.15;
PIN(freq) = 10000;
}
static void hw_init(void *ctx_ptr, hal_pin_inst_t *pin_ptr) {
struct res_ctx_t *ctx = (struct res_ctx_t *)ctx_ptr;
// struct res_pin_ctx_t *pins = (struct res_pin_ctx_t *)pin_ptr;
ctx->abspos = 0;
ctx->lastq = 0;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
#ifdef V4
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//timer init for v4, v3 uses slave timer
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = ADC_TRIGGER_FREQ / FRT_FREQ - 1; // 20kHz
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_External1); // Rising edges of the selected trigger (TRGI) clock the counter
TIM_ITRxExternalClockConfig(TIM4, TIM_TS_ITR2); // clk = TIM_MASTER(TIM2) trigger out
TIM_ARRPreloadConfig(TIM4, ENABLE);
TIM_Cmd(TIM4, ENABLE);
#endif
//12-1 40khz
//15-1 35khz
//20-1 30khz 2
//24-1 25khz
//30-1 20khz 3
//40-1 15khz 4
//60-1 10khz 6 default
//120-1 5khz 12
//res_en = ADC_GROUPS/2/(res_freq/rt_freq)
//arr = ADC_TRIGGER_FREQ/2/res_freq
// resolver reference signal OC
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
//ref is always OC3
TIM_OC3Init(FB0_RES_REF_TIM, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(FB0_RES_REF_TIM, TIM_OCPreload_Enable);
TIM_CtrlPWMOutputs(FB0_RES_REF_TIM, ENABLE);
//resolver ref signal generation
GPIO_InitStructure.GPIO_Pin = FB0_RES_REF_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(FB0_RES_REF_PORT, &GPIO_InitStructure);
GPIO_PinAFConfig(FB0_RES_REF_PORT, FB0_RES_REF_PIN_SOURCE, FB0_RES_REF_TIM_AF);
//txen
GPIO_InitStructure.GPIO_Pin = FB0_Z_TXEN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(FB0_Z_TXEN_PORT, &GPIO_InitStructure);
GPIO_SetBits(FB0_Z_TXEN_PORT, FB0_Z_TXEN_PIN);
}
static void rt_func(float period, void *ctx_ptr, hal_pin_inst_t *pin_ptr) {
struct res_ctx_t *ctx = (struct res_ctx_t *)ctx_ptr;
struct res_pin_ctx_t *pins = (struct res_pin_ctx_t *)pin_ptr;
//TODO: arr can change!
uint32_t mult = CLAMP(PIN(freq) / RT_FREQ + 0.5, 1, 4);
PIN(freq) = RT_FREQ * mult;
FB0_RES_REF_TIM->ARR = ADC_TRIGGER_FREQ / 2 / (RT_FREQ * mult) - 1;
FB0_RES_REF_TIM->CCR3 = (int)CLAMP(PIN(phase) * FB0_RES_REF_TIM->ARR, 0, FB0_RES_REF_TIM->ARR - 1);
PIN(res_mode) = ADC_GROUPS / 2 / mult;
float s = 0.0;
float c = 0.0;
float a = 0.0;
s = PIN(sin);
c = PIN(cos);
a = sqrtf(s * s + c * c);
float p = MAX(1.0, PIN(poles));
float pos = atan2f(s, c);
float dpos = PIN(vel) * period / 2.0;
if(a < PIN(min_amp)) {
PIN(error) = 1.0;
PIN(state) = 0.0;
} else {
PIN(error) = 0.0;
PIN(state) = 3.0;
if(p == 1.0f) {
PIN(pos) = mod(pos + dpos);
} else {
int q = PIN(quad); // current quadrant
if(ctx->lastq == 2 && q == 3)
ctx->abspos++;
if(ctx->lastq == 3 && q == 2)
ctx->abspos--;
if(ctx->abspos >= p) {
ctx->abspos = 0;
}
if(ctx->abspos <= -1) {
ctx->abspos = p - 1;
}
ctx->lastq = q;
//TODO: clamp ctx->abspos
float absa = pos + ctx->abspos * M_PI * 2.0f;
PIN(pos) = mod(absa / p + dpos);
}
}
PIN(amp) = a;
}
const hal_comp_t res_comp_struct = {
.name = "res",
.nrt = 0,
.rt = rt_func,
.frt = 0,
.nrt_init = nrt_init,
.hw_init = hw_init,
.rt_start = 0,
.frt_start = 0,
.rt_stop = 0,
.frt_stop = 0,
.ctx_size = sizeof(struct res_ctx_t),
.pin_count = sizeof(struct res_pin_ctx_t) / sizeof(struct hal_pin_inst_t),
};
4fca5f20eThis file is pinned to the selected release. Download the original to open it in your design tool.