
#include "misc.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"

/*


653 - 204ohm
16  - 100ohm

R - 100 = (Z* 1000 / 4096 -16) * 0.1633 


135 -> 122.3

*/


// A - PA7
#define SEG_A 0x40

// B - PA5
#define SEG_B 0x10

// C - PA2
#define SEG_C 0x02

// D - PA3
#define SEG_D 0x04

// E - PA4
#define SEG_E 0x08

// F - PA6
#define SEG_F 0x20

// G - PA1
#define SEG_G 0x01

static const uint8_t SYMBOLS[17] = {
/* 0 */    SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F,
/* 1 */    SEG_B | SEG_C,
/* 2 */    SEG_A | SEG_B | SEG_G | SEG_E | SEG_D,
/* 3 */    SEG_A | SEG_B | SEG_G | SEG_C | SEG_D,
/* 4 */    SEG_F | SEG_G | SEG_B | SEG_C,
/* 5 */    SEG_A | SEG_F | SEG_G | SEG_C | SEG_D,
/* 6 */    SEG_A | SEG_F | SEG_E | SEG_D | SEG_C | SEG_G,
/* 7 */    SEG_A | SEG_B | SEG_C,
/* 8 */    SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G,
/* 9 */    SEG_G | SEG_F | SEG_A | SEG_B | SEG_C | SEG_D,
/* A */    SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G,
/* B */    SEG_C | SEG_D | SEG_E | SEG_F | SEG_G ,
/* C */    SEG_A | SEG_D | SEG_E | SEG_F,
/* D */    SEG_B | SEG_C | SEG_D | SEG_E | SEG_G,
/* E */    SEG_A | SEG_F | SEG_G | SEG_E | SEG_D,
/* F */    SEG_A | SEG_E | SEG_F | SEG_G,
/* r */    SEG_E | SEG_G
};


/*
A1 - PC13
A2 - PC14
A3 - PC15
*/

static inline void SelectSymbol(uint32_t sym)
{
  uint32_t mask;
    
  mask = GPIOC->ODR & 0x1FFF;
  
  switch(sym)
  {
  case 0:
    mask |= 0xC000;
    break;
  case 1:
    mask |= 0xA000;
    break;
  case 2:
    mask |= 0x6000;
    break;
  }

  GPIOC->ODR = mask;
}

static inline void SetSymbol(uint32_t sym)
{
  GPIOA->ODR = (GPIOA->ODR & 0xFF01) | (SYMBOLS[sym % 17] << 1);
}

uint32_t DispState;
uint8_t DisplayDigits[4];

void TIM1_UP_IRQHandler (void)
{  
  TIM_ClearITPendingBit(TIM1,TIM_FLAG_Update); // Clear update interrupt bit

  SelectSymbol(DispState);
  SetSymbol(DisplayDigits[DispState]);

  DispState++;
  
  if(DispState >= 3)
    DispState = 0;
}

static const ADC_InitTypeDef   ADC_InitStructure = {
    .ADC_Mode = ADC_Mode_Independent,
    .ADC_ScanConvMode = ENABLE,
    .ADC_ContinuousConvMode = ENABLE,
    .ADC_ExternalTrigConv = ADC_ExternalTrigConv_None,
    .ADC_DataAlign = ADC_DataAlign_Right,
    .ADC_NbrOfChannel = 1
};  

static const USART_InitTypeDef USART_InitStructure = {
    .USART_BaudRate = 19200,
    .USART_WordLength = USART_WordLength_8b,
    .USART_StopBits = USART_StopBits_1,
    .USART_Parity = USART_Parity_No,
    .USART_HardwareFlowControl = USART_HardwareFlowControl_None,
    .USART_Mode = USART_Mode_Rx | USART_Mode_Tx
};

static const NVIC_InitTypeDef NVIC_InitStructure = {
    .NVIC_IRQChannel = TIM1_UP_IRQn,
    .NVIC_IRQChannelPreemptionPriority = 7,
    .NVIC_IRQChannelSubPriority = 0,
    .NVIC_IRQChannelCmd = ENABLE
};

static const TIM_TimeBaseInitTypeDef TIM1_TimeBaseInitStruct = {
    .TIM_Prescaler = 80,  // 8Mhz / 80 = 100khz
    .TIM_CounterMode = TIM_CounterMode_Up,
    .TIM_Period = 500,  // 100Khz / 500 = 200Hz
    .TIM_ClockDivision = TIM_CKD_DIV1,
    .TIM_RepetitionCounter = 0
};

int main()
{
  /*       работает на 8MHz RC, нам достаточно, PLL натачивать не будем      */
//  SystemInit();

  uint32_t AdcData;
  GPIO_InitTypeDef GPIO_InitStructure;  

  __disable_interrupt();
  
  // ставим таблицу прерываний
#ifndef  EMB_FLASH  
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); // Set the Vector Table base location at 0x20000000 
#else
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   // Set the Vector Table base location at 0x08000000 
#endif
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);  
  
  // включаем нужное нам оборудование
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_TIM1 | RCC_APB2Periph_ADC1 | RCC_APB2Periph_USART1, ENABLE);
  RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_TIM1 | RCC_APB2Periph_ADC1 | RCC_APB2Periph_USART1, DISABLE);    

  // инитим ноги
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  
  // Init PA0 as Analog input
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_0;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;  
  
  // Init PA1..PA7 as Push/Pull output
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  // Init PC13..PC15 as Push/Pull output 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_Init(GPIOC, &GPIO_InitStructure);  

  /* Configure USART1 Tx (PA9) push-pull */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USART1 Rx (PA10) as input floating */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_Init(GPIOA, &GPIO_InitStructure);  
  
  // настраиваем таймер period 5ms (200Hz)
  TIM_TimeBaseInit(TIM1, (TIM_TimeBaseInitTypeDef *) &TIM1_TimeBaseInitStruct);
  TIM_ClearITPendingBit(TIM1,TIM_FLAG_Update); // Clear update interrupt bit
  TIM_ITConfig(TIM1,TIM_FLAG_Update,ENABLE);  // Enable update interrupt
  NVIC_Init((NVIC_InitTypeDef *) &NVIC_InitStructure); // Enable IRQ for Timer1  
  TIM_Cmd(TIM1,ENABLE); // Enable timer counting
  
  // Настраиваем ADC  
  ADC_Init(ADC1, (ADC_InitTypeDef *)&ADC_InitStructure); // ADC1 configuration
  ADC_RegularChannelConfig(ADC1, 0, 1, ADC_SampleTime_55Cycles5); // ADC1 channel0 configuration  
  ADC_DMACmd(ADC1, DISABLE);  // Disable ADC1 DMA
  ADC_Cmd(ADC1, ENABLE);  // Enable ADC1

  ADC_ResetCalibration(ADC1); // Enable ADC1 reset calibaration register
  while(ADC_GetResetCalibrationStatus(ADC1));  // Check the end of ADC1 reset calibration register
  
  ADC_StartCalibration(ADC1); // Start ADC1 calibaration  
  while(ADC_GetCalibrationStatus(ADC1)); // Check the end of ADC1 calibration
  
  // Настраиваем USART1 
  USART_Init(USART1, (USART_InitTypeDef*) &USART_InitStructure);
  USART_Cmd(USART1, ENABLE);   // Enable the USART1 
  
  __enable_interrupt();
  
  // App cycle begin
  
  DisplayDigits[3] = 218; // = '\n' - '0'
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);   // Start ADC1 Software Conversion
   
  while(1)
  {
    AdcData = ADC_GetConversionValue(ADC1);
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);    

/*    
    AdcData = (AdcData * 1000 / 4096 - 16) * 1633;
    AdcData = (AdcData * 200) / 1000000; 
*/
  
/* DEC
    DisplayDigits[0] = AdcData / 100;
    DisplayDigits[1] = (AdcData / 10) % 10;
    DisplayDigits[2] = AdcData % 10;
*/

//  HEX    
    DisplayDigits[0] = AdcData >> 8;
    DisplayDigits[1] = (AdcData >> 4) & 0x0f;
    DisplayDigits[2] = AdcData & 0x0f;

    
    for(int i =0; i < 4; i++)
    {
        USART_SendData(USART1, '0' + DisplayDigits[i]);
        while(!(USART1->SR & USART_FLAG_TXE)) ;    
    }
  }
  
}
