Completed the board manager rewrite

This commit is contained in:
2024-08-22 21:07:32 -04:00
parent 48f83eee38
commit 3e4f0124db
17 changed files with 666 additions and 408 deletions

View File

@@ -2,20 +2,25 @@
#include <cstdint>
#include <array>
#include <WString.h>
#include "Cube.h"
#include "Color.h"
#include "Vector3D.h"
template <uint32_t X_SIZE, uint32_t Y_SIZE, uint32_t Z_SIZE>
template <V3D &BOARD_DIMS>
class Board{
public:
enum PLANE_NORMAL : uint32_t{
X = 0,
Y,
Z
};
Board();
~Board() = default;
constexpr uint32_t GetXSize() const{return X_SIZE;}
constexpr uint32_t GetYSize() const{return Y_SIZE;}
constexpr uint32_t GetZSize() const {return Z_SIZE;}
constexpr uint32_t GetNumberCubes() const{return X_SIZE * Y_SIZE * Z_SIZE;}
constexpr V3D &GetSize() const{return BOARD_DIMS;}
constexpr uint32_t GetNumberCubes() const{return BOARD_DIMS.x * BOARD_DIMS.y * BOARD_DIMS.z;}
/**
* @brief Returns a string in the format:
@@ -28,13 +33,25 @@ class Board{
/**
* @brief Returns a bool array representing the board
*/
std::array<uint32_t, X_SIZE * Y_SIZE> &LinearizeBoard() const;
std::array<uint32_t, BOARD_DIMS.x * BOARD_DIMS.y> &LinearizeBoard() const;
void Update();
void FillColor(const V3D &color);
void FillColor(const Color &color);
void SetCubeColor(const V3D &position, const V3D &color);
void SetCubeColor(uint32_t x_coord, uint32_t y_cord, uint32_t z_cord, const Color &color);
void SetCubeOccupation(const V3D &position, bool occupation);
bool BoardStateChanged(){return this->boardStateHasChanged;}
void ClearBoardStateChanged(){this->boardStateHasChanged = false;}
/**
* @brief Get a column along any axis
* @param column .z specifies the normal direction of the plane (see PLANE_NORMAL), and
* the x,y values specify the location of the column in that plane
* to fill. IE To fill one stack at 0,2 I would say give V3D(0,2,PLANE_NORMAL::Z)
* @returns an array of cubes along that column
*/
Cube * SliceBoard(const V3D &column);
private:
// this is a 3d array of cubes to represent the board. Good luck visualizing it
@@ -53,13 +70,13 @@ class Board{
bool boardStateHasChanged;
};
template <uint32_t X_SIZE, uint32_t Y_SIZE, uint32_t Z_SIZE>
Board<X_SIZE, Y_SIZE, Z_SIZE>::Board(){
template <V3D &BOARD_DIMS>
Board<BOARD_DIMS>::Board(){
this->FillColor(Color(0,0,0));
}
template <uint32_t X_SIZE, uint32_t Y_SIZE, uint32_t Z_SIZE>
void Board<X_SIZE, Y_SIZE, Z_SIZE>::ToStackString(String &stringBuffer) const{
template <V3D &BOARD_DIMS>
void Board<BOARD_DIMS>::ToStackString(String &stringBuffer) const{
std::array<uint32_t, X_SIZE*Y_SIZE> linearizedBoard = this->LinearizeBoard();
stringBuffer += "!" + String(linearizedBoard[0]);
@@ -71,10 +88,10 @@ void Board<X_SIZE, Y_SIZE, Z_SIZE>::ToStackString(String &stringBuffer) const{
stringBuffer += ";";
}
template <uint32_t X_SIZE, uint32_t Y_SIZE, uint32_t Z_SIZE>
std::array<uint32_t, X_SIZE * Y_SIZE> & Board<X_SIZE, Y_SIZE, Z_SIZE>::LinearizeBoard() const{
template <V3D &BOARD_DIMS>
std::array<uint32_t, BOARD_DIMS.x * BOARD_DIMS.y> & Board<BOARD_DIMS>::LinearizeBoard() const{
// convert the board into one array where each entry represents the height of one stack
std::array<uint32_t, X_SIZE*Y_SIZE> linearizedBoard;
std::array<uint32_t, BOARD_DIMS.x * BOARD_DIMS.y> linearizedBoard;
for(uint32_t x{0}; x < X_SIZE; x++){
for(uint32_t y{0}; y < Y_SIZE; y++){
for(uint32_t z{0}; z < Z_SIZE; z++){
@@ -86,24 +103,63 @@ std::array<uint32_t, X_SIZE * Y_SIZE> & Board<X_SIZE, Y_SIZE, Z_SIZE>::Linearize
return linearizedBoard;
}
template <uint32_t X_SIZE, uint32_t Y_SIZE, uint32_t Z_SIZE>
void Board<X_SIZE, Y_SIZE, Z_SIZE>::Update(){
}
template <uint32_t X_SIZE, uint32_t Y_SIZE, uint32_t Z_SIZE>
void Board<X_SIZE, Y_SIZE, Z_SIZE>::FillColor(const Color &color){
template <V3D &BOARD_DIMS>
void Board<BOARD_DIMS>::FillColor(const V3D &color){
for(uint32_t x{0}; x < X_SIZE; x++){
for(uint32_t y{0}; y < Y_SIZE; y++){
for(uint32_t z{0}; z < Z_SIZE; z++){
this->cubes[x][y][z].SetColor(color);
this->cubes[x][y][z].color = color;
}
}
}
}
template <uint32_t X_SIZE, uint32_t Y_SIZE, uint32_t Z_SIZE>
void Board<X_SIZE, Y_SIZE, Z_SIZE>::SetCubeColor(uint32_t x_coord, uint32_t y_cord, uint32_t z_cord, const Color &color){
this->cubes[x][y][z].SetColor(color);
template <V3D &BOARD_DIMS>
void Board<BOARD_DIMS>::SetCubeColor(const V3D &position, const V3D &color){
this->cubes[position.x][position.y][position.z].color = color;
}
template <V3D &BOARD_DIMS>
void Board<BOARD_DIMS>::SetCubeOccupation(const V3D &position, bool occupation){
bool oldOccupation{this->cubes[position.x][position.y][position.z].occupied};
this->cubes[position.x][position.y][position.z].occupied = occupation;
if(occupation != oldOccupation) this->boardStateHasChanged = true;
}
template <V3D &BOARD_DIMS>
Cube * Board<BOARD_DIMS>::SliceBoard(const V3D &column){
uint32_t columnLength{0};
V3D indexIncriment{};
V3D position{};
switch(column.z){
case Board::PLANE_NORMAL::X:
columnLength = BOARD_DIMS.x;
indexIncriment.x = 1;
position.z = column.x;
position.y = column.y;
break;
case Board::PLANE_NORMAL::Y:
columnLength = BOARD_DIMS.Y;
indexIncriment.y = 1;
position.x = column.x;
position.z = column.y;
break;
default:
case Board::PLANE_NORMAL::Z:
columnLength = BOARD_DIMS.Z;
indexIncriment.z = 1;
position.x = column.x;
position.y = column.y;
break;
}
std::array<Cube *, columnLength> columnSlice;
for(uint32_t i = 0; i < columnLength; i++){
V3D cubePosition = indexIncriment * i + position;
columnSlice[i] = &(this->cubes[cubePosition.x][cubePosition.y][cubePosition.z]);
}
return columnSlice.data();
}

View File

@@ -1,38 +0,0 @@
#include "BoardLayout.h"
uint8_t BoardLayout::GetNumberStacks(){
return this->boardWidth * this->boardHeight;
}
void BoardLayout::SetStackColors(uint8_t stackNum, Color * colors){
CubeStack * stack = this->stacks[stackNum];
stack->SetLEDColors(colors, this->boardHeight);
}
bool BoardLayout::BoardStateHasChanged(){
uint16_t boardState[this->boardWidth * this->boardLength];
this->GetBoardState(boardState);
// compare the board state to the last board state
for(int i = 0; i < (this->boardWidth * this->boardLength); i++){
uint16_t stackState = boardState[i];
uint16_t lastStackState = (this->lastBoardState)[i];
if(stackState != lastStackState){
// copy the board state into the last board state
for(int k = 0; k < (this->boardWidth * this->boardLength); k++){
this->lastBoardState[k] = boardState[k];
}
return true;
}
}
return false;
}
void BoardLayout::GetBoardState(uint16_t * boardStateBuffer){
for(int i = 0; i < (this->boardLength * this->boardWidth); i++){
CubeStack * stack = this->stacks[i];
stack->SendLEDData(); // Enable this if you want to constantly stream LED data
boardStateBuffer[i] = stack->GetNumberCubes();
}
}

View File

@@ -1,69 +0,0 @@
/**
* @brief This is the full board manager which handles the state of every stack on the board
*/
#pragma once
#include "CubeStack.h"
#include "Color.h"
class BoardLayout{
public:
/**
* @brief BoardLayout COnstructor
*/
BoardLayout(uint8_t boardWidth, uint8_t boardLength, uint8_t boardHeight, CubeStack ** stacks) :
boardWidth(boardWidth),
boardLength(boardLength),
boardHeight(boardHeight),
stacks(stacks)
{
this->lastBoardState = new uint16_t[boardWidth * boardLength];
}
/**
* @brief Check if our board state has changed
* @return true if the board state has changed, false otherwise
*/
bool BoardStateHasChanged();
/**
* @brief Get the Number of Stacks
* @return the number of stacks
*/
uint8_t GetNumberStacks();
/**
* @brief Set the LED Colors
* @param stackNum the stack index you would like to address.
* From top left to bottom right, the stack numbers are as follows:
* | 0 1 2 |
* | 3 4 5 |
* | 6 7 8 |
* @param Colors the array of colors to set the LEDs in a stack to
*/
void SetStackColors(uint8_t stackNum, Color * colors);
/**
* @brief Get the board population state
* @param boardStateBuffer the buffer to write the board state to. It must be at least boardWidth * boardLength in length
*/
void GetBoardState(uint16_t * boardStateBuffer);
private:
uint8_t boardWidth;
uint8_t boardLength;
uint8_t boardHeight;
/*
An array of arrays of stacks
[ [stack1, stack2, stack3],
[stack4, stack5, stack6],
[stack7, stack8, stack9] ]
etc
*/
CubeStack ** stacks;
// records the last known board state
uint16_t * lastBoardState;
};

View File

@@ -1,22 +0,0 @@
/**
* @file Color.h
* @brief This file contains the color struct
*/
#pragma once
#include <Arduino.h>
// store a color
struct Color{
public:
// create a constructor for this struct
Color(uint8_t red, uint8_t green, uint8_t blue) :
red(red),
green(green),
blue(blue)
{}
Color() = default;
uint8_t red{0};
uint8_t green{0};
uint8_t blue{0};
};

View File

@@ -1,61 +0,0 @@
#include "CubeStack.h"
CubeStack::CubeStack(uint16_t ADCPin, uint16_t ledPin, uint8_t numLEDs){
this->ADCPin = ADCPin;
this->blockLights = *(new Adafruit_NeoPixel(numLEDs*2, ledPin, NEO_GRB + NEO_KHZ800));
this->ledColors = new Color[numLEDs];
this->numLEDs = numLEDs;
// initialize the LED colors to off
for(int i = 0; i < numLEDs; i++){
this->ledColors[i] = *(new Color(0, 0, 0));
}
};
uint32_t CubeStack::GetNumberCubes(Cube &cube){
// read the ADC and return the number of cubes
/*
0 cubes: 1 : 4095-3400
1 cube: 1/2 3400-2500
2 cubes: 1/3 2500-1850
3 cubes: 1/4 1850-0
*/
uint16_t value = analogRead(cube.ADCPin);
uint16_t lowPassADCRead = static_cast<uint16_t>((static_cast<float>(cube.lastADCReading) * 0.9) + (static_cast<float>(value) * 0.1));
// temporary definitions to define value ranges:
uint16_t zeroCubesHigh = 4095;
uint16_t zeroCubesLow = 3400;
uint16_t oneCubeLow = 2500;
uint16_t twoCubesLow = 1850;
uint16_t threeCubesLow = 0;
uint8_t stackHeight = 0;
if(lowPassADCRead >= zeroCubesLow && lowPassADCRead <= zeroCubesHigh){
stackHeight = 0;
}
else if(lowPassADCRead >= oneCubeLow){
stackHeight = 1;
}
else if(lowPassADCRead >= twoCubesLow){
stackHeight = 2;
}
else if(lowPassADCRead >= threeCubesLow){
stackHeight = 3;
}
return stackHeight;
}
void CubeStack::SendLEDData(){
// we always initialize before we do anything because other CubeStacks could be hogging the hardware
// between our writes
this->blockLights.begin();
// set the LED colors
for(int i = 0; i < this->numLEDs; i++){
this->blockLights.setPixelColor(i*2, this->blockLights.Color(this->ledColors[i].red, this->ledColors[i].green, this->ledColors[i].blue));
this->blockLights.setPixelColor((i*2 + 1), this->blockLights.Color(this->ledColors[i].red, this->ledColors[i].green, this->ledColors[i].blue));
}
this->blockLights.show();
}

View File

@@ -1,31 +0,0 @@
/**
* @brief this manages a single cube stack and the lighting / detecting of how many cubes
*/
#pragma once
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include "Color.h"
#include "Cube.h"
namespace CubeStack{
/**
* @brief Construct a new Cube Stack object
* @param ADCPin the pin that the ADC is connected to
* @param ledPin the pin that the LED is connected to
*/
CubeStack(uint16_t ADCPin, uint16_t ledPin, uint8_t numLEDs);
/**
* @brief Returns the number of cubes in the stack
* @return the number of cubes in the stack
*/
uint32_t GetNumberCubes(Cube &cube);
/**
* @brief sends the LED data to the LED strip
*/
void SendLEDData();
};