Пример #1
0
PixelBone_Pixel::PixelBone_Pixel(uint16_t pixel_count)
    : pru0(pru_init(0)), num_pixels(pixel_count),
      buffer_size(pixel_count * sizeof(pixel_t)) {
  if (2 * buffer_size > pru0->ddr_size)
    die("Pixel data needs at least 2 * %zu, only %zu in DDR\n", buffer_size,
        pru0->ddr_size);

  ws281x = (ws281x_command_t *)pru0->data_ram;
  *(ws281x) = ws281x_command_t((unsigned)pixel_count);

  // Configure all of our output pins.
  pru_gpio(0, gpios0, 1, 0);

  // Initiate the PRU0 program
  pru_exec(pru0, "./ws281x.bin");

  // Watch for a done response that indicates a proper startup
  // TODO: timeout if it fails
  std::cout << "waiting for response from pru0... ";
  while (!ws281x->response)
    ;
  std::cout << "OK" << std::endl;
};
Пример #2
0
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;
}