Browse Source

Added gps and lcd files

Joachim M. Giæver 7 years ago
parent
commit
4d0b47446a
9 changed files with 563 additions and 2 deletions
  1. 0 1
      gps
  2. 0 0
      gps/__init__.py
  3. 206 0
      gps/gps.py
  4. 0 1
      lcd
  5. 0 0
      lcd/__init__.py
  6. 2 0
      lcd/color.py
  7. 41 0
      lcd/constant.py
  8. 99 0
      lcd/font.py
  9. 215 0
      lcd/lcd.py

+ 0 - 1
gps

@@ -1 +0,0 @@
-/home/joachim/Development/INF-3910-3/lopy-fannypack/gps/

+ 0 - 0
gps/__init__.py


+ 206 - 0
gps/gps.py

@@ -0,0 +1,206 @@
+import machine
+import time
+import struct
+
+class NMEA(object):
+    def __init__(self, id):
+        self.__id = str(id)
+
+class Value(object):
+    def __init__(self, v, u, t=(0,0,0.0)):
+        self.__val = float(v)
+        self.__unit = u
+        self.__time = t
+
+    def value(self):
+        return self.__val
+
+    def unit(self):
+        return self.__unit
+
+    def time(self):
+        return self.__time
+
+    def rad(self):
+        return self.__val * math.pi / 180
+
+    def __repr__(self):
+        return "%f %s" % (self.value(), self.unit())
+
+    def __float__(self):
+        return float(self.__val)
+
+class Distance(Value):
+    def __init__(self, v, u, t):
+        super().__init__(v, u, t)
+
+class Position(Value):
+    def __init__(self, v, u, t):
+        super().__init__(v if u in ("N", "E") else -v, u, t)
+
+    def __sub__(self, other):
+        return Position(self.value() - other.value())
+
+class Speed(Value):
+    def __init__(self, v, u, t):
+        super().__init__(v, u, t)
+
+    def to_kmh(self):
+        if self.unit() in ("knot", "N"):
+            return Speed(self.value() * 1.85200, "kmh", self.time())
+        return self
+
+    def to_knot(self):
+        if self.unit() in ("kmh", "K"):
+            return Speed(self.value() / 1.85200, "knot", self.time())
+        return self
+
+class Course(Value):
+    def __init__(self, v, t):
+        super().__init__(v, "D", t)
+
+class Location(object):
+    def __init__(self):
+        self.__valid = False
+        self.__lat = None
+        self.__long = None
+        self.__alt = None
+        self.__height = None
+        self.__speed = None
+        self.__course = None
+        self.__satellites = -1
+
+    def __repr__(self):
+        return "Satelittes: %s, %s\n\tLat/long: %s/%s\n\tAlt/h: %s/%s\n\tSpeed/course: %s/%s" % (
+            self.__satellites, repr(self.__valid),
+            self.__lat, self.__lat,
+            self.__alt, self.__height,
+            self.__speed, self.__course,
+        )
+
+    def set(self, msgid, segment):
+        data = segment.split(",")
+        if msgid == b'$GPGGA':
+            if len(data) >= 6 and data[5] in ("1", "2", "6"):
+                t = self.__time_from_seg(data[0])
+                self.__set_lat(data[1], data[2], t)
+                self.__set_long(data[3], data[4], t)
+
+                if self.__satellites < 0 and self.__seg_set(data, 6):
+                    self.__satellites = int(data[6])
+
+                if self.__seg_set(data, 7):
+                    self.__alt = Distance(data[7], "M", t)
+
+                if self.__seg_set(data, 8):
+                    self.__height = Distance(data[8], "M", t)
+        elif msgid == b'$GPGLL':
+            if len(data) >= 6 and data[5] == "A":
+                t = self.__time_from_seg(data[4])
+                self.__set_lat(data[0], data[1], t)
+                self.__set_long(data[2], data[3], t)
+        elif msgid == b'$GPRMC':
+            if len(data) >= 6 and data[1] == "A":
+                t = self.__time_from_seg(data[0])
+                self.__set_lat(data[2], data[3], t)
+                self.__set_long(data[4], data[5], t)
+                self.__set_speed(data[6], "N", t)
+                self.__set_course(data[7], t)
+        elif msgid == b'$GPVTG':
+            if len(data) >= 7 and data[2] == "T":
+                self.__set_speed(data[4], data[6], (0, 0, 0.0))
+                self.__set_course(data[5], data[0], (0, 0, 0.0))
+        elif msgid == b'$GPGSV':
+            if self.__seg_set(data, 2) and data[0] == data[1]:
+                self.__satellites = int(data[2])
+        elif msgid == b'$GPMSS':
+            pass
+
+        self.__valid = False if self.__lat is None or self.__long is None else True
+
+        return self.valid()
+
+    def valid(self):
+        return self.__valid
+
+    def __seg_set(self, d, i):
+        return len(d) >= (i + 1) and len(d[i]) != 0
+
+    def __set_speed(self, v, u, t):
+        if len(v) == 0:
+            return None
+
+        if self.__speed is None or self.__speed.time() < t:
+            self.__speed = Speed(v, u, t)
+
+    def __set_course(self, v, t):
+
+        if len(v) == 0:
+            return None
+        print("Course", v, t)
+
+        if self.__course is None or self.__course.time() < t:
+            self.__course = Course(v, t)
+
+    def __set_lat(self, v, d, t):
+        if len(v) == 0:
+            return None
+
+        if self.__lat is None or self.__lat.time() < t:
+            self.__lat = Position(float(v[0:2]) + (float(v[2:]) / 60), d, t)
+
+    def __set_long(self, v, d, t):
+        if len(v) == 0:
+            return None
+
+        if self.__long is None or self.__long.time() < t:
+            self.__long = Position(float(v[0:3]) + (float(v[3:]) / 60), d, t)
+
+    def __time_from_seg(self, ts):
+        return (int(ts[0:2]), int(ts[2:4]), float(ts[4:]))
+
+class Data(object):
+    def __init__(self, pins=("P3", "P4"), baud=9600):
+        self.__com = machine.UART(1, pins=pins, baudrate=baud)
+        self.__location = None
+        self.__last_update = time.time()
+
+    def new_location(self, ttw=5):
+        
+        if time.time() - (self.__last_update + ttw) < 0:
+            return False
+
+        self.__data = Location()
+        data = []
+
+        while self.__com.any():
+            tmp_data = self.__com.readline()
+
+            if tmp_data[0:1] == b'$':
+                self.__update(data)
+                data = [tmp_data]
+            elif len(data) != 0:
+                data.append(tmp_data)
+        else:
+            self.__update(data)
+        
+        return self.__data.valid()
+
+    def get_location(self):
+        return self.__data
+
+    def __update(self, data):
+
+        if len(data) == 0:
+            return False
+
+        data = b''.join(data)
+
+        if data[len(data)-1:len(data)] not in (b'\n', b'\r'):
+            return False
+
+        if data[len(data)-1:len(data)] != b'\n':
+            data += '\n'
+
+        if self.__data.set(data[0:6], ("%s" % (data[7:len(data)-2],))[2:-1]):
+            self.__last_update = time.time()

+ 0 - 1
lcd

@@ -1 +0,0 @@
-/home/joachim/Development/INF-3910-3/lopy-fannypack/lcd/

+ 0 - 0
lcd/__init__.py


+ 2 - 0
lcd/color.py

@@ -0,0 +1,2 @@
+BLACK = 0x0
+WHITE = 0x1

+ 41 - 0
lcd/constant.py

@@ -0,0 +1,41 @@
+# LCD TYPES
+I2CBAUDRATE=100000
+I2C128x32 = {'width': 128, 'height': 32}
+I2C128x64 = {'width': 128, 'height': 64}
+
+# LCD Control constants
+SSD1306_I2C_ADDRESS = 0x3C  
+SSD1306_SETCONTRAST = 0x81
+SSD1306_DISPLAYALLON_RESUME = 0xA4
+SSD1306_DISPLAYALLON = 0xA5
+SSD1306_NORMALDISPLAY = 0xA6
+SSD1306_INVERTDISPLAY = 0xA7
+SSD1306_DISPLAYOFF = 0xAE
+SSD1306_DISPLAYON = 0xAF
+SSD1306_SETDISPLAYOFFSET = 0xD3
+SSD1306_SETCOMPINS = 0xDA
+SSD1306_SETVCOMDETECT = 0xDB
+SSD1306_SETDISPLAYCLOCKDIV = 0xD5
+SSD1306_SETPRECHARGE = 0xD9
+SSD1306_SETMULTIPLEX = 0xA8
+SSD1306_SETLOWCOLUMN = 0x00
+SSD1306_SETHIGHCOLUMN = 0x10
+SSD1306_SETSTARTLINE = 0x40
+SSD1306_MEMORYMODE = 0x20
+SSD1306_COLUMNADDR = 0x21
+SSD1306_PAGEADDR = 0x22
+SSD1306_COMSCANINC = 0xC0
+SSD1306_COMSCANDEC = 0xC8
+SSD1306_SEGREMAP = 0xA0
+SSD1306_CHARGEPUMP = 0x8D
+SSD1306_EXTERNALVCC = 0x1
+SSD1306_SWITCHCAPVCC = 0x2
+
+# Scrolling constants
+SSD1306_ACTIVATE_SCROLL = 0x2F
+SSD1306_DEACTIVATE_SCROLL = 0x2E
+SSD1306_SET_VERTICAL_SCROLL_AREA = 0xA3
+SSD1306_RIGHT_HORIZONTAL_SCROLL = 0x26
+SSD1306_LEFT_HORIZONTAL_SCROLL = 0x27
+SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL = 0x29
+SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL = 0x2A

+ 99 - 0
lcd/font.py

@@ -0,0 +1,99 @@
+# Standard ASCII 5x7 font from <gldfont.c> in Adafruit GFX lib.
+ASCII = {'width': 5, 'height': 7, 'value': [
+    0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x5F, 0x00, 0x00,
+    0x00, 0x07, 0x00, 0x07, 0x00,
+    0x14, 0x7F, 0x14, 0x7F, 0x14,
+    0x24, 0x2A, 0x7F, 0x2A, 0x12,
+    0x23, 0x13, 0x08, 0x64, 0x62,
+    0x36, 0x49, 0x56, 0x20, 0x50,
+    0x00, 0x08, 0x07, 0x03, 0x00,
+    0x00, 0x1C, 0x22, 0x41, 0x00,
+    0x00, 0x41, 0x22, 0x1C, 0x00,
+    0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
+    0x08, 0x08, 0x3E, 0x08, 0x08,
+    0x00, 0x80, 0x70, 0x30, 0x00,
+    0x08, 0x08, 0x08, 0x08, 0x08,
+    0x00, 0x00, 0x60, 0x60, 0x00,
+    0x20, 0x10, 0x08, 0x04, 0x02,
+    0x3E, 0x51, 0x49, 0x45, 0x3E,
+    0x00, 0x42, 0x7F, 0x40, 0x00,
+    0x72, 0x49, 0x49, 0x49, 0x46,
+    0x21, 0x41, 0x49, 0x4D, 0x33,
+    0x18, 0x14, 0x12, 0x7F, 0x10,
+    0x27, 0x45, 0x45, 0x45, 0x39,
+    0x3C, 0x4A, 0x49, 0x49, 0x31,
+    0x41, 0x21, 0x11, 0x09, 0x07,
+    0x36, 0x49, 0x49, 0x49, 0x36,
+    0x46, 0x49, 0x49, 0x29, 0x1E,
+    0x00, 0x00, 0x14, 0x00, 0x00,
+    0x00, 0x40, 0x34, 0x00, 0x00,
+    0x00, 0x08, 0x14, 0x22, 0x41,
+    0x14, 0x14, 0x14, 0x14, 0x14,
+    0x00, 0x41, 0x22, 0x14, 0x08,
+    0x02, 0x01, 0x59, 0x09, 0x06,
+    0x3E, 0x41, 0x5D, 0x59, 0x4E,
+    0x7C, 0x12, 0x11, 0x12, 0x7C,
+    0x7F, 0x49, 0x49, 0x49, 0x36,
+    0x3E, 0x41, 0x41, 0x41, 0x22,
+    0x7F, 0x41, 0x41, 0x41, 0x3E,
+    0x7F, 0x49, 0x49, 0x49, 0x41,
+    0x7F, 0x09, 0x09, 0x09, 0x01,
+    0x3E, 0x41, 0x41, 0x51, 0x73,
+    0x7F, 0x08, 0x08, 0x08, 0x7F,
+    0x00, 0x41, 0x7F, 0x41, 0x00,
+    0x20, 0x40, 0x41, 0x3F, 0x01,
+    0x7F, 0x08, 0x14, 0x22, 0x41,
+    0x7F, 0x40, 0x40, 0x40, 0x40,
+    0x7F, 0x02, 0x1C, 0x02, 0x7F,
+    0x7F, 0x04, 0x08, 0x10, 0x7F,
+    0x3E, 0x41, 0x41, 0x41, 0x3E,
+    0x7F, 0x09, 0x09, 0x09, 0x06,
+    0x3E, 0x41, 0x51, 0x21, 0x5E,
+    0x7F, 0x09, 0x19, 0x29, 0x46,
+    0x26, 0x49, 0x49, 0x49, 0x32,
+    0x03, 0x01, 0x7F, 0x01, 0x03,
+    0x3F, 0x40, 0x40, 0x40, 0x3F,
+    0x1F, 0x20, 0x40, 0x20, 0x1F,
+    0x3F, 0x40, 0x38, 0x40, 0x3F,
+    0x63, 0x14, 0x08, 0x14, 0x63,
+    0x03, 0x04, 0x78, 0x04, 0x03,
+    0x61, 0x59, 0x49, 0x4D, 0x43,
+    0x00, 0x7F, 0x41, 0x41, 0x41,
+    0x02, 0x04, 0x08, 0x10, 0x20,
+    0x00, 0x41, 0x41, 0x41, 0x7F,
+    0x04, 0x02, 0x01, 0x02, 0x04,
+    0x40, 0x40, 0x40, 0x40, 0x40,
+    0x00, 0x03, 0x07, 0x08, 0x00,
+    0x20, 0x54, 0x54, 0x78, 0x40,
+    0x7F, 0x28, 0x44, 0x44, 0x38,
+    0x38, 0x44, 0x44, 0x44, 0x28,
+    0x38, 0x44, 0x44, 0x28, 0x7F,
+    0x38, 0x54, 0x54, 0x54, 0x18,
+    0x00, 0x08, 0x7E, 0x09, 0x02,
+    0x18, 0xA4, 0xA4, 0x9C, 0x78,
+    0x7F, 0x08, 0x04, 0x04, 0x78,
+    0x00, 0x44, 0x7D, 0x40, 0x00,
+    0x20, 0x40, 0x40, 0x3D, 0x00,
+    0x7F, 0x10, 0x28, 0x44, 0x00,
+    0x00, 0x41, 0x7F, 0x40, 0x00,
+    0x7C, 0x04, 0x78, 0x04, 0x78,
+    0x7C, 0x08, 0x04, 0x04, 0x78,
+    0x38, 0x44, 0x44, 0x44, 0x38,
+    0xFC, 0x18, 0x24, 0x24, 0x18,
+    0x18, 0x24, 0x24, 0x18, 0xFC,
+    0x7C, 0x08, 0x04, 0x04, 0x08,
+    0x48, 0x54, 0x54, 0x54, 0x24,
+    0x04, 0x04, 0x3F, 0x44, 0x24,
+    0x3C, 0x40, 0x40, 0x20, 0x7C,
+    0x1C, 0x20, 0x40, 0x20, 0x1C,
+    0x3C, 0x40, 0x30, 0x40, 0x3C,
+    0x44, 0x28, 0x10, 0x28, 0x44,
+    0x4C, 0x90, 0x90, 0x90, 0x7C,
+    0x44, 0x64, 0x54, 0x4C, 0x44,
+    0x00, 0x08, 0x36, 0x41, 0x00,
+    0x00, 0x00, 0x77, 0x00, 0x00,
+    0x00, 0x41, 0x36, 0x08, 0x00,
+    0x02, 0x01, 0x02, 0x04, 0x02,
+    0x3C, 0x26, 0x23, 0x26, 0x3C
+]}

+ 215 - 0
lcd/lcd.py

@@ -0,0 +1,215 @@
+import gc
+from machine import I2C
+from lcd import color, constant, font
+
+class LCD(object):
+    def __init__(self, dt=constant.I2C128x64, baud=constant.I2CBAUDRATE):
+        self.__width = int(dt['width'] if 'width' in dt else 0)
+        self.__height = int(dt['height'] if 'height' in dt else 0)
+        self.__pages = int(self.__height / 8)
+        self.__buff_size = int(self.__width * self.__height / 8)
+        self.__buffer = [0] * self.__buff_size
+
+        self.__i2c = I2C(0, I2C.MASTER, baudrate=baud)
+        
+        self.__write(constant.SSD1306_DISPLAYOFF)
+        self.__write(constant.SSD1306_SETDISPLAYCLOCKDIV, 0x80)
+        self.__write(constant.SSD1306_SETDISPLAYOFFSET, 0x0)
+        self.__write(constant.SSD1306_SETSTARTLINE | 0x0)
+        self.__write(constant.SSD1306_CHARGEPUMP, 0x14)
+        self.__write(constant.SSD1306_MEMORYMODE, 0x00)
+        self.__write(constant.SSD1306_COLUMNADDR, 0, self.__width - 1)
+        self.__write(constant.SSD1306_PAGEADDR, 0, self.__pages - 1)
+        self.__write(constant.SSD1306_SEGREMAP | 0x1)
+        self.__write(constant.SSD1306_COMSCANDEC)
+        self.__write(constant.SSD1306_SETPRECHARGE, 0xF1)
+        self.__write(constant.SSD1306_SETVCOMDETECT, 0x40)
+        self.__write(constant.SSD1306_DISPLAYALLON_RESUME)
+        self.__write(constant.SSD1306_NORMALDISPLAY)
+
+        if dt == constant.I2C128x32:
+            self.__write(constant.SSD1306_SETMULTIPLEX, 0x1F)
+            self.__write(constant.SSD1306_SETCOMPINS, 0x02)
+            self.__write(constant.SSD1306_SETCONTRAST, 0x8F)
+        elif dt == constant.I2C128x64:
+            self.__write(constant.SSD1306_SETMULTIPLEX, 0x3F)
+            self.__write(constant.SSD1306_SETCOMPINS, 0x12)
+            self.__write(constant.SSD1306_SETCONTRAST, 0xCF)
+        else:
+            raise NotImplementedError
+
+        self.display_clear(True)
+        self.display_off()
+
+    def __write(self, *args):
+
+        b = [0]
+        if len(args) == 1 and type(args[0]) == bytearray:
+            b = args[0]
+        else:
+            b = bytearray(b + list(args))
+
+        self.__i2c.writeto(constant.SSD1306_I2C_ADDRESS, b)
+        gc.collect()
+
+    def display_contrast(self, c):
+        if c < 0 or c > 255:
+            raise ValueError("Contrast must be between 0-255")
+        self.__write(constant.SSD1306_SETCONTRAST, c)
+
+    def display_off(self):
+        self.__write(constant.SSD1306_DISPLAYOFF)
+
+    def display_on(self):
+        self.__write(constant.SSD1306_DISPLAYON)
+
+    def display_clear(self, update=False):
+        self.__buffer = [0] * self.__buff_size
+
+        if update:
+            self.display_update()
+    
+    def draw_px(self, x, y, clr=color.WHITE):
+        pos = int(y / 8) * self.__width + x
+        bm = (0x1 << (y % 8))
+        bpos = self.__buffer[pos]
+        self.__buffer[pos] = bpos | bm if clr == color.WHITE else bpos & (0xff ^ bm) 
+
+    
+    def draw_line(self, x0, y0, x1, y1, clr=color.WHITE):
+        if x0 == x1:
+            self.__draw_v_line(x0, y0, abs(y1 - y0), clr)
+        elif y0 == y1:
+            self.__draw_h_line(x0, y0, abs(x1 - x0), clr)
+        else:
+            self.__draw_line(x0, y0, x1, y1, clr)
+
+    def __draw_line(self, x0, y0, x1, y1, clr):
+        steep = abs(y1 - y0) > abs(x1 - x0)
+        if steep:
+            x0, y0 = y0, x0
+            x1, y1 = y1, x1
+
+        if x0 > x1:
+            x0, x1 = x1, x0
+            y0, y1 = y1, y0
+
+        dx = abs(x1 - x0)
+        dy = abs(y1 - y0)
+
+        err = dx / 2
+        ystep = 1 if y0 < y1 else -1
+        y = y0
+
+        for x in range(x0, x1):
+            if steep:
+                self.draw_px(y, x, clr)
+            else:
+                self.draw_px(x, y, clr)
+            err = err - dy
+            if err < 0:
+                y += ystep
+                err += dx
+
+    def __draw_v_line(self, x, y, h, clr):
+        for y1 in range(y, y + h):
+            self.draw_px(x, y1, clr)
+
+    def __draw_h_line(self, x, y, w, clr):
+        for x1 in range(x, x + w):
+            self.draw_px(x1, y, clr)
+
+    def __bresenham_plot(self, x, d1, y, d2, clr):
+        self.draw_px(x + d1, y + d2)
+        self.draw_px(x + d1, y - d2)
+        self.draw_px(x - d1, y + d2)
+        self.draw_px(x - d1, y - d2)
+        self.draw_px(x + d2, y + d1)
+        self.draw_px(x + d2, y - d1)
+        self.draw_px(x - d2, y + d1)
+        self.draw_px(x - d2, y - d1)
+
+    def __bresenham_line(self, x, d1, y, d2, clr):
+        self.__draw_v_line(x + d1, y - d2, 2 * d2, clr)
+        self.__draw_v_line(x + d2, y - d1, 2 * d1, clr)
+        self.__draw_v_line(x - d1, y - d2, 2 * d2, clr)
+        self.__draw_v_line(x - d2, y - d1, 2 * d1, clr)
+
+    def draw_circle(self, x0, y0, r, clr=color.WHITE):
+        x = r
+        y = 0
+        err = 0
+
+        while x >= y:
+            self.__bresenham_plot(x0, x, y0, y, clr)
+            if err <= 0:
+                y += 1
+                err += (2 * y) + 1
+            else:
+                x -= 1
+                err -= (2 * x) + 1
+
+    def draw_rect(self, x, y, w, h, clr=color.WHITE):
+        self.__draw_h_line(x, y, w, clr)
+        self.__draw_h_line(x, y + h, w, clr)
+        self.__draw_v_line(x, y, h, clr)
+        self.__draw_v_line(x + w, y, h, clr)
+
+    def fill_circle(self, x0, y0, r, clr=color.WHITE):
+        x = r
+        y = 0
+        err = 0
+        while x >= y:
+            self.__bresenham_line(x0, x, y0, y, clr)
+            if err <= 0:
+                y += 1
+                err += (2 * y) + 1
+            else:
+                x -= 1
+                err -= (2 * x) + 1
+
+    def fill_rect(self, x, y, w, h, clr=color.WHITE):
+        for i in range(x, x+w):
+            self.__draw_v_line(i, y, h, clr)
+
+    def fill_screen(self, clr=color.WHITE):
+        self.fill_rect(0, 0, self.__width, self.__height, clr)
+
+    def invert_colors(self):
+        for i in range(0, len(self.__buffer)):
+            self.__buffer[i] = ~self.__buffer[i]
+
+    def draw_string(self, x, y, s, f=font.ASCII, clr=color.WHITE):
+        mx = int(self.__width / (f['width'] + 1))
+        my = int(self.__height / (f['height'] + 1))
+
+        if x < 0 or (x + len(s)) > mx:
+            raise ValueError("Out of X range")
+
+        if y < 0 or y > my:
+            raise ValueError("Out of Y range")
+
+        pos = (self.__width) * y + ((f['width'] + 1)  * x)
+        for i in range(0, len(s)):
+            c = 5 * (ord(s[i]) - 32)
+            for p in range(0, f['width']):
+                self.__buffer[pos + p] = f['value'][c + p]
+            pos = pos + 6
+
+    def display_text_mid_x(self, l, f=font.ASCII):
+        mx = int(self.__width / (f['width'] + 1))
+        return int((mx - l) / 2)
+
+    def display_text_mid_y(self, f=font.ASCII):
+        my = int(self.__height / (f['height'] + 1))
+        return int(my / 2)
+    def display_update(self):
+        self.__write(constant.SSD1306_SETLOWCOLUMN)
+        self.__write(constant.SSD1306_SETHIGHCOLUMN)
+        self.__write(constant.SSD1306_SETSTARTLINE)
+        line = [0] * 17
+        line[0] = 0x40
+        for i in range(0, len(self.__buffer), 16):
+            for pos in range(0, 16):
+                line[pos + 1] = self.__buffer[pos + i]
+            self.__write(bytearray(line))