-
Notifications
You must be signed in to change notification settings - Fork 0
/
rpi-spi-vfd.c
147 lines (130 loc) · 3.95 KB
/
rpi-spi-vfd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//Copyright (c) 2019 positronics.engineer at yandex dot com.
//Distributed under the terms of the MIT license.
/* A simple and basic driver for Futaba 8-MD-06INKM C2CIG type VFD display for Raspberry Pi.
*/
#include <stdio.h>
#include <unistd.h>
#include <bcm2835.h>
#include <string.h>
#include "rpi-spi-vfd.h"
#define DATA_LEN 2 //each command 2 bytes
/* VFD device needs LSB first out on SPI bus.
* This s not possible by BCM2835 SPI module hardware, use soft function to reverse order the byte data
* First the left four bits are swapped with the right four bits.
* Then all adjacent pairs are swapped and then all adjacent single bits.
* This results in a reversed order.
* https://stackoverflow.com/a/2602885
*/
uint8_t msb2lsb_revord(uint8_t msb)
{
msb = (msb & 0xF0) >> 4 | (msb & 0x0F) << 4;
msb = (msb & 0xCC) >> 2 | (msb & 0x33) << 2;
msb = (msb & 0xAA) >> 1 | (msb & 0x55) << 1;
return msb;
}
int vfd_set_spi(void)
{
if (!bcm2835_spi_begin())
{
printf("bcm2835_spi_begin() failed!!!\n");
return 0;
}
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_LSBFIRST); //This is important but it is fake in bcm2835 lib, need to use MSB to LSB reverse order function
bcm2835_spi_setDataMode(BCM2835_SPI_MODE3);
bcm2835_spi_setClockDivider(SPI_CLK_FREQ);
bcm2835_spi_chipSelect(SPI_CS_PIN);
bcm2835_spi_setChipSelectPolarity(SPI_CS_PIN, LOW);
// Set VFD_RST_PIN to be an output, once
bcm2835_gpio_fsel(VFD_RST_PIN, BCM2835_GPIO_FSEL_OUTP);
return 1;
}
void vfd_rst(void)
{
bcm2835_gpio_write(VFD_RST_PIN, LOW);
usleep(RST_DELAY);
bcm2835_gpio_write(VFD_RST_PIN, HIGH);
}
//Follow flow chart Fig 4-1-1 on page17 in spec
void vfd_init(void)
{
char wbuf[DATA_LEN], rbuf[DATA_LEN];
memset(rbuf, 0, sizeof(rbuf));
memset(wbuf, 0, sizeof(wbuf));
vfd_rst();
//set display timing
wbuf[0] = msb2lsb_revord(0xE0);
wbuf[1] = msb2lsb_revord(0x07); //0x07 for 8-MD-06INKM
bcm2835_spi_transfernb(wbuf, rbuf, DATA_LEN); //don't care read data
usleep(CMD_DELAY);
//set dimming, default 50/255
vfd_set_dimming (50);
//display light up
wbuf[0] = msb2lsb_revord(0xE8);
//wbuf[1] = msb2lsb_revord(0x00); //second byte don't care
bcm2835_spi_transfernb(wbuf, rbuf, DATA_LEN);
usleep(CMD_DELAY);
}
void vfd_set_dimming (const uint8_t dimm)
{
char wbuf[DATA_LEN], rbuf[DATA_LEN];
memset(rbuf, 0, sizeof(rbuf));
memset(wbuf, 0, sizeof(wbuf));
wbuf[0] = msb2lsb_revord(0xE4);
wbuf[1] = msb2lsb_revord(dimm);
bcm2835_spi_transfernb(wbuf, rbuf, DATA_LEN); //don't care read data
usleep(CMD_DELAY);
}
void vfd_stby (const uint8_t mode)
{
char wbuf[DATA_LEN], rbuf[DATA_LEN];
memset(rbuf, 0, sizeof(rbuf));
memset(wbuf, 0, sizeof(wbuf));
if ((mode == 1)|(mode == 0))
{
wbuf[0] = msb2lsb_revord(0xEC|mode);
//wbuf[1] = 0x00; //2nd byte don't care
bcm2835_spi_transfernb(wbuf, rbuf, DATA_LEN); //don't care read data
usleep(CMD_DELAY);
}
else
printf("invalid mode for stby command, set 0 or 1\n");
}
void vfd_end (void)
{
bcm2835_spi_end();
}
void vfd_clear_screen(void)
{
const char *blnk = " ";
vfd_put_str(blnk);
}
void vfd_put_char (const char ch, const uint8_t digit)
{
char wbuf[DATA_LEN], rbuf[DATA_LEN];
memset(rbuf, 0, sizeof(rbuf));
memset(wbuf, 0, sizeof(wbuf));
if(digit < VFD_WIDTH)
{
wbuf[0] = msb2lsb_revord((0b00100000|digit)); //assume digit equal or less than 0b00000111
wbuf[1] = msb2lsb_revord(ch);
bcm2835_spi_transfernb(wbuf, rbuf, DATA_LEN); //don't care read data
usleep(CMD_DELAY);
}
else
printf("Digit parameter is greater than 8-MD-06INKM VFD spec!!!\n");
}
void vfd_put_str(const char *str)
{
uint8_t i = 0;
if (strlen(str) <= VFD_WIDTH)
{
while (*str)
{
vfd_put_char(*str, i);
str++;
i++;
}
}
else
printf("Number of chars in string is greater than screen!!!\n");
}