ledscape_t * ledscape_init_with_modes( unsigned num_pixels, ledscape_output_mode_t pru0_mode, ledscape_output_mode_t pru1_mode ) { pru_t * const pru0 = pru_init(0); pru_t * const pru1 = pru_init(1); const size_t frame_size = num_pixels * LEDSCAPE_NUM_STRIPS * 4; if (2 *frame_size > pru0->ddr_size) die("Pixel data needs at least 2 * %zu, only %zu in DDR\n", frame_size, pru0->ddr_size ); ledscape_t * const leds = calloc(1, sizeof(*leds)); *leds = (ledscape_t) { .pru0 = pru0, .pru1 = pru1, .num_pixels = num_pixels, .frame_size = frame_size, .pru0_mode = pru0_mode, .pru1_mode = pru1_mode, .ws281x_0 = pru0->data_ram, .ws281x_1 = pru1->data_ram }; *(leds->ws281x_0) = *(leds->ws281x_1) = (ws281x_command_t) { .pixels_dma = 0, // will be set in draw routine .command = 0, .response = 0, .num_pixels = leds->num_pixels, }; // Configure all of our output pins. for (unsigned i = 0 ; i < ARRAY_COUNT(gpios0) ; i++) pru_gpio(0, gpios0[i], 1, 0); for (unsigned i = 0 ; i < ARRAY_COUNT(gpios1) ; i++) pru_gpio(1, gpios1[i], 1, 0); for (unsigned i = 0 ; i < ARRAY_COUNT(gpios2) ; i++) pru_gpio(2, gpios2[i], 1, 0); for (unsigned i = 0 ; i < ARRAY_COUNT(gpios3) ; i++) pru_gpio(3, gpios3[i], 1, 0); // Initiate the PRU0 program const char* pru0_program_filename; switch (pru0_mode) { case NOP: pru0_program_filename = "./nop_0.bin"; break; case WS281x: pru0_program_filename = "./ws281x_0.bin"; break; case DMX: pru0_program_filename = "./dmx_0.bin"; break; case WS2801: pru0_program_filename = "./ws2801_0.bin"; break; case WS2801_NEWPINS: pru0_program_filename = "./ws2801_newpins_0.bin"; break; default: warn("Invalid PRU0 Mode."); pru0_program_filename = "./ws281x_0.bin"; } pru_exec(pru0, pru0_program_filename); // Watch for a done response that indicates a proper startup // \todo timeout if it fails fprintf(stdout, "String PRU0 with %s... ", pru0_program_filename); while (!leds->ws281x_0->response); printf("OK\n"); // Initiate the PRU1 program const char* pru1_program_filename; switch (pru1_mode) { case NOP: pru1_program_filename = "./nop_1.bin"; break; case WS281x: pru1_program_filename = "./ws281x_1.bin"; break; case DMX: warn("PRU1 does not currently support DMX."); pru1_program_filename = "./ws281x_1.bin"; break; case WS2801: pru1_program_filename = "./ws2801_1.bin"; break; case WS2801_NEWPINS: pru1_program_filename = "./ws2801_newpins_1.bin"; break; default: pru1_program_filename = "./ws281x_1.bin"; warn("Invalid PRU1 Mode."); } pru_exec(pru1, pru1_program_filename); // Watch for a done response that indicates a proper startup // \todo timeout if it fails fprintf(stdout, "String PRU1 with %s... ", pru1_program_filename); while (!leds->ws281x_1->response); printf("OK\n"); return leds; } void ledscape_close( ledscape_t * const leds ) { // Signal a halt command leds->ws281x_0->command = 0xFF; leds->ws281x_1->command = 0xFF; pru_close(leds->pru0); pru_close(leds->pru1); } void ledscape_set_color( ledscape_frame_t * const frame, uint8_t strip, uint16_t pixel, uint8_t r, uint8_t g, uint8_t b ) { ledscape_pixel_t * const p = &frame[pixel].strip[strip]; p->r = r; p->g = g; p->b = b; }
PixelBone_Pixel::~PixelBone_Pixel() { ws281x->command = 0xFF; pru_close(pru0); }