]> git.walde.dev - epaper_display/commitdiff
Add e-paper drivers from Waveshare repo
authorDustin Walde <redacted>
Wed, 1 Jan 2025 01:51:19 +0000 (17:51 -0800)
committerDustin Walde <redacted>
Wed, 1 Jan 2025 01:51:19 +0000 (17:51 -0800)
src/drivers/__init__.py [new file with mode: 0644]
src/drivers/epd12in48.py [new file with mode: 0644]
src/drivers/epd12in48b.py [new file with mode: 0644]
src/drivers/epd12in48b_V2.py [new file with mode: 0644]
src/drivers/epd_12_in_48_lib_32bit.so [new file with mode: 0644]
src/drivers/epd_12_in_48_lib_64bit.so [new file with mode: 0644]
src/drivers/epdconfig.py [new file with mode: 0644]

diff --git a/src/drivers/__init__.py b/src/drivers/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/drivers/epd12in48.py b/src/drivers/epd12in48.py
new file mode 100644 (file)
index 0000000..16b33f5
--- /dev/null
@@ -0,0 +1,398 @@
+# /*****************************************************************************\r
+# * | File        :      epd12in48.py\r
+# * | Author      :   Waveshare electrices\r
+# * | Function    :   Hardware underlying interface\r
+# * | Info        :\r
+# *----------------\r
+# * |  This version:   V1.0\r
+# * | Date        :   2019-11-01\r
+# * | Info        :   \r
+# ******************************************************************************/\r
+# Permission is hereby granted, free of charge, to any person obtaining a copy\r
+# of this software and associated documnetation files (the "Software"), to deal\r
+# in the Software without restriction, including without limitation the rights\r
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+# copies of the Software, and to permit persons to  whom the Software is\r
+# furished to do so, subject to the following conditions:\r
+#\r
+# The above copyright notice and this permission notice shall be included in\r
+# all copies or substantial portions of the Software.\r
+#\r
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+# THE SOFTWARE.\r
+#\r
+import time\r
+import epdconfig\r
+\r
+EPD_WIDTH       = 1304\r
+EPD_HEIGHT      = 984\r
+\r
+class EPD(object):\r
+    def __init__(self):\r
+        self.width = EPD_WIDTH\r
+        self.height = EPD_HEIGHT\r
+        \r
+        self.EPD_M1_CS_PIN  = epdconfig.EPD_M1_CS_PIN\r
+        self.EPD_S1_CS_PIN  = epdconfig.EPD_S1_CS_PIN\r
+        self.EPD_M2_CS_PIN  = epdconfig.EPD_M2_CS_PIN\r
+        self.EPD_S2_CS_PIN  = epdconfig.EPD_S2_CS_PIN\r
+\r
+        self.EPD_M1S1_DC_PIN  = epdconfig.EPD_M1S1_DC_PIN\r
+        self.EPD_M2S2_DC_PIN  = epdconfig.EPD_M2S2_DC_PIN\r
+\r
+        self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN\r
+        self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN\r
+\r
+        self.EPD_M1_BUSY_PIN  = epdconfig.EPD_M1_BUSY_PIN\r
+        self.EPD_S1_BUSY_PIN  = epdconfig.EPD_S1_BUSY_PIN\r
+        self.EPD_M2_BUSY_PIN  = epdconfig.EPD_M2_BUSY_PIN\r
+        self.EPD_S2_BUSY_PIN  = epdconfig.EPD_S2_BUSY_PIN\r
+\r
+    def Init(self):\r
+        print("EPD init...")\r
+        epdconfig.module_init()\r
+        \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) \r
+        self.Reset() \r
+\r
+        #panel setting\r
+        self.M1_SendCommand(0x00) \r
+        self.M1_SendData(0x1f)         #KW-3f   KWR-2F BWROTP 0f       BWOTP 1f\r
+        self.S1_SendCommand(0x00) \r
+        self.S1_SendData(0x1f) \r
+        self.M2_SendCommand(0x00) \r
+        self.M2_SendData(0x13) \r
+        self.S2_SendCommand(0x00) \r
+        self.S2_SendData(0x13) \r
+\r
+        # booster soft start\r
+        self.M1_SendCommand(0x06) \r
+        self.M1_SendData(0x17)         #A\r
+        self.M1_SendData(0x17)         #B\r
+        self.M1_SendData(0x39)         #C\r
+        self.M1_SendData(0x17) \r
+        self.M2_SendCommand(0x06) \r
+        self.M2_SendData(0x17) \r
+        self.M2_SendData(0x17) \r
+        self.M2_SendData(0x39) \r
+        self.M2_SendData(0x17) \r
+\r
+        #resolution setting\r
+        self.M1_SendCommand(0x61) \r
+        self.M1_SendData(0x02) \r
+        self.M1_SendData(0x88)         #source 648\r
+        self.M1_SendData(0x01)         #gate 492\r
+        self.M1_SendData(0xEC) \r
+        self.S1_SendCommand(0x61) \r
+        self.S1_SendData(0x02) \r
+        self.S1_SendData(0x90)         #source 656\r
+        self.S1_SendData(0x01)         #gate 492\r
+        self.S1_SendData(0xEC) \r
+        self.M2_SendCommand(0x61) \r
+        self.M2_SendData(0x02) \r
+        self.M2_SendData(0x90)         #source 656\r
+        self.M2_SendData(0x01)         #gate 492\r
+        self.M2_SendData(0xEC) \r
+        self.S2_SendCommand(0x61) \r
+        self.S2_SendData(0x02) \r
+        self.S2_SendData(0x88)         #source 648\r
+        self.S2_SendData(0x01)         #gate 492\r
+        self.S2_SendData(0xEC) \r
+\r
+        self.M1S1M2S2_SendCommand(0x15)        #DUSPI\r
+        self.M1S1M2S2_SendData(0x20) \r
+\r
+        self.M1S1M2S2_SendCommand(0x50)        #Vcom and data interval setting\r
+        self.M1S1M2S2_SendData(0x21)  #Border KW\r
+        self.M1S1M2S2_SendData(0x07) \r
+\r
+        self.M1S1M2S2_SendCommand(0x60) #TCON\r
+        self.M1S1M2S2_SendData(0x22) \r
+\r
+        self.M1S1M2S2_SendCommand(0xE3) \r
+        self.M1S1M2S2_SendData(0x00) \r
+\r
+        #temperature\r
+        temp =  self.M1_ReadTemperature() \r
+\r
+        self.M1S1M2S2_SendCommand(0xe0) #Cascade setting\r
+        self.M1S1M2S2_SendData(0x03) \r
+        self.M1S1M2S2_SendCommand(0xe5) #Force temperature\r
+        self.M1S1M2S2_SendData(temp)\r
+        \r
+    def display(self, Image):\r
+        start = time.clock()\r
+        buf = [0x00] * int(self.width * self.height / 8)\r
+        image_monocolor = Image.convert('1')\r
+        imwidth, imheight = image_monocolor.size \r
+        pixels = image_monocolor.load()\r
+        temp=0;\r
+        for y in range(0, imheight):\r
+                for x in range(0, imwidth):\r
+                    # Set the bits for the column of pixels at the current position.\r
+                    if pixels[x, y] < 127:           # black\r
+                        buf[int((x + y*self.width)/8)] &= ~(0x80>>temp)\r
+                    else:                           # white\r
+                        buf[int((x + y*self.width)/8)] |= (0x80>>temp)\r
+                    temp=temp+1\r
+                    if(temp==8):\r
+                        temp=0\r
+\r
+        #M1 part 648*492    \r
+        self.M1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                    self.M1_SendData(buf[y*163 + x])\r
+\r
+        #S1 part 656*492\r
+        self.S1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(buf[y*163 + x])\r
+\r
+        #M2 part 656*492\r
+        self.M2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(buf[y*163 + x])\r
+\r
+        #S2 part 648*492\r
+        self.S2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(buf[y*163 + x])\r
+                \r
+        end = time.clock()\r
+        print("use time:%f"%(end - start))\r
+        self.TurnOnDisplay()\r
+\r
+    def clear(self):\r
+        """Clear contents of image buffer"""\r
+        start = time.clock()\r
+        self.M1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(0xff)\r
+\r
+        self.S1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(0xff)\r
+    \r
+        self.M2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(0xff)\r
+\r
+        self.S2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(0xff)\r
+        end = time.clock()\r
+        print("use time:%f"%(end - start))\r
+        self.TurnOnDisplay()\r
+        \r
+    """   M1S1M2S2 Write register address and data     """\r
+    def M1S1M2S2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+    \r
+    def M1S1M2S2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+\r
+    """   M1M2 Write register address and data     """\r
+    def M1M2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        \r
+    def M1S1M2S2_Senddata(self, val): \r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)   \r
+          \r
+    """   S2 Write register address and data     """\r
+    def S2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+\r
+\r
+    def S2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+        \r
+    """   M2 Write register address and data     """\r
+    def M2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+\r
+    def M2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+\r
+    """   S1 Write register address and data     """\r
+    def S1_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+\r
+    def S1_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        \r
+    """   M1 Write register address and data     """\r
+    def M1_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+\r
+    def M1_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+\r
+    def Reset(self):\r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 1) \r
+        time.sleep(0.2) \r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 0) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 0) \r
+        time.sleep(0.01) \r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 1) \r
+        time.sleep(0.2) \r
+    \r
+    def EPD_Sleep(self):\r
+        self.M1S1M2S2_SendCommand(0X02)        \r
+        time.sleep(0.3) \r
+\r
+        self.M1S1M2S2_SendCommand(0X07)        \r
+        self.M1S1M2S2_SendData(0xA5) \r
+        time.sleep(0.3) \r
+        print("module_exit")\r
+        epdconfig.module_exit()\r
+        \r
+        \r
+    def TurnOnDisplay(self):\r
+        self.M1M2_SendCommand(0x04)  \r
+        time.sleep(0.3) \r
+        self.M1S1M2S2_SendCommand(0x12) \r
+        self.M1_ReadBusy()\r
+        self.S1_ReadBusy()\r
+        self.M2_ReadBusy()\r
+        self.S2_ReadBusy()\r
+    \r
+    #Busy\r
+    def M1_ReadBusy(self):\r
+        self.M1_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        print("M1_ReadBusy")\r
+        while(busy):\r
+            self.M1_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)\r
+        \r
+    def M2_ReadBusy(self):\r
+        self.M2_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        print("M2_ReadBusy")\r
+        while(busy):\r
+            self.M2_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) \r
+            busy =not(busy & 0x01) \r
+        time.sleep(0.2)   \r
+        \r
+    def S1_ReadBusy(self):\r
+        self.S1_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        print("s1_ReadBusy")\r
+        while(busy):\r
+            self.S1_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)   \r
+        \r
+    def S2_ReadBusy(self):\r
+        self.S2_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        print("S2_ReadBusy")\r
+        while(busy):\r
+            self.S2_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)            \r
+        \r
+    def M1_ReadTemperature(self):\r
+        self.M1_SendCommand(0x40) \r
+        self.M1_ReadBusy() \r
+        time.sleep(0.3) \r
+\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0) \r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) \r
+        \r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1) \r
+        time.sleep(0.01) \r
+        \r
+        # temp = epdconfig.spi_readbyte(0x00)\r
+        temp = 25\r
+        print("Read Temperature Reg:%d"%temp)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) \r
+        # temp =0x29\r
+        return temp \r
diff --git a/src/drivers/epd12in48b.py b/src/drivers/epd12in48b.py
new file mode 100644 (file)
index 0000000..bf56c0c
--- /dev/null
@@ -0,0 +1,525 @@
+# /*****************************************************************************\r
+# * | File        :      epd12in48.py\r
+# * | Author      :   Waveshare electrices\r
+# * | Function    :   Hardware underlying interface\r
+# * | Info        :\r
+# *----------------\r
+# * |  This version:   V1.0\r
+# * | Date        :   2019-11-01\r
+# * | Info        :   \r
+# ******************************************************************************/\r
+# Permission is hereby granted, free of charge, to any person obtaining a copy\r
+# of this software and associated documnetation files (the "Software"), to deal\r
+# in the Software without restriction, including without limitation the rights\r
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+# copies of the Software, and to permit persons to  whom the Software is\r
+# furished to do so, subject to the following conditions:\r
+#\r
+# The above copyright notice and this permission notice shall be included in\r
+# all copies or substantial portions of the Software.\r
+#\r
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+# THE SOFTWARE.\r
+#\r
+import time\r
+import epdconfig\r
+\r
+EPD_WIDTH       = 1304\r
+EPD_HEIGHT      = 984\r
+\r
+class EPD(object):\r
+    def __init__(self):\r
+        self.width = EPD_WIDTH\r
+        self.height = EPD_HEIGHT\r
+        \r
+        self.EPD_M1_CS_PIN  = epdconfig.EPD_M1_CS_PIN\r
+        self.EPD_S1_CS_PIN  = epdconfig.EPD_S1_CS_PIN\r
+        self.EPD_M2_CS_PIN  = epdconfig.EPD_M2_CS_PIN\r
+        self.EPD_S2_CS_PIN  = epdconfig.EPD_S2_CS_PIN\r
+\r
+        self.EPD_M1S1_DC_PIN  = epdconfig.EPD_M1S1_DC_PIN\r
+        self.EPD_M2S2_DC_PIN  = epdconfig.EPD_M2S2_DC_PIN\r
+\r
+        self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN\r
+        self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN\r
+\r
+        self.EPD_M1_BUSY_PIN  = epdconfig.EPD_M1_BUSY_PIN\r
+        self.EPD_S1_BUSY_PIN  = epdconfig.EPD_S1_BUSY_PIN\r
+        self.EPD_M2_BUSY_PIN  = epdconfig.EPD_M2_BUSY_PIN\r
+        self.EPD_S2_BUSY_PIN  = epdconfig.EPD_S2_BUSY_PIN\r
+\r
+    def Init(self):\r
+        print("EPD init...")\r
+        epdconfig.module_init()\r
+        \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) \r
+        self.Reset() \r
+\r
+        #panel setting\r
+        self.M1_SendCommand(0x00) \r
+        self.M1_SendData(0x2f)         #KW-3f   KWR-2F BWROTP 0f       BWOTP 1f\r
+        self.S1_SendCommand(0x00) \r
+        self.S1_SendData(0x2f) \r
+        self.M2_SendCommand(0x00) \r
+        self.M2_SendData(0x23) \r
+        self.S2_SendCommand(0x00) \r
+        self.S2_SendData(0x23) \r
+\r
+        # POWER SETTING\r
+        self.M1_SendCommand(0x01)\r
+        self.M1_SendData(0x07)\r
+        self.M1_SendData(0x17) # VGH=20V,VGL=-20V\r
+        self.M1_SendData(0x3F)   # VDH=15V\r
+        self.M1_SendData(0x3F)   # VDL=-15V\r
+        self.M1_SendData(0x0d)\r
+        self.M2_SendCommand(0x01)\r
+        self.M2_SendData(0x07)\r
+        self.M2_SendData(0x17) # VGH=20V,VGL=-20V\r
+        self.M2_SendData(0x3F) # VDH=15V\r
+        self.M2_SendData(0x3F)  # VDL=-15V\r
+        self.M2_SendData(0x0d)\r
+        \r
+        # booster soft start\r
+        self.M1_SendCommand(0x06)\r
+        self.M1_SendData(0x17) #A\r
+        self.M1_SendData(0x17) #B\r
+        self.M1_SendData(0x39) #C\r
+        self.M1_SendData(0x17)\r
+        self.M2_SendCommand(0x06)\r
+        self.M2_SendData(0x17)\r
+        self.M2_SendData(0x17)\r
+        self.M2_SendData(0x39)\r
+        self.M2_SendData(0x17)\r
+\r
+        #resolution setting\r
+        self.M1_SendCommand(0x61)\r
+        self.M1_SendData(0x02)\r
+        self.M1_SendData(0x88) #source 648\r
+        self.M1_SendData(0x01) #gate 492\r
+        self.M1_SendData(0xEC)\r
+        self.S1_SendCommand(0x61)\r
+        self.S1_SendData(0x02)\r
+        self.S1_SendData(0x90) #source 656\r
+        self.S1_SendData(0x01) #gate 492\r
+        self.S1_SendData(0xEC)\r
+        self.M2_SendCommand(0x61)\r
+        self.M2_SendData(0x02)\r
+        self.M2_SendData(0x90) #source 656\r
+        self.M2_SendData(0x01) #gate 492\r
+        self.M2_SendData(0xEC)\r
+        self.S2_SendCommand(0x61)\r
+        self.S2_SendData(0x02)\r
+        self.S2_SendData(0x88) #source 648\r
+        self.S2_SendData(0x01) #gate 492\r
+        self.S2_SendData(0xEC)\r
+\r
+        self.M1S1M2S2_SendCommand(0x15)        #DUSPI\r
+        self.M1S1M2S2_SendData(0x20)\r
+\r
+        self.M1S1M2S2_SendCommand(0x30)        # PLL\r
+        self.M1S1M2S2_SendData(0x08)\r
+\r
+        self.M1S1M2S2_SendCommand(0x50)        #Vcom and data interval setting\r
+        self.M1S1M2S2_SendData(0x31)\r
+        self.M1S1M2S2_SendData(0x07)\r
+\r
+        self.M1S1M2S2_SendCommand(0x60)#TCON\r
+        self.M1S1M2S2_SendData(0x22)\r
+\r
+        self.M1_SendCommand(0xE0)                      #POWER SETTING\r
+        self.M1_SendData(0x01)\r
+        self.M2_SendCommand(0xE0)                      #POWER SETTING\r
+        self.M2_SendData(0x01)\r
+\r
+        self.M1S1M2S2_SendCommand(0xE3)\r
+        self.M1S1M2S2_SendData(0x00)\r
+\r
+        self.M1_SendCommand(0x82)\r
+        self.M1_SendData(0x1c)\r
+        self.M2_SendCommand(0x82)\r
+        self.M2_SendData(0x1c)\r
+\r
+        self.SetLut()\r
+        \r
+    def display(self, BlackImage, RedImage):\r
+        start = time.clock()\r
+        \r
+        Blackbuf = [0x00] * int(self.width * self.height / 8)\r
+        blackconvert = BlackImage.convert('1')       \r
+        bimwidth, bimheight = blackconvert.size \r
+        Blackpixles = blackconvert.load()\r
+        temp=0;\r
+        for y in range(0, bimheight):\r
+            for x in range(0, bimwidth):\r
+                if Blackpixles[x, y] < 127:           # black\r
+                    Blackbuf[int((x + y*self.width)/8)] &= ~(0x80>>temp)\r
+                else:                           # white\r
+                    Blackbuf[int((x + y*self.width)/8)] |= (0x80>>temp)\r
+                temp=temp+1\r
+                if(temp==8):\r
+                    temp=0\r
+                    \r
+        Redbuf = [0x00] * int(self.width * self.height / 8)\r
+        redconvert = RedImage.convert('1')\r
+        rimwidth, rimheight = redconvert.size \r
+        Redpixles = redconvert.load()\r
+        temp=0;\r
+        for y in range(0, rimheight):\r
+            for x in range(0, rimwidth):\r
+                if Redpixles[x, y] < 127:           # black\r
+                    Redbuf[int((x + y*self.width)/8)] &= ~(0x80>>temp)\r
+                else:                           # white\r
+                    Redbuf[int((x + y*self.width)/8)] |= (0x80>>temp)\r
+                temp=temp+1\r
+                if(temp==8):\r
+                    temp=0\r
+                    \r
+        #S2 part 648*492\r
+        self.S2_SendCommand(0x10)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(Blackbuf[y*163 + x])\r
+        self.S2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(~Redbuf[y*163 + x])\r
+                \r
+        #M2 part 656*492\r
+        self.M2_SendCommand(0x10)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(Blackbuf[y*163 + x])\r
+        self.M2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(~Redbuf[y*163 + x])\r
+\r
+        #M1 part 648*492    \r
+        self.M1_SendCommand(0x10)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(Blackbuf[y*163 + x])\r
+        self.M1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(~Redbuf[y*163 + x])\r
+        \r
+        #S1 part 656*492\r
+        self.S1_SendCommand(0x10)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(Blackbuf[y*163 + x])\r
+        self.S1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(~Redbuf[y*163 + x])\r
+                \r
+        end = time.clock()\r
+        print("use time: %f"%(end - start))\r
+        self.TurnOnDisplay()\r
+\r
+    def clear(self):\r
+        """Clear contents of image buffer"""\r
+        start = time.clock()\r
+        \r
+        self.S2_SendCommand(0x10)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(0xff)        \r
+        self.S2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(0x00)\r
+                \r
+        self.M2_SendCommand(0x10)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(0xff)\r
+        self.M2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(0x00)       \r
+                    \r
+        self.M1_SendCommand(0x10)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(0xff)\r
+        self.M1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(0x00)\r
+                \r
+        self.S1_SendCommand(0x10)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(0xff)\r
+        self.S1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(0x00)\r
+                \r
+        end = time.clock()\r
+        print (end)\r
+        print (start)\r
+        print("use time: %f" %(end - start))\r
+        \r
+        self.TurnOnDisplay()\r
+        \r
+    def Reset(self):\r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 1) \r
+        time.sleep(0.2) \r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 0) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 0) \r
+        time.sleep(0.01) \r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 1) \r
+        time.sleep(0.2) \r
+    \r
+    def EPD_Sleep(self):\r
+        self.M1S1M2S2_SendCommand(0X02)        \r
+        time.sleep(0.3) \r
+\r
+        self.M1S1M2S2_SendCommand(0X07)        \r
+        self.M1S1M2S2_SendData(0xA5) \r
+        time.sleep(0.3) \r
+        print("module_exit")\r
+        epdconfig.module_exit()\r
+\r
+    def TurnOnDisplay(self):\r
+        self.M1M2_SendCommand(0x04)  \r
+        time.sleep(0.3) \r
+        self.M1S1M2S2_SendCommand(0x12) \r
+        self.M1_ReadBusy()\r
+        self.S1_ReadBusy()\r
+        self.M2_ReadBusy()\r
+        self.S2_ReadBusy()   \r
+        \r
+    """   M1S1M2S2 Write register address and data     """\r
+    def M1S1M2S2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+    \r
+    def M1S1M2S2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+\r
+    """   M1M2 Write register address and data     """\r
+    def M1M2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        \r
+    def M1M2_Sendata(self, val): \r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)   \r
+          \r
+    """   S2 Write register address and data     """\r
+    def S2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+    def S2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+        \r
+    """   M2 Write register address and data     """\r
+    def M2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+    def M2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+\r
+    """   S1 Write register address and data     """\r
+    def S1_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+    def S1_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        \r
+    """   M1 Write register address and data     """\r
+    def M1_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+    def M1_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+\r
+    #Busy\r
+    def M1_ReadBusy(self):\r
+        self.M1_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        while(busy):\r
+            self.M1_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)\r
+    def M2_ReadBusy(self):\r
+        self.M2_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        self.M2_SendCommand(0x71) \r
+        while(busy):\r
+            self.M2_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) \r
+            busy =not(busy & 0x01) \r
+        time.sleep(0.2)\r
+    def S1_ReadBusy(self):\r
+        self.S1_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        while(busy):\r
+            self.S1_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)        \r
+    def S2_ReadBusy(self):\r
+        self.S2_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        while(busy):\r
+            self.S2_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)            \r
+\r
+    lut_vcom1 = [\r
+        0x00,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x00,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x00,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0x00,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    lut_ww1 = [\r
+        0x91,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x04,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x84,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x80,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0x08,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    lut_bw1 = [\r
+        0xA8,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x84,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x84,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x86,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x8C,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x8C,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0xF0,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    lut_wb1 = [\r
+        0x91,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x04,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x84,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x80,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0x08,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    lut_bb1 = [\r
+        0x92,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x80,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x84,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x04,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0x01,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    \r
+    def SetLut(self):\r
+        self.M1S1M2S2_SendCommand(0x20) #vcom\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_vcom1[count])\r
+\r
+        self.M1S1M2S2_SendCommand(0x21) #red not use\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_ww1[count])\r
+\r
+        self.M1S1M2S2_SendCommand(0x22) #bw r\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_bw1[count])   # bw=r\r
+\r
+        self.M1S1M2S2_SendCommand(0x23) #wb w\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_wb1[count])   # wb=w\r
+\r
+        self.M1S1M2S2_SendCommand(0x24) #bb b\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_bb1[count])   # bb=b\r
+            \r
+        self.M1S1M2S2_SendCommand(0x25) #bb b\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_ww1[count])   # bb=b\r
diff --git a/src/drivers/epd12in48b_V2.py b/src/drivers/epd12in48b_V2.py
new file mode 100644 (file)
index 0000000..b6e90a2
--- /dev/null
@@ -0,0 +1,529 @@
+# /*****************************************************************************\r
+# * | File        :      epd12in48b_V2.py\r
+# * | Author      :   Waveshare electrices\r
+# * | Function    :   Hardware underlying interface\r
+# * | Info        :\r
+# *----------------\r
+# * | This version:   V1.0\r
+# * | Date        :   2022-09-14\r
+# * | Info        :   \r
+# ******************************************************************************/\r
+# Permission is hereby granted, free of charge, to any person obtaining a copy\r
+# of this software and associated documnetation files (the "Software"), to deal\r
+# in the Software without restriction, including without limitation the rights\r
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+# copies of the Software, and to permit persons to  whom the Software is\r
+# furished to do so, subject to the following conditions:\r
+#\r
+# The above copyright notice and this permission notice shall be included in\r
+# all copies or substantial portions of the Software.\r
+#\r
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+# THE SOFTWARE.\r
+#\r
+import time\r
+import epdconfig\r
+\r
+EPD_WIDTH       = 1304\r
+EPD_HEIGHT      = 984\r
+\r
+class EPD(object):\r
+    def __init__(self):\r
+        self.width = EPD_WIDTH\r
+        self.height = EPD_HEIGHT\r
+        \r
+        self.EPD_M1_CS_PIN  = epdconfig.EPD_M1_CS_PIN\r
+        self.EPD_S1_CS_PIN  = epdconfig.EPD_S1_CS_PIN\r
+        self.EPD_M2_CS_PIN  = epdconfig.EPD_M2_CS_PIN\r
+        self.EPD_S2_CS_PIN  = epdconfig.EPD_S2_CS_PIN\r
+\r
+        self.EPD_M1S1_DC_PIN  = epdconfig.EPD_M1S1_DC_PIN\r
+        self.EPD_M2S2_DC_PIN  = epdconfig.EPD_M2S2_DC_PIN\r
+\r
+        self.EPD_M1S1_RST_PIN = epdconfig.EPD_M1S1_RST_PIN\r
+        self.EPD_M2S2_RST_PIN = epdconfig.EPD_M2S2_RST_PIN\r
+\r
+        self.EPD_M1_BUSY_PIN  = epdconfig.EPD_M1_BUSY_PIN\r
+        self.EPD_S1_BUSY_PIN  = epdconfig.EPD_S1_BUSY_PIN\r
+        self.EPD_M2_BUSY_PIN  = epdconfig.EPD_M2_BUSY_PIN\r
+        self.EPD_S2_BUSY_PIN  = epdconfig.EPD_S2_BUSY_PIN\r
+\r
+    def Init(self):\r
+        print("EPD init...")\r
+        epdconfig.module_init()\r
+        \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1) \r
+        self.Reset() \r
+\r
+        # panel setting for Clear\r
+        # self.M1_SendCommand(0x00)\r
+        # self.M1_SendData(0x07)       #KW-3f   KWR-2F BWROTP 0f       BWOTP 1f\r
+        # self.S1_SendCommand(0x00)\r
+        # self.S1_SendData(0x07)\r
+        # self.M2_SendCommand(0x00)\r
+        # self.M2_SendData(0x07)\r
+        # self.S2_SendCommand(0x00)\r
+        # self.S2_SendData(0x07)\r
+\r
+        # panel setting for Display\r
+        self.M1_SendCommand(0x00)\r
+        self.M1_SendData(0x0f) #KW-3f   KWR-2F BWROTP 0f       BWOTP 1f\r
+        self.S1_SendCommand(0x00)\r
+        self.S1_SendData(0x0f)\r
+        self.M2_SendCommand(0x00)\r
+        self.M2_SendData(0x03)\r
+        self.S2_SendCommand(0x00)\r
+        self.S2_SendData(0x03)\r
+\r
+        # booster soft start\r
+        self.M1_SendCommand(0x06)\r
+        self.M1_SendData(0x17) #A\r
+        self.M1_SendData(0x17) #B\r
+        self.M1_SendData(0x39) #C\r
+        self.M1_SendData(0x17)\r
+        self.M2_SendCommand(0x06)\r
+        self.M2_SendData(0x17)\r
+        self.M2_SendData(0x17)\r
+        self.M2_SendData(0x39)\r
+        self.M2_SendData(0x17)\r
+\r
+        #resolution setting\r
+        self.M1_SendCommand(0x61)\r
+        self.M1_SendData(0x02)\r
+        self.M1_SendData(0x88) #source 648\r
+        self.M1_SendData(0x01) #gate 492\r
+        self.M1_SendData(0xEC)\r
+        self.S1_SendCommand(0x61)\r
+        self.S1_SendData(0x02)\r
+        self.S1_SendData(0x90) #source 656\r
+        self.S1_SendData(0x01) #gate 492\r
+        self.S1_SendData(0xEC)\r
+        self.M2_SendCommand(0x61)\r
+        self.M2_SendData(0x02)\r
+        self.M2_SendData(0x90) #source 656\r
+        self.M2_SendData(0x01) #gate 492\r
+        self.M2_SendData(0xEC)\r
+        self.S2_SendCommand(0x61)\r
+        self.S2_SendData(0x02)\r
+        self.S2_SendData(0x88) #source 648\r
+        self.S2_SendData(0x01) #gate 492\r
+        self.S2_SendData(0xEC)\r
+\r
+        self.M1S1M2S2_SendCommand(0x15)        #DUSPI\r
+        self.M1S1M2S2_SendData(0x20)\r
+\r
+        self.M1S1M2S2_SendCommand(0x50)        #Vcom and data interval setting\r
+        self.M1S1M2S2_SendData(0x11)\r
+        self.M1S1M2S2_SendData(0x07)\r
+\r
+        self.M1S1M2S2_SendCommand(0x60)#TCON\r
+        self.M1S1M2S2_SendData(0x22)\r
+\r
+        self.M1S1M2S2_SendCommand(0xE3)\r
+        self.M1S1M2S2_SendData(0x00)\r
+\r
+        self.M1_ReadTemperature()\r
+        \r
+    def display(self, BlackImage, RedImage):\r
+        start = time.perf_counter()\r
+        \r
+        Blackbuf = [0x00] * int(self.width * self.height / 8)\r
+        blackconvert = BlackImage.convert('1')       \r
+        bimwidth, bimheight = blackconvert.size \r
+        Blackpixles = blackconvert.load()\r
+        temp=0\r
+        for y in range(0, bimheight):\r
+            for x in range(0, bimwidth):\r
+                if Blackpixles[x, y] < 127:           # black\r
+                    Blackbuf[int((x + y*self.width)/8)] &= ~(0x80>>temp)\r
+                else:                           # white\r
+                    Blackbuf[int((x + y*self.width)/8)] |= (0x80>>temp)\r
+                temp=temp+1\r
+                if(temp==8):\r
+                    temp=0\r
+                    \r
+        Redbuf = [0x00] * int(self.width * self.height / 8)\r
+        redconvert = RedImage.convert('1')\r
+        rimwidth, rimheight = redconvert.size \r
+        Redpixles = redconvert.load()\r
+        temp=0\r
+        for y in range(0, rimheight):\r
+            for x in range(0, rimwidth):\r
+                if Redpixles[x, y] < 127:           # black\r
+                    Redbuf[int((x + y*self.width)/8)] &= ~(0x80>>temp)\r
+                else:                           # white\r
+                    Redbuf[int((x + y*self.width)/8)] |= (0x80>>temp)\r
+                temp=temp+1\r
+                if(temp==8):\r
+                    temp=0\r
+                    \r
+        #S2 part 648*492\r
+        self.S2_SendCommand(0x10)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(Blackbuf[y*163 + x])\r
+        self.S2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(~Redbuf[y*163 + x])\r
+                \r
+        #M2 part 656*492\r
+        self.M2_SendCommand(0x10)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(Blackbuf[y*163 + x])\r
+        self.M2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(~Redbuf[y*163 + x])\r
+\r
+        #M1 part 648*492    \r
+        self.M1_SendCommand(0x10)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(Blackbuf[y*163 + x])\r
+        self.M1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(~Redbuf[y*163 + x])\r
+        \r
+        #S1 part 656*492\r
+        self.S1_SendCommand(0x10)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(Blackbuf[y*163 + x])\r
+        self.S1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(~Redbuf[y*163 + x])\r
+                \r
+        end = time.perf_counter()\r
+        print("use time: %f"%(end - start))\r
+        self.TurnOnDisplay()\r
+\r
+    def clear(self):\r
+        """Clear contents of image buffer"""\r
+        start = time.perf_counter()\r
+        \r
+        self.S2_SendCommand(0x10)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(0xff)        \r
+        self.S2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(0, 81):\r
+                self.S2_SendData(0x00)\r
+                \r
+        self.M2_SendCommand(0x10)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(0xff)\r
+        self.M2_SendCommand(0x13)\r
+        for y in  range(0, 492):\r
+            for x in  range(81, 163):\r
+                self.M2_SendData(0x00)       \r
+                    \r
+        self.M1_SendCommand(0x10)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(0xff)\r
+        self.M1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(0, 81):\r
+                self.M1_SendData(0x00)\r
+                \r
+        self.S1_SendCommand(0x10)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(0xff)\r
+        self.S1_SendCommand(0x13)\r
+        for y in  range(492, 984):\r
+            for x in  range(81, 163):\r
+                self.S1_SendData(0x00)\r
+                \r
+        end = time.perf_counter()\r
+        print (end)\r
+        print (start)\r
+        print("use time: %f" %(end - start))\r
+        \r
+        self.TurnOnDisplay()\r
+        \r
+    def Reset(self):\r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 1) \r
+        time.sleep(0.2) \r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 0) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 0) \r
+        time.sleep(0.01) \r
+        epdconfig.digital_write(self.EPD_M1S1_RST_PIN, 1) \r
+        epdconfig.digital_write(self.EPD_M2S2_RST_PIN, 1) \r
+        time.sleep(0.2) \r
+    \r
+    def EPD_Sleep(self):\r
+        self.M1S1M2S2_SendCommand(0X02)        \r
+        time.sleep(0.3) \r
+\r
+        self.M1S1M2S2_SendCommand(0X07)        \r
+        self.M1S1M2S2_SendData(0xA5) \r
+        time.sleep(0.3) \r
+        print("module_exit")\r
+        epdconfig.module_exit()\r
+\r
+    def TurnOnDisplay(self):\r
+        self.M1M2_SendCommand(0x04)  \r
+        time.sleep(0.3) \r
+        self.M1S1M2S2_SendCommand(0x12) \r
+        self.M1_ReadBusy()\r
+        self.S1_ReadBusy()\r
+        self.M2_ReadBusy()\r
+        self.S2_ReadBusy()   \r
+        \r
+    """   M1S1M2S2 Write register address and data     """\r
+    def M1S1M2S2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+    \r
+    def M1S1M2S2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+\r
+    """   M1M2 Write register address and data     """\r
+    def M1M2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        \r
+    def M1M2_Sendata(self, val): \r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)   \r
+          \r
+    """   S2 Write register address and data     """\r
+    def S2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+    def S2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+        \r
+    """   M2 Write register address and data     """\r
+    def M2_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+    def M2_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M2S2_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val) \r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+\r
+    """   S1 Write register address and data     """\r
+    def S1_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+    def S1_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        \r
+    """   M1 Write register address and data     """\r
+    def M1_SendCommand(self, cmd):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(cmd)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+    def M1_SendData(self, val):\r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.spi_writebyte(val)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+\r
+    #Busy\r
+    def M1_ReadBusy(self):\r
+        self.M1_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        while(busy):\r
+            self.M1_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_M1_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)\r
+    def M2_ReadBusy(self):\r
+        self.M2_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        self.M2_SendCommand(0x71) \r
+        while(busy):\r
+            self.M2_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_M2_BUSY_PIN) \r
+            busy =not(busy & 0x01) \r
+        time.sleep(0.2)\r
+    def S1_ReadBusy(self):\r
+        self.S1_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        while(busy):\r
+            self.S1_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_S1_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)        \r
+    def S2_ReadBusy(self):\r
+        self.S2_SendCommand(0x71) \r
+        busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) \r
+        busy = not(busy & 0x01) \r
+        while(busy):\r
+            self.S2_SendCommand(0x71) \r
+            busy = epdconfig.digital_read(self.EPD_S2_BUSY_PIN) \r
+            busy = not(busy & 0x01) \r
+        time.sleep(0.2)            \r
+\r
+    lut_vcom1 = [\r
+        0x00,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x00,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x00,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0x00,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    lut_ww1 = [\r
+        0x91,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x04,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x84,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x80,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0x08,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    lut_bw1 = [\r
+        0xA8,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x84,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x84,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x86,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x8C,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x8C,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0xF0,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    lut_wb1 = [\r
+        0x91,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x04,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x84,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x80,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0x08,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    lut_bb1 = [\r
+        0x92,  0x10,   0x10,   0x01,   0x08,   0x01,\r
+        0x80,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x84,  0x08,   0x01,   0x08,   0x01,   0x06,\r
+        0x04,  0x06,   0x01,   0x06,   0x01,   0x05,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x06,\r
+        0x00,  0x05,   0x01,   0x1E,   0x0F,   0x01,\r
+        0x01,  0x04,   0x05,   0x08,   0x08,   0x01,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+        0x00,  0x00,   0x00,   0x00,   0x00,   0x00,\r
+    ]\r
+    \r
+    def SetLut(self):\r
+        self.M1S1M2S2_SendCommand(0x20) #vcom\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_vcom1[count])\r
+\r
+        self.M1S1M2S2_SendCommand(0x21) #red not use\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_ww1[count])\r
+\r
+        self.M1S1M2S2_SendCommand(0x22) #bw r\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_bw1[count])   # bw=r\r
+\r
+        self.M1S1M2S2_SendCommand(0x23) #wb w\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_wb1[count])   # wb=w\r
+\r
+        self.M1S1M2S2_SendCommand(0x24) #bb b\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_bb1[count])   # bb=b\r
+            \r
+        self.M1S1M2S2_SendCommand(0x25) #bb b\r
+        for count in range(0, 60):\r
+            self.M1S1M2S2_SendData(self.lut_ww1[count])   # bb=b\r
+\r
+    def M1_ReadTemperature(self):\r
+        self.M1_SendCommand(0x40)\r
+        self.M1_ReadBusy()\r
+        time.sleep(0.3)\r
+        \r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 0)\r
+        epdconfig.digital_write(self.EPD_S1_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_M2_CS_PIN, 1)\r
+        epdconfig.digital_write(self.EPD_S2_CS_PIN, 1)\r
+        \r
+        epdconfig.digital_write(self.EPD_M1S1_DC_PIN, 1)\r
+        time.sleep(0.05)\r
+        \r
+        temp = epdconfig.spi_readbyte(0x00)\r
+        epdconfig.digital_write(self.EPD_M1_CS_PIN, 1)\r
+        \r
+        self.M1S1M2S2_SendCommand(0xE0)\r
+        self.M1S1M2S2_SendData(0x03)\r
+        self.M1S1M2S2_SendCommand(0xE5)\r
+        self.M1S1M2S2_SendData(temp)\r
diff --git a/src/drivers/epd_12_in_48_lib_32bit.so b/src/drivers/epd_12_in_48_lib_32bit.so
new file mode 100644 (file)
index 0000000..acdbb26
Binary files /dev/null and b/src/drivers/epd_12_in_48_lib_32bit.so differ
diff --git a/src/drivers/epd_12_in_48_lib_64bit.so b/src/drivers/epd_12_in_48_lib_64bit.so
new file mode 100644 (file)
index 0000000..ed8ae87
Binary files /dev/null and b/src/drivers/epd_12_in_48_lib_64bit.so differ
diff --git a/src/drivers/epdconfig.py b/src/drivers/epdconfig.py
new file mode 100644 (file)
index 0000000..c321f39
--- /dev/null
@@ -0,0 +1,99 @@
+# /*****************************************************************************\r
+# * | File        :      epdconfig.py\r
+# * | Author      :   Waveshare electrices\r
+# * | Function    :   Hardware underlying interface\r
+# * | Info        :\r
+# *----------------\r
+# * |  This version:   V1.0\r
+# * | Date        :   2019-11-01\r
+# * | Info        :   \r
+# ******************************************************************************/\r
+# Permission is hereby granted, free of charge, to any person obtaining a copy\r
+# of this software and associated documnetation files (the "Software"), to deal\r
+# in the Software without restriction, including without limitation the rights\r
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
+# copies of the Software, and to permit persons to  whom the Software is\r
+# furished to do so, subject to the following conditions:\r
+#\r
+# The above copyright notice and this permission notice shall be included in\r
+# all copies or substantial portions of the Software.\r
+#\r
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
+# THE SOFTWARE.\r
+#\r
+import time\r
+import os\r
+import logging\r
+import sys\r
+\r
+from ctypes import *\r
+\r
+EPD_SCK_PIN   =11\r
+EPD_MOSI_PIN  =10\r
+\r
+EPD_M1_CS_PIN  =8\r
+EPD_S1_CS_PIN  =7\r
+EPD_M2_CS_PIN  =17\r
+EPD_S2_CS_PIN  =18\r
+\r
+EPD_M1S1_DC_PIN  =13\r
+EPD_M2S2_DC_PIN  =22\r
+\r
+EPD_M1S1_RST_PIN =6\r
+EPD_M2S2_RST_PIN =23\r
+\r
+EPD_M1_BUSY_PIN  =5\r
+EPD_S1_BUSY_PIN  =19\r
+EPD_M2_BUSY_PIN  =27\r
+EPD_S2_BUSY_PIN  =24\r
+\r
+find_dirs = [\r
+    os.path.dirname(os.path.realpath(__file__)),\r
+    '/usr/local/lib',\r
+    '/usr/lib',\r
+]\r
+spi = None\r
+for find_dir in find_dirs:\r
+    val = int(os.popen('getconf LONG_BIT').read())\r
+    logging.debug("System is %d bit"%val)\r
+    if val == 64:\r
+        so_filename = os.path.join(find_dir, 'DEV_Config_64.so')\r
+    else:\r
+        so_filename = os.path.join(find_dir, 'DEV_Config_32.so')\r
+    if os.path.exists(so_filename):\r
+        spi = CDLL(so_filename)\r
+        break\r
+if spi is None:\r
+    RuntimeError('Cannot find DEV_Config.so')\r
+\r
+def digital_write(pin, value):\r
+    spi.DEV_Digital_Write(pin, value)\r
+\r
+def digital_read(pin):\r
+    return spi.DEV_Digital_Read(pin)\r
+\r
+def spi_writebyte(value): \r
+    spi.DEV_SPI_WriteByte(value)\r
\r
+def delay_ms(delaytime):\r
+    time.sleep(delaytime / 1000.0)\r
+        \r
+def module_init():\r
+    spi.DEV_ModuleInit()\r
+\r
+def module_exit():\r
+    spi.DEV_ModuleExit()\r
+\r
+\r
+def spi_readbyte(Reg):\r
+    return spi.DEV_SPI_ReadByte(Reg)\r
+    \r
+def delay_ms(delaytime):\r
+    time.sleep(delaytime / 1000.0)\r
+\r
+  
\ No newline at end of file