Advertisement
Guest User

VFD controller

a guest
Jul 31st, 2018
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.07 KB | None | 0 0
  1. /* Ketturi Fox 2013
  2.  * File:    main.c
  3.  * Project: VFD Driver
  4.  * Project folder:
  5.  */
  6.  
  7. #ifndef F_CPU
  8. #define F_CPU   16000000UL // 16 Mhz
  9. #endif
  10.  
  11. #define USART_BAUDRATE  19200 //UART baud rate, 19200 works with 16Mhz clock, 38400 works too(tested)
  12.  
  13. #include <inttypes.h>
  14. #include <stdint.h>
  15. #include <avr/io.h>
  16. #include <avr/interrupt.h>
  17. #include <avr/pgmspace.h>
  18. #include <util/delay.h>
  19.    
  20.  
  21. // Macros for bit manipulation
  22. #define SET_BIT(target, bit) ((target) |=   _BV((unsigned char) (bit)))
  23. #define CLR_BIT(target, bit) ((target) &= ~(_BV((unsigned char) (bit))))
  24.  
  25. #define DISPLAY_SIZE 32 //digits
  26. #define LONG_DELAY  450 //Delays for multiplexing
  27. #define SHORT_DELAY  50 //need to be made interrupts/something useful during delays
  28.  
  29. /*                  
  30. * Font for segments
  31. */                  
  32. // First byte  == PORT_A
  33. // Second byte == PORT_C
  34. //{ (d,c,e,g2,g1,f,b,a),(n/c,i,j,h,m,k,l,dp) },
  35. // ASCII, control charters not handled here, only for reference
  36. //some charters, like 1-5 need to be re-purposed as Γ€,ΓΆ,Γ„,Γ– and forwarded from 132, 148, 142, 153
  37. //handling d.p. should be rethough, now it leaves empty charter left to it
  38. //darn I love ASCII <3
  39. const unsigned char font[128][2] = {
  40.     { 0b00000000, 0b00000000 }, //NUL Null \0 ^@      (null charter, but shows as empty block dunno)
  41.     { 0b11111111, 0b01111111 }, //can be used like test charter lighting all segments
  42.     { 0b00000000, 0b00000000 },
  43.     { 0b00000000, 0b00000000 },
  44.     { 0b00000000, 0b00000000 },
  45.     { 0b00000000, 0b00000000 },
  46.     { 0b00000000, 0b00000000 }, //ACK Acknowledge     (send for data successfully received)
  47.     { 0b00000000, 0b00000000 }, //BEL  Bell \a ^G     (make audible notification for email etc)
  48.     { 0b00000000, 0b00000000 }, //BS Backspace \b ^H  (remove last charter from textBuffer)
  49.     { 0b00000000, 0b00000000 },
  50.     { 0b00000000, 0b00000000 }, //LF Linefeed \n ~J   (clear textBuffer)
  51.     { 0b00000000, 0b00000000 },
  52.     { 0b00000000, 0b00000000 }, //FF Formfeed \f ^L   (clear textBuffer, for compatibly)
  53.     { 0b00000000, 0b00000000 }, //CR Carriage return \r ^M (Return "cursor" to first digit)
  54.     { 0b00000000, 0b00000000 },
  55.     { 0b00000000, 0b00000000 },
  56.     { 0b00000000, 0b00000000 },
  57.     { 0b00000000, 0b00000000 }, //DC1 Device control (Turn leds on/off or sumthing)
  58.     { 0b00000000, 0b00000000 }, //DC2
  59.     { 0b00000000, 0b00000000 }, //DC3
  60.     { 0b00000000, 0b00000000 }, //DC4
  61.     { 0b00000000, 0b00000000 }, //NAK neg. acknowledge (Houston, we have problem)
  62.     { 0b00000000, 0b00000000 },
  63.     { 0b00000000, 0b00000000 },
  64.     { 0b00000000, 0b00000000 },
  65.     { 0b00000000, 0b00000000 },
  66.     { 0b00000000, 0b00000000 },
  67.     { 0b00000000, 0b00000000 }, //ESC Escape \e ^[     (dunno, not needed)
  68.     { 0b00000000, 0b00000000 },  
  69.     { 0b00000000, 0b00000000 },
  70.     { 0b00000000, 0b00000000 },
  71.     { 0b00000000, 0b00000000 },
  72.     { 0b00000000, 0b00000000 }, //" " space or empty block
  73.     { 0b01000010, 0b00000001 }, //"!"
  74.     { 0b00000100, 0b01000000 },
  75.     { 0b11011010, 0b01000010 },
  76.     { 0b11011101, 0b01000010 },
  77.     { 0b01000100, 0b00101000 },
  78.     { 0b11101001, 0b01010100 },
  79.     { 0b00000000, 0b00100000 },
  80.     { 0b00000000, 0b00100100 },
  81.     { 0b00000000, 0b00011000 },
  82.     { 0b00011000, 0b01111110 },
  83.     { 0b00011000, 0b01000010 },
  84.     { 0b00000000, 0b00001000 },
  85.     { 0b00011000, 0b00000000 },
  86.     { 0b00000000, 0b00000001 }, // "."    (light dot in display)
  87.     { 0b00000000, 0b00101000 },
  88.     { 0b11100111, 0b00101000 },
  89.     { 0b01000010, 0b00000000 }, //"0"
  90.     { 0b10111011, 0b00000000 },
  91.     { 0b11011011, 0b00000000 },
  92.     { 0b01011110, 0b00000000 },
  93.     { 0b11011101, 0b00000000 },
  94.     { 0b11111101, 0b00000000 },
  95.     { 0b01000011, 0b00000000 },
  96.     { 0b11111111, 0b00000000 },
  97.     { 0b11011111, 0b00000000 },
  98.     { 0b00000000, 0b01000010 }, //"9"
  99.     { 0b00000000, 0b01001000 },
  100.     { 0b00000000, 0b00100100 },
  101.     { 0b10011000, 0b00000000 },
  102.     { 0b00000000, 0b00011000 },
  103.     { 0b00010011, 0b00000011 }, //"?"
  104.     { 0b11101011, 0b00000010 },
  105.     { 0b01111111, 0b00000000 }, //"A"
  106.     { 0b11010011, 0b01000010 },
  107.     { 0b10100101, 0b00000000 },
  108.     { 0b11000011, 0b01000010 },
  109.     { 0b10101101, 0b00000000 },
  110.     { 0b00101101, 0b00000000 },
  111.     { 0b11110101, 0b00000000 },
  112.     { 0b01111110, 0b00000000 },
  113.     { 0b10000001, 0b01000010 },
  114.     { 0b11100010, 0b00000000 },
  115.     { 0b00101100, 0b00100100 },
  116.     { 0b10100100, 0b00000000 },
  117.     { 0b01100110, 0b00110000 },
  118.     { 0b01100110, 0b00010100 },
  119.     { 0b11100111, 0b00000000 },
  120.     { 0b00111111, 0b00000000 },
  121.     { 0b11100111, 0b00000100 },
  122.     { 0b00111111, 0b00000100 },
  123.     { 0b11010001, 0b00010000 },
  124.     { 0b00000001, 0b01000010 },
  125.     { 0b11100110, 0b00000000 },
  126.     { 0b00100100, 0b00101000 },
  127.     { 0b01100110, 0b00001100 },
  128.     { 0b00000000, 0b00111100 },
  129.     { 0b00000000, 0b00110010 },
  130.     { 0b10000001, 0b00101000 }, //"Z"
  131.     { 0b10100101, 0b00000000 },
  132.     { 0b00000000, 0b00010100 },
  133.     { 0b11000011, 0b00000000 },
  134.     { 0b00000000, 0b00001100 },
  135.     { 0b10000000, 0b00000000 },
  136.     { 0b00000000, 0b00010000 },
  137.     { 0b10101000, 0b00000010 }, //"a"
  138.     { 0b10101100, 0b00000100 },
  139.     { 0b10111000, 0b00000000 },
  140.     { 0b11010010, 0b00001000 },
  141.     { 0b10101000, 0b00001000 },
  142.     { 0b00101101, 0b00000000 },
  143.     { 0b11010010, 0b00100000 },
  144.     { 0b00101100, 0b00000010 },
  145.     { 0b00000000, 0b00000010 },
  146.     { 0b11000010, 0b00000000 },
  147.     { 0b00000000, 0b01100110 },
  148.     { 0b00100100, 0b00000000 },
  149.     { 0b01111000, 0b00000010 },
  150.     { 0b00101000, 0b00000010 },
  151.     { 0b11111000, 0b00000000 },
  152.     { 0b00101100, 0b00010000 },
  153.     { 0b01010010, 0b00100000 },
  154.     { 0b00101000, 0b00000000 },
  155.     { 0b10010000, 0b00000100 },
  156.     { 0b10101100, 0b00000000 },
  157.     { 0b11100000, 0b00000000 },
  158.     { 0b01000000, 0b00000100 },
  159.     { 0b01100000, 0b00001100 },
  160.     { 0b00011000, 0b00001100 },
  161.     { 0b11000000, 0b00000100 },
  162.     { 0b10001000, 0b00001000 }, //"z"
  163.     { 0b10001001, 0b00011000 },
  164.     { 0b00000000, 0b01000010 },
  165.     { 0b10010001, 0b00100100 },
  166.     { 0b00000100, 0b00110000 },
  167.     { 0b11111111, 0b01111110 } //DEL    (also not needed, ignored charter"
  168. };
  169.  
  170.  
  171. /*
  172.  * Port & device init
  173.  */
  174. void boot(void) {
  175.     // Set port directions and pull-ups
  176.     DDRA = 0b11111111;
  177.     DDRC = 0b11111111;
  178.     DDRB = 0b00001111;
  179. }
  180.  
  181.  
  182. void writeBitToShiftRegister(int bit){
  183. /* Shiftregister configuration:
  184. *Strobe (outputs enabled) PB0
  185. *Latch enable (Latch clock) PB1
  186. *Clock PB2
  187. *Data In PB3
  188. *
  189. *Data is entered with L -> H clock edge
  190. *While Latch Enable is H, Data -> Outputs
  191. *Strobe puts outputs on when L. (can be tied to L)
  192. */
  193.  
  194. #define Strobe_PORT     PORTB
  195. #define Latch_PORT      PORTB
  196. #define Clock_PORT      PORTB
  197. #define Data_PORT       PORTB
  198.  
  199. #define Strobe_BIT      0
  200. #define Latch_BIT       1
  201. #define Clock_BIT       2
  202. #define Data_BIT        3
  203.  
  204.     #define SET_Strobe ((Strobe_PORT) |= _BV(Strobe_BIT))
  205.     #define CLR_Strobe ((Strobe_PORT) &= ~(_BV(Strobe_BIT)))
  206.  
  207.     #define SET_Latch ((Latch_PORT) |= _BV(Latch_BIT))
  208.     #define CLR_Latch ((Latch_PORT) &= ~(_BV(Latch_BIT)))
  209.  
  210.     #define SET_Clock ((Clock_PORT) |= _BV(Clock_BIT))
  211.     #define CLR_Clock ((Clock_PORT) &= ~(_BV(Clock_BIT)))
  212.  
  213.     #define SET_Data ((Data_PORT) |= _BV(Data_BIT))
  214.     #define CLR_Data ((Data_PORT) &= ~(_BV(Data_BIT)))
  215.  
  216.  
  217.     SET_Strobe;        //Put all outputs low
  218. //asm ("nop") //62.5ns delay, shortest delay that can be used
  219.  
  220.       _delay_us(0.010);
  221.    
  222.     CLR_Latch;        //Latch low(keep previoysly stored data in latch)
  223.       _delay_us(0.010);
  224.          
  225.     if (bit == 1)    //Load data from function to shift register input
  226.         SET_Data;
  227.     else
  228.         CLR_Data;
  229.         _delay_us(0.150); //Setup time, DATA IN before rising CLOCK edge   
  230.        
  231.     CLR_Clock;        //Start Clock cycle should last 1000ns
  232.       _delay_us(0.500); //Pulse furation, CLOCK High
  233.     SET_Clock;        //End Clock cycle
  234.       _delay_us(0.500); //Pulse duration, CLOCK Low
  235.    
  236.     SET_Latch;        //Move data to latch (New data in latch)
  237.     CLR_Strobe;       //Enable output buffers
  238.  
  239. }
  240.  
  241. unsigned char textBuffer[32]; //here goes the text on display
  242.  
  243. void refreshDisplay() {  //draws every digit to display, must be executed constantly
  244.  
  245.        
  246.        
  247.         // Make sure everything is off.
  248.         PORTA = 0;
  249.         PORTC = 0;
  250.          
  251.         // Clear shift register to be sure.
  252.         for (char i = 0; i < DISPLAY_SIZE; i++) {
  253.                 writeBitToShiftRegister(0);
  254.         }
  255.  
  256.         // Select first display digit.
  257.         writeBitToShiftRegister(1);
  258.        
  259.         int i;
  260.         // Loop through all digits
  261.         for (i = 0; i < DISPLAY_SIZE; i++) {
  262.  
  263.                 // Read next character.
  264.                 // The character is masked to make sure it doesn't go outside font range.
  265.                 const unsigned char c = textBuffer[i] & 0b01111111;
  266.              
  267.                 // Read bytes for corresponding segment configuration.
  268.                 const unsigned char byteA = font[c][0];
  269.                 const unsigned char byteB = font[c][1];
  270.                
  271.                 // Turn segments on.
  272.                 PORTA = byteA;
  273.                 PORTC = byteB;
  274.              
  275.                 // Wait. interrupt/other stuff here, delay is stupid
  276.                 _delay_us(LONG_DELAY);
  277.            
  278.                 // Turn segments off.
  279.                 PORTA = 0;
  280.                 PORTC = 0;
  281.                
  282.                 // Wait.
  283.                 _delay_us(SHORT_DELAY);
  284.                
  285.                 // Prepare for next display module.
  286.                 writeBitToShiftRegister(0);
  287.         }
  288. }
  289.  
  290. void uart_init(uint16_t baudrate) {
  291.     UBRRL = baudrate;
  292.     UBRRH = (baudrate >> 8);
  293.     UCSRC = (1 << URSEL) | (3 << UCSZ0);
  294.     UCSRB = (1 << RXEN) | (1 << TXEN); // Enable RX and TX
  295. }
  296.  
  297. void uart_putchar(char c) { //puts one charter to serial send buffer
  298.     loop_until_bit_is_set(UCSRA, UDRE); // Wait until data register empty.
  299.     UDR = c;
  300. }
  301.  
  302. char uart_getchar(void) { //gets 1 charter from serial receive buffer
  303.     loop_until_bit_is_set(UCSRA, RXC); // Wait until data exists.
  304.     return UDR;
  305. }
  306.  
  307. int main(void){
  308. //textBuffer = "Hello World!                    ";
  309. memmove(textBuffer,"Hello World!                    ",32);
  310. refreshDisplay();
  311.  
  312.  
  313. //loop here to get charter from uart_getchar();
  314. //and put it to textBuffer, and then refreshDisplay();
  315. //interrupts etc. stuff would be nice
  316. uart_init((((F_CPU / (USART_BAUDRATE * 16UL))) - 1)); //initialize uart at calculated baudrate
  317.  
  318. while(1){
  319.     uart_putchar('H');
  320.  
  321.     }
  322. return 0;
  323. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement