Created
July 10, 2020 19:01
-
-
Save kauailabs/29496c8b4e069575e9e77d1985d54b1a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * The ledarray_onewire example demonstrates controlling an array of 30 LEDs controlled using the | |
| * "one wire" protocol found in the WS2811, SK6812 and WS2812 LED controllers. Otherwise known as | |
| * "neopixel" arrays, each LED is serially daisy-chained, and the Red, Green and Blue (RGB) values | |
| * for each pixel can range of 0 (off) to 255 (fully on). The values are transmitted via a series | |
| * of pulses, which have different lengths depending whether a "one" or a "zero" symbol is being | |
| * communicated. Once all LED values have been transmitted, a reset signal is transmitted (comprised | |
| * of holding the signal low for at least a "reset time period". | |
| * | |
| * Note that each controller can specify a slightly different duration for the "one" and "zero" symbols, | |
| * as specified in the controller datasheet. The LEDArray_OneWireConfig object may be configured | |
| * to specify these values. In the example below, the timing values for the SK6812 are used. | |
| * | |
| * By default, the symbol frequency is 800k symbols/second (all neopixel devices support this frequency). | |
| * The underlying bit-timing pulse frequency is equal to the symbol frequency * 10. This results in a | |
| * minimum granularity in pulse time of 1 second / 8,000,000 = 125 nanoseconds. If non-default values | |
| * are specified within the LEDArray_OneWireConfig object, they will be rounded to the nearest 125 nanosecond period. | |
| * | |
| * Currently, VMX-pi only supports "One Wire" LED Arrays on VMXChannelIndex 31. Internally, data is transmitted | |
| * to the array using the Raspberry Pi "SPI" resource, which internally uses hardware-controlled DMA transfers | |
| * when sending bits to the LEDArray. Note that by default, the Raspberry PI SPI Transmit Buffer size is 4096. | |
| * This value sets a limit on the maximum number of "pixels" in the LED Array, per the following calculation: | |
| * | |
| * BytesPerPixel = 10 bits/symbol * 3 colors * 8 symbols/color = 240 bits = 30 bytes | |
| * ResetOverHeadBytes = (55 microseconds * 800Khz * 10 bits/symbol) / 1000000 = 440 bits = 55 bytes | |
| * MaxNumPixels = (SPIBufferSize - ResetOverHeadBytes) / BytesPerPixel = (4096 - 55) / 30 bytes = 134 | |
| * | |
| * If for some reason this maximum must be exceeded, the default maximum SPI transfer size can be | |
| * increased (up to a maximum of 65536 bytes) by editing the Raspberry Pi /boot/cmdline.txt file. For example, to set the SPI transfer | |
| * size to 65536 bytes, add "spidev.bufsize=65536" to the first line of text in the /boot/cmdline.txt file | |
| * and then reboot the Raspberry Pi. Note when editing this file that errors in this file can prohibit | |
| * the Raspberry Pi from booting correctly (so be careful!) and that /boot/cmdline.txt should contain only a single line of text. | |
| * | |
| * In this example, a continuous up/down ramp of purple values is output to the array. | |
| */ | |
| #include <stdio.h> /* printf() */ | |
| #include <string.h> /* memcpy() */ | |
| #include <inttypes.h> | |
| #include "VMXPi.h" | |
| void DisplayVMXError(VMXErrorCode vmxerr) { | |
| const char *p_err_description = GetVMXErrorString(vmxerr); | |
| printf("VMXError %d: %s\n", vmxerr, p_err_description); | |
| } | |
| int main(int argc, char *argv[]) | |
| { | |
| bool realtime = true; | |
| uint8_t update_rate_hz = 50; | |
| VMXPi vmx(realtime, update_rate_hz); | |
| try { | |
| VMXErrorCode vmxerr; | |
| VMXResourceHandle ledarray_res_handle; | |
| VMXChannelInfo ledarray_channel_info = VMXChannelInfo(vmx.getIO().GetSoleChannelIndex(VMXChannelCapability::LEDArray_OneWire), VMXChannelCapability::LEDArray_OneWire); | |
| // NOTE: The Raspberry PI SPI Buffer size may need to be increased if the number of LEDs | |
| // exceeds the current buffer size. See notes above. | |
| LEDArray_OneWireConfig ledarray_cfg(30); // Configure LED Array to be 30 pixels long | |
| // Configure "OneWire" protocol timing for the SK6812, based on datasheet specifications | |
| // NOTE: Reasonable defaults for the following are provided, so this detailed configuration | |
| // may not be necessary. | |
| ledarray_cfg.SetResetWaitTimeMicroseconds(80); | |
| ledarray_cfg.SetOneSymbolHighTimeNanoseconds(600); | |
| ledarray_cfg.SetZeroSymbolHighTimeNanoseconds(300); | |
| if (!vmx.io.ActivateSinglechannelResource(ledarray_channel_info, &ledarray_cfg, ledarray_res_handle, &vmxerr)) { | |
| printf("Failed to Activate LEDArray_OneWire Resource.\n"); | |
| DisplayVMXError(vmxerr); | |
| } else { | |
| printf("Successfully Activated LEDArray_OneWire Resource Resource with VMXChannel %d\n", | |
| ledarray_channel_info.index); | |
| } | |
| LEDArrayBufferHandle buffer_handle; | |
| if (vmx.io.LEDArrayBuffer_Create(ledarray_cfg.n_pixels, buffer_handle, &vmxerr)) { | |
| if (!vmx.io.LEDArray_SetBuffer(ledarray_res_handle, buffer_handle, &vmxerr)) { | |
| printf("Error setting LED Array buffer into LEDArray Driver Resource\n"); | |
| DisplayVMXError(vmxerr); | |
| } else { | |
| printf("Successfully created LEDArray buffer and registered it with the LEDArray Driver.\n"); | |
| bool increasing = false; | |
| int red = 255; | |
| for (int i = 0; i < 10000; i++) { | |
| for (int i = 0; i < ledarray_cfg.n_pixels; i++) { | |
| int green = 0; | |
| int blue = red; | |
| if (!vmx.io.LEDArrayBuffer_SetRGBValue(buffer_handle, i, red, green, blue, &vmxerr)) { | |
| printf("Error setting RGB Value to LED Array buffer for index %d\n", i); | |
| DisplayVMXError(vmxerr); | |
| } | |
| int curr_red, curr_green, curr_blue; | |
| if (!vmx.io.LEDArrayBuffer_GetRBGValue(buffer_handle, i, curr_red, curr_green, curr_blue, &vmxerr)) { | |
| printf("Error getting RGB Value from LED Array buffer for index %d\n", i); | |
| DisplayVMXError(vmxerr); | |
| } else { | |
| if ((curr_red != red) || (curr_green != green) || (curr_blue != blue)) { | |
| printf("Readback of RGB values from LED Array buffer at index %d returned unexpected values.\n", i); | |
| } | |
| } | |
| } | |
| if (increasing) { | |
| if (red < 255) { | |
| red+= 2; | |
| } else { | |
| increasing = false; | |
| } | |
| } | |
| if (!increasing) { | |
| if (red > 20) { | |
| red-= 2; | |
| } else { | |
| increasing = true; | |
| } | |
| } | |
| if (!vmx.io.LEDArray_Render(ledarray_res_handle, &vmxerr)) { | |
| printf("Error Rendering updates via LEDArray Driver Resource\n"); | |
| DisplayVMXError(vmxerr); | |
| break; | |
| } else { | |
| // Increasing the delay here will slow the overall refresh rate, | |
| // but may decrease overall cpu usage. | |
| vmx.time.DelayMilliseconds(25); | |
| } | |
| } | |
| } | |
| if (!vmx.io.LEDArrayBuffer_Delete(buffer_handle, &vmxerr)) { | |
| printf("Error deleting LEDArray_OneWire Buffer."); | |
| DisplayVMXError(vmxerr); | |
| } else { | |
| printf("Successfully Deleted LEDArray_OneWire Buffer\n"); | |
| } | |
| } else { | |
| printf("Error creating LEDArray_OneWire Buffer."); | |
| DisplayVMXError(vmxerr); | |
| } | |
| if (!vmx.io.DeallocateResource(ledarray_res_handle, &vmxerr)) { | |
| printf("Error deallocating LEDArray_OneWire resource.\n"); | |
| DisplayVMXError(vmxerr); | |
| } else { | |
| printf("Successfully deallocated LED Array resource\n"); | |
| } | |
| } | |
| catch(const std::exception& ex){ | |
| printf("Caught exception: %s", ex.what()); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment