001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj; 006 007import edu.wpi.first.wpilibj.util.Color; 008import edu.wpi.first.wpilibj.util.Color8Bit; 009 010/** Buffer storage for Addressable LEDs. */ 011public class AddressableLEDBuffer { 012 byte[] m_buffer; 013 014 /** 015 * Constructs a new LED buffer with the specified length. 016 * 017 * @param length The length of the buffer in pixels 018 */ 019 public AddressableLEDBuffer(int length) { 020 m_buffer = new byte[length * 4]; 021 } 022 023 /** 024 * Sets a specific led in the buffer. 025 * 026 * @param index the index to write 027 * @param r the r value [0-255] 028 * @param g the g value [0-255] 029 * @param b the b value [0-255] 030 */ 031 public void setRGB(int index, int r, int g, int b) { 032 m_buffer[index * 4] = (byte) b; 033 m_buffer[(index * 4) + 1] = (byte) g; 034 m_buffer[(index * 4) + 2] = (byte) r; 035 m_buffer[(index * 4) + 3] = 0; 036 } 037 038 /** 039 * Sets a specific led in the buffer. 040 * 041 * @param index the index to write 042 * @param h the h value [0-180) 043 * @param s the s value [0-255] 044 * @param v the v value [0-255] 045 */ 046 public void setHSV(final int index, final int h, final int s, final int v) { 047 if (s == 0) { 048 setRGB(index, v, v, v); 049 return; 050 } 051 052 // The below algorithm is copied from Color.fromHSV and moved here for 053 // performance reasons. 054 055 // Loosely based on 056 // https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB 057 // The hue range is split into 60 degree regions where in each region there 058 // is one rgb component at a low value (m), one at a high value (v) and one 059 // that changes (X) from low to high (X+m) or high to low (v-X) 060 061 // Difference between highest and lowest value of any rgb component 062 final int chroma = (s * v) / 255; 063 064 // Because hue is 0-180 rather than 0-360 use 30 not 60 065 final int region = (h / 30) % 6; 066 067 // Remainder converted from 0-30 to 0-255 068 final int remainder = (int) Math.round((h % 30) * (255 / 30.0)); 069 070 // Value of the lowest rgb component 071 final int m = v - chroma; 072 073 // Goes from 0 to chroma as hue increases 074 final int X = (chroma * remainder) >> 8; 075 076 switch (region) { 077 case 0: 078 setRGB(index, v, X + m, m); 079 break; 080 case 1: 081 setRGB(index, v - X, v, m); 082 break; 083 case 2: 084 setRGB(index, m, v, X + m); 085 break; 086 case 3: 087 setRGB(index, m, v - X, v); 088 break; 089 case 4: 090 setRGB(index, X + m, m, v); 091 break; 092 default: 093 setRGB(index, v, m, v - X); 094 break; 095 } 096 } 097 098 /** 099 * Sets a specific LED in the buffer. 100 * 101 * @param index The index to write 102 * @param color The color of the LED 103 */ 104 public void setLED(int index, Color color) { 105 setRGB(index, (int) (color.red * 255), (int) (color.green * 255), (int) (color.blue * 255)); 106 } 107 108 /** 109 * Sets a specific LED in the buffer. 110 * 111 * @param index The index to write 112 * @param color The color of the LED 113 */ 114 public void setLED(int index, Color8Bit color) { 115 setRGB(index, color.red, color.green, color.blue); 116 } 117 118 /** 119 * Gets the buffer length. 120 * 121 * @return the buffer length 122 */ 123 public int getLength() { 124 return m_buffer.length / 4; 125 } 126 127 /** 128 * Gets the color at the specified index. 129 * 130 * @param index the index to get 131 * @return the LED color at the specified index 132 */ 133 public Color8Bit getLED8Bit(int index) { 134 return new Color8Bit( 135 m_buffer[index * 4 + 2] & 0xFF, m_buffer[index * 4 + 1] & 0xFF, m_buffer[index * 4] & 0xFF); 136 } 137 138 /** 139 * Gets the color at the specified index. 140 * 141 * @param index the index to get 142 * @return the LED color at the specified index 143 */ 144 public Color getLED(int index) { 145 return new Color( 146 (m_buffer[index * 4 + 2] & 0xFF) / 255.0, 147 (m_buffer[index * 4 + 1] & 0xFF) / 255.0, 148 (m_buffer[index * 4] & 0xFF) / 255.0); 149 } 150}