├── pcd8544 ├── pcd8544_test.go └── pcd8544.go ├── lib └── PCD8544 │ ├── build.sh │ ├── PCD8544.h │ └── PCD8544.c ├── .gitmodules ├── .gitignore ├── rpi_test.go ├── README.md ├── examples └── lcd_switch.go └── rpi.go /pcd8544/pcd8544_test.go: -------------------------------------------------------------------------------- 1 | package pcd8544 2 | -------------------------------------------------------------------------------- /lib/PCD8544/build.sh: -------------------------------------------------------------------------------- 1 | gcc PCD8544.c -shared -o libPCD8544.so 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "WiringPi"] 2 | path = WiringPi 3 | url = https://github.com/WiringPi/WiringPi.git 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | -------------------------------------------------------------------------------- /rpi_test.go: -------------------------------------------------------------------------------- 1 | package rpi 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_hello(t *testing.T) { 8 | t.Log("hello world") 9 | } 10 | 11 | func Test_Setup(t *testing.T) { 12 | WiringPiSetup() 13 | } 14 | 15 | func Test_PinToGpio(t *testing.T) { 16 | for i := 0; i <= 26; i++ { 17 | t.Log("PinToGpio", i, PinToGpio(i)) 18 | } 19 | } 20 | 21 | func Test_BoardToPin(t *testing.T) { 22 | for i := 1; i <= 26; i++ { 23 | t.Log("BoardToPin", i, BoardToPin(i)) 24 | } 25 | } 26 | 27 | func Test_GpioToPin(t *testing.T) { 28 | for i := 0; i <= 31; i++ { 29 | t.Log("Test_GpioToPin", i, GpioToPin(i)) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pcd8544/pcd8544.go: -------------------------------------------------------------------------------- 1 | package pcd8544 2 | 3 | /* 4 | #cgo LDFLAGS: -L . -lPCD8544 -lwiringPi 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | void Test(char *c, char *c2) { 13 | LCDclear(); 14 | LCDdrawstring(0, 24, c); 15 | LCDdrawstring(0, 34, c2); 16 | LCDdisplay(); 17 | } 18 | */ 19 | import "C" 20 | 21 | const ( 22 | BLACK = 1 23 | WHITE = 0 24 | ) 25 | 26 | func LCDclear() { 27 | C.LCDclear() 28 | } 29 | 30 | func Test(s1 string, s2 string) { 31 | C.Test(C.CString(s1), C.CString(s2)) 32 | } 33 | 34 | func LCDInit(_sclk int, _din int, _dc int, _cs int, _rst int, contrast int) { 35 | C.LCDInit(C.uint8_t(_sclk), C.uint8_t(_din), C.uint8_t(_dc), C.uint8_t(_cs), C.uint8_t(_rst), C.uint8_t(contrast)) 36 | } 37 | 38 | func LCDcommand(c int) { 39 | C.LCDcommand(C.uint8_t(c)) 40 | } 41 | 42 | func LCDdata(c int8) { 43 | C.LCDdata(C.uint8_t(c)) 44 | } 45 | 46 | func LCDdrawstring(x int8, y int8, str string) { 47 | C.LCDdrawstring(C.uint8_t(x), C.uint8_t(y), C.CString(str)) 48 | } 49 | 50 | func LCDdisplay() { 51 | C.LCDdisplay() 52 | } 53 | 54 | func LCDdrawline(x0 int, y0 int, x1 int, y1 int, color int) { 55 | C.LCDdrawline(C.uint8_t(x0), C.uint8_t(y0), C.uint8_t(x1), C.uint8_t(y1), C.uint8_t(color)) 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WiringPi-Go 2 | ============ 3 | 4 | Golang wrapped version of Gordon's Arduino-like WiringPi for the Raspberry Pi 5 | 6 | # Installation 7 | 8 | install WiringPi first 9 | 10 | ``` 11 | cd WiringPi\wiringPi 12 | sudo make install 13 | 14 | go get github.com/hugozhu/rpi 15 | ``` 16 | 17 | # GPIO numbering 18 | 19 | wiringPi | Name | GPIO.BOARD | GPIO.BCM 20 | ---------- | -------- | ------------ | -------- 21 | 0 |GPIO 0 | 11 | 17 22 | 1 |GPIO 1 | 12 | 18 23 | 2 |GPIO 2 | 13 | 21 24 | 3 |GPIO 3 | 15 | 22 25 | 4 |GPIO 4 | 16 | 23 26 | 5 |GPIO 5 | 18 | 24 27 | 6 |GPIO 6 | 22 | 25 28 | 7 |GPIO 7 | 7 | 4 29 | 8 |SDA | 3 | 0 30 | 9 |SCL | 5 | 1 31 | 10 |CE0 | 24 | 8 32 | 11 |CE1 | 26 | 7 33 | 12 |MOSI | 19 | 10 34 | 13 |MOSO | 21 | 9 35 | 14 |SCLK | 23 | 11 36 | 15 |TXD | 8 | 14 37 | 16 |RXD | 10 | 15 38 | 39 | more to read at: [http://hugozhu.myalert.info/2013/03/22/19-raspberry-pi-gpio-port-naming.html](http://hugozhu.myalert.info/2013/03/22/19-raspberry-pi-gpio-port-naming.html) 40 | 41 | # Sample codes 42 | 43 | ## `lcd.go` 44 | ```go 45 | package main 46 | 47 | import ( 48 | . "github.com/hugozhu/rpi" 49 | ) 50 | 51 | func main() { 52 | WiringPiSetup() 53 | 54 | //use default pin naming 55 | PinMode(PIN_GPIO_4, OUTPUT) 56 | DigitalWrite(PIN_GPIO_4, LOW) 57 | Delay(400) 58 | DigitalWrite(PIN_GPIO_4, HIGH) 59 | 60 | //use raspberry pi board pin numbering, similiar to RPi.GPIO.setmode(RPi.GPIO.BOARD) 61 | Delay(400) 62 | DigitalWrite(BoardToPin(16), LOW) 63 | Delay(400) 64 | DigitalWrite(BoardToPin(16), HIGH) 65 | 66 | //use raspberry pi bcm gpio numbering, similiar to RPi.GPIO.setmode(RPi.GPIO.BCM) 67 | Delay(400) 68 | DigitalWrite(GpioToPin(23), LOW) 69 | Delay(400) 70 | DigitalWrite(GpioToPin(23), HIGH) 71 | } 72 | ``` 73 | 74 | ## Run 75 | 76 | ``` 77 | export GOPATH=`pwd` 78 | go install github.com/hugozhu/rpi 79 | go run src/lcd.go 80 | ``` 81 | -------------------------------------------------------------------------------- /examples/lcd_switch.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | . "github.com/hugozhu/rpi" 5 | "github.com/hugozhu/rpi/pcd8544" 6 | "log" 7 | "os/exec" 8 | "time" 9 | ) 10 | 11 | const ( 12 | DIN = PIN_MOSI 13 | SCLK = PIN_SCLK 14 | DC = PIN_GPIO_2 15 | RST = PIN_GPIO_0 16 | CS = PIN_CE0 17 | PUSHBUTTON = PIN_GPIO_6 18 | CONTRAST = 40 //may need tweak for each Nokia 5110 screen 19 | ) 20 | 21 | var screen_chan chan int 22 | var TOTAL_MODES = 3 23 | 24 | func init() { 25 | WiringPiSetup() 26 | pcd8544.LCDInit(SCLK, DIN, DC, CS, RST, CONTRAST) 27 | screen_chan = make(chan int, 1) 28 | } 29 | 30 | func main() { 31 | //a goroutine to check button push event 32 | go func() { 33 | last_time := time.Now().UnixNano() / 1000000 34 | btn_pushed := 0 35 | for pin := range WiringPiISR(PUSHBUTTON, INT_EDGE_FALLING) { 36 | if pin > -1 { 37 | n := time.Now().UnixNano() / 1000000 38 | delta := n - last_time 39 | if delta > 300 { //software debouncing 40 | log.Println("btn pushed") 41 | last_time = n 42 | btn_pushed++ 43 | screen_chan <- btn_pushed % TOTAL_MODES //switch the screen display 44 | } 45 | } 46 | } 47 | }() 48 | 49 | //a groutine to update display every 5 seconds 50 | go loop_update_display() 51 | 52 | //set screen 0 to be default 53 | screen_chan <- 0 54 | 55 | ticker := time.NewTicker(5 * time.Second) 56 | 57 | for { 58 | <-ticker.C 59 | screen_chan <- -1 //refresh current screen every 5 seconds 60 | } 61 | } 62 | 63 | func loop_update_display() { 64 | current_screen := 0 65 | for screen := range screen_chan { 66 | if screen >= 0 { 67 | if screen != current_screen { 68 | //btn pushed 69 | current_screen = screen 70 | display_loading() 71 | } 72 | } 73 | switch current_screen { 74 | case 0: 75 | display_screen0() 76 | case 1: 77 | display_screen1() 78 | case 2: 79 | display_screen2() 80 | } 81 | } 82 | } 83 | 84 | func display_loading() { 85 | pcd8544.LCDclear() 86 | pcd8544.LCDdrawstring(0, 20, "Loading ...") 87 | pcd8544.LCDdisplay() 88 | } 89 | 90 | func display_screen0() { 91 | out, err := exec.Command("/root/bin/screen_1.sh").CombinedOutput() 92 | if err != nil { 93 | out = []byte(err.Error()) 94 | } 95 | 96 | pcd8544.LCDclear() 97 | pcd8544.LCDdrawstring(0, 0, string(out)) 98 | pcd8544.LCDdisplay() 99 | } 100 | 101 | func display_screen1() { 102 | out, err := exec.Command("/root/bin/screen_1.sh").CombinedOutput() 103 | if err != nil { 104 | out = []byte(err.Error()) 105 | } 106 | 107 | pcd8544.LCDclear() 108 | pcd8544.LCDdrawstring(0, 0, string(out)) 109 | pcd8544.LCDdisplay() 110 | } 111 | 112 | func display_screen2() { 113 | out, err := exec.Command("/root/bin/screen_2.sh").CombinedOutput() 114 | if err != nil { 115 | out = []byte(err.Error()) 116 | } 117 | 118 | pcd8544.LCDclear() 119 | pcd8544.LCDdrawstring(0, 0, string(out)) 120 | pcd8544.LCDdisplay() 121 | } 122 | -------------------------------------------------------------------------------- /lib/PCD8544/PCD8544.h: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : PCD8544.h 4 | Version : 0.1 5 | 6 | Copyright (C) 2010 Limor Fried, Adafruit Industries 7 | CORTEX-M3 version by Le Dang Dung, 2011 LeeDangDung@gmail.com (tested on LPC1769) 8 | Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de 9 | 10 | Description : PCD8544 LCD library! 11 | 12 | ================================================================================ 13 | This library is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU Lesser General Public 15 | License as published by the Free Software Foundation; either 16 | version 2.1 of the License, or (at your option) any later version. 17 | 18 | This library is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | Lesser General Public License for more details. 22 | ================================================================================ 23 | */ 24 | #include 25 | 26 | #define BLACK 1 27 | #define WHITE 0 28 | 29 | #define LCDWIDTH 84 30 | #define LCDHEIGHT 48 31 | 32 | #define PCD8544_POWERDOWN 0x04 33 | #define PCD8544_ENTRYMODE 0x02 34 | #define PCD8544_EXTENDEDINSTRUCTION 0x01 35 | 36 | #define PCD8544_DISPLAYBLANK 0x0 37 | #define PCD8544_DISPLAYNORMAL 0x4 38 | #define PCD8544_DISPLAYALLON 0x1 39 | #define PCD8544_DISPLAYINVERTED 0x5 40 | 41 | // H = 0 42 | #define PCD8544_FUNCTIONSET 0x20 43 | #define PCD8544_DISPLAYCONTROL 0x08 44 | #define PCD8544_SETYADDR 0x40 45 | #define PCD8544_SETXADDR 0x80 46 | 47 | // H = 1 48 | #define PCD8544_SETTEMP 0x04 49 | #define PCD8544_SETBIAS 0x10 50 | #define PCD8544_SETVOP 0x80 51 | 52 | #define swap(a, b) { uint8_t t = a; a = b; b = t; } 53 | 54 | // calibrate clock constants 55 | #define CLKCONST_1 8000 56 | #define CLKCONST_2 200 // 400 is a good tested value for Raspberry Pi 57 | 58 | // keywords 59 | #define LSBFIRST 0 60 | #define MSBFIRST 1 61 | 62 | int LCDInit(uint8_t SCLK, uint8_t DIN, uint8_t DC, uint8_t CS, uint8_t RST, uint8_t contrast); 63 | void LCDcommand(uint8_t c); 64 | void LCDdata(uint8_t c); 65 | void LCDsetContrast(uint8_t val); 66 | void LCDclear(); 67 | void LCDdisplay(); 68 | void LCDsetPixel(uint8_t x, uint8_t y, uint8_t color); 69 | uint8_t LCDgetPixel(uint8_t x, uint8_t y); 70 | void LCDfillcircle(uint8_t x0, uint8_t y0, uint8_t r,uint8_t color); 71 | void LCDdrawcircle(uint8_t x0, uint8_t y0, uint8_t r,uint8_t color); 72 | void LCDdrawrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,uint8_t color); 73 | void LCDfillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,uint8_t color); 74 | void LCDdrawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color); 75 | void LCDsetCursor(uint8_t x, uint8_t y); 76 | void LCDsetTextSize(uint8_t s); 77 | void LCDsetTextColor(uint8_t c); 78 | void LCDwrite(uint8_t c); 79 | void LCDshowLogo(); 80 | void LCDdrawchar(uint8_t x, uint8_t line, char c); 81 | void LCDdrawstring(uint8_t x, uint8_t line, char *c); 82 | void LCDdrawstring_P(uint8_t x, uint8_t line, const char *c); 83 | void LCDdrawbitmap(uint8_t x, uint8_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color); 84 | void LCDspiwrite(uint8_t c); 85 | 86 | -------------------------------------------------------------------------------- /rpi.go: -------------------------------------------------------------------------------- 1 | package rpi 2 | 3 | /* 4 | #cgo LDFLAGS: -lwiringPi 5 | 6 | #include 7 | #include 8 | #include 9 | #define nil ((void*)0) 10 | 11 | #define GEN_INTERRUPTER(PIN) static void interrupt_handler_##PIN() { \ 12 | context ctxt; \ 13 | ctxt.pin = PIN; \ 14 | ctxt.ret = PIN; \ 15 | callback_func(goCallback, &ctxt); \ 16 | } 17 | 18 | typedef struct context context; 19 | struct context { 20 | int pin; 21 | int ret; 22 | }; 23 | 24 | static void my_pinMode(int p, int m) { 25 | pinMode(p,m); 26 | } 27 | 28 | static void my_digitalWrite(int p, int m) { 29 | digitalWrite(p,m); 30 | } 31 | 32 | static int my_digitalRead(int p) { 33 | return digitalRead(p); 34 | } 35 | 36 | static void(*callback_func)(void (*f)(void*), void*); 37 | 38 | extern void goCallback(void *); 39 | 40 | GEN_INTERRUPTER(0) 41 | GEN_INTERRUPTER(1) 42 | GEN_INTERRUPTER(2) 43 | GEN_INTERRUPTER(3) 44 | GEN_INTERRUPTER(4) 45 | GEN_INTERRUPTER(5) 46 | GEN_INTERRUPTER(6) 47 | GEN_INTERRUPTER(7) 48 | GEN_INTERRUPTER(8) 49 | GEN_INTERRUPTER(9) 50 | GEN_INTERRUPTER(10) 51 | GEN_INTERRUPTER(11) 52 | GEN_INTERRUPTER(12) 53 | GEN_INTERRUPTER(13) 54 | GEN_INTERRUPTER(14) 55 | GEN_INTERRUPTER(15) 56 | GEN_INTERRUPTER(16) 57 | GEN_INTERRUPTER(17) 58 | GEN_INTERRUPTER(18) 59 | GEN_INTERRUPTER(19) 60 | GEN_INTERRUPTER(20) 61 | 62 | static int my_wiringPiISR(int pin, int mode) { 63 | switch(pin) { 64 | case 0: return wiringPiISR(pin, mode, &interrupt_handler_0); 65 | case 1: return wiringPiISR(pin, mode, &interrupt_handler_1); 66 | case 2: return wiringPiISR(pin, mode, &interrupt_handler_2); 67 | case 3: return wiringPiISR(pin, mode, &interrupt_handler_3); 68 | case 4: return wiringPiISR(pin, mode, &interrupt_handler_4); 69 | case 5: return wiringPiISR(pin, mode, &interrupt_handler_5); 70 | case 6: return wiringPiISR(pin, mode, &interrupt_handler_6); 71 | case 7: return wiringPiISR(pin, mode, &interrupt_handler_7); 72 | case 8: return wiringPiISR(pin, mode, &interrupt_handler_8); 73 | case 9: return wiringPiISR(pin, mode, &interrupt_handler_9); 74 | case 10: return wiringPiISR(pin, mode, &interrupt_handler_10); 75 | case 11: return wiringPiISR(pin, mode, &interrupt_handler_11); 76 | case 12: return wiringPiISR(pin, mode, &interrupt_handler_12); 77 | case 13: return wiringPiISR(pin, mode, &interrupt_handler_13); 78 | case 14: return wiringPiISR(pin, mode, &interrupt_handler_14); 79 | case 15: return wiringPiISR(pin, mode, &interrupt_handler_15); 80 | case 16: return wiringPiISR(pin, mode, &interrupt_handler_16); 81 | case 17: return wiringPiISR(pin, mode, &interrupt_handler_17); 82 | case 18: return wiringPiISR(pin, mode, &interrupt_handler_18); 83 | case 19: return wiringPiISR(pin, mode, &interrupt_handler_19); 84 | case 20: return wiringPiISR(pin, mode, &interrupt_handler_20); 85 | } 86 | return -1; 87 | } 88 | 89 | static void init(void *p) { 90 | callback_func = p; 91 | } 92 | */ 93 | import "C" 94 | import "unsafe" 95 | 96 | import ( 97 | "github.com/rogpeppe/rog-go/tree/master/exp/callback" 98 | "errors" 99 | "fmt" 100 | "sync" 101 | ) 102 | 103 | const ( 104 | VERSION = "0.2" 105 | AUTHOR = "@hugozhu" 106 | ) 107 | 108 | var ( 109 | board2pin = []int{ 110 | -1, 111 | -1, 112 | -1, 113 | 8, 114 | -1, 115 | 9, 116 | -1, 117 | 7, 118 | 15, 119 | -1, 120 | 16, 121 | 0, 122 | 1, 123 | 2, 124 | -1, 125 | -1, 126 | 4, 127 | -1, 128 | 5, 129 | 12, 130 | -1, 131 | 13, 132 | 6, 133 | 14, 134 | 10, 135 | -1, 136 | 11, 137 | } 138 | gpio2pin = []int{ 139 | 8, 140 | 9, 141 | -1, 142 | -1, 143 | 7, 144 | -1, 145 | -1, 146 | 11, 147 | 10, 148 | 13, 149 | 12, 150 | 14, 151 | -1, 152 | -1, 153 | 15, 154 | 16, 155 | -1, 156 | 0, 157 | 1, 158 | -1, 159 | -1, 160 | 2, 161 | 3, 162 | 4, 163 | 5, 164 | 6, 165 | -1, 166 | -1, 167 | 17, 168 | 18, 169 | 19, 170 | 20, 171 | } 172 | ) 173 | 174 | const ( 175 | PIN_GPIO_0 = 0 176 | PIN_GPIO_1 = 1 177 | PIN_GPIO_2 = 2 178 | PIN_GPIO_3 = 3 179 | PIN_GPIO_4 = 4 180 | PIN_GPIO_5 = 5 181 | PIN_GPIO_6 = 6 182 | PIN_GPIO_7 = 7 183 | PIN_SDA = 8 184 | PIN_SCL = 9 185 | PIN_CE0 = 10 186 | PIN_CE1 = 11 187 | PIN_MOSI = 12 188 | PIN_MOSO = 13 189 | PIN_SCLK = 14 190 | PIN_TXD = 15 191 | PIN_RXD = 16 192 | PIN_GPIO_8 = 17 193 | PIN_GPIO_9 = 18 194 | PIN_GPIO_10 = 19 195 | PIN_GPIO_11 = 20 196 | 197 | WPI_MODE_PINS = C.WPI_MODE_PINS 198 | WPI_MODE_GPIO = C.WPI_MODE_GPIO 199 | WPI_MODE_GPIO_SYS = C.WPI_MODE_GPIO_SYS 200 | WPI_MODE_PIFACE = C.WPI_MODE_PIFACE 201 | WPI_MODE_UNINITIALISED = C.WPI_MODE_UNINITIALISED 202 | 203 | OUTPUT = C.OUTPUT 204 | INPUT = C.INPUT 205 | PWM_OUTPUT = C.PWM_OUTPUT 206 | GPIO_CLOCK = C.GPIO_CLOCK 207 | 208 | LOW = C.LOW 209 | HIGH = C.HIGH 210 | 211 | PUD_OFF = C.PUD_OFF 212 | PUD_DOWN = C.PUD_DOWN 213 | PUD_UP = C.PUD_UP 214 | 215 | // PWM 216 | 217 | PWM_MODE_MS = C.PWM_MODE_MS 218 | PWM_MODE_BAL = C.PWM_MODE_BAL 219 | 220 | INT_EDGE_SETUP = C.INT_EDGE_SETUP 221 | INT_EDGE_FALLING = C.INT_EDGE_FALLING 222 | INT_EDGE_RISING = C.INT_EDGE_RISING 223 | INT_EDGE_BOTH = C.INT_EDGE_BOTH 224 | ) 225 | 226 | var mutex = &sync.Mutex{} 227 | 228 | //use RPi.GPIO's BOARD numbering 229 | func BoardToPin(pin int) int { 230 | if pin < 1 || pin >= len(board2pin) { 231 | panic(fmt.Sprintf("Invalid board pin number: %d", pin)) 232 | } 233 | return board2pin[pin] 234 | } 235 | 236 | func GpioToPin(pin int) int { 237 | if pin < 0 || pin >= len(gpio2pin) { 238 | panic(fmt.Sprintf("Invalid bcm gpio number: %d", pin)) 239 | } 240 | return gpio2pin[pin] 241 | } 242 | 243 | func PinToGpio(pin int) int { 244 | return int(C.wpiPinToGpio(C.int(pin))) 245 | } 246 | 247 | func WiringPiSetup() error { 248 | if -1 == int(C.wiringPiSetup()) { 249 | return errors.New("wiringPiSetup failed to call") 250 | } 251 | return nil 252 | } 253 | 254 | func PinMode(pin int, mode int) { 255 | C.my_pinMode(C.int(pin), C.int(mode)) 256 | } 257 | 258 | func DigitalWrite(pin int, mode int) { 259 | C.my_digitalWrite(C.int(pin), C.int(mode)) 260 | } 261 | 262 | func DigitalRead(pin int) int { 263 | return int(C.my_digitalRead(C.int(pin))) 264 | } 265 | 266 | func Delay(ms int) { 267 | C.delay(C.uint(ms)) 268 | } 269 | 270 | func DelayMicroseconds(microSec int) { 271 | C.delayMicroseconds(C.uint(microSec)) 272 | } 273 | 274 | func WiringPiISR(pin int, mode int) chan int { 275 | mutex.Lock() 276 | defer mutex.Unlock() 277 | if interrupt_chans[pin] == nil { 278 | interrupt_chans[pin] = make(chan int) 279 | } 280 | C.my_wiringPiISR(C.int(pin), C.int(mode)) 281 | return interrupt_chans[pin] 282 | } 283 | 284 | func init() { 285 | C.init(callback.Func) 286 | } 287 | 288 | var interrupt_chans = [64]chan int{} 289 | 290 | //export goCallback 291 | func goCallback(arg unsafe.Pointer) { 292 | ctxt := (*C.context)(arg) 293 | interrupt_chans[int(ctxt.pin)] <- int(ctxt.ret) 294 | } 295 | -------------------------------------------------------------------------------- /lib/PCD8544/PCD8544.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : PCD8544.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2010 Limor Fried, Adafruit Industries 7 | CORTEX-M3 version by Le Dang Dung, 2011 LeeDangDung@gmail.com (tested on LPC1769) 8 | Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de 9 | Constantin Petra: Switched to hardware SPI 10 | 11 | Description : 12 | A simple PCD8544 LCD (Nokia3310/5110) driver. Target board is Raspberry Pi. 13 | This driver uses 5 GPIOs on target board with a bit-bang SPI implementation 14 | (hence, may not be as fast). 15 | Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/) 16 | 17 | Recommended connection (http://www.raspberrypi.org/archives/384): 18 | LCD pins Raspberry Pi 19 | LCD1 - GND P06 - GND 20 | LCD2 - VCC P01 - 3.3V 21 | LCD3 - CLK P11 - GPIO0 22 | LCD4 - Din P12 - GPIO1 23 | LCD5 - D/C P13 - GPIO2 24 | LCD6 - CS P15 - GPIO3 25 | LCD7 - RST P16 - GPIO4 26 | LCD8 - LED P01 - 3.3V 27 | 28 | References : 29 | http://www.arduino.cc/playground/Code/PCD8544 30 | http://ladyada.net/products/nokia5110/ 31 | http://code.google.com/p/meshphone/ 32 | 33 | ================================================================================ 34 | This library is free software; you can redistribute it and/or 35 | modify it under the terms of the GNU Lesser General Public 36 | License as published by the Free Software Foundation; either 37 | version 2.1 of the License, or (at your option) any later version. 38 | 39 | This library is distributed in the hope that it will be useful, 40 | but WITHOUT ANY WARRANTY; without even the implied warranty of 41 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 42 | Lesser General Public License for more details. 43 | ================================================================================ 44 | */ 45 | #include 46 | #include 47 | #include "PCD8544.h" 48 | 49 | // An abs() :) 50 | #define abs(a) (((a) < 0) ? -(a) : (a)) 51 | 52 | // bit set 53 | #define _BV(bit) (0x1 << (bit)) 54 | #define USE_SPI_DRIVER 55 | // LCD port variables 56 | static uint8_t cursor_x, cursor_y, textsize, textcolor; 57 | static int8_t _din, _sclk, _dc, _rst, _cs; 58 | 59 | // font bitmap 60 | static unsigned char font[] = { 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 62 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 63 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 64 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 65 | 0x18, 0x3C, 0x7E, 0x3C, 0x18, 66 | 0x1C, 0x57, 0x7D, 0x57, 0x1C, 67 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 68 | 0x00, 0x18, 0x3C, 0x18, 0x00, 69 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 70 | 0x00, 0x18, 0x24, 0x18, 0x00, 71 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 72 | 0x30, 0x48, 0x3A, 0x06, 0x0E, 73 | 0x26, 0x29, 0x79, 0x29, 0x26, 74 | 0x40, 0x7F, 0x05, 0x05, 0x07, 75 | 0x40, 0x7F, 0x05, 0x25, 0x3F, 76 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 77 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 78 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 79 | 0x14, 0x22, 0x7F, 0x22, 0x14, 80 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 81 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 82 | 0x00, 0x66, 0x89, 0x95, 0x6A, 83 | 0x60, 0x60, 0x60, 0x60, 0x60, 84 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 85 | 0x08, 0x04, 0x7E, 0x04, 0x08, 86 | 0x10, 0x20, 0x7E, 0x20, 0x10, 87 | 0x08, 0x08, 0x2A, 0x1C, 0x08, 88 | 0x08, 0x1C, 0x2A, 0x08, 0x08, 89 | 0x1E, 0x10, 0x10, 0x10, 0x10, 90 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 91 | 0x30, 0x38, 0x3E, 0x38, 0x30, 92 | 0x06, 0x0E, 0x3E, 0x0E, 0x06, 93 | 0x00, 0x00, 0x00, 0x00, 0x00, 94 | 0x00, 0x00, 0x5F, 0x00, 0x00, 95 | 0x00, 0x07, 0x00, 0x07, 0x00, 96 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 97 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 98 | 0x23, 0x13, 0x08, 0x64, 0x62, 99 | 0x36, 0x49, 0x56, 0x20, 0x50, 100 | 0x00, 0x08, 0x07, 0x03, 0x00, 101 | 0x00, 0x1C, 0x22, 0x41, 0x00, 102 | 0x00, 0x41, 0x22, 0x1C, 0x00, 103 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 104 | 0x08, 0x08, 0x3E, 0x08, 0x08, 105 | 0x00, 0x80, 0x70, 0x30, 0x00, 106 | 0x08, 0x08, 0x08, 0x08, 0x08, 107 | 0x00, 0x00, 0x60, 0x60, 0x00, 108 | 0x20, 0x10, 0x08, 0x04, 0x02, 109 | 0x3E, 0x51, 0x49, 0x45, 0x3E, 110 | 0x00, 0x42, 0x7F, 0x40, 0x00, 111 | 0x72, 0x49, 0x49, 0x49, 0x46, 112 | 0x21, 0x41, 0x49, 0x4D, 0x33, 113 | 0x18, 0x14, 0x12, 0x7F, 0x10, 114 | 0x27, 0x45, 0x45, 0x45, 0x39, 115 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 116 | 0x41, 0x21, 0x11, 0x09, 0x07, 117 | 0x36, 0x49, 0x49, 0x49, 0x36, 118 | 0x46, 0x49, 0x49, 0x29, 0x1E, 119 | 0x00, 0x00, 0x14, 0x00, 0x00, 120 | 0x00, 0x40, 0x34, 0x00, 0x00, 121 | 0x00, 0x08, 0x14, 0x22, 0x41, 122 | 0x14, 0x14, 0x14, 0x14, 0x14, 123 | 0x00, 0x41, 0x22, 0x14, 0x08, 124 | 0x02, 0x01, 0x59, 0x09, 0x06, 125 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 126 | 0x7C, 0x12, 0x11, 0x12, 0x7C, 127 | 0x7F, 0x49, 0x49, 0x49, 0x36, 128 | 0x3E, 0x41, 0x41, 0x41, 0x22, 129 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 130 | 0x7F, 0x49, 0x49, 0x49, 0x41, 131 | 0x7F, 0x09, 0x09, 0x09, 0x01, 132 | 0x3E, 0x41, 0x41, 0x51, 0x73, 133 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 134 | 0x00, 0x41, 0x7F, 0x41, 0x00, 135 | 0x20, 0x40, 0x41, 0x3F, 0x01, 136 | 0x7F, 0x08, 0x14, 0x22, 0x41, 137 | 0x7F, 0x40, 0x40, 0x40, 0x40, 138 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 139 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 140 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 141 | 0x7F, 0x09, 0x09, 0x09, 0x06, 142 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 143 | 0x7F, 0x09, 0x19, 0x29, 0x46, 144 | 0x26, 0x49, 0x49, 0x49, 0x32, 145 | 0x03, 0x01, 0x7F, 0x01, 0x03, 146 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 147 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 148 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 149 | 0x63, 0x14, 0x08, 0x14, 0x63, 150 | 0x03, 0x04, 0x78, 0x04, 0x03, 151 | 0x61, 0x59, 0x49, 0x4D, 0x43, 152 | 0x00, 0x7F, 0x41, 0x41, 0x41, 153 | 0x02, 0x04, 0x08, 0x10, 0x20, 154 | 0x00, 0x41, 0x41, 0x41, 0x7F, 155 | 0x04, 0x02, 0x01, 0x02, 0x04, 156 | 0x40, 0x40, 0x40, 0x40, 0x40, 157 | 0x00, 0x03, 0x07, 0x08, 0x00, 158 | 0x20, 0x54, 0x54, 0x78, 0x40, 159 | 0x7F, 0x28, 0x44, 0x44, 0x38, 160 | 0x38, 0x44, 0x44, 0x44, 0x28, 161 | 0x38, 0x44, 0x44, 0x28, 0x7F, 162 | 0x38, 0x54, 0x54, 0x54, 0x18, 163 | 0x00, 0x08, 0x7E, 0x09, 0x02, 164 | 0x18, 0xA4, 0xA4, 0x9C, 0x78, 165 | 0x7F, 0x08, 0x04, 0x04, 0x78, 166 | 0x00, 0x44, 0x7D, 0x40, 0x00, 167 | 0x20, 0x40, 0x40, 0x3D, 0x00, 168 | 0x7F, 0x10, 0x28, 0x44, 0x00, 169 | 0x00, 0x41, 0x7F, 0x40, 0x00, 170 | 0x7C, 0x04, 0x78, 0x04, 0x78, 171 | 0x7C, 0x08, 0x04, 0x04, 0x78, 172 | 0x38, 0x44, 0x44, 0x44, 0x38, 173 | 0xFC, 0x18, 0x24, 0x24, 0x18, 174 | 0x18, 0x24, 0x24, 0x18, 0xFC, 175 | 0x7C, 0x08, 0x04, 0x04, 0x08, 176 | 0x48, 0x54, 0x54, 0x54, 0x24, 177 | 0x04, 0x04, 0x3F, 0x44, 0x24, 178 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 179 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 180 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 181 | 0x44, 0x28, 0x10, 0x28, 0x44, 182 | 0x4C, 0x90, 0x90, 0x90, 0x7C, 183 | 0x44, 0x64, 0x54, 0x4C, 0x44, 184 | 0x00, 0x08, 0x36, 0x41, 0x00, 185 | 0x00, 0x00, 0x77, 0x00, 0x00, 186 | 0x00, 0x41, 0x36, 0x08, 0x00, 187 | 0x02, 0x01, 0x02, 0x04, 0x02, 188 | 0x3C, 0x26, 0x23, 0x26, 0x3C, 189 | 0x1E, 0xA1, 0xA1, 0x61, 0x12, 190 | 0x3A, 0x40, 0x40, 0x20, 0x7A, 191 | 0x38, 0x54, 0x54, 0x55, 0x59, 192 | 0x21, 0x55, 0x55, 0x79, 0x41, 193 | 0x21, 0x54, 0x54, 0x78, 0x41, 194 | 0x21, 0x55, 0x54, 0x78, 0x40, 195 | 0x20, 0x54, 0x55, 0x79, 0x40, 196 | 0x0C, 0x1E, 0x52, 0x72, 0x12, 197 | 0x39, 0x55, 0x55, 0x55, 0x59, 198 | 0x39, 0x54, 0x54, 0x54, 0x59, 199 | 0x39, 0x55, 0x54, 0x54, 0x58, 200 | 0x00, 0x00, 0x45, 0x7C, 0x41, 201 | 0x00, 0x02, 0x45, 0x7D, 0x42, 202 | 0x00, 0x01, 0x45, 0x7C, 0x40, 203 | 0xF0, 0x29, 0x24, 0x29, 0xF0, 204 | 0xF0, 0x28, 0x25, 0x28, 0xF0, 205 | 0x7C, 0x54, 0x55, 0x45, 0x00, 206 | 0x20, 0x54, 0x54, 0x7C, 0x54, 207 | 0x7C, 0x0A, 0x09, 0x7F, 0x49, 208 | 0x32, 0x49, 0x49, 0x49, 0x32, 209 | 0x32, 0x48, 0x48, 0x48, 0x32, 210 | 0x32, 0x4A, 0x48, 0x48, 0x30, 211 | 0x3A, 0x41, 0x41, 0x21, 0x7A, 212 | 0x3A, 0x42, 0x40, 0x20, 0x78, 213 | 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 214 | 0x39, 0x44, 0x44, 0x44, 0x39, 215 | 0x3D, 0x40, 0x40, 0x40, 0x3D, 216 | 0x3C, 0x24, 0xFF, 0x24, 0x24, 217 | 0x48, 0x7E, 0x49, 0x43, 0x66, 218 | 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 219 | 0xFF, 0x09, 0x29, 0xF6, 0x20, 220 | 0xC0, 0x88, 0x7E, 0x09, 0x03, 221 | 0x20, 0x54, 0x54, 0x79, 0x41, 222 | 0x00, 0x00, 0x44, 0x7D, 0x41, 223 | 0x30, 0x48, 0x48, 0x4A, 0x32, 224 | 0x38, 0x40, 0x40, 0x22, 0x7A, 225 | 0x00, 0x7A, 0x0A, 0x0A, 0x72, 226 | 0x7D, 0x0D, 0x19, 0x31, 0x7D, 227 | 0x26, 0x29, 0x29, 0x2F, 0x28, 228 | 0x26, 0x29, 0x29, 0x29, 0x26, 229 | 0x30, 0x48, 0x4D, 0x40, 0x20, 230 | 0x38, 0x08, 0x08, 0x08, 0x08, 231 | 0x08, 0x08, 0x08, 0x08, 0x38, 232 | 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 233 | 0x2F, 0x10, 0x28, 0x34, 0xFA, 234 | 0x00, 0x00, 0x7B, 0x00, 0x00, 235 | 0x08, 0x14, 0x2A, 0x14, 0x22, 236 | 0x22, 0x14, 0x2A, 0x14, 0x08, 237 | 0xAA, 0x00, 0x55, 0x00, 0xAA, 238 | 0xAA, 0x55, 0xAA, 0x55, 0xAA, 239 | 0x00, 0x00, 0x00, 0xFF, 0x00, 240 | 0x10, 0x10, 0x10, 0xFF, 0x00, 241 | 0x14, 0x14, 0x14, 0xFF, 0x00, 242 | 0x10, 0x10, 0xFF, 0x00, 0xFF, 243 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 244 | 0x14, 0x14, 0x14, 0xFC, 0x00, 245 | 0x14, 0x14, 0xF7, 0x00, 0xFF, 246 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 247 | 0x14, 0x14, 0xF4, 0x04, 0xFC, 248 | 0x14, 0x14, 0x17, 0x10, 0x1F, 249 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 250 | 0x14, 0x14, 0x14, 0x1F, 0x00, 251 | 0x10, 0x10, 0x10, 0xF0, 0x00, 252 | 0x00, 0x00, 0x00, 0x1F, 0x10, 253 | 0x10, 0x10, 0x10, 0x1F, 0x10, 254 | 0x10, 0x10, 0x10, 0xF0, 0x10, 255 | 0x00, 0x00, 0x00, 0xFF, 0x10, 256 | 0x10, 0x10, 0x10, 0x10, 0x10, 257 | 0x10, 0x10, 0x10, 0xFF, 0x10, 258 | 0x00, 0x00, 0x00, 0xFF, 0x14, 259 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 260 | 0x00, 0x00, 0x1F, 0x10, 0x17, 261 | 0x00, 0x00, 0xFC, 0x04, 0xF4, 262 | 0x14, 0x14, 0x17, 0x10, 0x17, 263 | 0x14, 0x14, 0xF4, 0x04, 0xF4, 264 | 0x00, 0x00, 0xFF, 0x00, 0xF7, 265 | 0x14, 0x14, 0x14, 0x14, 0x14, 266 | 0x14, 0x14, 0xF7, 0x00, 0xF7, 267 | 0x14, 0x14, 0x14, 0x17, 0x14, 268 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 269 | 0x14, 0x14, 0x14, 0xF4, 0x14, 270 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 271 | 0x00, 0x00, 0x1F, 0x10, 0x1F, 272 | 0x00, 0x00, 0x00, 0x1F, 0x14, 273 | 0x00, 0x00, 0x00, 0xFC, 0x14, 274 | 0x00, 0x00, 0xF0, 0x10, 0xF0, 275 | 0x10, 0x10, 0xFF, 0x10, 0xFF, 276 | 0x14, 0x14, 0x14, 0xFF, 0x14, 277 | 0x10, 0x10, 0x10, 0x1F, 0x00, 278 | 0x00, 0x00, 0x00, 0xF0, 0x10, 279 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 280 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 281 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 282 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 283 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 284 | 0x38, 0x44, 0x44, 0x38, 0x44, 285 | 0x7C, 0x2A, 0x2A, 0x3E, 0x14, 286 | 0x7E, 0x02, 0x02, 0x06, 0x06, 287 | 0x02, 0x7E, 0x02, 0x7E, 0x02, 288 | 0x63, 0x55, 0x49, 0x41, 0x63, 289 | 0x38, 0x44, 0x44, 0x3C, 0x04, 290 | 0x40, 0x7E, 0x20, 0x1E, 0x20, 291 | 0x06, 0x02, 0x7E, 0x02, 0x02, 292 | 0x99, 0xA5, 0xE7, 0xA5, 0x99, 293 | 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 294 | 0x4C, 0x72, 0x01, 0x72, 0x4C, 295 | 0x30, 0x4A, 0x4D, 0x4D, 0x30, 296 | 0x30, 0x48, 0x78, 0x48, 0x30, 297 | 0xBC, 0x62, 0x5A, 0x46, 0x3D, 298 | 0x3E, 0x49, 0x49, 0x49, 0x00, 299 | 0x7E, 0x01, 0x01, 0x01, 0x7E, 300 | 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 301 | 0x44, 0x44, 0x5F, 0x44, 0x44, 302 | 0x40, 0x51, 0x4A, 0x44, 0x40, 303 | 0x40, 0x44, 0x4A, 0x51, 0x40, 304 | 0x00, 0x00, 0xFF, 0x01, 0x03, 305 | 0xE0, 0x80, 0xFF, 0x00, 0x00, 306 | 0x08, 0x08, 0x6B, 0x6B, 0x08, 307 | 0x36, 0x12, 0x36, 0x24, 0x36, 308 | 0x06, 0x0F, 0x09, 0x0F, 0x06, 309 | 0x00, 0x00, 0x18, 0x18, 0x00, 310 | 0x00, 0x00, 0x10, 0x10, 0x00, 311 | 0x30, 0x40, 0xFF, 0x01, 0x01, 312 | 0x00, 0x1F, 0x01, 0x01, 0x1E, 313 | 0x00, 0x19, 0x1D, 0x17, 0x12, 314 | 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 315 | 0x00, 0x00, 0x00, 0x00, 0x00, 316 | }; 317 | 318 | // the memory buffer for the LCD 319 | uint8_t pcd8544_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0,}; 320 | 321 | // Le: get the bitmap assistance here! : http://en.radzio.dxp.pl/bitmap_converter/ 322 | // Andre: or here! : http://www.henningkarlsen.com/electronics/t_imageconverter_mono.php 323 | const uint8_t pi_logo [] = { 324 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0010 (16) pixels 325 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xFC, 0xAE, 0x0E, 0x0E, 0x06, 0x0E, 0x06, // 0x0020 (32) pixels 326 | 0xCE, 0x86, 0x8E, 0x0E, 0x0E, 0x1C, 0xB8, 0xF0, 0xF8, 0x78, 0x38, 0x1E, 0x0E, 0x8E, 0x8E, 0xC6, // 0x0030 (48) pixels 327 | 0x0E, 0x06, 0x0E, 0x06, 0x0E, 0x9E, 0xFE, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0040 (64) pixels 328 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0050 (80) pixels 329 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0060 (96) pixels 330 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0xFE, // 0x0070 (112) pixels 331 | 0xF8, 0xF0, 0x60, 0x60, 0xE0, 0xE1, 0xE3, 0xF7, 0x7E, 0x3E, 0x1E, 0x1F, 0x1F, 0x1F, 0x3E, 0x7E, // 0x0080 (128) pixels 332 | 0xFB, 0xF3, 0xE1, 0xE0, 0x60, 0x70, 0xF0, 0xF8, 0xBE, 0x1F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00, // 0x0090 (144) pixels 333 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00A0 (160) pixels 334 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00B0 (176) pixels 335 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, // 0x00C0 (192) pixels 336 | 0xE0, 0xFC, 0xFE, 0xFF, 0xF3, 0x38, 0x38, 0x0C, 0x0E, 0x0F, 0x0F, 0x0F, 0x0E, 0x3C, 0x38, 0xF8, // 0x00D0 (208) pixels 337 | 0xF8, 0x38, 0x3C, 0x0E, 0x0F, 0x0F, 0x0F, 0x0E, 0x0C, 0x38, 0x38, 0xF3, 0xFF, 0xFF, 0xF8, 0xE0, // 0x00E0 (224) pixels 338 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00F0 (240) pixels 339 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0100 (256) pixels 340 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0110 (272) pixels 341 | 0x00, 0x7F, 0xFF, 0xE7, 0xC3, 0xC1, 0xE0, 0xFF, 0xFF, 0x78, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, // 0x0120 (288) pixels 342 | 0x60, 0x78, 0x38, 0x3F, 0x3F, 0x38, 0x38, 0x60, 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xF8, 0x7F, // 0x0130 (304) pixels 343 | 0xFF, 0xE0, 0xC1, 0xC3, 0xE7, 0x7F, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0140 (320) pixels 344 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0150 (336) pixels 345 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0160 (352) pixels 346 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x7F, 0xFF, 0xF1, 0xE0, 0xC0, 0x80, 0x01, // 0x0170 (368) pixels 347 | 0x03, 0x9F, 0xFF, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xFF, 0x9F, // 0x0180 (384) pixels 348 | 0x03, 0x01, 0x80, 0xC0, 0xE0, 0xF1, 0x7F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0190 (400) pixels 349 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01A0 (416) pixels 350 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01B0 (432) pixels 351 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 0x01C0 (448) pixels 352 | 0x03, 0x03, 0x07, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3B, 0x71, 0x60, 0x60, 0x60, 0x60, 0x60, 0x71, // 0x01D0 (464) pixels 353 | 0x3B, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01E0 (480) pixels 354 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01F0 (496) pixels 355 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 356 | }; 357 | 358 | #ifndef USE_SPI_DRIVER 359 | static void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); 360 | #endif 361 | static void _delay_ms(uint32_t t); 362 | 363 | 364 | // reduces how much is refreshed, which speeds it up! 365 | // originally derived from Steve Evans/JCW's mod but cleaned up and optimized 366 | //#define enablePartialUpdate 367 | 368 | static void my_setpixel(uint8_t x, uint8_t y, uint8_t color) 369 | { 370 | if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) 371 | return; 372 | // x is which column 373 | if (color) 374 | pcd8544_buffer[x+ (y/8)*LCDWIDTH] |= _BV(y%8); 375 | else 376 | pcd8544_buffer[x+ (y/8)*LCDWIDTH] &= ~_BV(y%8); 377 | } 378 | 379 | void LCDshowLogo() 380 | { 381 | uint32_t i; 382 | for (i = 0; i < LCDWIDTH * LCDHEIGHT / 8; i++ ) 383 | { 384 | pcd8544_buffer[i] = pi_logo[i]; 385 | } 386 | LCDdisplay(); 387 | } 388 | 389 | #ifdef enablePartialUpdate 390 | static uint8_t xUpdateMin, xUpdateMax, yUpdateMin, yUpdateMax; 391 | #endif 392 | 393 | static void updateBoundingBox(uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax) { 394 | #ifdef enablePartialUpdate 395 | if (xmin < xUpdateMin) xUpdateMin = xmin; 396 | if (xmax > xUpdateMax) xUpdateMax = xmax; 397 | if (ymin < yUpdateMin) yUpdateMin = ymin; 398 | if (ymax > yUpdateMax) yUpdateMax = ymax; 399 | #endif 400 | } 401 | 402 | int LCDInit(uint8_t SCLK, uint8_t DIN, uint8_t DC, uint8_t CS, uint8_t RST, uint8_t contrast) 403 | { 404 | _din = DIN; 405 | _sclk = SCLK; 406 | _dc = DC; 407 | _rst = RST; 408 | _cs = CS; 409 | cursor_x = cursor_y = 0; 410 | textsize = 1; 411 | textcolor = BLACK; 412 | 413 | #ifdef USE_SPI_DRIVER 414 | if (wiringPiSPISetup(0, 5000000) == -1) { 415 | return -1; 416 | } 417 | #else 418 | pinMode(_din, OUTPUT); 419 | pinMode(_sclk, OUTPUT); 420 | 421 | #endif 422 | // set pin directions 423 | pinMode(_dc, OUTPUT); 424 | pinMode(_rst, OUTPUT); 425 | pinMode(_cs, OUTPUT); 426 | 427 | // toggle RST low to reset; CS low so it'll listen to us 428 | if (_cs > 0) 429 | digitalWrite(_cs, LOW); 430 | 431 | digitalWrite(_rst, LOW); 432 | _delay_ms(500); 433 | digitalWrite(_rst, HIGH); 434 | 435 | // get into the EXTENDED mode! 436 | LCDcommand(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION ); 437 | 438 | // LCD bias select (4 is optimal?) 439 | LCDcommand(PCD8544_SETBIAS | 0x4); 440 | 441 | // set VOP 442 | if (contrast > 0x7f) 443 | contrast = 0x7f; 444 | 445 | LCDcommand( PCD8544_SETVOP | contrast); // Experimentally determined 446 | 447 | // normal mode 448 | LCDcommand(PCD8544_FUNCTIONSET); 449 | 450 | // Set display to Normal 451 | LCDcommand(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL); 452 | 453 | // set up a bounding box for screen updates 454 | updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1); 455 | 456 | return 0; 457 | } 458 | 459 | void LCDdrawbitmap(uint8_t x, uint8_t y,const uint8_t *bitmap, uint8_t w, uint8_t h,uint8_t color) 460 | { 461 | uint8_t j,i; 462 | for ( j=0; j= LCDHEIGHT) return; 501 | if ((x+5) >= LCDWIDTH) return; 502 | uint8_t i,j; 503 | for ( i =0; i<5; i++ ) 504 | { 505 | uint8_t d = *(font+(c*5)+i); 506 | uint8_t j; 507 | for (j = 0; j<8; j++) 508 | { 509 | if (d & _BV(j)) 510 | { 511 | my_setpixel(x+i, y+j, textcolor); 512 | } 513 | else 514 | { 515 | my_setpixel(x+i, y+j, !textcolor); 516 | } 517 | } 518 | } 519 | 520 | for ( j = 0; j<8; j++) 521 | { 522 | my_setpixel(x+5, y+j, !textcolor); 523 | } 524 | updateBoundingBox(x, y, x+5, y + 8); 525 | } 526 | 527 | void LCDwrite(uint8_t c) 528 | { 529 | if (c == '\n') 530 | { 531 | cursor_y += textsize*8; 532 | cursor_x = 0; 533 | } 534 | else if (c == '\r') 535 | { 536 | // skip em 537 | } 538 | else 539 | { 540 | LCDdrawchar(cursor_x, cursor_y, c); 541 | cursor_x += textsize*6; 542 | if (cursor_x >= (LCDWIDTH-5)) 543 | { 544 | cursor_x = 0; 545 | cursor_y+=8; 546 | } 547 | if (cursor_y >= LCDHEIGHT) 548 | cursor_y = 0; 549 | } 550 | } 551 | 552 | void LCDsetCursor(uint8_t x, uint8_t y) 553 | { 554 | cursor_x = x; 555 | cursor_y = y; 556 | } 557 | 558 | // bresenham's algorithm - thx wikpedia 559 | void LCDdrawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color) 560 | { 561 | uint8_t steep = abs(y1 - y0) > abs(x1 - x0); 562 | if (steep) 563 | { 564 | swap(x0, y0); 565 | swap(x1, y1); 566 | } 567 | 568 | if (x0 > x1) 569 | { 570 | swap(x0, x1); 571 | swap(y0, y1); 572 | } 573 | 574 | // much faster to put the test here, since we've already sorted the points 575 | updateBoundingBox(x0, y0, x1, y1); 576 | 577 | uint8_t dx, dy; 578 | dx = x1 - x0; 579 | dy = abs(y1 - y0); 580 | 581 | int8_t err = dx / 2; 582 | int8_t ystep; 583 | 584 | if (y0 < y1) 585 | { 586 | ystep = 1; 587 | } else 588 | { 589 | ystep = -1; 590 | } 591 | 592 | for (; x0<=x1; x0++) 593 | { 594 | if (steep) 595 | { 596 | my_setpixel(y0, x0, color); 597 | } 598 | else 599 | { 600 | my_setpixel(x0, y0, color); 601 | } 602 | err -= dy; 603 | if (err < 0) 604 | { 605 | y0 += ystep; 606 | err += dx; 607 | } 608 | } 609 | } 610 | 611 | // filled rectangle 612 | void LCDfillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) 613 | { 614 | // stupidest version - just pixels - but fast with internal buffer! 615 | uint8_t i,j; 616 | for ( i=x; i= 0) 662 | { 663 | y--; 664 | ddF_y += 2; 665 | f += ddF_y; 666 | } 667 | x++; 668 | ddF_x += 2; 669 | f += ddF_x; 670 | 671 | my_setpixel(x0 + x, y0 + y, color); 672 | my_setpixel(x0 - x, y0 + y, color); 673 | my_setpixel(x0 + x, y0 - y, color); 674 | my_setpixel(x0 - x, y0 - y, color); 675 | 676 | my_setpixel(x0 + y, y0 + x, color); 677 | my_setpixel(x0 - y, y0 + x, color); 678 | my_setpixel(x0 + y, y0 - x, color); 679 | my_setpixel(x0 - y, y0 - x, color); 680 | 681 | } 682 | } 683 | 684 | void LCDfillcircle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color) 685 | { 686 | updateBoundingBox(x0-r, y0-r, x0+r, y0+r); 687 | int8_t f = 1 - r; 688 | int8_t ddF_x = 1; 689 | int8_t ddF_y = -2 * r; 690 | int8_t x = 0; 691 | int8_t y = r; 692 | uint8_t i; 693 | 694 | for (i=y0-r; i<=y0+r; i++) 695 | { 696 | my_setpixel(x0, i, color); 697 | } 698 | 699 | while (x= 0) 702 | { 703 | y--; 704 | ddF_y += 2; 705 | f += ddF_y; 706 | } 707 | x++; 708 | ddF_x += 2; 709 | f += ddF_x; 710 | 711 | for ( i=y0-y; i<=y0+y; i++) 712 | { 713 | my_setpixel(x0+x, i, color); 714 | my_setpixel(x0-x, i, color); 715 | } 716 | for ( i=y0-x; i<=y0+x; i++) 717 | { 718 | my_setpixel(x0+y, i, color); 719 | my_setpixel(x0-y, i, color); 720 | } 721 | } 722 | } 723 | 724 | // the most basic function, set a single pixel 725 | void LCDsetPixel(uint8_t x, uint8_t y, uint8_t color) 726 | { 727 | if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) 728 | return; 729 | 730 | // x is which column 731 | if (color) 732 | pcd8544_buffer[x+ (y/8)*LCDWIDTH] |= _BV(y%8); 733 | else 734 | pcd8544_buffer[x+ (y/8)*LCDWIDTH] &= ~_BV(y%8); 735 | updateBoundingBox(x,y,x,y); 736 | } 737 | 738 | // the most basic function, get a single pixel 739 | uint8_t LCDgetPixel(uint8_t x, uint8_t y) 740 | { 741 | if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) 742 | return 0; 743 | 744 | return (pcd8544_buffer[x+ (y/8)*LCDWIDTH] >> (7-(y%8))) & 0x1; 745 | } 746 | 747 | void LCDspiwrite(uint8_t c) 748 | { 749 | #ifdef USE_SPI_DRIVER 750 | wiringPiSPIDataRW (0, &c, 1); 751 | #else 752 | shiftOut(_din, _sclk, MSBFIRST, c); 753 | #endif 754 | } 755 | 756 | void LCDcommand(uint8_t c) 757 | { 758 | digitalWrite( _dc, LOW); 759 | LCDspiwrite(c); 760 | } 761 | 762 | void LCDdata(uint8_t c) 763 | { 764 | digitalWrite(_dc, HIGH); 765 | LCDspiwrite(c); 766 | } 767 | 768 | void LCDsetContrast(uint8_t val) 769 | { 770 | if (val > 0x7f) { 771 | val = 0x7f; 772 | } 773 | LCDcommand(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION ); 774 | LCDcommand( PCD8544_SETVOP | val); 775 | LCDcommand(PCD8544_FUNCTIONSET); 776 | } 777 | 778 | void LCDdisplay(void) 779 | { 780 | 781 | #ifdef USE_SPI_DRIVER 782 | LCDcommand(PCD8544_SETYADDR | 0); /* Set column 0 */ 783 | digitalWrite(_dc, HIGH); 784 | wiringPiSPIDataRW (0, pcd8544_buffer, 6 * LCDWIDTH); 785 | #else 786 | uint8_t col, maxcol, p; 787 | for(p = 0; p < 6; p++) 788 | { 789 | #ifdef enablePartialUpdate 790 | // check if this page is part of update 791 | if ( yUpdateMin >= ((p+1)*8) ) 792 | { 793 | continue; // nope, skip it! 794 | } 795 | if (yUpdateMax < p*8) 796 | { 797 | break; 798 | } 799 | #endif 800 | 801 | LCDcommand(PCD8544_SETYADDR | p); 802 | 803 | 804 | #ifdef enablePartialUpdate 805 | col = xUpdateMin; 806 | maxcol = xUpdateMax; 807 | #else 808 | // start at the beginning of the row 809 | col = 0; 810 | maxcol = LCDWIDTH-1; 811 | #endif 812 | 813 | LCDcommand(PCD8544_SETXADDR | col); 814 | 815 | for(; col <= maxcol; col++) { 816 | //uart_putw_dec(col); 817 | //uart_putchar(' '); 818 | LCDdata(pcd8544_buffer[(LCDWIDTH*p)+col]); 819 | } 820 | } 821 | 822 | #endif 823 | LCDcommand(PCD8544_SETYADDR ); // no idea why this is necessary but it is to finish the last byte? 824 | #ifdef enablePartialUpdate 825 | xUpdateMin = LCDWIDTH - 1; 826 | xUpdateMax = 0; 827 | yUpdateMin = LCDHEIGHT-1; 828 | yUpdateMax = 0; 829 | #endif 830 | 831 | } 832 | 833 | // clear everything 834 | void LCDclear(void) { 835 | //memset(pcd8544_buffer, 0, LCDWIDTH*LCDHEIGHT/8); 836 | uint32_t i; 837 | for ( i = 0; i < LCDWIDTH*LCDHEIGHT/8 ; i++) 838 | pcd8544_buffer[i] = 0; 839 | updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1); 840 | cursor_y = cursor_x = 0; 841 | } 842 | 843 | // bitbang serial shift out on select GPIO pin. Data rate is defined by CPU clk speed and CLKCONST_2. 844 | // Calibrate these value for your need on target platform. 845 | #ifndef USE_SPI_DRIVER 846 | static void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) 847 | { 848 | uint8_t i; 849 | uint32_t j; 850 | 851 | for (i = 0; i < 8; i++) { 852 | if (bitOrder == LSBFIRST) 853 | digitalWrite(dataPin, !!(val & (1 << i))); 854 | else 855 | digitalWrite(dataPin, !!(val & (1 << (7 - i)))); 856 | 857 | for (j = CLKCONST_2; j > 0; j--); // clock speed, anyone? (LCD Max CLK input: 4MHz) 858 | digitalWrite(clockPin, HIGH); 859 | 860 | for (j = CLKCONST_2; j > 0; j--); // clock speed, anyone? (LCD Max CLK input: 4MHz) 861 | digitalWrite(clockPin, LOW); 862 | } 863 | } 864 | #endif 865 | // roughly calibrated spin delay 866 | static void _delay_ms(uint32_t t) 867 | { 868 | uint32_t nCount = 0; 869 | while (t != 0) 870 | { 871 | nCount = CLKCONST_1; 872 | while(nCount != 0) 873 | nCount--; 874 | t--; 875 | } 876 | } 877 | --------------------------------------------------------------------------------