#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

import serial
import struct
from time import sleep
from sys import argv

font = []
font += [ 0x00, 0x38, 0x44, 0x44, 0x44, 0x44, 0x38, 0x00] # /* 0 */
font += [ 0x00, 0x08, 0x38, 0x08, 0x08, 0x08, 0x08, 0x00] # /* 1 */
font += [ 0x00, 0x38, 0x44, 0x08, 0x10, 0x20, 0x7C, 0x00] # /* 2 */
font += [ 0x00, 0x38, 0x44, 0x18, 0x04, 0x44, 0x38, 0x00] # /* 3 */
font += [ 0x00, 0x08, 0x18, 0x28, 0x48, 0x7C, 0x08, 0x00] # /* 4 */
font += [ 0x00, 0x7C, 0x40, 0x78, 0x04, 0x44, 0x38, 0x00] # /* 5 */
font += [ 0x00, 0x38, 0x40, 0x78, 0x44, 0x44, 0x38, 0x00] # /* 6 */
font += [ 0x00, 0x7C, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00] # /* 7 */
font += [ 0x00, 0x38, 0x44, 0x38, 0x44, 0x44, 0x38, 0x00] # /* 8 */
font += [ 0x00, 0x38, 0x44, 0x44, 0x3C, 0x04, 0x38, 0x00] # /* 9 */
font += [ 0x00, 0x30, 0x48, 0x84, 0xFC, 0x84, 0x84, 0x00] # /* A */
font += [ 0x00, 0xF8, 0x84, 0xF8, 0x84, 0x84, 0xF8, 0x00] # /* B */
font += [ 0x00, 0x78, 0x84, 0x80, 0x80, 0x84, 0x78, 0x00] # /* C */
font += [ 0x00, 0xF8, 0x84, 0x84, 0x84, 0x84, 0xF8, 0x00] # /* D */
font += [ 0x00, 0xFC, 0x80, 0xF8, 0x80, 0x80, 0xFC, 0x00] # /* E */
font += [ 0x00, 0xFC, 0x80, 0xF8, 0x80, 0x80, 0x80, 0x00] # /* F */
font += [ 0x00, 0x78, 0x84, 0x80, 0x9C, 0x84, 0x7C, 0x00] # /* G */
font += [ 0x00, 0x84, 0x84, 0xFC, 0x84, 0x84, 0x84, 0x00] # /* H */
font += [ 0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00] # /* I */
font += [ 0x00, 0x1C, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00] # /* J */
font += [ 0x00, 0x88, 0x90, 0xA0, 0xD0, 0x88, 0x84, 0x00] # /* K */
font += [ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFC, 0x00] # /* L */
font += [ 0x00, 0x84, 0xCC, 0xB4, 0x84, 0x84, 0x84, 0x00] # /* M */
font += [ 0x00, 0x84, 0xC4, 0xA4, 0x94, 0x8C, 0x84, 0x00] # /* N */
font += [ 0x00, 0x78, 0x84, 0x84, 0x84, 0x84, 0x78, 0x00] # /* O */
font += [ 0x00, 0xF8, 0x84, 0x84, 0xF8, 0x80, 0x80, 0x00] # /* P */
font += [ 0x00, 0x78, 0x84, 0x84, 0x84, 0x94, 0x78, 0x04] # /* Q */
font += [ 0x00, 0xF8, 0x84, 0x84, 0xF8, 0x88, 0x84, 0x00] # /* R */
font += [ 0x00, 0x78, 0x84, 0x60, 0x18, 0x84, 0x78, 0x00] # /* S */
font += [ 0x00, 0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00] # /* T */
font += [ 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, 0x78, 0x00] # /* U */
font += [ 0x00, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x00] # /* V */
font += [ 0x00, 0x82, 0x82, 0x92, 0xAA, 0x44, 0x44, 0x00] # /* W */
font += [ 0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x00] # /* X */
font += [ 0x00, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x00] # /* Y */
font += [ 0x00, 0xFC, 0x08, 0x10, 0x20, 0x40, 0xFC, 0x00] # /* Z */


class ColorduinoPutChar():
  "Print a character on Colorduino LED matrix."
  def __init__(self, device='/dev/ttyUSB1', speed=19200):
    #print 'ColorduinoPutChar: device =' , device , ', speed =' , speed
    self.display = serial.Serial(device, speed, timeout=1)

  def SwitchMode(self):
    "Switch Colorduino in frame buffer mode."
    frame = []
    frame += [ 0xaa ]
    frame += [ 0x04 ]
    frame += [ 1 ]
    frame += [ 2 ]
    
    csum = 0
    for c in frame[1:len(frame)]:
      csum += c
    
    frame += [ csum & 0xFF ]
    
    #print frame
    
    pkt=struct.pack('B'*len(frame),*frame)
    
    self.display.write(pkt)
    
    rval = self.display.read(1)
    
    toHex = lambda x:"".join([hex(ord(c))[2:].zfill(2) for c in x])
    
    #print toHex(rval)

  def PutChar(self, char, color):
    "Switch Colorduino in frame buffer mode."

    display = []
    for i in range (8, 0, -1):
      line = font[char * 8 + i]
      for j in range (8, 0, -1):
        bit = (line >> j) & 0x1
        if (bit == 1):
          if (color == 1):
            display += [0xFF0000]
          elif (color == 2):
            display += [0x00FF00]
          elif (color == 3):
            display += [0x0000FF]
          else:
            display += [0xFFFFFF]
        else:
          display += [0x000000]
  
    frame  = []
    frame += [ 0xaa ]
    frame += [ 0x02 ]
    frame += [ 96 ]
    
    rest = 0
    for i in range(len(display)):
      pixel = display[i]
      r = (pixel >> 16)
      g = (pixel >> 8) & 0xFF
      b = pixel & 0xFF
      r4 = r >> 4
      g4 = g >> 4
      b4 = b >> 4
      if ((i & 1) == 0):
        frame += [(r4 << 4) | g4]
        rest = b4
      else:
        frame += [(rest << 4) | r4]
        frame += [(g4 << 4) | b4]
    
    csum = 0
    for c in frame[1:len(frame)]:
      csum += c
    
    frame += [ csum & 0xFF ]
    
    #print frame
    
    pkt=struct.pack('B'*len(frame),*frame)
    
    self.display.write(pkt)
    
    rval = self.display.read(1)
  
    #print toHex(rval)
  
    #sleep(1)


if __name__ == '__main__':

  opts = { }

  argc = len(argv)

  if argc > 1:
    symbol      = int(argv[1])

  if argc > 2:
    color      = int(argv[2])

  if argc > 3:
    opts["device"]    = argv[3]
  
  if argc > 4:
    opts["speed"]    = int(argv[4])



  session = ColorduinoPutChar(**opts)

  session.SwitchMode()

  session.PutChar(symbol, color)

  #display.close()
