292 lines
9.2 KiB
C
292 lines
9.2 KiB
C
|
/* -*- mode: c; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4; coding: utf-8 -*- */
|
||
|
/************************************************************************************
|
||
|
** **
|
||
|
** mcHF QRP Transceiver **
|
||
|
** K Atanassov - M0NKA 2014 **
|
||
|
** **
|
||
|
**---------------------------------------------------------------------------------**
|
||
|
** **
|
||
|
** File name: **
|
||
|
** Description: **
|
||
|
** Last Modified: **
|
||
|
** Licence: GNU GPLv3 **
|
||
|
************************************************************************************/
|
||
|
|
||
|
// Common
|
||
|
#include "uhsdr_board.h"
|
||
|
#include "ui_driver.h"
|
||
|
#include "stdlib.h"
|
||
|
#include "ui_rotary.h"
|
||
|
#include "tim.h"
|
||
|
// ------------------------------------------------
|
||
|
// Encoder 1-4 Array
|
||
|
__IO EncoderSelection encSel[4];
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
GPIO_TypeDef* pio;
|
||
|
uint16_t pin;
|
||
|
uint8_t af;
|
||
|
} pin_t;
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
TIM_TypeDef* tim;
|
||
|
TIM_HandleTypeDef * htim;
|
||
|
pin_t pin[2];
|
||
|
|
||
|
} encoder_io_t;
|
||
|
|
||
|
const encoder_io_t encoderIO[4] =
|
||
|
{
|
||
|
{
|
||
|
.tim = TIM3,
|
||
|
.htim = &htim3,
|
||
|
.pin =
|
||
|
{
|
||
|
{ ENC_ONE_CH1_PIO, ENC_ONE_CH1, GPIO_AF2_TIM3 } ,
|
||
|
{ ENC_ONE_CH2_PIO, ENC_ONE_CH2, GPIO_AF2_TIM3 }
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.tim = TIM4,
|
||
|
.htim = &htim4,
|
||
|
.pin =
|
||
|
{
|
||
|
{ ENC_TWO_CH1_PIO, ENC_TWO_CH1, GPIO_AF2_TIM4 } ,
|
||
|
{ ENC_TWO_CH2_PIO, ENC_TWO_CH2, GPIO_AF2_TIM4 }
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.tim = TIM5,
|
||
|
.htim = &htim5,
|
||
|
.pin =
|
||
|
{
|
||
|
{ ENC_THREE_CH1_PIO, ENC_THREE_CH1, GPIO_AF2_TIM5 } ,
|
||
|
{ ENC_THREE_CH2_PIO, ENC_THREE_CH2, GPIO_AF2_TIM5 }
|
||
|
}
|
||
|
},
|
||
|
{
|
||
|
.tim = TIM8,
|
||
|
.htim = &htim8,
|
||
|
.pin =
|
||
|
{
|
||
|
{ FREQ_ENC_CH1_PIO, FREQ_ENC_CH1, GPIO_AF3_TIM8 } ,
|
||
|
{ FREQ_ENC_CH2_PIO, FREQ_ENC_CH2, GPIO_AF3_TIM8 }
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
void UiRotaryEncoderInit(uint8_t id)
|
||
|
{
|
||
|
const encoder_io_t* encIO = &encoderIO[id];
|
||
|
// Init encoder one
|
||
|
encSel[id].value_old = 0;
|
||
|
encSel[id].value_new = ENCODER_RANGE;
|
||
|
encSel[id].de_detent = 0;
|
||
|
encSel[id].tim = encIO->tim;
|
||
|
HAL_TIM_Encoder_Start(encIO->htim, TIM_CHANNEL_1 | TIM_CHANNEL_2);
|
||
|
|
||
|
#if 0
|
||
|
GPIO_InitTypeDef GPIO_InitStructure;
|
||
|
|
||
|
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
|
||
|
GPIO_InitStructure.Speed = GPIO_SPEED_LOW;
|
||
|
GPIO_InitStructure.Pull = GPIO_PULLUP;
|
||
|
|
||
|
for (uint32_t pinIdx = 0; pinIdx < 2; pinIdx++)
|
||
|
{
|
||
|
GPIO_InitStructure.Alternate = encIO->pin[pinIdx].af;
|
||
|
GPIO_InitStructure.Pin = encIO->pin[pinIdx].pin;
|
||
|
GPIO_Init(encIO->pin[pinIdx].pio, &GPIO_InitStructure);
|
||
|
}
|
||
|
|
||
|
|
||
|
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||
|
|
||
|
TIM_TimeBaseStructure.TIM_Period = (ENCODER_RANGE/ENCODER_LOG_D) + (ENCODER_FLICKR_BAND*2); // range + 3 + 3
|
||
|
TIM_TimeBaseStructure.TIM_Prescaler = 0;
|
||
|
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||
|
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||
|
|
||
|
TIM_EncoderInterfaceConfig(encIO->tim,TIM_EncoderMode_TI12,TIM_ICPolarity_Falling,TIM_ICPolarity_Falling);
|
||
|
|
||
|
TIM_TimeBaseInit(encIO->tim, &TIM_TimeBaseStructure);
|
||
|
TIM_Cmd(encIO->tim, ENABLE);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
//*----------------------------------------------------------------------------
|
||
|
//* Function Name : UiRotaryFreqEncoderInit
|
||
|
//* Object :
|
||
|
//* Input Parameters :
|
||
|
//* Output Parameters :
|
||
|
//* Functions called :
|
||
|
//*----------------------------------------------------------------------------
|
||
|
void UiRotaryFreqEncoderInit(void)
|
||
|
{
|
||
|
///RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
|
||
|
UiRotaryEncoderInit(ENCFREQ);
|
||
|
}
|
||
|
|
||
|
//*----------------------------------------------------------------------------
|
||
|
//* Function Name : UiRotaryEncoderOneInit
|
||
|
//* Object : audio gain
|
||
|
//* Input Parameters :
|
||
|
//* Output Parameters :
|
||
|
//* Functions called :
|
||
|
//*----------------------------------------------------------------------------
|
||
|
void UiRotaryEncoderOneInit(void)
|
||
|
{
|
||
|
///RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
|
||
|
UiRotaryEncoderInit(ENC1);
|
||
|
}
|
||
|
|
||
|
//*----------------------------------------------------------------------------
|
||
|
//* Function Name : UiRotaryEncoderTwoInit
|
||
|
//* Object : rfgain
|
||
|
//* Input Parameters :
|
||
|
//* Output Parameters :
|
||
|
//* Functions called :
|
||
|
//*----------------------------------------------------------------------------
|
||
|
void UiRotaryEncoderTwoInit(void)
|
||
|
{
|
||
|
///RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
|
||
|
UiRotaryEncoderInit(ENC2);
|
||
|
}
|
||
|
|
||
|
//*----------------------------------------------------------------------------
|
||
|
//* Function Name : UiRotaryEncoderThreeInit
|
||
|
//* Object :
|
||
|
//* Input Parameters :
|
||
|
//* Output Parameters :
|
||
|
//* Functions called :
|
||
|
//*----------------------------------------------------------------------------
|
||
|
void UiRotaryEncoderThreeInit(void)
|
||
|
{
|
||
|
///RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
|
||
|
UiRotaryEncoderInit(ENC3);
|
||
|
}
|
||
|
|
||
|
|
||
|
int UiDriverEncoderRead(const uint32_t encId)
|
||
|
{
|
||
|
bool no_change = false;
|
||
|
int pot_diff = 0;
|
||
|
int32_t delta;
|
||
|
|
||
|
if (encId < ENC_MAX)
|
||
|
{
|
||
|
encSel[encId].value_new = encSel[encId].tim->CNT;
|
||
|
|
||
|
if (encSel[encId].value_old != encSel[encId].value_new)
|
||
|
{
|
||
|
//checking for the overflow/underflow crossing
|
||
|
delta=encSel[encId].value_new - encSel[encId].value_old;
|
||
|
if(delta>(ENCODER_RANGE/2))
|
||
|
{
|
||
|
delta-=ENCODER_RANGE+1;
|
||
|
}
|
||
|
else if(delta<-(ENCODER_RANGE/2))
|
||
|
{
|
||
|
delta+=ENCODER_RANGE+1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
no_change = true;
|
||
|
}
|
||
|
|
||
|
|
||
|
// SW de-detent routine
|
||
|
//left this code but think that it is useless because in our encoders (detent count)=(steps per rotation). 03.06.2018 SP9BSL
|
||
|
|
||
|
if (no_change == false)
|
||
|
{
|
||
|
encSel[encId].de_detent+=abs(delta);// corrected detent behaviour
|
||
|
// double counts are now processed - not count lost!
|
||
|
if (encSel[encId].de_detent < USE_DETENTED_VALUE)
|
||
|
{
|
||
|
encSel[encId].value_old = encSel[encId].value_new; // update and skip
|
||
|
no_change = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
encSel[encId].de_detent = 0;
|
||
|
}
|
||
|
}
|
||
|
// Encoder value to difference
|
||
|
if (no_change == false)
|
||
|
{
|
||
|
pot_diff = delta;
|
||
|
encSel[encId].value_old = encSel[encId].value_new;
|
||
|
}
|
||
|
}
|
||
|
// encoders reverse
|
||
|
// if(((ts.expflags1 & EXPFLAGS1_ENC123_REVERSE) && (encId < 3)) || ((ts.expflags1 & EXPFLAGS1_ENC4_REVERSE) && (encId == 3)))
|
||
|
if(((ts.expflags1 & EXPFLAGS1_ENC1_REVERSE) && (encId == 0)) ||
|
||
|
((ts.expflags2 & EXPFLAGS2_ENC2_REVERSE) && (encId == 1)) ||
|
||
|
((ts.expflags2 & EXPFLAGS2_ENC3_REVERSE) && (encId == 2)) ||
|
||
|
((ts.expflags1 & EXPFLAGS1_ENC4_REVERSE) && (encId == 3)))
|
||
|
{
|
||
|
pot_diff = -pot_diff;
|
||
|
}
|
||
|
|
||
|
return pot_diff;
|
||
|
}
|
||
|
|
||
|
//left for some time only for reference.
|
||
|
|
||
|
/*
|
||
|
|
||
|
int UiDriverEncoderRead(const uint32_t encId)
|
||
|
{
|
||
|
bool no_change = false;
|
||
|
int pot_diff = 0;
|
||
|
|
||
|
if (encId < ENC_MAX)
|
||
|
{
|
||
|
encSel[encId].value_new = encSel[encId].tim->CNT;
|
||
|
// Ignore lower value flickr
|
||
|
if (encSel[encId].value_new < ENCODER_FLICKR_BAND)
|
||
|
{
|
||
|
no_change = true;
|
||
|
}
|
||
|
else if (encSel[encId].value_new >
|
||
|
(ENCODER_RANGE / ENCODER_LOG_D) + ENCODER_FLICKR_BAND)
|
||
|
{
|
||
|
no_change = true;
|
||
|
}
|
||
|
else if (encSel[encId].value_old == encSel[encId].value_new)
|
||
|
{
|
||
|
no_change = true;
|
||
|
}
|
||
|
|
||
|
// SW de-detent routine
|
||
|
|
||
|
if (no_change == false)
|
||
|
{
|
||
|
encSel[encId].de_detent+=abs(encSel[encId].value_new - encSel[encId].value_old);// corrected detent behaviour
|
||
|
// double counts are now processed - not count lost!
|
||
|
if (encSel[encId].de_detent < USE_DETENTED_VALUE)
|
||
|
{
|
||
|
encSel[encId].value_old = encSel[encId].value_new; // update and skip
|
||
|
no_change = true;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
encSel[encId].de_detent = 0;
|
||
|
}
|
||
|
}
|
||
|
// Encoder value to difference
|
||
|
if (no_change == false)
|
||
|
{
|
||
|
pot_diff = encSel[encId].value_new - encSel[encId].value_old;
|
||
|
encSel[encId].value_old = encSel[encId].value_new;
|
||
|
}
|
||
|
}
|
||
|
return pot_diff;
|
||
|
}
|
||
|
*/
|