├── .gitignore
├── LICENSE
├── README.md
├── badgyRev2C.py
├── badgy_python.jpg
├── epaper2in9.py
├── image.py
├── main.py
└── text.py
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 SQFMI
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Instructions
2 | 1. Follow this guide to install MicroPython on Badgy [Getting started with MicroPython on the ESP8266](https://docs.micropython.org/en/latest/esp8266/tutorial/intro.html)
3 | 2. Install [ampy](https://learn.adafruit.com/micropython-basics-load-files-and-run-code/install-ampy) or use the [WebREPL](https://micropython.org/webrepl/) for uploading files
4 | 3. Upload [main.py](main.py), [image.py](image.py), and [epaper2in9.py](epaper2in9.py)
5 | 4. Reset Badgy and see the image!
6 |
7 |
8 |
9 | ## Next Steps
10 | * Check out this [library](https://github.com/mcauser/micropython-waveshare-epaper) by [@mcauser](https://github.com/mcauser) for more examples and function calls
11 | * We'll be adding more examples shortly!
12 |
--------------------------------------------------------------------------------
/badgyRev2C.py:
--------------------------------------------------------------------------------
1 | from micropython import const
2 | from time import sleep_ms
3 |
4 | # Display resolution
5 | EPD_WIDTH = const(128)
6 | EPD_HEIGHT = const(296)
7 |
8 | BUSY = const(1) # 1=busy\=idle
9 |
10 | class EPD:
11 | def __init__(self, spi, cs, dc, rst, busy):
12 | self.spi = spi
13 | self.cs = cs
14 | self.dc = dc
15 | self.rst = rst
16 | self.busy = busy
17 | self.cs.init(self.cs.OUT, value=1)
18 | self.dc.init(self.dc.OUT, value=0)
19 | self.rst.init(self.rst.OUT, value=0)
20 | self.busy.init(self.busy.IN)
21 | self.width = EPD_WIDTH
22 | self.height = EPD_HEIGHT
23 |
24 | LUT_20_VCOMDC = bytearray(b'\x00\x08\x00\x00\x00\x02\x60\x28\x28\x00\x00\x01\x00\x14\x00\x00\x00\x01\x00\x12\x12\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
25 | LUT_21_WW = bytearray(b'\x40\x08\x00\x00\x00\x02\x90\x28\x28\x00\x00\x01\x40\x14\x00\x00\x00\x01\xA0\x12\x12\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
26 | LUT_22_BW = bytearray(b'\x40\x08\x00\x00\x00\x02\x90\x28\x28\x00\x00\x01\x40\x14\x00\x00\x00\x01\xA0\x12\x12\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
27 | LUT_23_WB = bytearray(b'\x80\x08\x00\x00\x00\x02\x90\x28\x28\x00\x00\x01\x80\x14\x00\x00\x00\x01\x50\x12\x12\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
28 | LUT_24_BB = bytearray(b'\x80\x08\x00\x00\x00\x02\x90\x28\x28\x00\x00\x01\x80\x14\x00\x00\x00\x01\x50\x12\x12\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
29 |
30 | def _command(self, command, data=None):
31 | self.dc(0)
32 | self.cs(0)
33 | self.spi.write(bytearray([command]))
34 | self.cs(1)
35 | if data is not None:
36 | self._data(data)
37 |
38 | def _data(self, data):
39 | self.dc(1)
40 | self.cs(0)
41 | self.spi.write(data)
42 | self.cs(1)
43 |
44 | def init(self):
45 | self.reset()
46 |
47 | def wait_until_idle(self):
48 | while self.busy.value() == BUSY:
49 | sleep_ms(100)
50 |
51 | def reset(self):
52 | self.rst(0)
53 | sleep_ms(200)
54 | self.rst(1)
55 | sleep_ms(200)
56 |
57 | # put an image in the frame memory
58 | def set_frame_memory(self, image, x, y, w, h):
59 | self.clear_frame_memory(0xFF)
60 | self._command(0x13, image)
61 |
62 | # replace the frame memory with the specified color
63 | def clear_frame_memory(self, color):
64 | self._wake_up()
65 | self._command(0x10)
66 | # send the color data
67 | for i in range(0, self.width // 8 * self.height):
68 | self._data(bytearray([color]))
69 |
70 | # draw the current frame memory and switch to the next memory area
71 | def display_frame(self):
72 | self._command(0x12)
73 | self.wait_until_idle()
74 | self._sleep()
75 |
76 | def _init_full_update(self):
77 | self._command(0x82,b'\x08')
78 | self._command(0X50,b'\x97')
79 |
80 | self._command(0x20)
81 | self._data(self.LUT_20_VCOMDC)
82 | self._command(0x21)
83 | self._data(self.LUT_21_WW)
84 | self._command(0x22)
85 | self._data(self.LUT_22_BW)
86 | self._command(0x23)
87 | self._data(self.LUT_23_WB)
88 | self._command(0x24)
89 | self._data(self.LUT_24_BB)
90 |
91 | def _wake_up(self):
92 | self.reset()
93 | self._command(0x01,b'\x03\x00\x2B\x2B\x03')
94 | self._command(0x06,b'\x17\x17\x17')
95 | self._command(0x04);
96 | self.wait_until_idle()
97 |
98 | self._command(0x00,b'\xBF\x0D')
99 | self._command(0x30,b'\x3A')
100 |
101 | self._command(0x61)
102 | self._data(bytearray([EPD_WIDTH]))
103 | self._data(bytearray([EPD_HEIGHT >> 8]))
104 | self._data(bytearray([EPD_HEIGHT & 0xFF]))
105 | self._init_full_update()
106 |
107 | def _sleep(self):
108 | self._command(0x02)
109 | self._command(0x07, b'\xA5')
110 | self.wait_until_idle()
111 |
--------------------------------------------------------------------------------
/badgy_python.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sqfmi/badgy-python/e68aadcf3167fdf8d7015b67a0d6bda2e525a2b1/badgy_python.jpg
--------------------------------------------------------------------------------
/epaper2in9.py:
--------------------------------------------------------------------------------
1 | """
2 | MicroPython Waveshare 2.9" Black/White GDEH029A1 e-paper display driver
3 | https://github.com/mcauser/micropython-waveshare-epaper
4 |
5 | MIT License
6 | Copyright (c) 2017 Waveshare
7 | Copyright (c) 2018 Mike Causer
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy
10 | of this software and associated documentation files (the "Software"), to deal
11 | in the Software without restriction, including without limitation the rights
12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | copies of the Software, and to permit persons to whom the Software is
14 | furnished to do so, subject to the following conditions:
15 |
16 | The above copyright notice and this permission notice shall be included in all
17 | copies or substantial portions of the Software.
18 |
19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | SOFTWARE.
26 | """
27 |
28 | from micropython import const
29 | from time import sleep_ms
30 | import ustruct
31 |
32 | # Display resolution
33 | EPD_WIDTH = const(128)
34 | EPD_HEIGHT = const(296)
35 |
36 | # Display commands
37 | DRIVER_OUTPUT_CONTROL = const(0x01)
38 | BOOSTER_SOFT_START_CONTROL = const(0x0C)
39 | #GATE_SCAN_START_POSITION = const(0x0F)
40 | DEEP_SLEEP_MODE = const(0x10)
41 | DATA_ENTRY_MODE_SETTING = const(0x11)
42 | #SW_RESET = const(0x12)
43 | #TEMPERATURE_SENSOR_CONTROL = const(0x1A)
44 | MASTER_ACTIVATION = const(0x20)
45 | #DISPLAY_UPDATE_CONTROL_1 = const(0x21)
46 | DISPLAY_UPDATE_CONTROL_2 = const(0x22)
47 | WRITE_RAM = const(0x24)
48 | WRITE_VCOM_REGISTER = const(0x2C)
49 | WRITE_LUT_REGISTER = const(0x32)
50 | SET_DUMMY_LINE_PERIOD = const(0x3A)
51 | SET_GATE_TIME = const(0x3B)
52 | #BORDER_WAVEFORM_CONTROL = const(0x3C)
53 | SET_RAM_X_ADDRESS_START_END_POSITION = const(0x44)
54 | SET_RAM_Y_ADDRESS_START_END_POSITION = const(0x45)
55 | SET_RAM_X_ADDRESS_COUNTER = const(0x4E)
56 | SET_RAM_Y_ADDRESS_COUNTER = const(0x4F)
57 | TERMINATE_FRAME_READ_WRITE = const(0xFF)
58 |
59 | BUSY = const(1) # 1=busy, 0=idle
60 |
61 | class EPD:
62 | def __init__(self, spi, cs, dc, rst, busy):
63 | self.spi = spi
64 | self.cs = cs
65 | self.dc = dc
66 | self.rst = rst
67 | self.busy = busy
68 | self.cs.init(self.cs.OUT, value=1)
69 | self.dc.init(self.dc.OUT, value=0)
70 | self.rst.init(self.rst.OUT, value=0)
71 | self.busy.init(self.busy.IN)
72 | self.width = EPD_WIDTH
73 | self.height = EPD_HEIGHT
74 |
75 | # 30 bytes (look up tables)
76 | # original waveshare example
77 | LUT_FULL_UPDATE = bytearray(b'\x02\x02\x01\x11\x12\x12\x22\x22\x66\x69\x69\x59\x58\x99\x99\x88\x00\x00\x00\x00\xF8\xB4\x13\x51\x35\x51\x51\x19\x01\x00')
78 | LUT_PARTIAL_UPDATE = bytearray(b'\x10\x18\x18\x08\x18\x18\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x14\x44\x12\x00\x00\x00\x00\x00\x00')
79 |
80 | # https://github.com/ZinggJM/GxEPD/blob/master/GxGDEH029A1/GxGDEH029A1.cpp
81 | #LUT_FULL_UPDATE = bytearray(b'\x50\xAA\x55\xAA\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x1F\x00\x00\x00\x00\x00\x00\x00')
82 | #LUT_PARTIAL_UPDATE = bytearray(b'\x10\x18\x18\x08\x18\x18\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x14\x44\x12\x00\x00\x00\x00\x00\x00')
83 |
84 | def _command(self, command, data=None):
85 | self.dc(0)
86 | self.cs(0)
87 | self.spi.write(bytearray([command]))
88 | self.cs(1)
89 | if data is not None:
90 | self._data(data)
91 |
92 | def _data(self, data):
93 | self.dc(1)
94 | self.cs(0)
95 | self.spi.write(data)
96 | self.cs(1)
97 |
98 | def init(self):
99 | self.reset()
100 | self._command(DRIVER_OUTPUT_CONTROL, ustruct.pack("= self.width):
128 | x_end = self.width - 1
129 | else:
130 | x_end = x + w - 1
131 |
132 | if (y + h >= self.height):
133 | y_end = self.height - 1
134 | else:
135 | y_end = y + h - 1
136 |
137 | self.set_memory_area(x, y, x_end, y_end)
138 | self.set_memory_pointer(x, y)
139 | self._command(WRITE_RAM, image)
140 |
141 | # replace the frame memory with the specified color
142 | def clear_frame_memory(self, color):
143 | self.set_memory_area(0, 0, self.width - 1, self.height - 1)
144 | self.set_memory_pointer(0, 0)
145 | self._command(WRITE_RAM)
146 | # send the color data
147 | for i in range(0, self.width // 8 * self.height):
148 | self._data(bytearray([color]))
149 |
150 | # draw the current frame memory and switch to the next memory area
151 | def display_frame(self):
152 | self._command(DISPLAY_UPDATE_CONTROL_2, b'\xC4')
153 | self._command(MASTER_ACTIVATION)
154 | self._command(TERMINATE_FRAME_READ_WRITE)
155 | self.wait_until_idle()
156 |
157 | # specify the memory area for data R/W
158 | def set_memory_area(self, x_start, y_start, x_end, y_end):
159 | self._command(SET_RAM_X_ADDRESS_START_END_POSITION)
160 | # x point must be the multiple of 8 or the last 3 bits will be ignored
161 | self._data(bytearray([(x_start >> 3) & 0xFF]))
162 | self._data(bytearray([(x_end >> 3) & 0xFF]))
163 | self._command(SET_RAM_Y_ADDRESS_START_END_POSITION, ustruct.pack("> 3) & 0xFF]))
170 | self._command(SET_RAM_Y_ADDRESS_COUNTER, ustruct.pack("