Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
6828423fcThis file is pinned to the selected release. Download the original to open it in your design tool.
//using FB_TX
//TODO: ready pin
#define NUM_OF_SAMPLES_Y 800
HAL_COMP(yaskawa);
HAL_PIN(pos) = 0.0;
HAL_PIN(error) = 0.0;
HAL_PIN(dump) = 0;
HAL_PIN(len) = 16;
HAL_PIN(off) = 60;
MEM(volatile uint32_t rxbuf[NUM_OF_SAMPLES_Y + 1]);
MEM(volatile uint32_t txbuf[128]);
MEM(int pos) = 0;
MEM(char data[150]);
MEM(DMA_InitTypeDef DMA_InitStructurerx);
RT_INIT(
GPIO_InitTypeDef GPIO_InitStruct;
//TX enable
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
//TX
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_TIM2);
//TIM2 is used to toggle tx pin
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
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;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);
TIM_CtrlPWMOutputs(TIM2, ENABLE);
//RX
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
//TIM8 triggers DMA to sample reply
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 20; // 168 / (20 + 1) = 8MHz
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure);
TIM_ARRPreloadConfig(TIM8,ENABLE);
TIM_DMACmd(TIM8, TIM_DMA_Update, ENABLE);
TIM_Cmd(TIM8, ENABLE);
DMA_InitStructurerx.DMA_Channel = DMA_Channel_7; //TIM8 ch1
DMA_InitStructurerx.DMA_PeripheralBaseAddr = (uint32_t)&GPIOB->IDR;
DMA_InitStructurerx.DMA_Memory0BaseAddr = (uint32_t)&rxbuf;
DMA_InitStructurerx.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructurerx.DMA_BufferSize = NUM_OF_SAMPLES_Y;
DMA_InitStructurerx.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructurerx.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructurerx.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructurerx.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructurerx.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructurerx.DMA_Priority = DMA_Priority_High;
DMA_InitStructurerx.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructurerx.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructurerx.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructurerx.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
//manchaster
//0 -> 01
//1 -> 10
//SYNC framing framing
//0101010101010101010 01111110 111110 111110 111110 1 01111110;
//010101... are to sync receiver
//01111110 is hdlc start and end flag for framing
//0 is appended after 5 ones => transmitted data is 0xffff
//reply has the same format
const char request[] = "0101010101010101010 01111110 111110 111110 111110 1 01111110";
char request_m[sizeof(request)*2];
uint32_t tim_a = TIM2->CCER;
uint32_t tim_b = tim_a;
tim_a &= ~(1<<9);//0
tim_b |= (1<<9);//1
//encode in manchaster
int j = 0;
for(int i = 0;request[i];i++){
if(request[i] == '0'){
request_m[j++] = '0';
request_m[j++] = '1';
}else if(request[i] == '1'){
request_m[j++] = '1';
request_m[j++] = '0';
}
}
request_m[j] = '\0';
//build txbuf for dma
for(int i = 0;request_m[i];i++){
if(request_m[i] == '0'){
txbuf[pos++] = tim_a;
}else if(request_m[i] == '1'){
txbuf[pos++] = tim_b;
}
}
txbuf[pos++] = tim_a;
txbuf[pos++] = tim_a;
);
RT(
// DMA2-Config
DMA_Cmd(DMA2_Stream1, DISABLE);
DMA_DeInit(DMA2_Stream1);
DMA_InitStructure.DMA_Channel = DMA_Channel_7; //TIM8 ch1
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM2->CCER;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&txbuf;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = pos;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Word;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream1, &DMA_InitStructure);
TIM8->ARR = 20; // 168 / (20 + 1) = 8MHz
GPIOB->BSRRL = GPIO_Pin_12;//TX enable
DMA_Cmd(DMA2_Stream1, DISABLE);
DMA_ClearFlag(DMA2_Stream1, DMA_FLAG_TCIF1);
DMA_Cmd(DMA2_Stream1, ENABLE);//transmit request
while (!(DMA2->LISR & DMA_FLAG_TCIF1));//wait for request
GPIOB->BSRRH = GPIO_Pin_12;//TX disable
//DMA2-Config
DMA_Cmd(DMA2_Stream1, DISABLE);
DMA_DeInit(DMA2_Stream1);
TIM8->ARR = 6; // 168 / (6 + 1) = 24MHz
DMA_Init(DMA2_Stream1, &DMA_InitStructurerx);
uint32_t error = 0;
GPIOB->BSRRH = GPIO_Pin_3;//messpin
//start DMA
DMA_Cmd(DMA2_Stream1, DISABLE);
DMA_ClearFlag(DMA2_Stream1, DMA_FLAG_TCIF1);
DMA_Cmd(DMA2_Stream1, ENABLE);
//wait for DMA transfer complete
while (DMA_GetFlagStatus(DMA2_Stream1, DMA_FLAG_TCIF1) == RESET);
GPIOB->BSRRL = GPIO_Pin_3;//messpin
uint32_t current;
uint32_t last = (rxbuf[0] & GPIO_Pin_11);
uint32_t first_edge = 0;
//find any edge
for(int j = 1; j < 20; j++){
current = (rxbuf[j] & GPIO_Pin_11);
if(current != last){
first_edge = j;
break;
}
last = current;
}
last = (rxbuf[first_edge] & GPIO_Pin_11);
//align edge
for(int j = first_edge+3; j < 20; j+=3){
current = (rxbuf[j] & GPIO_Pin_11);
if(current == last && last != 0){
first_edge = j;
break;
}
last = current;
}
if(first_edge == 0 || first_edge == 19){
error++;
}
first_edge %= 6;
uint32_t bit = 0;// 2 manchaster bits = 1 bit
uint32_t ones = 0;// received ones, needed for framing and unstuffing
uint32_t j = 0;// unstuffing and start offset
int pos_length = PIN(len);// position length
int pos_offset = PIN(off);// position offset
int decode_length = pos_length + pos_offset + 1;
//decode manchaster and unstuff
for(int i = j; i < (decode_length+j); i++){
bit = 0;
if(rxbuf[i*6+first_edge+1]&GPIO_Pin_11){
bit += 2;
}
if(rxbuf[i*6+first_edge+4]&GPIO_Pin_11){
bit += 1;
}
switch(bit){
case 1://01 -> manchaster encoded 0
if(ones == 5){// 0 after 5 ones => stuffed data
j++;
}else{
data[i-j] = '0';
}
ones = 0;
break;
case 2://10 -> manchaster encoded 1
if(ones == 5){// 1 after 5 ones => start of packet
j = ++i;
ones = 0;
}else{
ones++;
data[i-j] = '1';
}
break;
case 0://00 -> manchaster alignment error
case 3://11 -> manchaster alignment error
default://obsolete
data[i-j] = 'X';
error++;
break;
}
}
data[100] = 0; // terminate string
uint32_t pos = 0;
//extract position data
for(int i = 0; i < pos_length; i++){
pos += (data[i + pos_offset]=='1') << i;
}
if(error){
PIN(error) = 1.0;
}else{
PIN(error) = 0.0;
PIN(pos) = (float)pos / (float)(1<<pos_length) * M_PI * 2.0 - M_PI;
}
);
NRT(
if(RISING_EDGE(PIN(dump))){
printf("%s\n",data);
}
);
ENDCOMP;