//------------------------------------------------------------------------------
// 模块名称：数码管驱动模块
// 文件名称：bsp_digital_tube
// 版本名称：V1.0
// 文件说明：8个0.2寸共阴数码管轮流刷新控制点亮。
// 日期时间：2018年8月15日16点42分
// 文件作者：Jackie Chan
// 修改记录：
//    版本号  日期        作者  说明
//    V1.0    2018.08.15  J.C   正式发布
//
// 公司名称：多场低温科技有限公司
//
//------------------------------------------------------------------------------

#include "bsp.h"
#include <string.h>
#include <ctype.h>
#include <math.h>

// 数码管控制引脚对应的RCC时钟
#define RCC_ALL_TUBE (RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD)
// 数码管的位选，高电平有效
#define GPIO_PORT_A GPIOD
#define GPIO_PIN_A GPIO_Pin_0
#define GPIO_PORT_B GPIOD
#define GPIO_PIN_B GPIO_Pin_1
#define GPIO_PORT_C GPIOD
#define GPIO_PIN_C GPIO_Pin_2
#define GPIO_PORT_D GPIOD
#define GPIO_PIN_D GPIO_Pin_3
#define GPIO_PORT_E GPIOD
#define GPIO_PIN_E GPIO_Pin_4
#define GPIO_PORT_F GPIOD
#define GPIO_PIN_F GPIO_Pin_5
#define GPIO_PORT_G GPIOD
#define GPIO_PIN_G GPIO_Pin_6
#define GPIO_PORT_H GPIOD
#define GPIO_PIN_H GPIO_Pin_7
// 数码管的段选，高电平有效
#define GPIO_PORT_DS1 GPIOC
#define GPIO_PIN_DS1 GPIO_Pin_9
#define GPIO_PORT_DS2 GPIOC
#define GPIO_PIN_DS2 GPIO_Pin_8
#define GPIO_PORT_DS3 GPIOC
#define GPIO_PIN_DS3 GPIO_Pin_10
#define GPIO_PORT_DS4 GPIOC
#define GPIO_PIN_DS4 GPIO_Pin_6
#define GPIO_PORT_DS5 GPIOD
#define GPIO_PIN_DS5 GPIO_Pin_11
#define GPIO_PORT_DS6 GPIOD
#define GPIO_PIN_DS6 GPIO_Pin_10
#define GPIO_PORT_DS7 GPIOD
#define GPIO_PIN_DS7 GPIO_Pin_9
#define GPIO_PORT_DS8 GPIOD
#define GPIO_PIN_DS8 GPIO_Pin_8

// 关闭所有段选
#define CLOSE_ALL_TUBE_COM             \
  do                                   \
  {                                    \
    GPIO_PORT_DS1->BRR = GPIO_PIN_DS1; \
    GPIO_PORT_DS2->BRR = GPIO_PIN_DS2; \
    GPIO_PORT_DS3->BRR = GPIO_PIN_DS3; \
    GPIO_PORT_DS4->BRR = GPIO_PIN_DS4; \
    GPIO_PORT_DS5->BRR = GPIO_PIN_DS5; \
    GPIO_PORT_DS6->BRR = GPIO_PIN_DS6; \
    GPIO_PORT_DS7->BRR = GPIO_PIN_DS7; \
    GPIO_PORT_DS8->BRR = GPIO_PIN_DS8; \
  } while (0)
// 关闭所有位选
#define CLOSE_ALL_TUBE_SEG         \
  do                               \
  {                                \
    GPIO_PORT_A->BRR = GPIO_PIN_A; \
    GPIO_PORT_B->BRR = GPIO_PIN_B; \
    GPIO_PORT_C->BRR = GPIO_PIN_C; \
    GPIO_PORT_D->BRR = GPIO_PIN_D; \
    GPIO_PORT_E->BRR = GPIO_PIN_E; \
    GPIO_PORT_F->BRR = GPIO_PIN_F; \
    GPIO_PORT_G->BRR = GPIO_PIN_G; \
    GPIO_PORT_H->BRR = GPIO_PIN_H; \
  } while (0)

// 数码管共阴或者共阳选择，用于正确输出位选电平
#define SEG_A 0X01
#define SEG_B 0X01
#define SEG_C 0X01
#define SEG_D 0X01
#define SEG_E 0X01
#define SEG_F 0X01
#define SEG_G 0X01
#define SEG_H 0X01
#define SEG_0 0X00 // 数码管的该段<不点亮>

const uint8_t g_tube_table[12][7] = {
    {SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_F, SEG_0}, // NO_0
    {SEG_0, SEG_B, SEG_C, SEG_0, SEG_0, SEG_0, SEG_0}, // NO_1
    {SEG_A, SEG_B, SEG_0, SEG_D, SEG_E, SEG_0, SEG_G}, // NO_2
    {SEG_A, SEG_B, SEG_C, SEG_D, SEG_0, SEG_0, SEG_G}, // NO_3
    {SEG_0, SEG_B, SEG_C, SEG_0, SEG_0, SEG_F, SEG_G}, // NO_4
    {SEG_A, SEG_0, SEG_C, SEG_D, SEG_0, SEG_F, SEG_G}, // NO_5
    {SEG_A, SEG_0, SEG_C, SEG_D, SEG_E, SEG_F, SEG_G}, // NO_6
    {SEG_A, SEG_B, SEG_C, SEG_0, SEG_0, SEG_0, SEG_0}, // NO_7
    {SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_F, SEG_G}, // NO_8
    {SEG_A, SEG_B, SEG_C, SEG_D, SEG_0, SEG_F, SEG_G}, // NO_9
    {SEG_0, SEG_0, SEG_0, SEG_0, SEG_0, SEG_0, SEG_G}, // NO__
    {SEG_0, SEG_0, SEG_0, SEG_0, SEG_0, SEG_0, SEG_0}, // NO_NULL
};

// 全局变量声明
DIGITIAL_TUBE_T g_tTube;
extern MOTO_T g_tMoto;

// 该文件中的所有函数声明
void bsp_InitDigitalTube(void);
void bsp_DigitalTubeMainLoop(void);
void bsp_TubeTest(uint8_t _com, uint8_t _seg);
void bsp_InitTubeVar(void);
void bsp_UpdateDisplayBuf(void);
void bsp_ToogleWorkMode(void);
void bsp_ToogleStateMode(void);
void bsp_Pulse2Buf(void);
void bsp_Angle2Buf(void);
static void bsp_ReadDatFromEEPROM(void);

void bsp_InitTubeVar(void)
{
  uint8_t i = 0;

  for (i = 0; i < 8; i++)
  {
    g_tTube.buf[i] = NO_NULL;
  }
  g_tTube.disp_mode = MODE_PULSE;
  g_tTube.cnt = 0;
  g_tTube.state = IDLE;
  // g_tTube.state = WORK;
  g_tTube.dir = DIR_CW;
  g_tTube.pulse = 0;
  g_tTube.tim_pulse_cnt = 0;
  g_tTube.angle = 0;
}

void bsp_TubeTest(uint8_t _com, uint8_t _seg)
{
  if (_seg == ' ')
    _seg = NO_NULL;
  if (_seg >= 12)
    return;

  CLOSE_ALL_TUBE_COM;
  CLOSE_ALL_TUBE_SEG;

  if (g_tube_table[_seg][0])
  {
    GPIO_PORT_A->BSRR = GPIO_PIN_A;
  };
  if (g_tube_table[_seg][1])
  {
    GPIO_PORT_B->BSRR = GPIO_PIN_B;
  };
  if (g_tube_table[_seg][2])
  {
    GPIO_PORT_C->BSRR = GPIO_PIN_C;
  };
  if (g_tube_table[_seg][3])
  {
    GPIO_PORT_D->BSRR = GPIO_PIN_D;
  };
  if (g_tube_table[_seg][4])
  {
    GPIO_PORT_E->BSRR = GPIO_PIN_E;
  };
  if (g_tube_table[_seg][5])
  {
    GPIO_PORT_F->BSRR = GPIO_PIN_F;
  };
  if (g_tube_table[_seg][6])
  {
    GPIO_PORT_G->BSRR = GPIO_PIN_G;
  };
  if ((_com == 5) && (g_tTube.disp_mode == MODE_ANGLE))
  {
    GPIO_PORT_H->BSRR = GPIO_PIN_H;
  }

  switch (_com)
  {
  case 0:
    GPIO_PORT_DS1->BSRR = GPIO_PIN_DS1;
    break;
  case 1:
    GPIO_PORT_DS2->BSRR = GPIO_PIN_DS2;
    break;
  case 2:
    GPIO_PORT_DS3->BSRR = GPIO_PIN_DS3;
    break;
  case 3:
    GPIO_PORT_DS4->BSRR = GPIO_PIN_DS4;
    break;
  case 4:
    GPIO_PORT_DS5->BSRR = GPIO_PIN_DS5;
    break;
  case 5:
    GPIO_PORT_DS6->BSRR = GPIO_PIN_DS6;
    break;
  case 6:
    GPIO_PORT_DS7->BSRR = GPIO_PIN_DS7;
    break;
  case 7:
    GPIO_PORT_DS8->BSRR = GPIO_PIN_DS8;
    break;
  default:
    break;
  }
}
void bsp_ToogleDispMode(void)
{
  uint8_t buf[5]; // PULSE: 55AA00FF; ANGLE: FF00AA55

  switch (g_tTube.disp_mode)
  {
  case MODE_PULSE:
    g_tTube.disp_mode = MODE_ANGLE;
    break;
  case MODE_ANGLE:
    g_tTube.disp_mode = MODE_PULSE;
    break;
  default:
    break;
  }

  if (g_tTube.disp_mode == MODE_ANGLE)
  {
    buf[0] = 0xFF;
    buf[1] = 0x00;
    buf[2] = 0xAA;
    buf[3] = 0x55;
    ee_WriteBytes(buf, 0, 4);
  }
  else if (g_tTube.disp_mode == MODE_PULSE)
  {
    buf[0] = 0x55;
    buf[1] = 0xAA;
    buf[2] = 0x00;
    buf[3] = 0xFF;
    ee_WriteBytes(buf, 0, 4);
  }

  bsp_UpdateDisplayBuf();
}
void bsp_ToogleStateMode(void)
{
  switch (g_tTube.state)
  {
  case IDLE:
    g_tTube.state = WORK;
    break;
  case WORK:
    g_tTube.state = IDLE;
    break;
  default:
    break;
  }
  bsp_UpdateDisplayBuf();
}

void bsp_UpdateDisplayBuf(void)
{
  uint8_t i = 0;

  // 开机或执行了搜索命令但未找到零点时的数码管显示状态
  if ((g_tTube.state == IDLE) || (g_tTube.state == SEARCH))
  {
    if (g_tTube.disp_mode == MODE_PULSE) // 数码管显示[--------]
    {
      memset(g_tTube.buf, NO__, 8);
    }
    else if (g_tTube.disp_mode == MODE_ANGLE) // 数码管显示[     -.--]
    {
      for (i = 0; i < 5; i++)
      {
        g_tTube.buf[i] = NO_NULL;
      }
      g_tTube.buf[5] = NO__;
      g_tTube.buf[6] = NO__;
      g_tTube.buf[7] = NO__;
    }
  }
  else if (g_tTube.state == WORK) // 已经找到零点后数码管的显示状态
  {
    bsp_Angle2Buf(); // 数码管显示，例如[-1234567]
  }
}
void bsp_Pulse2Buf(void)
{
  uint8_t i = 0;

  memset(g_tTube.buf, 0, 8);
  snprintf(g_tTube.buf, 9, "%8d", g_tTube.pulse);
  for (i = 0; i < 8; i++)
  {
    if (g_tTube.buf[i] == ' ')
    {
      g_tTube.buf[i] = NO_NULL;
    }
    else if (g_tTube.buf[i] == '-')
    {
      g_tTube.buf[i] = NO__;
    }
    else if (isdigit(g_tTube.buf[i]))
    {
      g_tTube.buf[i] = g_tTube.buf[i] - '0';
    }
  }
}
void bsp_Angle2Buf(void)
{
  uint8_t i = 0;
  float angle = (((g_tTube.pulse % STEP_PER_LAP) + STEP_PER_LAP) % STEP_PER_LAP) * 360.0f / (STEP_PER_LAP / 100.0f);
  // printf("angle = %f\r\n", angle);
  if (angle < 0)
  {
    angle -= 0.5f;   // 负数向下取整
    angle += 360.0f; // 转换成整角度
  }
  else
    angle += 0.5f; // 正数向上取整

  // printf("angle = %f\r\n", angle);

  memset(g_tTube.buf, 0, 8);
  g_tTube.angle = angle;
  snprintf(g_tTube.buf, 9, "%8d", g_tTube.angle);
  for (i = 0; i < 8; i++)
  {
    if (g_tTube.buf[i] == ' ')
    {
      g_tTube.buf[i] = NO_NULL;
      if (i >= 5)
      {
        g_tTube.buf[i] = NO_0;
      }
    }
    else if (g_tTube.buf[i] == '-')
    {
      if (i >= 5)
      {
        g_tTube.buf[4] = NO__;
        g_tTube.buf[i] = NO_0;
      }
      else
      {
        g_tTube.buf[i] = NO__;
      }
    }
    else if (isdigit(g_tTube.buf[i]))
    {
      g_tTube.buf[i] = g_tTube.buf[i] - '0';
    }
  }
}

void bsp_DigitalTubeMainLoop(void)
{
  static uint8_t i = 0;
  if (++i >= 50) // 该函数每1ms调用一次，每50ms刷新一次脉冲或角度值
  {
    i = 0;
    if (g_tTube.dir == DIR_CCW)
    {
      g_tTube.pulse = g_tMoto.pv_pulse;
    }
    else
    {
      g_tTube.pulse = g_tMoto.pv_pulse;
    }
    bsp_UpdateDisplayBuf();
  }
  bsp_TubeTest(g_tTube.cnt, g_tTube.buf[g_tTube.cnt]);
  if (++g_tTube.cnt >= 8)
    g_tTube.cnt = 0;
}

//------------------------------------------------------------------------------
// 函 数 名: bsp_InitDigitalTube
// 功能说明: 配置数码管相关的GPIO,  该函数被 bsp_Init() 调用。
// 形    参:  无
// 返 回 值: 无
//------------------------------------------------------------------------------
void bsp_InitDigitalTube(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  // 打开数码管GPIO时钟
  RCC_APB2PeriphClockCmd(RCC_ALL_TUBE, ENABLE);
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出模式

  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_A; // 位 a
  GPIO_Init(GPIO_PORT_A, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_B; // 位 b
  GPIO_Init(GPIO_PORT_B, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_C; // 位 c
  GPIO_Init(GPIO_PORT_C, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_D; // 位 d
  GPIO_Init(GPIO_PORT_D, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_E; // 位 e
  GPIO_Init(GPIO_PORT_E, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_F; // 位 f
  GPIO_Init(GPIO_PORT_F, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_G; // 位 g
  GPIO_Init(GPIO_PORT_G, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_H; // 位 h
  GPIO_Init(GPIO_PORT_H, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS1; // 段 1
  GPIO_Init(GPIO_PORT_DS1, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS2; // 段 2
  GPIO_Init(GPIO_PORT_DS2, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS3; // 段 3
  GPIO_Init(GPIO_PORT_DS3, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS4; // 段 4
  GPIO_Init(GPIO_PORT_DS4, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS5; // 段 5
  GPIO_Init(GPIO_PORT_DS5, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS6; // 段 6
  GPIO_Init(GPIO_PORT_DS6, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS7; // 段 7
  GPIO_Init(GPIO_PORT_DS7, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_PIN_DS8; // 段 8
  GPIO_Init(GPIO_PORT_DS8, &GPIO_InitStructure);

  bsp_InitTubeVar();
  bsp_ReadDatFromEEPROM();
  bsp_UpdateDisplayBuf();
}

static void bsp_ReadDatFromEEPROM(void)
{
  uint8_t buf[5]; // PULSE: 55AA00FF; ANGLE: FF00AA55

  ee_ReadBytes((uint8_t *)buf, 0, 4);
  if ((buf[0] == 0X55) && (buf[1] == 0XAA) && (buf[2] == 0X00) && (buf[3] == 0XFF))
  {
    g_tTube.disp_mode = MODE_PULSE;
  }
  else if ((buf[0] == 0XFF) && (buf[1] == 0X00) && (buf[2] == 0XAA) && (buf[3] == 0X55))
  {
    g_tTube.disp_mode = MODE_ANGLE;
  }
}

//-------------------------------- End of file ---------------------------------
