int o = 0;
#include <FastLED.h>
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace Constants
{
constexpr int BOARD_WIDTH = 20;
constexpr int BOARD_HEIGHT = 15;
constexpr int NUM_LEDS = BOARD_WIDTH * BOARD_HEIGHT;
constexpr int DATA_PIN = 3;
constexpr float FPS = 60;
} // namespace Constants
#endif
#ifndef VECTOR2_H
#define VECTOR2_H
struct Vector2
{
public:
int X;
int Y;
Vector2(int x, int y);
};
#endif
Vector2::Vector2(const int x, const int y)
{
X = x;
Y = y;
}
#ifndef UTILS_H
#define UTILS_H
#include <Arduino.h>
#include "FastLED.h"
class Utils
{
public:
static int bytes_to_int(byte *data, int *start_index);
static CRGB bytes_to_CRGB(byte *data, int *start_index);
static void bytes_to_CRGB_array(byte *data, int *start_index, CRGB *array, byte array_size);
static CRGB lerp_CRGB(CRGB start, CRGB goal, float progress);
static CRGB lerp_CRGB(CRGB start, CRGB middle, CRGB goal, float progress);
static CHSV random_CHSV();
static float deg2rad(float angle);
static float tan_angle(double value);
static Vector2 get_led_position_from_index(int index);
static int get_led_index_from_position(int x, int y);
static float positive_mod(float dividend, float divisor);
static float positive_mod(float dividend, int divisor);
static int positive_mod(int dividend, int divisor);
static uint32_t hash(uint32_t n);
};
#endif
#include <Arduino.h>
#include <FastLED.h>
#include <math.h>
/**
* Converts bytes to an integer
* Assumes the date provided is in litte-endian
*
* @param data The data stream to convert from
* @param start_index The position of the first byte of the integer
*
* @returns a new integer
*/
int Utils::bytes_to_int(byte *data, int *start_index)
{
int result = 0;
for (int i = *start_index + (int)(sizeof(result)); i >= *start_index; i--)
{
result = (result << 8) + data[i];
}
*start_index += sizeof(result);
return result;
}
/**
* Converts bytes to a \a CRGB object
*
* @param data The data stream to convert from
* @param start_index The position of the first byte of the color
*
* @returns a new \a CRGB object
*/
CRGB Utils::bytes_to_CRGB(byte *data, int *start_index)
{
byte r = data[(*start_index)++];
byte g = data[(*start_index)++];
byte b = data[(*start_index)++];
return {r, g, b};
}
/**
* Converts bytes to a \a CRGB array of length \a array_size
*
* @param data The data stream to convert from
* @param start_index The position of the first byte of the first color
* @param array The array to store the \a CRGB colors in
* @param array_size the amount of colors to read from \a data
*/
void Utils::bytes_to_CRGB_array(byte *data, int *start_index, CRGB *array, byte array_size)
{
for (int i = 0; i < array_size; i++)
{
array[i] = Utils::bytes_to_CRGB(data, start_index);
}
}
/**
* Lerps between \a start and \a goal
*
* @param start The initial color
* @param goal The target color
* @param progress The progress between \a start and \a goal between 0 and 1
*
* @returns The color between \a start and \a end at \a progress
*/
CRGB Utils::lerp_CRGB(CRGB start, CRGB goal, float progress)
{
progress = constrain(progress, 0, 1);
uint8_t r = start.r + (progress * (goal.r - start.r));
uint8_t g = start.g + (progress * (goal.g - start.g));
uint8_t b = start.b + (progress * (goal.b - start.b));
return {r, g, b};
}
/**
* Lerps between \a start, \a middle and \a goal
*
* @param start The initial color
* @param middle The middle color
* @param goal The target color
* @param progress The progress between \a start, \a middle and \a goal between 0 and 1
*
* @returns The color between \a start, \a middle and \a end at \a progress
*/
CRGB Utils::lerp_CRGB(CRGB start, CRGB middle, CRGB goal, float progress)
{
if (progress < 0.5f)
{
return Utils::lerp_CRGB(start, middle, 2 * progress);
}
else
{
progress = 2 * (progress - 0.5);
return Utils::lerp_CRGB(middle, goal, progress);
}
}
/**
* @returns A random, bright \a CHSV
*/
CHSV Utils::random_CHSV()
{
return CHSV(random8(), 255, 255);
}
/**
* @param angle The angle to convert to radians
*
* @returns \a angle converted into radians
*/
float Utils::deg2rad(float angle)
{
return angle * PI / 180;
}
/**
* @param value The value to take the cotangent of, measured in degrees
*
* @returns The cotangent of \a value, measured in radians
*/
float Utils::tan_angle(double value)
{
return tan(deg2rad(value));
}
/**
* Calculates the position for a LED at the given index assuming a zig-zagging LED-matrix
*
* -------------
* | 0 | 1 | 2 |
* |-----------|
* | 5 | 4 | 3 |
* |-----------|
* | 6 | 7 | 8 |
* -------------
*
* @param index The index of the LED to get the position from
*
* @returns A \a Vector2 containing the column and row position for the given index
*/
Vector2 Utils::get_led_position_from_index(const int index)
{
int row = index / Constants::BOARD_WIDTH;
int col = row % 2 == 0 ? index % Constants::BOARD_WIDTH : Constants::BOARD_WIDTH - 1 - (index % Constants::BOARD_WIDTH);
return Vector2(col, row);
}
/**
* Calculates the index for a LED at the given position assuming a zig-zagging LED-matrix
* 0 1 2
* -------------
* 0 | 0 | 1 | 2 |
* |-----------|
* 1 | 5 | 4 | 3 |
* |-----------|
* 2 | 6 | 7 | 8 |
* -------------
*
* @param x The x component of the position
* @param y The y component of the position
*
* @returns A \a int representing the index of the led at postion [x, y]
*/
int Utils::get_led_index_from_position(const int x, const int y)
{
int index;
if (y % 2 == 0||true)
{
index = (Constants::BOARD_WIDTH * y) + x;
}
else
{
index = (Constants::BOARD_WIDTH * (y + 1)) - 1 - x;
}
return index;
}
/**
* @param divisor The divisor
* @param dividend The dividend
*
* @returns The floating point remainder of \a divisor / \a dividend, such that -1 % 3 == 2
*/
float Utils::positive_mod(float dividend, float divisor)
{
return fmod(fmod(dividend, divisor) + divisor, divisor);
}
/**
* @param divisor The divisor
* @param dividend The dividend
*
* @returns The floating point remainder of \a divisor / \a dividend, such that -1 % 3 == 2
*/
float Utils::positive_mod(float dividend, int divisor)
{
return fmod(fmod(dividend, divisor) + divisor, divisor);
}
/**
* @param divisor The divisor
* @param dividend The dividend
*
* @returns The integer remainder of \a divisor / \a dividend, such that -1 % 3 == 2
*/
int Utils::positive_mod(int dividend, int divisor)
{
return ((dividend % divisor) + divisor) % divisor;
}
/**
* Taken from https://stackoverflow.com/a/12996028/9209836
*
* @param n The number to hash
*
* @returns The hashed value for n
*/
uint32_t Utils::hash(uint32_t n)
{
n = ((n >> 16) ^ n) * 0x45d9f3b;
n = ((n >> 16) ^ n) * 0x45d9f3b;
n = (n >> 16) ^ n;
return n;
}
unsigned long lastUpdate = 0;
unsigned long currentTime = 0;
int delta = 0;
// Define the array of leds
CRGB leds[Constants::NUM_LEDS];
CRGB colors[] = {CRGB(255, 0, 0), CRGB(0, 255, 0), CRGB(0, 0, 255)};
void setup() {
Serial.begin(115200);
FastLED.addLeds<WS2812B, 3, GRB>(leds, Constants::NUM_LEDS);
FastLED.show();
}
void processBluetoothInput()
{
// Call destructor for lightMode on switch
if (Serial.available())
{
Serial.println(Serial.read());
}
}
void loop()
{
processBluetoothInput();
}