/* -*- 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; } */