Advertisement
Guest User

Untitled

a guest
Jul 23rd, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.17 KB | None | 0 0
  1. #include "main.h"
  2. #include "cmsis_os.h"
  3. #include "adc.h"
  4. #include "rtc.h"
  5. #include "spi.h"
  6. #include "tim.h"
  7. #include "usb_device.h"
  8. #include "gpio.h"
  9. #include <math.h>
  10.  
  11. #include "h/tube.h"
  12.  
  13. typedef struct {
  14.   TIM_HandleTypeDef *timer;
  15.   uint32_t channel;
  16. } anode_channel;
  17.  
  18. SPI_HandleTypeDef *tubes_spi = &hspi1;
  19. anode_channel tube_anode[4] = {
  20.   { .timer = &htim2, .channel = TIM_CHANNEL_1 },
  21.   { .timer = &htim4, .channel = TIM_CHANNEL_1 },
  22.   { .timer = &htim4, .channel = TIM_CHANNEL_2 },
  23.   { .timer = &htim2, .channel = TIM_CHANNEL_2 },
  24. };
  25.  
  26.  
  27. uint8_t tube_bits[4][11] = {
  28.   // [dot] [0 1 ... 9]
  29.   {43, 37, 32, 47, 46, 45, 33, 34, 35, 44, 36},
  30.   {52, 50, 39, 38, 42, 41, 40, 55, 54, 53, 51},
  31.   {12, 26, 25, 14, 13, 11, 10,  9,  8, 23, 22},
  32.   {21, 17, 27, 28, 29, 20, 30, 31, 16, 19, 18},
  33. };
  34.  
  35.  
  36. // tube class
  37.  
  38. typedef struct {
  39.   uint8_t state[8];
  40. } tubes_state;
  41.  
  42.  
  43.  
  44. typedef struct {
  45.   tubes_state state;
  46.   tubes_state displayed_state;
  47.  
  48.   float current;
  49.   uint16_t pwm;
  50.   uint8_t awaiting_transmit;
  51.  
  52. } tube_display;
  53.  
  54. tube_display tdisplay = {
  55.   .state = { .state = {0,0,0,0, 0,0,0,0} },
  56.   .displayed_state = { .state = {0,0,0,0, 0,0,0,0} },
  57.  
  58.   .awaiting_transmit = 1,
  59.  
  60.   .current = 2,
  61.  
  62.   .pwm = 15,
  63. };
  64.  
  65.  
  66. void tube_reset_state(void){
  67.   memset(&tdisplay.state, 0, sizeof(tdisplay.state));
  68. }
  69.  
  70. void tube_set_current(uint8_t tube, float current){
  71.   float pwm_period = current / ANODE_CURRENT_CONST;
  72.    
  73.   __HAL_TIM_SET_COMPARE(tube_anode[tube].timer, tube_anode[tube].channel, (uint32_t)pwm_period);
  74. }
  75.  
  76.  
  77. void tube_set_digit(uint8_t tube, int8_t digit){
  78.   // d < 0 - blank;
  79.   if(digit < 0 || digit > 9) {
  80.     return;
  81.   }
  82.  
  83.   uint8_t bitnum = tube_bits[tube][digit+1];
  84.  
  85.   tdisplay.state.state[bitnum / 8] |= 1 << (bitnum % 8);
  86. }
  87.  
  88. void tube_set_dot(uint8_t tube){
  89.   uint8_t bitnum = tube_bits[tube][0];
  90.  
  91.   tdisplay.state.state[bitnum / 8] |= 1 << (bitnum % 8);
  92. }
  93.  
  94. void tube_refresh_all(void){
  95.   tdisplay.displayed_state = tdisplay.state;
  96.  
  97.   tdisplay.awaiting_transmit = 1;
  98. }
  99.  
  100. void tube__transmit_state(void){
  101.   HAL_SPI_Transmit_IT(tubes_spi, tdisplay.displayed_state.state, sizeof(tdisplay.displayed_state.state));
  102.  
  103.   tdisplay.awaiting_transmit = 0;
  104. }
  105.  
  106. void tube_set_pwm(uint16_t pwm){
  107.   // -1 because if there is no blanking time indication won't work,
  108.   // indication code does register refresh when tubes are blank
  109.  
  110.   if(pwm >= (DISPLAY_PWM_LEVELS-1) ){
  111.     pwm = (DISPLAY_PWM_LEVELS-1);
  112.   }
  113.  
  114.   if(pwm <= 0 ){
  115.     pwm = 1;
  116.   }
  117.  
  118.  
  119.   tdisplay.pwm = pwm;
  120. }
  121.  
  122. void tube_set_current_all(float current){
  123.   tdisplay.current = current;
  124. }
  125.  
  126.  
  127.  
  128.  
  129. // display class
  130.  
  131.  
  132. display_state d_state = {
  133.   .animation = NULL,
  134.   // init disabled digits too if will move this to stack or heap
  135. };
  136.  
  137. void display_number(uint16_t number){
  138.   int16_t i = DISPLAY_DIGITS_COUNT - 1;
  139.  
  140.   while (i >= 0) {
  141.     int digit = number % 10;
  142.    
  143.     display_digit(i, digit);
  144.    
  145.     i--;
  146.     number /= 10;
  147.   }
  148.  
  149. }
  150.  
  151.  
  152. void display_init_animation(display_animation ani){
  153.  
  154.   d_state.animation = animations_list[ani];
  155.  
  156.  
  157.   d_state.animation->previous = d_state.digits;
  158.   d_state.animation->step = 0;
  159.  
  160.   if(d_state.animation->animation_init ){
  161.     d_state.animation->animation_init(&d_state);
  162.   }
  163. }
  164.  
  165. void display_start_animation(void){
  166.    
  167. }
  168.  
  169. void display_digit(uint8_t tube, int8_t digit){
  170.   if(d_state.digits.disabled[tube]){
  171.     digit = -1;
  172.   }
  173.  
  174.   d_state.digits.digit[tube] = digit;
  175. }
  176.  
  177. void display_set_dot(uint8_t tube, uint8_t enabled){
  178.   d_state.digits.dot[tube] = enabled;
  179. }
  180.  
  181. void display_reset_dots(void){
  182.    for(uint8_t i = 0; i < DISPLAY_DIGITS_COUNT; i++){
  183.      display_set_dot(i, 0);
  184.    }
  185. }
  186.  
  187.  
  188.  
  189. void display_set_tube_state(uint8_t tube, uint8_t enabled){
  190.   d_state.digits.disabled[tube] = !enabled;
  191. }
  192.  
  193.  
  194. void display_finish_animation(display_animation ani){
  195.  
  196. }
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207. void DisplayIndicationTask(void const * argument)
  208. {
  209.  
  210.   for(;;){
  211.     display_digits* to_display;
  212.    
  213.     if(d_state.animation){
  214.       d_state.animation->step++;
  215.      
  216.       if(d_state.animation->animation_step ){
  217.         to_display = d_state.animation->animation_step(&d_state);
  218.       } else {
  219.         to_display = &d_state.digits;
  220.       }
  221.     }
  222.    
  223.     tube_reset_state();
  224.    
  225.     for(uint8_t i = 0; i < DISPLAY_DIGITS_COUNT; i++){
  226.       tube_set_digit(i, to_display->digit[i]);
  227.      
  228.       if(to_display->dot[i]){
  229.         tube_set_dot(i);
  230.       }
  231.      
  232.     }
  233.    
  234.     tube_refresh_all();
  235.    
  236.    
  237.     osDelay(10);
  238.   }
  239. }
  240.  
  241.    
  242.  
  243. static uint16_t step = 0;
  244. float td_current = 0.0;
  245.  
  246. void DisplayIrqHandler(void){
  247.  
  248.   if(td_current == 0.0){ // it was blanked for some time, so flush state now to prevent unwanted glow
  249.    
  250.     if(tdisplay.awaiting_transmit){
  251.       tube__transmit_state();
  252.     }
  253.    
  254.   }
  255.  
  256.  
  257.   float current_new = 0.0;
  258.  
  259.   if(step++ % (DISPLAY_PWM_LEVELS+1) > tdisplay.pwm){
  260.     current_new = 0.0;
  261.   } else{
  262.     current_new = tdisplay.current;
  263.   }
  264.  
  265.   if(current_new != td_current){
  266.     td_current = current_new;
  267.    
  268.     for(uint8_t i = 0; i < DISPLAY_DIGITS_COUNT; i++){
  269.       tube_set_current(i, td_current);
  270.     }
  271.   }
  272.  
  273. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement