Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Ketturi Fox 2013
- * File: main.c
- * Project: VFD Driver
- * Project folder:
- */
- #ifndef F_CPU
- #define F_CPU 16000000UL // 16 Mhz
- #endif
- #define USART_BAUDRATE 19200 //UART baud rate, 19200 works with 16Mhz clock, 38400 works too(tested)
- #include <inttypes.h>
- #include <stdint.h>
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/pgmspace.h>
- #include <util/delay.h>
- // Macros for bit manipulation
- #define SET_BIT(target, bit) ((target) |= _BV((unsigned char) (bit)))
- #define CLR_BIT(target, bit) ((target) &= ~(_BV((unsigned char) (bit))))
- #define DISPLAY_SIZE 32 //digits
- #define LONG_DELAY 450 //Delays for multiplexing
- #define SHORT_DELAY 50 //need to be made interrupts/something useful during delays
- /*
- * Font for segments
- */
- // First byte == PORT_A
- // Second byte == PORT_C
- //{ (d,c,e,g2,g1,f,b,a),(n/c,i,j,h,m,k,l,dp) },
- // ASCII, control charters not handled here, only for reference
- //some charters, like 1-5 need to be re-purposed as Γ€,ΓΆ,Γ,Γ and forwarded from 132, 148, 142, 153
- //handling d.p. should be rethough, now it leaves empty charter left to it
- //darn I love ASCII <3
- const unsigned char font[128][2] = {
- { 0b00000000, 0b00000000 }, //NUL Null \0 ^@ (null charter, but shows as empty block dunno)
- { 0b11111111, 0b01111111 }, //can be used like test charter lighting all segments
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 }, //ACK Acknowledge (send for data successfully received)
- { 0b00000000, 0b00000000 }, //BEL Bell \a ^G (make audible notification for email etc)
- { 0b00000000, 0b00000000 }, //BS Backspace \b ^H (remove last charter from textBuffer)
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 }, //LF Linefeed \n ~J (clear textBuffer)
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 }, //FF Formfeed \f ^L (clear textBuffer, for compatibly)
- { 0b00000000, 0b00000000 }, //CR Carriage return \r ^M (Return "cursor" to first digit)
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 }, //DC1 Device control (Turn leds on/off or sumthing)
- { 0b00000000, 0b00000000 }, //DC2
- { 0b00000000, 0b00000000 }, //DC3
- { 0b00000000, 0b00000000 }, //DC4
- { 0b00000000, 0b00000000 }, //NAK neg. acknowledge (Houston, we have problem)
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 }, //ESC Escape \e ^[ (dunno, not needed)
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 },
- { 0b00000000, 0b00000000 }, //" " space or empty block
- { 0b01000010, 0b00000001 }, //"!"
- { 0b00000100, 0b01000000 },
- { 0b11011010, 0b01000010 },
- { 0b11011101, 0b01000010 },
- { 0b01000100, 0b00101000 },
- { 0b11101001, 0b01010100 },
- { 0b00000000, 0b00100000 },
- { 0b00000000, 0b00100100 },
- { 0b00000000, 0b00011000 },
- { 0b00011000, 0b01111110 },
- { 0b00011000, 0b01000010 },
- { 0b00000000, 0b00001000 },
- { 0b00011000, 0b00000000 },
- { 0b00000000, 0b00000001 }, // "." (light dot in display)
- { 0b00000000, 0b00101000 },
- { 0b11100111, 0b00101000 },
- { 0b01000010, 0b00000000 }, //"0"
- { 0b10111011, 0b00000000 },
- { 0b11011011, 0b00000000 },
- { 0b01011110, 0b00000000 },
- { 0b11011101, 0b00000000 },
- { 0b11111101, 0b00000000 },
- { 0b01000011, 0b00000000 },
- { 0b11111111, 0b00000000 },
- { 0b11011111, 0b00000000 },
- { 0b00000000, 0b01000010 }, //"9"
- { 0b00000000, 0b01001000 },
- { 0b00000000, 0b00100100 },
- { 0b10011000, 0b00000000 },
- { 0b00000000, 0b00011000 },
- { 0b00010011, 0b00000011 }, //"?"
- { 0b11101011, 0b00000010 },
- { 0b01111111, 0b00000000 }, //"A"
- { 0b11010011, 0b01000010 },
- { 0b10100101, 0b00000000 },
- { 0b11000011, 0b01000010 },
- { 0b10101101, 0b00000000 },
- { 0b00101101, 0b00000000 },
- { 0b11110101, 0b00000000 },
- { 0b01111110, 0b00000000 },
- { 0b10000001, 0b01000010 },
- { 0b11100010, 0b00000000 },
- { 0b00101100, 0b00100100 },
- { 0b10100100, 0b00000000 },
- { 0b01100110, 0b00110000 },
- { 0b01100110, 0b00010100 },
- { 0b11100111, 0b00000000 },
- { 0b00111111, 0b00000000 },
- { 0b11100111, 0b00000100 },
- { 0b00111111, 0b00000100 },
- { 0b11010001, 0b00010000 },
- { 0b00000001, 0b01000010 },
- { 0b11100110, 0b00000000 },
- { 0b00100100, 0b00101000 },
- { 0b01100110, 0b00001100 },
- { 0b00000000, 0b00111100 },
- { 0b00000000, 0b00110010 },
- { 0b10000001, 0b00101000 }, //"Z"
- { 0b10100101, 0b00000000 },
- { 0b00000000, 0b00010100 },
- { 0b11000011, 0b00000000 },
- { 0b00000000, 0b00001100 },
- { 0b10000000, 0b00000000 },
- { 0b00000000, 0b00010000 },
- { 0b10101000, 0b00000010 }, //"a"
- { 0b10101100, 0b00000100 },
- { 0b10111000, 0b00000000 },
- { 0b11010010, 0b00001000 },
- { 0b10101000, 0b00001000 },
- { 0b00101101, 0b00000000 },
- { 0b11010010, 0b00100000 },
- { 0b00101100, 0b00000010 },
- { 0b00000000, 0b00000010 },
- { 0b11000010, 0b00000000 },
- { 0b00000000, 0b01100110 },
- { 0b00100100, 0b00000000 },
- { 0b01111000, 0b00000010 },
- { 0b00101000, 0b00000010 },
- { 0b11111000, 0b00000000 },
- { 0b00101100, 0b00010000 },
- { 0b01010010, 0b00100000 },
- { 0b00101000, 0b00000000 },
- { 0b10010000, 0b00000100 },
- { 0b10101100, 0b00000000 },
- { 0b11100000, 0b00000000 },
- { 0b01000000, 0b00000100 },
- { 0b01100000, 0b00001100 },
- { 0b00011000, 0b00001100 },
- { 0b11000000, 0b00000100 },
- { 0b10001000, 0b00001000 }, //"z"
- { 0b10001001, 0b00011000 },
- { 0b00000000, 0b01000010 },
- { 0b10010001, 0b00100100 },
- { 0b00000100, 0b00110000 },
- { 0b11111111, 0b01111110 } //DEL (also not needed, ignored charter"
- };
- /*
- * Port & device init
- */
- void boot(void) {
- // Set port directions and pull-ups
- DDRA = 0b11111111;
- DDRC = 0b11111111;
- DDRB = 0b00001111;
- }
- void writeBitToShiftRegister(int bit){
- /* Shiftregister configuration:
- *Strobe (outputs enabled) PB0
- *Latch enable (Latch clock) PB1
- *Clock PB2
- *Data In PB3
- *
- *Data is entered with L -> H clock edge
- *While Latch Enable is H, Data -> Outputs
- *Strobe puts outputs on when L. (can be tied to L)
- */
- #define Strobe_PORT PORTB
- #define Latch_PORT PORTB
- #define Clock_PORT PORTB
- #define Data_PORT PORTB
- #define Strobe_BIT 0
- #define Latch_BIT 1
- #define Clock_BIT 2
- #define Data_BIT 3
- #define SET_Strobe ((Strobe_PORT) |= _BV(Strobe_BIT))
- #define CLR_Strobe ((Strobe_PORT) &= ~(_BV(Strobe_BIT)))
- #define SET_Latch ((Latch_PORT) |= _BV(Latch_BIT))
- #define CLR_Latch ((Latch_PORT) &= ~(_BV(Latch_BIT)))
- #define SET_Clock ((Clock_PORT) |= _BV(Clock_BIT))
- #define CLR_Clock ((Clock_PORT) &= ~(_BV(Clock_BIT)))
- #define SET_Data ((Data_PORT) |= _BV(Data_BIT))
- #define CLR_Data ((Data_PORT) &= ~(_BV(Data_BIT)))
- SET_Strobe; //Put all outputs low
- //asm ("nop") //62.5ns delay, shortest delay that can be used
- _delay_us(0.010);
- CLR_Latch; //Latch low(keep previoysly stored data in latch)
- _delay_us(0.010);
- if (bit == 1) //Load data from function to shift register input
- SET_Data;
- else
- CLR_Data;
- _delay_us(0.150); //Setup time, DATA IN before rising CLOCK edge
- CLR_Clock; //Start Clock cycle should last 1000ns
- _delay_us(0.500); //Pulse furation, CLOCK High
- SET_Clock; //End Clock cycle
- _delay_us(0.500); //Pulse duration, CLOCK Low
- SET_Latch; //Move data to latch (New data in latch)
- CLR_Strobe; //Enable output buffers
- }
- unsigned char textBuffer[32]; //here goes the text on display
- void refreshDisplay() { //draws every digit to display, must be executed constantly
- // Make sure everything is off.
- PORTA = 0;
- PORTC = 0;
- // Clear shift register to be sure.
- for (char i = 0; i < DISPLAY_SIZE; i++) {
- writeBitToShiftRegister(0);
- }
- // Select first display digit.
- writeBitToShiftRegister(1);
- int i;
- // Loop through all digits
- for (i = 0; i < DISPLAY_SIZE; i++) {
- // Read next character.
- // The character is masked to make sure it doesn't go outside font range.
- const unsigned char c = textBuffer[i] & 0b01111111;
- // Read bytes for corresponding segment configuration.
- const unsigned char byteA = font[c][0];
- const unsigned char byteB = font[c][1];
- // Turn segments on.
- PORTA = byteA;
- PORTC = byteB;
- // Wait. interrupt/other stuff here, delay is stupid
- _delay_us(LONG_DELAY);
- // Turn segments off.
- PORTA = 0;
- PORTC = 0;
- // Wait.
- _delay_us(SHORT_DELAY);
- // Prepare for next display module.
- writeBitToShiftRegister(0);
- }
- }
- void uart_init(uint16_t baudrate) {
- UBRRL = baudrate;
- UBRRH = (baudrate >> 8);
- UCSRC = (1 << URSEL) | (3 << UCSZ0);
- UCSRB = (1 << RXEN) | (1 << TXEN); // Enable RX and TX
- }
- void uart_putchar(char c) { //puts one charter to serial send buffer
- loop_until_bit_is_set(UCSRA, UDRE); // Wait until data register empty.
- UDR = c;
- }
- char uart_getchar(void) { //gets 1 charter from serial receive buffer
- loop_until_bit_is_set(UCSRA, RXC); // Wait until data exists.
- return UDR;
- }
- int main(void){
- //textBuffer = "Hello World! ";
- memmove(textBuffer,"Hello World! ",32);
- refreshDisplay();
- //loop here to get charter from uart_getchar();
- //and put it to textBuffer, and then refreshDisplay();
- //interrupts etc. stuff would be nice
- uart_init((((F_CPU / (USART_BAUDRATE * 16UL))) - 1)); //initialize uart at calculated baudrate
- while(1){
- uart_putchar('H');
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement