--- /dev/null
+#include <Adafruit_NeoPixel.h>
+
+#define NUM_PIXELS 6
+#define MIN_DELAY 30
+
+#define TOP_ROW 2
+#define MID_ROW 3
+#define BOT_ROW 4
+#define UP_BUTTON 6
+#define DOWN_BUTTON 5
+#define NOISE A0
+
+#define PLAYER 1
+#define CAR 2
+#define EMPTY 0
+#define CRASH 3
+
+Adafruit_NeoPixel top_row(NUM_PIXELS, TOP_ROW, NEO_GRB);
+Adafruit_NeoPixel mid_row(NUM_PIXELS, MID_ROW, NEO_GRB);
+Adafruit_NeoPixel bot_row(NUM_PIXELS, BOT_ROW, NEO_GRB);
+
+// Video RAM - every element corresponds to one pixel
+int vram[3][NUM_PIXELS] = {{0}}; // 2 - TOP, 1 - MID, 0 - BOT
+int player_pos = 1;
+int next_car_in = 1;
+int delay_time = 500;
+int crashed = 0;
+
+void setup()
+{
+ pinMode(TOP_ROW, OUTPUT);
+ pinMode(MID_ROW, OUTPUT);
+ pinMode(BOT_ROW, OUTPUT);
+ pinMode(UP_BUTTON, INPUT);
+ pinMode(DOWN_BUTTON, INPUT);
+ pinMode(NOISE, INPUT);
+
+ // LED strip initialization
+ top_row.begin();
+ mid_row.begin();
+ bot_row.begin();
+
+ // set the seed for the random number generator
+ int seed = analogRead(NOISE) * 42;
+ randomSeed(seed);
+
+ Serial.begin(9600);
+}
+
+void loop()
+{
+ int i;
+ int new_car;
+
+ // update player position
+ if (digitalRead(UP_BUTTON) == HIGH)
+ {
+ player_pos++;
+ }
+ else if (digitalRead(DOWN_BUTTON) == HIGH)
+ {
+ player_pos--;
+ }
+ if (player_pos > 2)
+ {
+ player_pos = 2;
+ }
+ else if (player_pos < 0)
+ {
+ player_pos = 0;
+ }
+
+ // draw the player
+ for (i = 0; i < 3; i++)
+ {
+ if (player_pos == i)
+ {
+ // detect collision
+ if (vram[i][1] == CAR)
+ {
+ vram[i][0] = CRASH;
+ crashed = 1;
+ }
+ else
+ {
+ vram[i][0] = PLAYER;
+ }
+ }
+ else
+ {
+ vram[i][0] = vram[i][1];
+ }
+ }
+
+ // move everything one pixel to the left
+ for (i = 1; i < (NUM_PIXELS - 1); i++)
+ {
+ vram[0][i] = vram[0][i + 1];
+ vram[1][i] = vram[1][i + 1];
+ vram[2][i] = vram[2][i + 1];
+ }
+
+ // generate next car
+ for (i = 0; i < 3; i++)
+ {
+ vram[i][NUM_PIXELS - 1] = EMPTY;
+ }
+ next_car_in--;
+ if (next_car_in == 0)
+ {
+ new_car = random(3);
+ vram[new_car][NUM_PIXELS - 1] = CAR;
+ next_car_in = 3;
+ }
+
+ // render the image
+ for (i = 0; i < NUM_PIXELS; i++)
+ {
+ if (vram[0][i] == EMPTY)
+ {
+ bot_row.setPixelColor(i, bot_row.Color(0, 0, 0));
+ }
+ else if (vram[0][i] == CAR)
+ {
+ bot_row.setPixelColor(i, bot_row.Color(0, 0, 255));
+ }
+ else if (vram[0][i] == PLAYER)
+ {
+ bot_row.setPixelColor(i, bot_row.Color(0, 255, 0));
+ }
+ else if (vram[0][i] == CRASH)
+ {
+ bot_row.setPixelColor(i, bot_row.Color(255, 0, 0));
+ }
+
+ if (vram[1][i] == EMPTY)
+ {
+ mid_row.setPixelColor(i, mid_row.Color(0, 0, 0));
+ }
+ else if (vram[1][i] == CAR)
+ {
+ mid_row.setPixelColor(i, mid_row.Color(0, 0, 255));
+ }
+ else if (vram[1][i] == PLAYER)
+ {
+ mid_row.setPixelColor(i, mid_row.Color(0, 255, 0));
+ }
+ else if (vram[1][i] == CRASH)
+ {
+ mid_row.setPixelColor(i, mid_row.Color(255, 0, 0));
+ }
+
+ if (vram[2][i] == EMPTY)
+ {
+ top_row.setPixelColor(i, top_row.Color(0, 0, 0));
+ }
+ else if (vram[2][i] == CAR)
+ {
+ top_row.setPixelColor(i, top_row.Color(0, 0, 255));
+ }
+ else if (vram[2][i] == PLAYER)
+ {
+ top_row.setPixelColor(i, top_row.Color(0, 255, 0));
+ }
+ else if (vram[2][i] == CRASH)
+ {
+ top_row.setPixelColor(i, top_row.Color(255, 0, 0));
+ }
+ }
+ top_row.show();
+ mid_row.show();
+ bot_row.show();
+ Serial.println(delay_time);
+ // stop the game if crashed
+ if (crashed)
+ {
+ while (1);
+ }
+ // delay before the next frame
+ else
+ {
+ delay(delay_time);
+ }
+ // slowly make the game faster
+ if (delay_time > MIN_DELAY)
+ {
+ delay_time--;
+ }
+}
--- /dev/null
+#include <Adafruit_NeoPixel.h>
+#include <inttypes.h>
+
+#define NUM_PIXELS 16
+
+#define TOP_ROW 4
+#define MID_ROW 3
+#define BOT_ROW 2
+
+#define PPM_HEADER_LENGHT 58
+#define IMAGE_FILE_LENGHT 202
+
+/*
+typedef enum {RED, GREEN, BLUE, YELLOW, MAGENTA, CYAN} simple_color_t;
+int display_enum(simple_color_t buff[]);
+*/
+
+int render_image(uint8_t buff[3][NUM_PIXELS][3], const uint8_t image[]);
+int display_rgb(uint8_t buff[3][NUM_PIXELS][3]);
+
+const uint8_t image_data_0[IMAGE_FILE_LENGHT] =
+{
+ 0x50, 0x36, 0x0a, 0x23, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
+ 0x47, 0x49, 0x4d, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x31,
+ 0x30, 0x2e, 0x32, 0x32, 0x20, 0x50, 0x4e, 0x4d, 0x20, 0x70, 0x6c, 0x75, 0x67, 0x2d, 0x69, 0x6e,
+ 0x0a, 0x31, 0x36, 0x20, 0x33, 0x0a, 0x32, 0x35, 0x35, 0x0a, 0xb9, 0x78, 0x90, 0xbc, 0x7b, 0x93,
+ 0xbe, 0x7e, 0x98, 0xbe, 0x7e, 0x98, 0xbc, 0x7d, 0x98, 0xba, 0x7b, 0x96, 0xb8, 0x79, 0x96, 0xb4,
+ 0x75, 0x92, 0xb1, 0x72, 0x8f, 0xaf, 0x70, 0x8d, 0xab, 0x6c, 0x89, 0xa7, 0x68, 0x85, 0xa2, 0x61,
+ 0x7f, 0x9c, 0x5b, 0x79, 0x9a, 0x57, 0x76, 0x9b, 0x56, 0x75, 0xb8, 0x77, 0x8f, 0xbb, 0x7a, 0x92,
+ 0xbc, 0x7c, 0x96, 0xbc, 0x7c, 0x96, 0xbb, 0x7b, 0x96, 0xb9, 0x79, 0x94, 0xb5, 0x76, 0x91, 0xb2,
+ 0x73, 0x8e, 0xae, 0x6f, 0x8c, 0xac, 0x6d, 0x8a, 0xa4, 0x65, 0x82, 0xa0, 0x61, 0x7e, 0x9b, 0x5a,
+ 0x78, 0x96, 0x55, 0x73, 0x94, 0x51, 0x70, 0x97, 0x52, 0x71, 0xb9, 0x75, 0x8c, 0xba, 0x79, 0x91,
+ 0xbd, 0x7c, 0x94, 0xbb, 0x7b, 0x95, 0xba, 0x7a, 0x95, 0xb8, 0x78, 0x93, 0xb5, 0x75, 0x90, 0xb0,
+ 0x71, 0x8c, 0xad, 0x6e, 0x8b, 0xaa, 0x6b, 0x88, 0xa3, 0x64, 0x81, 0xa0, 0x5f, 0x7d, 0x9b, 0x5a,
+ 0x78, 0x97, 0x54, 0x73, 0x95, 0x52, 0x71, 0x99, 0x53, 0x75
+};
+
+const uint8_t image_data_1[IMAGE_FILE_LENGHT] =
+{
+ 0x50, 0x36, 0x0a, 0x23, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
+ 0x47, 0x49, 0x4d, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x31,
+ 0x30, 0x2e, 0x32, 0x32, 0x20, 0x50, 0x4e, 0x4d, 0x20, 0x70, 0x6c, 0x75, 0x67, 0x2d, 0x69, 0x6e,
+ 0x0a, 0x31, 0x36, 0x20, 0x33, 0x0a, 0x32, 0x35, 0x35, 0x0a, 0xb9, 0xa9, 0xd6, 0xb8, 0xa7, 0xd4,
+ 0xba, 0xaa, 0xd7, 0xbd, 0xac, 0xd9, 0xbc, 0xab, 0xd8, 0xbc, 0xab, 0xd7, 0xba, 0xa9, 0xd5, 0xb5,
+ 0xa4, 0xd0, 0xaf, 0x9e, 0xca, 0x98, 0x89, 0xb2, 0x8d, 0x7e, 0xa5, 0x7c, 0x6d, 0x94, 0x70, 0x62,
+ 0x86, 0x6b, 0x5d, 0x80, 0x6c, 0x5e, 0x81, 0x6e, 0x60, 0x81, 0xb9, 0xac, 0xd8, 0xc2, 0xb2, 0xdf,
+ 0xbe, 0xb1, 0xdd, 0xbd, 0xad, 0xda, 0xbb, 0xae, 0xda, 0xba, 0xad, 0xd9, 0xb7, 0xaa, 0xd6, 0xb2,
+ 0xa5, 0xd1, 0xae, 0xa1, 0xcc, 0x9d, 0x8e, 0xb7, 0x8f, 0x80, 0xa7, 0x80, 0x72, 0x96, 0x77, 0x69,
+ 0x8d, 0x72, 0x64, 0x87, 0x6e, 0x60, 0x83, 0x6c, 0x5e, 0x7f, 0xbe, 0xb1, 0xdd, 0xc4, 0xb7, 0xe3,
+ 0xc2, 0xb5, 0xe1, 0xc1, 0xb4, 0xe0, 0xc0, 0xb3, 0xdf, 0xbe, 0xb3, 0xde, 0xbb, 0xb0, 0xdb, 0xb7,
+ 0xac, 0xd7, 0xb3, 0xa8, 0xd2, 0xa0, 0x91, 0xba, 0x93, 0x84, 0xab, 0x83, 0x75, 0x99, 0x78, 0x6a,
+ 0x8e, 0x72, 0x64, 0x87, 0x6d, 0x5f, 0x82, 0x6b, 0x5d, 0x7e
+};
+
+const uint8_t image_data_2[] =
+{
+ 0x50, 0x36, 0x0a, 0x23, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
+ 0x47, 0x49, 0x4d, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x31,
+ 0x30, 0x2e, 0x32, 0x32, 0x20, 0x50, 0x4e, 0x4d, 0x20, 0x70, 0x6c, 0x75, 0x67, 0x2d, 0x69, 0x6e,
+ 0x0a, 0x31, 0x36, 0x20, 0x33, 0x0a, 0x32, 0x35, 0x35, 0x0a, 0x1a, 0x0a, 0xfe, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x1a, 0x0a, 0xfe, 0x1a, 0x0a, 0xfe, 0x1a, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x1a,
+ 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x1f, 0xee, 0x1d, 0x00, 0x00,
+ 0x00, 0x1f, 0xee, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x0a, 0xfe, 0x04, 0x04, 0x04,
+ 0x00, 0x00, 0x00, 0x1a, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x1a, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x1a,
+ 0x0a, 0xfe, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0xdd, 0xfa, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xdd, 0xfa, 0x03, 0x00, 0x00, 0x00, 0x1a, 0x0a, 0xfe, 0x1a, 0x0a, 0xfe,
+ 0x00, 0x00, 0x00, 0x1a, 0x0a, 0xfe, 0x1a, 0x0a, 0xfe, 0x1a, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0x1a,
+ 0x0a, 0xfe, 0x1a, 0x0a, 0xfe, 0x00, 0x00, 0x00, 0xdd, 0xfa, 0x03, 0xdd, 0xfa, 0x03, 0xdd, 0xfa,
+ 0x03, 0xdd, 0xfa, 0x03, 0xdd, 0xfa, 0x03, 0x00, 0x00, 0x00
+};
+
+Adafruit_NeoPixel top_row(NUM_PIXELS, TOP_ROW, NEO_GRB);
+Adafruit_NeoPixel mid_row(NUM_PIXELS, MID_ROW, NEO_GRB);
+Adafruit_NeoPixel bot_row(NUM_PIXELS, BOT_ROW, NEO_GRB);
+
+void setup()
+{
+ pinMode(TOP_ROW, OUTPUT);
+ pinMode(MID_ROW, OUTPUT);
+ pinMode(BOT_ROW, OUTPUT);
+
+ // LED strip initialization
+ top_row.begin();
+ mid_row.begin();
+ bot_row.begin();
+}
+
+void loop()
+{
+ uint8_t frame_buffer[3][NUM_PIXELS][3] = {{{0}}};
+
+ render_image(frame_buffer, image_data_2);
+ display_rgb(frame_buffer);
+}
+
+int render_image(uint8_t buff[3][NUM_PIXELS][3], const uint8_t image[])
+{
+ if (buff == NULL || image == NULL)
+ return -1;
+
+ for (uint8_t row = 0; row < 3; row++)
+ {
+ for (uint8_t col = 0; col < NUM_PIXELS; col++)
+ {
+ for (uint8_t i = 0; i < 3; i++)
+ {
+ buff[row][col][i] = image[PPM_HEADER_LENGHT + row * NUM_PIXELS * 3 + col * 3 + i];
+ }
+ }
+ }
+
+ return 0;
+}
+
+int display_rgb(uint8_t buff[3][NUM_PIXELS][3])
+{
+ if (buff == NULL)
+ return -1;
+
+ for (uint8_t col; col < NUM_PIXELS; col++)
+ {
+ top_row.setPixelColor(col, top_row.Color(buff[0][col][0], buff[0][col][1], buff[0][col][2]));
+ mid_row.setPixelColor(col, mid_row.Color(buff[1][col][0], buff[1][col][1], buff[1][col][2]));
+ bot_row.setPixelColor(col, bot_row.Color(buff[2][col][0], buff[2][col][1], buff[2][col][2]));
+ }
+
+ top_row.show();
+ mid_row.show();
+ bot_row.show();
+
+ return 0;
+}
--- /dev/null
+0x50, 0x36, 0x0a, 0x23, 0x20, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
+0x47, 0x49, 0x4d, 0x50, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x32, 0x2e, 0x31,
+0x30, 0x2e, 0x32, 0x32, 0x20, 0x50, 0x4e, 0x4d, 0x20, 0x70, 0x6c, 0x75, 0x67, 0x2d, 0x69, 0x6e,
+0x0a, 0x31, 0x36, 0x20, 0x33, 0x0a, 0x32, 0x35, 0x35, 0x0a, 0xb9, 0xa9, 0xd6, 0xb8, 0xa7, 0xd4,
+0xba, 0xaa, 0xd7, 0xbd, 0xac, 0xd9, 0xbc, 0xab, 0xd8, 0xbc, 0xab, 0xd7, 0xba, 0xa9, 0xd5, 0xb5,
+0xa4, 0xd0, 0xaf, 0x9e, 0xca, 0x98, 0x89, 0xb2, 0x8d, 0x7e, 0xa5, 0x7c, 0x6d, 0x94, 0x70, 0x62,
+0x86, 0x6b, 0x5d, 0x80, 0x6c, 0x5e, 0x81, 0x6e, 0x60, 0x81, 0xb9, 0xac, 0xd8, 0xc2, 0xb2, 0xdf,
+0xbe, 0xb1, 0xdd, 0xbd, 0xad, 0xda, 0xbb, 0xae, 0xda, 0xba, 0xad, 0xd9, 0xb7, 0xaa, 0xd6, 0xb2,
+0xa5, 0xd1, 0xae, 0xa1, 0xcc, 0x9d, 0x8e, 0xb7, 0x8f, 0x80, 0xa7, 0x80, 0x72, 0x96, 0x77, 0x69,
+0x8d, 0x72, 0x64, 0x87, 0x6e, 0x60, 0x83, 0x6c, 0x5e, 0x7f, 0xbe, 0xb1, 0xdd, 0xc4, 0xb7, 0xe3,
+0xc2, 0xb5, 0xe1, 0xc1, 0xb4, 0xe0, 0xc0, 0xb3, 0xdf, 0xbe, 0xb3, 0xde, 0xbb, 0xb0, 0xdb, 0xb7,
+0xac, 0xd7, 0xb3, 0xa8, 0xd2, 0xa0, 0x91, 0xba, 0x93, 0x84, 0xab, 0x83, 0x75, 0x99, 0x78, 0x6a,
+0x8e, 0x72, 0x64, 0x87, 0x6d, 0x5f, 0x82, 0x6b, 0x5d, 0x7e
\ No newline at end of file