import sys
import time

import smbus

SEGMENTS_OFF = 0x00
SEGMENT_G    = 0x01
SEGMENT_F    = 0x02
SEGMENT_E    = 0x04
SEGMENT_D    = 0x08
SEGMENT_C    = 0x10
SEGMENT_B    = 0x20
SEGMENT_A    = 0x40
SEGMENT_DOT  = 0x80

DIGIT_0 = SEGMENT_A | SEGMENT_B | SEGMENT_C | SEGMENT_D | SEGMENT_E | SEGMENT_F
DIGIT_1 = SEGMENT_B | SEGMENT_C
DIGIT_2 = SEGMENT_A | SEGMENT_B | SEGMENT_G | SEGMENT_E | SEGMENT_D
DIGIT_3 = SEGMENT_A | SEGMENT_B | SEGMENT_G | SEGMENT_C | SEGMENT_D
DIGIT_4 = SEGMENT_F | SEGMENT_G | SEGMENT_B | SEGMENT_C
DIGIT_5 = SEGMENT_A | SEGMENT_F | SEGMENT_G | SEGMENT_C | SEGMENT_D
DIGIT_6 = SEGMENT_A | SEGMENT_F | SEGMENT_G | SEGMENT_E | SEGMENT_D | SEGMENT_C
DIGIT_7 = SEGMENT_A | SEGMENT_B | SEGMENT_C
DIGIT_8 = SEGMENT_A | SEGMENT_B | SEGMENT_C | SEGMENT_D | SEGMENT_E | SEGMENT_F | SEGMENT_G
DIGIT_9 = SEGMENT_A | SEGMENT_B | SEGMENT_C | SEGMENT_D | SEGMENT_F | SEGMENT_G

class SevenSegmentDisplay(object):

    digit_map = {'0': DIGIT_0,
                 '1': DIGIT_1,
                 '2': DIGIT_2,
                 '3': DIGIT_3,
                 '4': DIGIT_4,
                 '5': DIGIT_5,
                 '6': DIGIT_6,
                 '7': DIGIT_7,
                 '8': DIGIT_8,
                 '9': DIGIT_9}

    def __init__(self):
        self.bus = smbus.SMBus(1)
        self.address = 0x38
        # 2 digits at 9ma sink
        self.bus.write_byte_data(self.address, 0x00, 0x35)

    def segment_test(self):
        print 'Testing segments...'
        self.bus.write_byte_data(self.address, 0x00, 0x3E)
        time.sleep(3)
        self.bus.write_byte_data(self.address, 0x00, 0x35)
        print 'Test complete'

    def read_status(self):
        return bus.read_byte(address)

    def write_digit0(self, pattern):
        self.bus.write_byte_data(self.address, 0x03, pattern)

    def write_digit1(self, pattern):
        self.bus.write_byte_data(self.address, 0x01, pattern)

    def clear(self):
        self.write_digit0(SEGMENTS_OFF)
        self.write_digit1(SEGMENTS_OFF)

    def display_number(self, number):
        str_num = '%02d' % number
        self.write_digit1(self.digit_map[str_num[1]])
        self.write_digit0(self.digit_map[str_num[0]])



def main():
    
    display = SevenSegmentDisplay()

    # segment test
    display.segment_test()

    # blink segment G x20
    for ctr in xrange(20):
        display.clear()
        time.sleep(0.1)
        SEGMENT_G
        display.write_digit1(SEGMENT_G)
        display.write_digit0(SEGMENT_G)
        time.sleep(0.1) 

    # outer snake clockwise, both
    segs = [SEGMENT_F, SEGMENT_A, SEGMENT_B, SEGMENT_C, 
            SEGMENT_D, SEGMENT_E]

    for xtr in xrange(2):
        for segment in segs:
            display.clear()
            display.write_digit1(segment)
            display.write_digit0(segment)
            time.sleep(0.2)

    # outer snake counter clockwise, both
    segs = [SEGMENT_E, SEGMENT_D, SEGMENT_C, SEGMENT_B, 
            SEGMENT_A, SEGMENT_F]

    for xtr in xrange(2):
        for segment in segs:
            display.clear()
            display.write_digit1(segment)
            display.write_digit0(segment)
            time.sleep(0.2)

    # figure 8 both (clockwise start)
    segs = [SEGMENT_G, SEGMENT_F, SEGMENT_A, SEGMENT_B, SEGMENT_G, 
            SEGMENT_E, SEGMENT_D, SEGMENT_C]

    for xtr in xrange(3):
        for segment in segs:
            display.clear()
            display.write_digit1(segment)
            display.write_digit0(segment)
            time.sleep(0.1)

    # figure 8 both (counter clockwise start)
    segs = [SEGMENT_G, SEGMENT_E, SEGMENT_D, SEGMENT_C, SEGMENT_G, 
            SEGMENT_F, SEGMENT_A, SEGMENT_B]

    for xtr in xrange(3):
        for segment in segs:
            display.clear()
            display.write_digit1(segment)
            display.write_digit0(segment)
            time.sleep(0.1)

    # count down
    while True:
        for num in xrange(99, -1, -1):
            display.clear()
            display.display_number(num)
            time.sleep(0.3)

if __name__ == '__main__':
    sys.exit(main())