Exemple #1
0
    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip (required)")
            return

        self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
        except:
            print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            return

        for i in range(config.LED_ROWS*config.LED_COLS):
            r, g, b = colorsys.hsv_to_rgb(1.0*i/(config.LED_ROWS*config.LED_COLS), 1, 0.1)
            self.rainbow[i] = (int(r*255), int(g*255), int(b*255))

        self.okay = True

        self.update_frame_rate()
        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         self.frame_rendered)
Exemple #2
0
    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip (required)")
            return

        self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
        except:
            print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            return

        self.kp = KeyPress(self.ipcon)
        self.display = TetrisSegmentDisplay(self.ipcon)
        self.speaker = TetrisSpeaker(self.ipcon)

        self.okay = True

        self.led_strip.set_frame_duration(40)
        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         self.frame_rendered)

        self.init_game()
Exemple #3
0
    def __init__(self, ipcon):
        self.letter_table = {}

        for form in letter_forms:
            if '|' in form:
                self.letter_table[form[-2]] = form[:-3].split('|')

        self.set_new_text('Starter Kit: Blinkenlights')

        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip (required)")
            return

        self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            print("Found: LED Strip ({0})").format(config.UID_LED_STRIP_BRICKLET)
        except:
            print("Not Found: LED Strip ({0})").format(config.UID_LED_STRIP_BRICKLET)
            return

        self.okay = True

        self.update_frame_rate()
        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         self.frame_rendered)
Exemple #4
0
    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip or LED Strip V2 (required)")
            return

        if not config.IS_LED_STRIP_V2:
            self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)
        else:
            self.led_strip = LEDStripV2(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            if not config.IS_LED_STRIP_V2:
                print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            else:
                print("Found: LED Strip V2 ({0})".format(config.UID_LED_STRIP_BRICKLET))
        except:
            if not config.IS_LED_STRIP_V2:
                print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            else:
                print("Not Found: LED Strip V2({0})".format(config.UID_LED_STRIP_BRICKLET))
            return

        self.kp = KeyPress(self.ipcon)
        self.speaker = PongSpeaker(self.ipcon)

        self.okay = True

        self.led_strip.set_frame_duration(40)

        if not config.IS_LED_STRIP_V2:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                             self.frame_rendered)
        else:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED,
                                             self.frame_rendered)

        self.led_strip.set_channel_mapping(config.CHANNEL_MAPPING)
        self.init_game()
Exemple #5
0
    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print('Not Configured: LED Strip (required)')
            return

        self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            print('Found: LED Strip ({0})'.format(config.UID_LED_STRIP_BRICKLET))
        except:
            print('Not Found: LED Strip ({0})'.format(config.UID_LED_STRIP_BRICKLET))
            return

        self.okay = True

        self.update_frame_rate()
        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         self.frame_rendered)
Exemple #6
0
class Fire:
    values = [
        [ 32,  16,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  16,  32],
        [ 64,  32,  16,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  16,  32,  64],
        [ 96,  64,  32,  32,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,  32,  32,  64,  96],
        [128,  96,  64,  64,  32,  32,   0,   0,   0,   0,   0,   0,   0,   0,  32,  32,  64,  64,  96, 128],
        [160, 128,  96,  96,  64,  64,  32,  32,   0,   0,   0,   0,  32,  32,  64,  64,  96,  96, 128, 160],
        [192, 160, 128, 128,  96,  96,  64,  64,  32,   0,   0,  32,  64,  64,  96,  96, 128, 128, 160, 192],
        [255, 192, 160, 160, 128, 128,  96,  96,  64,  32,  32,  64,  96,  96, 128, 128, 160, 160, 192, 255],
        [255, 255, 192, 192, 160, 160, 128, 128,  96,  64,  64,  96, 128, 128, 160, 160, 192, 192, 255, 255],
        [255, 255, 255, 255, 192, 192, 160, 160, 128,  96,  96, 128, 160, 160, 192, 192, 255, 255, 255, 255],
        [255, 255, 255, 255, 255, 255, 192, 192, 160, 128, 128, 160, 192, 192, 255, 255, 255, 255, 255, 255]
    ]

    hues = [
        [1, 3, 4, 5, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 6, 4, 3, 1],
        [1, 2, 3, 3, 5, 6, 7, 7, 8, 8, 8, 8, 9, 9, 8, 7, 5, 3, 2, 1],
        [1, 2, 3, 3, 5, 5, 6, 6, 5, 6, 6, 7, 7, 7, 6, 6, 4, 3, 2, 1],
        [1, 1, 2, 3, 4, 4, 5, 5, 4, 4, 5, 5, 6, 5, 5, 5, 3, 2, 1, 1],
        [1, 1, 2, 2, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 2, 2, 1, 1],
        [0, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 1, 1, 0, 0],
        [0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    ]

#    values = [
#        [ 32,   0,   0,   0,   0,   0,   0,   0,   0,  32],
#        [ 64,   0,   0,   0,   0,   0,   0,   0,   0,  64],
#        [ 96,  32,   0,   0,   0,   0,   0,   0,  32,  96],
#        [128,  64,  32,   0,   0,   0,   0,  32,  64, 128],
#        [160,  96,  64,  32,   0,   0,  32,  64,  96, 160],
#        [192, 128,  96,  64,  32,  32,  64,  96, 128, 192],
#        [255, 160, 128,  96,  64,  64,  96, 128, 160, 255],
#        [255, 192, 160, 128,  96,  96, 128, 160, 192, 255],
#        [255, 255, 192, 160, 128, 128, 160, 192, 255, 255],
#        [255, 255, 255, 192, 160, 160, 192, 255, 255, 255]
#    ]

#    hues = [
#        [1, 4, 7, 9, 9, 9, 9, 8, 4, 1],
#        [1, 3, 5, 7, 8, 8, 9, 7, 3, 1],
#        [1, 3, 5, 6, 5, 6, 7, 6, 3, 1],
#        [1, 2, 4, 5, 4, 5, 5, 5, 2, 1],
#        [1, 2, 4, 4, 4, 5, 4, 4, 2, 1],
#        [0, 1, 2, 3, 3, 3, 3, 2, 1, 0],
#        [0, 0, 1, 2, 2, 2, 2, 1, 0, 0],
#        [0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
#        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
#    ]

    line = [0]*config.LED_ROWS
    matrix = [x[:] for x in [[0]*config.LED_COLS]*config.LED_ROWS]
    leds = [x[:] for x in [[(0, 0, 0)]*config.LED_COLS]*config.LED_ROWS]
    percent = 0

    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip or LED Strip V2 (required)")
            return

        if not config.IS_LED_STRIP_V2:
            self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)
        else:
            self.led_strip = LEDStripV2(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            if not config.IS_LED_STRIP_V2:
                print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            else:
                print("Found: LED Strip V2 ({0})".format(config.UID_LED_STRIP_BRICKLET))
        except:
            if not config.IS_LED_STRIP_V2:
                print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            else:
                print("Not Found: LED Strip V2({0})".format(config.UID_LED_STRIP_BRICKLET))
            return

        self.okay = True

        self.update_frame_rate()
        if not config.IS_LED_STRIP_V2:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                             self.frame_rendered)
        else:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED,
                                             self.frame_rendered)

        self.led_strip.set_channel_mapping(config.CHANNEL_MAPPING)
    def stop_rendering(self):
        if not self.okay:
            return

        if not config.IS_LED_STRIP_V2:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                             None)
        else:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED,
                                             None)

    def update_frame_rate(self):
        if not self.okay:
            return

        self.led_strip.set_frame_duration(int(1000.0 / config.FIRE_FRAME_RATE))

    def frame_rendered(self, _):
        self.frame_upload()
        self.frame_prepare_next()

    def frame_upload(self):
        if not self.okay:
            return

        # Reorder LED data into R, G and B channel
        r = []
        g = []
        b = []
        frame = []

        for row in range(config.LED_ROWS):
            col_range = range(config.LED_COLS)
            if row % 2 == 0:
                col_range = reversed(col_range)
            for col in col_range:
                r.append(self.leds[row][col][0])
                g.append(self.leds[row][col][1])
                b.append(self.leds[row][col][2])
                frame.append(self.leds[row][col][0])
                frame.append(self.leds[row][col][1])
                frame.append(self.leds[row][col][2])

        if not config.IS_LED_STRIP_V2:
            # Make chunks of size 16
            r_chunk = [r[i:i+16] for i in range(0, len(r), 16)]
            g_chunk = [g[i:i+16] for i in range(0, len(g), 16)]
            b_chunk = [b[i:i+16] for i in range(0, len(b), 16)]

            for i in range(len(r_chunk)):
                length = len(r_chunk[i])

                # Fill up chunks with zeros
                r_chunk[i].extend([0]*(16-len(r_chunk[i])))
                g_chunk[i].extend([0]*(16-len(g_chunk[i])))
                b_chunk[i].extend([0]*(16-len(b_chunk[i])))

                try:
                    self.led_strip.set_rgb_values(i*16, length, r_chunk[i], g_chunk[i], b_chunk[i])
                except:
                    break
        else:
            try:
                self.led_strip.set_led_values(0, frame)
            except:
                return

    def frame_prepare_next(self):
        def shift_up():
            for y in reversed(range(1, config.LED_COLS)):
                for x in range(config.LED_ROWS):
                    self.matrix[x][y] = self.matrix[x][y-1]

            for x in range(config.LED_ROWS):
                self.matrix[x][0] = self.line[x]

        def generate_line():
            start = min(config.FIRE_RAND_VALUE_START, config.FIRE_RAND_VALUE_END)
            end = config.FIRE_RAND_VALUE_END

            for x in range(config.LED_ROWS):
                self.line[x] = random.randint(start, end)

        def make_frame():
            def hsv_to_rgb(h, s, v):
                r, g, b = colorsys.hsv_to_rgb(h/255.0, s/255.0, v/255.0)
                return ((int(255*r), int(255*g), int(255*b)))

            def interpolate2(x, y):
                p0 = 100.0 - self.percent
                p1 = self.percent
                m0 = self.matrix[x][y]
                m1 = self.matrix[x][y-1]

                return (p0*m0 + p1*m1) / 100.0

            def interpolate1(x):
                p0 = 100.0 - self.percent
                p1 = self.percent
                m0 = self.matrix[x][0]
                m1 = self.line[x]

                return (p0*m0 + p1*m1) / 100.0

            for y in reversed(range(1, config.LED_COLS)):
                for x in range(config.LED_ROWS):
                    rgb = hsv_to_rgb(self.hues[y][x]*config.FIRE_HUE_FACTOR, 255,
                                     max(0, interpolate2(x, y) - self.values[y][x]))
                    self.leds[x][config.LED_COLS-1-y] = rgb

            for x in range(config.LED_ROWS):
                rgb = hsv_to_rgb(self.hues[0][x]*config.FIRE_HUE_FACTOR, 255,
                                 max(0, interpolate1(x)))
                self.leds[x][config.LED_COLS-1] = rgb

        self.percent += 20
        if self.percent >= 100:
            shift_up()
            generate_line()
            self.percent = 0

        make_frame()
Exemple #7
0
class Tetris:
    FIELD_ROWS = config.LED_ROWS+4 # 22 rows in playfield, with only 20 columns visible and 2 coloms border
    FIELD_COLS = config.LED_COLS+2 # 10 columns in playfield, 2 column border

    FIELD_ROW_START = 2
    FIELD_COL_START = 4

    COLORS = [
        ( 10,  10,  10), # grey
        (255,   0,   0), # red
        (255,  80,   0), # orange
        (255, 255,   0), # yellow
        (  0, 255,   0), # green
        (  0,   0, 255), # blue
        (255,   0, 150), # violet
        (255,   0,  40), # purple
    ]

    TETROMINOS = {
        None: [[[0], [0], [0], [0]]],

        'I': [[[0,0,0,0], [0,0,2,0], [0,0,0,0], [0,2,0,0]],
              [[2,2,2,2], [0,0,2,0], [0,0,0,0], [0,2,0,0]],
              [[0,0,0,0], [0,0,2,0], [2,2,2,2], [0,2,0,0]],
              [[0,0,0,0], [0,0,2,0], [0,0,0,0], [0,2,0,0]]],

        'J': [[[6,0,0], [0,6,6], [0,0,0], [0,6,0]],
              [[6,6,6], [0,6,0], [6,6,6], [0,6,0]],
              [[0,0,0], [0,6,0], [0,0,6], [6,6,0]]],

        'L': [[[0,0,5], [0,5,0], [0,0,0], [5,5,0]],
              [[5,5,5], [0,5,0], [5,5,5], [0,5,0]],
              [[0,0,0], [0,5,5], [5,0,0], [0,5,0]]],

        'O': [[[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]],
              [[0,1,1,0], [0,1,1,0], [0,1,1,0], [0,1,1,0]],
              [[0,1,1,0], [0,1,1,0], [0,1,1,0], [0,1,1,0]]],

        'S': [[[0,3,3], [0,3,0], [0,0,0], [3,0,0]],
              [[3,3,0], [0,3,3], [0,3,3], [3,3,0]],
              [[0,0,0], [0,0,3], [3,3,0], [0,3,0]]],

        'T': [[[0,7,0], [0,7,0], [0,0,0], [0,7,0]],
              [[7,7,7], [0,7,7], [7,7,7], [7,7,0]],
              [[0,0,0], [0,7,0], [0,7,0], [0,7,0]]],

        'Z': [[[4,4,0], [0,0,4], [0,0,0], [0,4,0]],
              [[0,4,4], [0,4,4], [4,4,0], [4,4,0]],
              [[0,0,0], [0,4,0], [0,4,4], [4,0,0]]]
    }

    GAME_OVER_TEXT = [
        "GameOverGameOverGameOverGameOverGameOverGameOverGameOve",
        "                                                       ",
        "         GGGG                      OO                  ",
        "        G   GG                    O  O                 ",
        "        G      aaa  mmm mm   ee   O  O v   v  ee   rr  ",
        "        G  GG     a m  m  m e  e  O  O v   v e  e r  r ",
        "        G    G aaaa m  m  m eeee  O  O  v v  eeee r    ",
        "        G    G a  a m  m  m e     O  O  v v  e    r    ",
        "         GGGG  aaaa m  m  m  eee   OO    v    eee r    ",
        "                                                       ",
        "                                                       ",
        "GameOverGameOverGameOverGameOverGameOverGameOverGameOve"
    ]

    GAME_OVER_COLORS = {
        ' ': 0,
        'G': 1,
        'a': 2,
        'm': 3,
        'e': 4,
        'O': 5,
        'v': 6,
        'r': 7
    }

    drop_timer = None
    tetromino_current = 'O'
    tetromino_form = 0
    tetromino_pos_row = FIELD_ROW_START
    tetromino_pos_col = FIELD_COL_START
    playfield = [x[:] for x in [[0]*FIELD_COLS]*FIELD_ROWS]
    random_bag = ['O', 'I', 'S', 'Z', 'L', 'J', 'T']
    random_bag_index = len(random_bag)-1
    game_over_position = 0
    is_game_over = False
    loop = True

    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip (required)")
            return

        self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
        except:
            print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            return

        self.kp = KeyPress(self.ipcon)
        self.display = TetrisSegmentDisplay(self.ipcon)
        self.speaker = TetrisSpeaker(self.ipcon)

        self.okay = True

        self.led_strip.set_frame_duration(40)
        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         self.frame_rendered)

        self.init_game()

    def init_game(self):
        self.tetromino_current = 'O'
        self.tetromino_form = 0
        self.tetromino_pos_row = self.FIELD_ROW_START
        self.tetromino_pos_col = self.FIELD_COL_START

        # Add border to playfield
        self.playfield = [x[:] for x in [[0]*self.FIELD_COLS]*self.FIELD_ROWS]
        self.playfield[0] = [255]*self.FIELD_COLS
        self.playfield[-1] = [255]*self.FIELD_COLS
        for col in self.playfield[1:-1]:
            col[0] = 255
            col[-1] = 255

        # initialize current tetronimo randomly
        self.tetromino_current = self.get_random_tetromino()
        self.is_game_over = False
        if self.drop_timer:
            self.drop_timer.interval = 1

    def frame_rendered(self, length):
        self.write_playfield()

    # See http://tetris.wikia.com/wiki/Random_Generator for
    # details of random bag implementation according to tetris specification
    def get_random_tetromino(self):
        self.random_bag_index += 1
        if self.random_bag_index >= len(self.random_bag):
            self.random_bag_index = 0
            random.shuffle(self.random_bag)

        return self.random_bag[self.random_bag_index]

    def add_tetromino_to_field(self, field, pos_row, pos_col, tetromino, form):
        for index_col, col in enumerate(self.TETROMINOS[tetromino]):
            for index_row, color in enumerate(col[form]):
                if color != 0:
                    row = pos_row + index_row
                    col = pos_col + index_col
                    if row >= 0 and row < self.FIELD_ROWS and col >= 0 and col < self.FIELD_COLS:
                        field[row][col] = color

    def tetromino_fits(self, field, pos_row, pos_col, tetromino, form):
        for index_col, col in enumerate(self.TETROMINOS[tetromino]):
            for index_row, color in enumerate(col[form]):
                if color != 0:
                    row = pos_row + index_row
                    col = pos_col + index_col
                    if row >= 0 and row < self.FIELD_ROWS and col >= 0 and col < self.FIELD_COLS:
                        if field[row][col] != 0:
                            return False
        return True

    def write_playfield(self):
        if not self.okay:
            return

        field = copy.deepcopy(self.playfield)
        if not self.is_game_over:
            self.add_tetromino_to_field(field, self.tetromino_pos_row,
                                        self.tetromino_pos_col,
                                        self.tetromino_current,
                                        self.tetromino_form)

        # Reorder LED data into R, G and B channel
        r = []
        g = []
        b = []
        for row in reversed(range(3, self.FIELD_ROWS-1)):
            col_range = range(1, self.FIELD_COLS-1)
            if row % 2 == 0:
                col_range = reversed(col_range)
            for col in col_range:
                r.append(self.COLORS[field[row][col]][config.R_INDEX])
                g.append(self.COLORS[field[row][col]][config.G_INDEX])
                b.append(self.COLORS[field[row][col]][config.B_INDEX])

        # Make chunks of size 16
        r_chunk = [r[i:i+16] for i in range(0, len(r), 16)]
        g_chunk = [g[i:i+16] for i in range(0, len(g), 16)]
        b_chunk = [b[i:i+16] for i in range(0, len(b), 16)]

        for i in range(len(r_chunk)):
            length = len(r_chunk[i])

            # Fill up chunks with zeros
            r_chunk[i].extend([0]*(16-len(r_chunk[i])))
            g_chunk[i].extend([0]*(16-len(g_chunk[i])))
            b_chunk[i].extend([0]*(16-len(b_chunk[i])))

            try:
                self.led_strip.set_rgb_values(i*16, length, r_chunk[i], g_chunk[i], b_chunk[i])
            except:
                break

    def clear_lines(self, rows_to_clear):
        if not self.okay:
            return

        self.drop_timer.stop()
        rows_save = {}

        for to_clear in rows_to_clear:
            rows_save[to_clear] = self.playfield[to_clear]

        self.display.increase_line_count(len(rows_to_clear))
        self.speaker.beep_delete_line(len(rows_to_clear))

        for i in range(6):
            if i % 2 == 0:
                for to_clear in rows_to_clear:
                    self.playfield[to_clear] = [255] + [0]*(self.FIELD_COLS-2) + [255]
            else:
                for to_clear in rows_to_clear:
                    self.playfield[to_clear] = rows_save[to_clear]

            time.sleep(0.1)

        for to_clear in rows_to_clear:
            for row in reversed(range(1, to_clear+1)):
                self.playfield[row] = self.playfield[row-1]

            self.playfield[1] = [255] + [0]*(self.FIELD_COLS-2) + [255]

        self.drop_timer.start()

    def check_for_lines_to_clear(self):
        rows_to_clear = []

        for row_index, col in enumerate(self.playfield[1:-1]):
            to_clear = True

            for color in col[1:-1]:
                if color == 0:
                    to_clear = False
                    break

            if to_clear:
                rows_to_clear.append(row_index+1)

        if len(rows_to_clear) > 0:
            self.clear_lines(rows_to_clear)

    def new_tetromino(self):
        self.add_tetromino_to_field(self.playfield, self.tetromino_pos_row,
                                    self.tetromino_pos_col, self.tetromino_current,
                                    self.tetromino_form)
        self.tetromino_current = None

        self.check_for_lines_to_clear()

        self.tetromino_current = self.get_random_tetromino()
        self.tetromino_pos_row = self.FIELD_ROW_START
        self.tetromino_pos_col = self.FIELD_COL_START
        self.tetromino_form = 0

        if not self.tetromino_fits(self.playfield, self.tetromino_pos_row,
                                   self.tetromino_pos_col, self.tetromino_current,
                                   self.tetromino_form):
            self.is_game_over = True
            self.game_over_position = 0
            self.drop_timer.interval = 0.15

    def next_game_over_step(self):
        for row in range(len(self.GAME_OVER_TEXT)):
            for col in range(config.LED_COLS):
                k = (self.game_over_position+col) % len(self.GAME_OVER_TEXT[0])
                self.playfield[7+row][1+col] = self.GAME_OVER_COLORS[self.GAME_OVER_TEXT[row][k]]

        self.game_over_position += 1

    def drop_tetromino(self):
        if self.is_game_over:
            self.next_game_over_step()
            return

        if self.tetromino_fits(self.playfield, self.tetromino_pos_row+1,
                               self.tetromino_pos_col, self.tetromino_current,
                               self.tetromino_form):
            self.tetromino_pos_row += 1
        else:
            self.new_tetromino()

    def move_tetromino(self, row, col, form):
        if self.is_game_over:
            return

        if self.tetromino_fits(self.playfield, self.tetromino_pos_row+row,
                               self.tetromino_pos_col+col, self.tetromino_current, form):
            self.tetromino_pos_row += row
            self.tetromino_pos_col += col
            self.tetromino_form = form

            if row > 0:
                # restart drop timer, so we don't drop two tetrominos in a row
                self.drop_timer.stop()
                self.drop_timer.start()
        elif row == 1: # user is at bottom and hits button to go down again
            self.new_tetromino()

    def run_game_loop(self):
        self.frame_rendered(0)

        self.drop_timer = RepeatedTimer(1.0, self.drop_tetromino)

        while self.loop:
            key = self.kp.read_single_keypress()

            if key == 'a':
                self.speaker.beep_input()
                self.move_tetromino(0, -1, self.tetromino_form)
            elif key == 'd':
                self.speaker.beep_input()
                self.move_tetromino(0, 1, self.tetromino_form)
            elif key == 's':
                self.speaker.beep_input()
                self.move_tetromino(1, 0, self.tetromino_form)
            elif key == 'k':
                self.speaker.beep_input()
                self.move_tetromino(0, 0, (self.tetromino_form-1) % 4)
            elif key == 'l':
                self.speaker.beep_input()
                self.move_tetromino(0, 0, (self.tetromino_form+1) % 4)
            elif key == 'r':
                self.init_game()
            elif not config.HAS_GUI and key == 'q':
                break

        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED, None)
        self.drop_timer.stop()
        self.kp.stop()
Exemple #8
0
class Pong:
    PADDLE_SIZE = 3

# Antialased ball?
#    PONG_COLOR_INDEX_BALL_TOP = 8
#    PONG_COLOR_INDEX_BALL_LEFT = 9
#    PONG_COLOR_INDEX_BALL_RIGHT = 10
#    PONG_COLOR_INDEX_BALL_BOTTOM = 11

    COLORS = [
        (  0,   0,   0), # off
#       ( 10,  10,  10), # grey
        (255,   0,   0), # red
        (255,  80,   0), # orange
        (255, 255,   0), # yellow
        (  0, 255,   0), # green
        (  0,   0, 255), # blue
        (255,   0, 150), # violet
        (255,   0,  40), # purple
        (  0,   0,   0), # ball top
        (  0,   0,   0), # ball left
        (  0,   0,   0), # ball right
        (  0,   0,   0)  # ball bottom
    ]

    SCORE_FONT = {
        0: ["222",
            "202",
            "202",
            "202",
            "222"],
        1: ["020",
            "020",
            "020",
            "020",
            "020"],
        2: ["222",
            "002",
            "222",
            "200",
            "222"],
        3: ["222",
            "002",
            "222",
            "002",
            "222"],
        4: ["202",
            "202",
            "222",
            "002",
            "002"],
        5: ["222",
            "200",
            "222",
            "002",
            "222"],
        6: ["222",
            "200",
            "222",
            "202",
            "222"],
        7: ["222",
            "002",
            "002",
            "002",
            "002"],
        8: ["222",
            "202",
            "222",
            "202",
            "222"],
        9: ["222",
            "202",
            "222",
            "002",
            "002"],
    }

    playfield = [x[:] for x in [[0]*config.LED_COLS]*config.LED_ROWS]
    score = [0, 0]
    paddle_position_x = [4, 15]
    paddle_position_y = [3, 3]
    ball_position = [10, 5]
    ball_direction = [0.1, 0.2]
    timer = None
    loop = True

    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip or LED Strip V2 (required)")
            return

        if not config.IS_LED_STRIP_V2:
            self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)
        else:
            self.led_strip = LEDStripV2(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            if not config.IS_LED_STRIP_V2:
                print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            else:
                print("Found: LED Strip V2 ({0})".format(config.UID_LED_STRIP_BRICKLET))
        except:
            if not config.IS_LED_STRIP_V2:
                print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            else:
                print("Not Found: LED Strip V2({0})".format(config.UID_LED_STRIP_BRICKLET))
            return

        self.kp = KeyPress(self.ipcon)
        self.speaker = PongSpeaker(self.ipcon)

        self.okay = True

        self.led_strip.set_frame_duration(40)

        if not config.IS_LED_STRIP_V2:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                             self.frame_rendered)
        else:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED,
                                             self.frame_rendered)

        self.led_strip.set_channel_mapping(config.CHANNEL_MAPPING)
        self.init_game()

    def init_game(self):
        self.new_ball()
        self.paddle_position_y = [3, 3]
        self.score = [0, 0]

    def frame_rendered(self, length):
        self.write_playfield()

    def write_playfield(self):
        if not self.okay:
            return

        field = copy.deepcopy(self.playfield)

        self.add_score_to_playfield(field)
        self.add_paddles_to_playfield(field)
        self.add_ball_to_playfield(field)

        # Reorder LED data into R, G and B channel
        r = []
        g = []
        b = []
        frame = []

        for row in range(config.LED_ROWS):
            col_range = range(config.LED_COLS)
            if row % 2 == 0:
                col_range = reversed(col_range)
            for col in col_range:
                r.append(self.COLORS[field[row][col]][0])
                g.append(self.COLORS[field[row][col]][1])
                b.append(self.COLORS[field[row][col]][2])
                frame.append(self.COLORS[field[row][col]][0])
                frame.append(self.COLORS[field[row][col]][1])
                frame.append(self.COLORS[field[row][col]][2])

        if not config.IS_LED_STRIP_V2:
            # Make chunks of size 16
            r_chunk = [r[i:i+16] for i in range(0, len(r), 16)]
            g_chunk = [g[i:i+16] for i in range(0, len(g), 16)]
            b_chunk = [b[i:i+16] for i in range(0, len(b), 16)]

            for i in range(len(r_chunk)):
                length = len(r_chunk[i])

                # Fill up chunks with zeros
                r_chunk[i].extend([0]*(16-len(r_chunk[i])))
                g_chunk[i].extend([0]*(16-len(g_chunk[i])))
                b_chunk[i].extend([0]*(16-len(b_chunk[i])))

                try:
                    self.led_strip.set_rgb_values(i*16, length, r_chunk[i], g_chunk[i], b_chunk[i])
                except:
                    break
        else:
            try:
                self.led_strip.set_led_values(0, frame)
            except:
                return

    def add_score_to_playfield(self, field):
        for row in range(3):
            for col in range(5):
                field[row][col+1] = int(self.SCORE_FONT[self.score[0]][col][row])
                field[row+17][col+1] = int(self.SCORE_FONT[self.score[1]][col][row])

    def add_ball_to_playfield(self, field):
        x = max(0, min(19, int(self.ball_position[0])))
        y = max(0, min(9, int(self.ball_position[1])))
        field[x][y] = config.PONG_COLOR_INDEX_BALL

# Antialased ball?
#        x = max(0, min(19, self.ball_position[0]))
#        y = max(0, min(9, self.ball_position[1]))
#        ix = int(x)
#        iy = int(y)
#        field[ix][iy] = config.PONG_COLOR_INDEX_BALL
#        if ix + 1 < config.LED_ROWS:
#            field[ix+1][iy] = PONG_COLOR_INDEX_BALL_RIGHT
#        if ix - 1 > 0:
#            field[ix-1][iy] = PONG_COLOR_INDEX_BALL_LEFT
#        if iy + 1 < config.LED_COLS:
#            field[ix][iy+1] = PONG_COLOR_INDEX_BALL_TOP
#        if iy - 1 > 0:
#            field[ix][iy-1] = PONG_COLOR_INDEX_BALL_BOTTOM
#
#        dx = x - int(x)
#        dy = x - int(x)
#        self.COLORS[PONG_COLOR_INDEX_BALL_RIGHT] = (0, 255*dx/64, 0)
#        self.COLORS[PONG_COLOR_INDEX_BALL_LEFT] = (0, 255*(1-dx)/64, 0)
#        self.COLORS[PONG_COLOR_INDEX_BALL_TOP] = (0, 255*dy/64, 0)
#        self.COLORS[PONG_COLOR_INDEX_BALL_BOTTOM] = (0, 255*(1-dy)/64, 0)

    def add_paddles_to_playfield(self, field):
        for player in range(2):
            for i in range(self.PADDLE_SIZE):
                field[self.paddle_position_x[player]][self.paddle_position_y[player]+i] = config.PONG_COLOR_INDEX_PLAYER[player]

    def move_paddle(self, player, change):
        new_pos = self.paddle_position_y[player] + change
        if new_pos >= 0 and new_pos <= config.LED_COLS - self.PADDLE_SIZE:
            self.paddle_position_y[player] = new_pos

    def new_ball(self):
        self.ball_position = [(config.LED_ROWS - 1.0) / 2.0, (config.LED_COLS - 1.0) / 2.0]
        self.ball_direction = [random.choice([-0.2, 0.2]), random.choice([random.randrange(1, 9)/10.0, random.randrange(-9, -1)/10.0])]

    def tick(self):
        # Move ball
        for i in range(2):
            self.ball_position[i] += self.ball_direction[i]

        # Wall collision top/bottom
        if self.ball_position[1] < 0 or self.ball_position[1] >= config.LED_COLS:
            self.ball_direction[1] = -self.ball_direction[1]

        # Wall collision left/right
        def hit_left_right(player):
            self.speaker.beep_sirene()
            self.new_ball()

            self.score[player] += 1
            if self.score[player] > 9:
                self.score[player] = 0

        if self.ball_position[0] < 0:
            hit_left_right(1)

        if self.ball_position[0] >= config.LED_ROWS:
            hit_left_right(0)

        # Paddle collision
        def hit_paddle(skew):
            self.speaker.beep_paddle_hit()
            self.ball_direction[0] = -self.ball_direction[0]
            self.ball_direction[1] -= skew
            for i in range(2):
                self.ball_direction[i] *= 1.1 # Increase speed

        if self.ball_direction[0] < 0:
            if self.paddle_position_x[0] + 0.5 <= self.ball_position[0] <= self.paddle_position_x[0] + 1.5:
                if self.paddle_position_y[0] - 0.5 <= self.ball_position[1] <= self.paddle_position_y[0] + self.PADDLE_SIZE + 0.5:
                    paddle_skew = (self.paddle_position_y[0] + self.PADDLE_SIZE/2.0 - self.ball_position[1])/10.0
                    hit_paddle(paddle_skew)

        if self.ball_direction[0] > 0:
            if self.paddle_position_x[1] - 0.5 <= self.ball_position[0] <= self.paddle_position_x[1] + 0.5:
                if self.paddle_position_y[1] - 0.5 <= self.ball_position[1] <= self.paddle_position_y[1] + self.PADDLE_SIZE + 0.5:
                    paddle_skew = (self.paddle_position_y[1] + self.PADDLE_SIZE/2.0 - self.ball_position[1])/10.0
                    hit_paddle(paddle_skew)

    def run_game_loop(self):
        self.frame_rendered(0)

        self.timer = RepeatedTimer(0.1, self.tick)

        while self.loop:
            key = self.kp.read_single_keypress().lower()

            if key == 'a':
                self.move_paddle(0, -1)
            elif key == 's':
                self.move_paddle(0, 1)
            elif key == 'k':
                self.move_paddle(1, -1)
            elif key == 'l':
                self.move_paddle(1, 1)
            elif key == 'r':
                self.init_game()
            elif not config.HAS_GUI and key == 'q':
                break

        if not config.IS_LED_STRIP_V2:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED, None)
        else:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED, None)

        self.timer.stop()
        self.kp.stop()
Exemple #9
0
class Rainbow:
    leds = [x[:] for x in [(0, 0, 0)]*config.LED_ROWS*config.LED_COLS]
    rainbow = [x[:] for x in [(0, 0, 0)]*config.LED_ROWS*config.LED_COLS]
    rainbow_position = 0

    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip (required)")
            return

        self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
        except:
            print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            return

        for i in range(config.LED_ROWS*config.LED_COLS):
            r, g, b = colorsys.hsv_to_rgb(1.0*i/(config.LED_ROWS*config.LED_COLS), 1, 0.1)
            self.rainbow[i] = (int(r*255), int(g*255), int(b*255))

        self.okay = True

        self.update_frame_rate()
        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         self.frame_rendered)

    def stop_rendering(self):
        if not self.okay:
            return

        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         None)

    def update_frame_rate(self):
        if not self.okay:
            return

        self.led_strip.set_frame_duration(int(1000.0 / config.RAINBOW_FRAME_RATE))

    def frame_rendered(self, _):
        self.frame_upload()
        self.frame_prepare_next()

    def frame_upload(self):
        if not self.okay:
            return

        # Reorder LED data into R, G and B channel
        r = []
        g = []
        b = []
        for i in range(config.LED_ROWS*config.LED_COLS):
            r.append(self.leds[i][config.R_INDEX])
            g.append(self.leds[i][config.G_INDEX])
            b.append(self.leds[i][config.B_INDEX])

        # Make chunks of size 16
        r_chunk = [r[i:i+16] for i in range(0, len(r), 16)]
        g_chunk = [g[i:i+16] for i in range(0, len(g), 16)]
        b_chunk = [b[i:i+16] for i in range(0, len(b), 16)]

        for i in range(len(r_chunk)):
            length = len(r_chunk[i])

            # Fill up chunks with zeros
            r_chunk[i].extend([0]*(16-len(r_chunk[i])))
            g_chunk[i].extend([0]*(16-len(g_chunk[i])))
            b_chunk[i].extend([0]*(16-len(b_chunk[i])))

            try:
                self.led_strip.set_rgb_values(i*16, length, r_chunk[i], g_chunk[i], b_chunk[i])
            except:
                break

    def frame_prepare_next(self):
        self.leds = self.rainbow[int(self.rainbow_position) % (config.LED_ROWS*config.LED_COLS):] + self.rainbow[:int(self.rainbow_position) % (config.LED_ROWS*config.LED_COLS)]
        self.rainbow_position += (config.LED_ROWS*config.LED_COLS) * config.RAINBOW_STEP
Exemple #10
0
class Images:
    leds = [x[:] for x in [[(0, 0, 0)]*config.LED_COLS]*config.LED_ROWS]
    images = []
    image_position = 0

    def __init__(self, ipcon):
        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print('Not Configured: LED Strip (required)')
            return

        self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            print('Found: LED Strip ({0})'.format(config.UID_LED_STRIP_BRICKLET))
        except:
            print('Not Found: LED Strip ({0})'.format(config.UID_LED_STRIP_BRICKLET))
            return

        self.okay = True

        self.update_frame_rate()
        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         self.frame_rendered)

    def stop_rendering(self):
        if not self.okay:
            return

        self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                         None)

    def update_frame_rate(self):
        if not self.okay:
            return

        self.led_strip.set_frame_duration(int(1000.0 / config.IMAGES_FRAME_RATE))

    def set_new_images(self, image_urls):
        self.images = []

        for url in image_urls:
            loader = ImageLoader(url)
            image = [x[:] for x in [[(0, 0, 0)]*config.LED_COLS]*config.LED_ROWS]

            for y in range(config.LED_ROWS):
                for x in range(config.LED_COLS):
                    image[y][x] = loader.get_pixel(y, x)

            self.images.append(image)

        self.image_position = 0

    def frame_rendered(self, _):
        self.frame_upload()
        self.frame_prepare_next()

    def frame_upload(self):
        if not self.okay:
            return

        # Reorder LED data into R, G and B channel
        r = []
        g = []
        b = []
        for row in range(config.LED_ROWS):
            col_range = range(config.LED_COLS)
            if row % 2 == 0:
                col_range = reversed(col_range)
            for col in col_range:
                r.append(self.leds[row][col][config.R_INDEX])
                g.append(self.leds[row][col][config.G_INDEX])
                b.append(self.leds[row][col][config.B_INDEX])

        # Make chunks of size 16
        r_chunk = [r[i:i+16] for i in range(0, len(r), 16)]
        g_chunk = [g[i:i+16] for i in range(0, len(g), 16)]
        b_chunk = [b[i:i+16] for i in range(0, len(b), 16)]

        for i in range(len(r_chunk)):
            length = len(r_chunk[i])

            # Fill up chunks with zeros
            r_chunk[i].extend([0]*(16-len(r_chunk[i])))
            g_chunk[i].extend([0]*(16-len(g_chunk[i])))
            b_chunk[i].extend([0]*(16-len(b_chunk[i])))

            try:
                self.led_strip.set_rgb_values(i*16, length, r_chunk[i], g_chunk[i], b_chunk[i])
            except:
                break

    def frame_prepare_next(self):
        if len(self.images) == 0:
            return

        self.leds = self.images[self.image_position]
        self.image_position = (self.image_position + 1) % len(self.images)
Exemple #11
0
class Text:
    leds = [x[:] for x in [[(0, 0, 0)]*config.LED_COLS]*config.LED_ROWS]
    text_position = 0
    rainbow_length = 32
    rainbow_index = 0

    def __init__(self, ipcon):
        self.letter_table = {}

        for form in letter_forms:
            if '|' in form:
                self.letter_table[form[-2]] = form[:-3].split('|')

        self.set_new_text('Starter Kit: Blinkenlights')

        self.okay = False
        self.ipcon = ipcon

        if not config.UID_LED_STRIP_BRICKLET:
            print("Not Configured: LED Strip or LED Strip V2 (required)")
            return

        if not config.IS_LED_STRIP_V2:
            self.led_strip = LEDStrip(config.UID_LED_STRIP_BRICKLET, self.ipcon)
        else:
            self.led_strip = LEDStripV2(config.UID_LED_STRIP_BRICKLET, self.ipcon)

        try:
            self.led_strip.get_frame_duration()
            if not config.IS_LED_STRIP_V2:
                print("Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            else:
                print("Found: LED Strip V2 ({0})".format(config.UID_LED_STRIP_BRICKLET))
        except:
            if not config.IS_LED_STRIP_V2:
                print("Not Found: LED Strip ({0})".format(config.UID_LED_STRIP_BRICKLET))
            else:
                print("Not Found: LED Strip V2({0})".format(config.UID_LED_STRIP_BRICKLET))
            return

        self.okay = True

        self.update_frame_rate()
        if not config.IS_LED_STRIP_V2:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                             self.frame_rendered)
        else:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED,
                                             self.frame_rendered)
        self.led_strip.set_channel_mapping(config.CHANNEL_MAPPING)
    def stop_rendering(self):
        if not self.okay:
            return

        if not config.IS_LED_STRIP_V2:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_RENDERED,
                                             None)
        else:
            self.led_strip.register_callback(self.led_strip.CALLBACK_FRAME_STARTED,
                                             None)

    def update_frame_rate(self):
        if not self.okay:
            return

        self.led_strip.set_frame_duration(int(1000.0 / config.TEXT_FRAME_RATE))

    def set_new_text(self, text):
        text = '   ' + text
        self.text_cols = ['','','','','','','']

        for col in range(len(self.text_cols)):
            for c in text:
                try:
                    self.text_cols[col] += self.letter_table[c][col]
                except:
                    self.text_cols[col] += ' '

        self.text_position = 0

    def frame_rendered(self, _):
        self.frame_upload()
        self.frame_prepare_next()

    def frame_upload(self):
        if not self.okay:
            return

        # Reorder LED data into R, G and B channel
        r = []
        g = []
        b = []
        frame = []

        for row in range(config.LED_ROWS):
            col_range = range(config.LED_COLS)
            if row % 2 == 0:
                col_range = reversed(col_range)
            for col in col_range:
                r.append(self.leds[row][col][0])
                g.append(self.leds[row][col][1])
                b.append(self.leds[row][col][2])
                frame.append(self.leds[row][col][0])
                frame.append(self.leds[row][col][1])
                frame.append(self.leds[row][col][2])

        if not config.IS_LED_STRIP_V2:
            # Make chunks of size 16
            r_chunk = [r[i:i+16] for i in range(0, len(r), 16)]
            g_chunk = [g[i:i+16] for i in range(0, len(g), 16)]
            b_chunk = [b[i:i+16] for i in range(0, len(b), 16)]

            for i in range(len(r_chunk)):
                length = len(r_chunk[i])

                # Fill up chunks with zeros
                r_chunk[i].extend([0]*(16-len(r_chunk[i])))
                g_chunk[i].extend([0]*(16-len(g_chunk[i])))
                b_chunk[i].extend([0]*(16-len(b_chunk[i])))

                try:
                    self.led_strip.set_rgb_values(i*16, length, r_chunk[i], g_chunk[i], b_chunk[i])
                except:
                    break
        else:
            try:
                self.led_strip.set_led_values(0, frame)
            except:
                return

    def frame_prepare_next(self):
        self.leds = [x[:] for x in [[(0, 0, 0)]*config.LED_COLS]*config.LED_ROWS]

        if config.TEXT_COLOR is None:
            r, g, b = colorsys.hsv_to_rgb(1.0*self.rainbow_index/self.rainbow_length, 1, 0.1)
            r, g, b = int(r*255), int(g*255), int(b*255)
            self.rainbow_index = (self.rainbow_index + 1) % self.rainbow_length
        else:
            r, g, b = config.TEXT_COLOR

        for col in range(len(self.text_cols)):
            for row in range(config.LED_ROWS):
                if self.text_cols[col][(self.text_position+row) % len(self.text_cols[0])] == 'X':
                    self.leds[row][col + config.TEXT_TOP_OFFSET] = (r, g, b)
                else:
                    self.leds[row][col + config.TEXT_TOP_OFFSET] = (0, 0, 0)

        self.text_position += 1