Got the refactor building

This commit is contained in:
2024-08-22 23:00:55 -04:00
parent 3e4f0124db
commit 3a49761b66
10 changed files with 274 additions and 224 deletions

View File

@@ -8,55 +8,58 @@
#include <array> #include <array>
#include "PINOUT.h" #include "PINOUT.h"
#include "BoardDriverTypes.h" #include "BoardTypes.h"
#include "Vector3D.h"
// define the physical dimensions of the board // define the physical dimensions of the board
static constexpr uint32_t BOARD_WIDTH{3}; static constexpr uint32_t BOARD_WIDTH{3};
static constexpr uint32_t BOARD_LENGTH{3}; static constexpr uint32_t BOARD_LENGTH{3};
static constexpr uint32_t BOARD_HEIGHT{3}; static constexpr uint32_t BOARD_HEIGHT{3};
static constexpr V3D BOARD_DIMENSIONS{BOARD_WIDTH, BOARD_LENGTH, BOARD_HEIGHT};
// define the number of stacks // define the number of stacks
static constexpr uint32_t NUMBER_STACKS{BOARD_WIDTH * BOARD_LENGTH}; static constexpr uint32_t NUMBER_STACKS{BOARD_WIDTH * BOARD_LENGTH};
// define the CubeStacks // define the CubeStacks
static BoardDriverTypes::CubeStack stack1{ static BOARD_TYPES::CubeStack stack1{
.adcPin=STACK1_ADC_PIN, .adcPin=STACK1_ADC_PIN,
.ledPin=STACK1_LED_PIN .ledPin=STACK1_LED_PIN
}; };
static BoardDriverTypes::CubeStack stack2{ static BOARD_TYPES::CubeStack stack2{
.adcPin=STACK2_ADC_PIN, .adcPin=STACK2_ADC_PIN,
.ledPin=STACK2_LED_PIN .ledPin=STACK2_LED_PIN
}; };
static BoardDriverTypes::CubeStack stack3{ static BOARD_TYPES::CubeStack stack3{
.adcPin=STACK3_ADC_PIN, .adcPin=STACK3_ADC_PIN,
.ledPin=STACK3_LED_PIN .ledPin=STACK3_LED_PIN
}; };
static BoardDriverTypes::CubeStack stack4{ static BOARD_TYPES::CubeStack stack4{
.adcPin=STACK4_ADC_PIN, .adcPin=STACK4_ADC_PIN,
.ledPin=STACK4_LED_PIN .ledPin=STACK4_LED_PIN
}; };
static BoardDriverTypes::CubeStack stack5{ static BOARD_TYPES::CubeStack stack5{
.adcPin=STACK5_ADC_PIN, .adcPin=STACK5_ADC_PIN,
.ledPin=STACK5_LED_PIN .ledPin=STACK5_LED_PIN
}; };
static BoardDriverTypes::CubeStack stack6{ static BOARD_TYPES::CubeStack stack6{
.adcPin=STACK6_ADC_PIN, .adcPin=STACK6_ADC_PIN,
.ledPin=STACK6_LED_PIN .ledPin=STACK6_LED_PIN
}; };
static BoardDriverTypes::CubeStack stack7{ static BOARD_TYPES::CubeStack stack7{
.adcPin=STACK7_ADC_PIN, .adcPin=STACK7_ADC_PIN,
.ledPin=STACK7_LED_PIN .ledPin=STACK7_LED_PIN
}; };
static BoardDriverTypes::CubeStack stack8{ static BOARD_TYPES::CubeStack stack8{
.adcPin=STACK8_ADC_PIN, .adcPin=STACK8_ADC_PIN,
.ledPin=STACK8_LED_PIN .ledPin=STACK8_LED_PIN
}; };
static BoardDriverTypes::CubeStack stack9{ static BOARD_TYPES::CubeStack stack9{
.adcPin=STACK9_ADC_PIN, .adcPin=STACK9_ADC_PIN,
.ledPin=STACK9_LED_PIN .ledPin=STACK9_LED_PIN
}; };
static std::array<BoardDriverTypes::CubeStack, NUMBER_STACKS> stacks{ static std::array<BOARD_TYPES::CubeStack, NUMBER_STACKS> stacks{
stack1, stack2, stack3, stack1, stack2, stack3,
stack4, stack5, stack6, stack4, stack5, stack6,
stack7, stack8, stack9 stack7, stack8, stack9

View File

@@ -5,45 +5,47 @@
#pragma once #pragma once
#include <cstdint>
// Stack pins // Stack pins
// Stack 1 pins // Stack 1 pins
#define STACK1_ADC_PIN 6 static constexpr uint8_t STACK1_ADC_PIN{6};
#define STACK1_LED_PIN 11 static constexpr uint8_t STACK1_LED_PIN{11};
// Stack 2 pins // Stack 2 pins
#define STACK2_ADC_PIN 16 static constexpr uint8_t STACK2_ADC_PIN{16};
#define STACK2_LED_PIN 14 static constexpr uint8_t STACK2_LED_PIN{14};
// Stack 3 pins // Stack 3 pins
#define STACK3_ADC_PIN 8 static constexpr uint8_t STACK3_ADC_PIN{8};
#define STACK3_LED_PIN 45 static constexpr uint8_t STACK3_LED_PIN{45};
// Stack 4 pins // Stack 4 pins
#define STACK4_ADC_PIN 5 static constexpr uint8_t STACK4_ADC_PIN{5};
#define STACK4_LED_PIN 10 static constexpr uint8_t STACK4_LED_PIN{10};
// Stack 5 pins // Stack 5 pins
#define STACK5_ADC_PIN 15 static constexpr uint8_t STACK5_ADC_PIN{15};
#define STACK5_LED_PIN 13 static constexpr uint8_t STACK5_LED_PIN{13};
// Stack 6 pins // Stack 6 pins
#define STACK6_ADC_PIN 18 static constexpr uint8_t STACK6_ADC_PIN{18};
#define STACK6_LED_PIN 38 static constexpr uint8_t STACK6_LED_PIN{38};
// Stack 7 pins // Stack 7 pins
#define STACK7_ADC_PIN 4 static constexpr uint8_t STACK7_ADC_PIN{4};
#define STACK7_LED_PIN 9 static constexpr uint8_t STACK7_LED_PIN{9};
// Stack 8 pins // Stack 8 pins
#define STACK8_ADC_PIN 7 static constexpr uint8_t STACK8_ADC_PIN{7};
#define STACK8_LED_PIN 12 static constexpr uint8_t STACK8_LED_PIN{12};
// Stack 9 pins // Stack 9 pins
#define STACK9_ADC_PIN 17 static constexpr uint8_t STACK9_ADC_PIN{17};
#define STACK9_LED_PIN 37 static constexpr uint8_t STACK9_LED_PIN{37};
// Bluetooth module configuration pins // Bluetooth module configuration pins
#define BT_STATE_PIN 2 static constexpr uint8_t BT_STATE_PIN{2};
#define BT_EN_PIN 3 static constexpr uint8_t BT_EN_PIN{3};

View File

@@ -5,7 +5,7 @@
class V3D{ class V3D{
public: public:
V3D(uint32_t x=0, uint32_t y=0, uint32_t z=0): constexpr V3D(uint32_t x=0, uint32_t y=0, uint32_t z=0):
x(x), x(x),
y(y), y(y),
z(z){} z(z){}
@@ -41,6 +41,14 @@ class V3D{
return vector; return vector;
} }
V3D operator*(const uint32_t scalar){
V3D vector{};
vector.x = this->x * scalar;
vector.y = this->y * scalar;
vector.z = this->z * scalar;
return vector;
}
bool operator==(const V3D &other){ bool operator==(const V3D &other){
return this->x == other.x && this->y == other.y && this->z == other.z; return this->x == other.x && this->y == other.y && this->z == other.z;
} }

View File

@@ -7,19 +7,14 @@
#include "Cube.h" #include "Cube.h"
#include "Vector3D.h" #include "Vector3D.h"
template <V3D &BOARD_DIMS> template <const V3D &BOARD_DIMS>
class Board{ class Board{
public: public:
enum PLANE_NORMAL : uint32_t{
X = 0,
Y,
Z
};
Board(); Board();
~Board() = default; ~Board() = default;
constexpr V3D &GetSize() const{return BOARD_DIMS;} constexpr const V3D &GetSize() const{return BOARD_DIMS;}
constexpr uint32_t GetNumberCubes() const{return BOARD_DIMS.x * BOARD_DIMS.y * BOARD_DIMS.z;} constexpr uint32_t GetNumberCubes() const{return BOARD_DIMS.x * BOARD_DIMS.y * BOARD_DIMS.z;}
/** /**
@@ -42,7 +37,7 @@ class Board{
void SetCubeOccupation(const V3D &position, bool occupation); void SetCubeOccupation(const V3D &position, bool occupation);
bool BoardStateChanged(){return this->boardStateHasChanged;} bool BoardStateChanged(){return this->boardStateHasChanged;}
void ClearBoardStateChanged(){this->boardStateHasChanged = false;} void SetStateChanged(bool boardState){this->boardStateHasChanged = boardState;}
/** /**
* @brief Get a column along any axis * @brief Get a column along any axis
@@ -51,7 +46,7 @@ class Board{
* to fill. IE To fill one stack at 0,2 I would say give V3D(0,2,PLANE_NORMAL::Z) * 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 * @returns an array of cubes along that column
*/ */
Cube * SliceBoard(const V3D &column); Cube ** SliceBoard(const V3D &column);
private: private:
// this is a 3d array of cubes to represent the board. Good luck visualizing it // this is a 3d array of cubes to represent the board. Good luck visualizing it
@@ -65,36 +60,34 @@ class Board{
| | / | | /
|____________|/ |____________|/
*/ */
std::array<std::array<std::array<Cube, Z_SIZE>, Y_SIZE>, X_SIZE> cubes; std::array<std::array<std::array<Cube, BOARD_DIMS.z>, BOARD_DIMS.y>, BOARD_DIMS.x> cubes;
bool boardStateHasChanged; bool boardStateHasChanged;
}; };
template <V3D &BOARD_DIMS> template <const V3D &BOARD_DIMS>
Board<BOARD_DIMS>::Board(){ Board<BOARD_DIMS>::Board(){
this->FillColor(Color(0,0,0)); this->FillColor(V3D{});
} }
template <V3D &BOARD_DIMS> template <const V3D &BOARD_DIMS>
void Board<BOARD_DIMS>::ToStackString(String &stringBuffer) const{ void Board<BOARD_DIMS>::ToStackString(String &stringBuffer) const{
std::array<uint32_t, X_SIZE*Y_SIZE> linearizedBoard = this->LinearizeBoard(); std::array<uint32_t, BOARD_DIMS.x*BOARD_DIMS.y> linearizedBoard = this->LinearizeBoard();
stringBuffer += "!" + String(linearizedBoard[0]); stringBuffer += String(linearizedBoard[0]);
for(uint32_t i = 0; i < X_SIZE * Y_SIZE; i++){ for(uint32_t i = 0; i < BOARD_DIMS.x * BOARD_DIMS.y; i++){
stringBuffer += "," + String(linearizedBoard[i]); stringBuffer += "," + String(linearizedBoard[i]);
} }
stringBuffer += ";";
} }
template <V3D &BOARD_DIMS> template <const V3D &BOARD_DIMS>
std::array<uint32_t, BOARD_DIMS.x * BOARD_DIMS.y> & Board<BOARD_DIMS>::LinearizeBoard() const{ 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 // convert the board into one array where each entry represents the height of one stack
std::array<uint32_t, BOARD_DIMS.x * BOARD_DIMS.y> linearizedBoard; std::array<uint32_t, BOARD_DIMS.x * BOARD_DIMS.y> linearizedBoard;
for(uint32_t x{0}; x < X_SIZE; x++){ for(uint32_t x{0}; x < BOARD_DIMS.x; x++){
for(uint32_t y{0}; y < Y_SIZE; y++){ for(uint32_t y{0}; y < BOARD_DIMS.y; y++){
for(uint32_t z{0}; z < Z_SIZE; z++){ for(uint32_t z{0}; z < BOARD_DIMS.z; z++){
bool isOccupied{this->cubes[x][y][z].isOccupied}; bool isOccupied{this->cubes[x][y][z].isOccupied};
linearizedBoard[x + y*3] += static_cast<uint32_t>(isOccupied); linearizedBoard[x + y*3] += static_cast<uint32_t>(isOccupied);
} }
@@ -103,63 +96,63 @@ std::array<uint32_t, BOARD_DIMS.x * BOARD_DIMS.y> & Board<BOARD_DIMS>::Linearize
return linearizedBoard; return linearizedBoard;
} }
template <V3D &BOARD_DIMS> template <const V3D &BOARD_DIMS>
void Board<BOARD_DIMS>::FillColor(const V3D &color){ void Board<BOARD_DIMS>::FillColor(const V3D &color){
for(uint32_t x{0}; x < X_SIZE; x++){ for(uint32_t x{0}; x < BOARD_DIMS.x; x++){
for(uint32_t y{0}; y < Y_SIZE; y++){ for(uint32_t y{0}; y < BOARD_DIMS.y; y++){
for(uint32_t z{0}; z < Z_SIZE; z++){ for(uint32_t z{0}; z < BOARD_DIMS.z; z++){
this->cubes[x][y][z].color = color; this->cubes[x][y][z].color = color;
} }
} }
} }
} }
template <V3D &BOARD_DIMS> template <const V3D &BOARD_DIMS>
void Board<BOARD_DIMS>::SetCubeColor(const V3D &position, const V3D &color){ void Board<BOARD_DIMS>::SetCubeColor(const V3D &position, const V3D &color){
this->cubes[position.x][position.y][position.z].color = color; this->cubes[position.x][position.y][position.z].color = color;
} }
template <V3D &BOARD_DIMS> template <const V3D &BOARD_DIMS>
void Board<BOARD_DIMS>::SetCubeOccupation(const V3D &position, bool occupation){ void Board<BOARD_DIMS>::SetCubeOccupation(const V3D &position, bool occupation){
bool oldOccupation{this->cubes[position.x][position.y][position.z].occupied}; bool oldOccupation{this->cubes[position.x][position.y][position.z].isOccupied};
this->cubes[position.x][position.y][position.z].occupied = occupation; this->cubes[position.x][position.y][position.z].isOccupied = occupation;
if(occupation != oldOccupation) this->boardStateHasChanged = true; if(occupation != oldOccupation) this->boardStateHasChanged = true;
} }
template <V3D &BOARD_DIMS> template <const V3D &BOARD_DIMS>
Cube * Board<BOARD_DIMS>::SliceBoard(const V3D &column){ Cube ** Board<BOARD_DIMS>::SliceBoard(const V3D &column){
uint32_t columnLength{0}; uint32_t columnLength{0};
V3D indexIncriment{}; V3D indexIncriment{};
V3D position{}; V3D position{};
switch(column.z){ switch(column.z){
case Board::PLANE_NORMAL::X: case BOARD_TYPES::PLANE_NORMAL::X:
columnLength = BOARD_DIMS.x; columnLength = BOARD_DIMS.x;
indexIncriment.x = 1; indexIncriment.x = 1;
position.z = column.x; position.z = column.x;
position.y = column.y; position.y = column.y;
break; break;
case Board::PLANE_NORMAL::Y: case BOARD_TYPES::PLANE_NORMAL::Y:
columnLength = BOARD_DIMS.Y; columnLength = BOARD_DIMS.y;
indexIncriment.y = 1; indexIncriment.y = 1;
position.x = column.x; position.x = column.x;
position.z = column.y; position.z = column.y;
break; break;
default: default:
case Board::PLANE_NORMAL::Z: case BOARD_TYPES::PLANE_NORMAL::Z:
columnLength = BOARD_DIMS.Z; columnLength = BOARD_DIMS.z;
indexIncriment.z = 1; indexIncriment.z = 1;
position.x = column.x; position.x = column.x;
position.y = column.y; position.y = column.y;
break; break;
} }
std::array<Cube *, columnLength> columnSlice; Cube* columnSlice[columnLength];
for(uint32_t i = 0; i < columnLength; i++){ for(uint32_t i = 0; i < columnLength; i++){
V3D cubePosition = indexIncriment * i + position; V3D cubePosition = indexIncriment * i + position;
columnSlice[i] = &(this->cubes[cubePosition.x][cubePosition.y][cubePosition.z]); columnSlice[i] = &(this->cubes[cubePosition.x][cubePosition.y][cubePosition.z]);
} }
return columnSlice.data(); return columnSlice;
} }

View File

@@ -7,13 +7,13 @@
#include <Arduino.h> #include <Arduino.h>
#include "Cube.h" #include "Cube.h"
#include "BoardDriverTypes.h" #include "BoardTypes.h"
template <uint32_t NUM_STACKS> template <uint32_t NUM_STACKS>
class BoardDriver{ class BoardDriver{
public: public:
BoardDriver(std::array<BoardDriverTypes::CubeStack, NUM_STACKS> &stacks, Adafruit_NeoPixel &pixelController); BoardDriver(std::array<BOARD_TYPES::CubeStack, NUM_STACKS> &stacks, Adafruit_NeoPixel &pixelController);
~BoardDriver() = default; ~BoardDriver() = default;
void Init(); void Init();
@@ -21,17 +21,17 @@ public:
uint32_t GetNumberCubes(uint32_t numXStacks, uint32_t X_COORD, uint32_t Y_COORD); uint32_t GetNumberCubes(uint32_t numXStacks, uint32_t X_COORD, uint32_t Y_COORD);
uint32_t GetNumberCubes(uint32_t stackIndex); uint32_t GetNumberCubes(uint32_t stackIndex);
void UpdateStackLEDs(uint32_t numXStacks, uint32_t X_COORD, uint32_t Y_COORD, Cube cubes[], uint32_t numCubes); void UpdateStackLEDs(uint32_t numXStacks, uint32_t X_COORD, uint32_t Y_COORD, Cube* cubes[], uint32_t numCubes);
void UpdateStackLEDs(uint32_t stackIndex, Cube cubes[], uint32_t numCubes); void UpdateStackLEDs(uint32_t stackIndex, Cube* cubes[], uint32_t numCubes);
private: private:
std::array<CubeStack, NUM_STACKS> &stacks; std::array<BOARD_TYPES::CubeStack, NUM_STACKS> &stacks;
Adafruit_NeoPixel &pixelController; Adafruit_NeoPixel &pixelController;
std::array<uint16_t, NUM_STACKS> filteredReadings; std::array<uint16_t, NUM_STACKS> filteredReadings;
uint32_t xy2StackIndex(uint32_t x_coord, uint32_t y_coord, uint32_t numXStacks){ uint32_t xy2StackIndex(uint32_t x_coord, uint32_t y_coord, uint32_t numXStacks){
return X_COORD + Y_COORD*numXStacks; return x_coord + y_coord*numXStacks;
} }
}; };
@@ -46,7 +46,7 @@ void BoardDriver<NUM_STACKS>::Init(){
} }
template<uint32_t NUM_STACKS> template<uint32_t NUM_STACKS>
BoardDriver<NUM_STACKS>::BoardDriver(std::array<BoardDriverTypes::CubeStack, NUM_STACKS> &stacks, Adafruit_NeoPixel &pixelController): BoardDriver<NUM_STACKS>::BoardDriver(std::array<BOARD_TYPES::CubeStack, NUM_STACKS> &stacks, Adafruit_NeoPixel &pixelController):
stacks(stacks), stacks(stacks),
pixelController(pixelController) pixelController(pixelController)
{ {
@@ -56,24 +56,24 @@ pixelController(pixelController)
} }
template<uint32_t NUM_STACKS> template<uint32_t NUM_STACKS>
void BoardDriver<NUM_STACKS>::UpdateStackLEDs(uint32_t numXStacks, uint32_t X_COORD, uint32_t Y_COORD, Cube cubes[], uint32_t numCubes){ void BoardDriver<NUM_STACKS>::UpdateStackLEDs(uint32_t numXStacks, uint32_t X_COORD, uint32_t Y_COORD, Cube* cubes[], uint32_t numCubes){
this->UpdateStackLEDs(this->xy2StackIndex(X_COORD, Y_COORD, numXStacks), cubes, numCubes); this->UpdateStackLEDs(this->xy2StackIndex(X_COORD, Y_COORD, numXStacks), cubes, numCubes);
} }
template<uint32_t NUM_STACKS> template<uint32_t NUM_STACKS>
void BoardDriver<NUM_STACKS>::UpdateStackLEDs(uint32_t stackIndex, Cube cubes[], uint32_t numCubes){ void BoardDriver<NUM_STACKS>::UpdateStackLEDs(uint32_t stackIndex, Cube* cubes[], uint32_t numCubes){
this->pixelController.setPin(this->stacks[stackIndex].ledPin); this->pixelController.setPin(this->stacks[stackIndex].ledPin);
for(int i = 0; i < numCubes; i++){ for(int i = 0; i < numCubes; i++){
Color color{cubes[i].color}; V3D color{cubes[i]->color};
this->pixelController.setPixelColor(i*2, this->pixelController.Color(color.red, color.green, color.blue)); this->pixelController.setPixelColor(i*2, this->pixelController.Color(color.x, color.y, color.z));
this->pixelController.setPixelColor((i*2 + 1), this->pixelController.Color(color.red, color.green, color.blue)); this->pixelController.setPixelColor((i*2 + 1), this->pixelController.Color(color.x, color.y, color.z));
} }
this->pixelController.show(); this->pixelController.show();
} }
template<uint32_t NUM_STACKS> template<uint32_t NUM_STACKS>
uint32_t BoardDriver<NUM_STACKS>::GetNumberCubes(uint32_t numXStacks, uint32_t X_COORD, uint32_t Y_COORD){ uint32_t BoardDriver<NUM_STACKS>::GetNumberCubes(uint32_t numXStacks, uint32_t X_COORD, uint32_t Y_COORD){
return this->GetNumberCubes(this->xy2StackIndex(x_coord, y_coord, numXStacks)); return this->GetNumberCubes(this->xy2StackIndex(X_COORD, Y_COORD, numXStacks));
} }
template<uint32_t NUM_STACKS> template<uint32_t NUM_STACKS>
@@ -85,7 +85,7 @@ uint32_t BoardDriver<NUM_STACKS>::GetNumberCubes(uint32_t stackIndex){
2 cubes: 1/3 2500-1850 2 cubes: 1/3 2500-1850
3 cubes: 1/4 1850-0 3 cubes: 1/4 1850-0
*/ */
uint16_t value = analogRead(cube.ADCPin); uint16_t value = analogRead(this->stacks[stackIndex].adcPin);
uint16_t lowPassADCRead = uint16_t lowPassADCRead =
static_cast<uint16_t>( static_cast<uint16_t>(
(static_cast<float>(this->filteredReadings[stackIndex]) * 0.9) (static_cast<float>(this->filteredReadings[stackIndex]) * 0.9)

142
lib/Board/BoardManager.h Normal file
View File

@@ -0,0 +1,142 @@
#pragma once
#include "Board.h"
#include "BoardDriver.h"
#include "Vector3D.h"
template <const V3D &BOARD_DIMS>
class BoardManager{
public:
BoardManager(BoardDriver<BOARD_WIDTH*BOARD_LENGTH> &boardDriver);
~BoardManager() = default;
void Init();
void Update();
void SetCubeColor(const V3D &position, const V3D &color);
void SetColumnColors(const V3D &column, const V3D *color);
/**
* @brief Fill a column along any axis with a color
* @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)
* @param color the color you want to fill the column with
*/
void FillColumnColor(const V3D &column, const V3D &color);
bool HasBoardChanged();
void ClearBoardChanged();
String &Board2StackString();
private:
BoardDriver<BOARD_WIDTH*BOARD_LENGTH> &driver;
Board<BOARD_DIMS> board{};
bool hasBoardChanged{false};
void updateBoardColors(const V3D &column);
uint32_t getColumnHeight(BOARD_TYPES::PLANE_NORMAL normal){
switch(normal){
case BOARD_TYPES::PLANE_NORMAL::X:
return BOARD_DIMS.x;
break;
case BOARD_TYPES::PLANE_NORMAL::Y:
return BOARD_DIMS.y;
break;
case BOARD_TYPES::PLANE_NORMAL::Z:
return BOARD_DIMS.z;
break;
default:
return 0;
}
}
};
template <const V3D &BOARD_DIMS>
BoardManager<BOARD_DIMS>::BoardManager(BoardDriver<BOARD_WIDTH*BOARD_LENGTH> &boardDriver):
driver(boardDriver){}
template <const V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::Init(){
this->driver.Init();
}
template <const V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::Update(){
// update the occupied cubes on the board and the cube colors
for(uint32_t x = 0; x < BOARD_DIMS.x; x++){
for(uint32_t y = 0; y < BOARD_DIMS.y; y++){
uint32_t stackIndex{y * BOARD_DIMS.x + x};
uint32_t numCubes{this->driver.GetNumberCubes(stackIndex)};
for(uint32_t z = 0; z < BOARD_DIMS.z; z++){
V3D cubePosition{x, y, z};
this->board.SetCubeOccupation(cubePosition, z < numCubes);
cubePosition.z = BOARD_TYPES::PLANE_NORMAL::Z;
this->driver.UpdateStackLEDs(stackIndex, this->board.SliceBoard(cubePosition), BOARD_DIMS.z);
}
}
}
}
template <const V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::updateBoardColors(const V3D &column){
Cube ** cubeSlice{this->board.SliceBoard(column)};
uint32_t numCubes{this->getColumnHeight(static_cast<BOARD_TYPES::PLANE_NORMAL>(column.z))};
this->driver.UpdateStackLEDs(BOARD_DIMS.x, cubeSlice, numCubes);
}
template <const V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::SetCubeColor(const V3D &position, const V3D &color){
this->board.SetCubeColor(position, color);
V3D slice{position.x, position.y, BOARD_TYPES::PLANE_NORMAL::Z};
this->updateBoardColors(slice);
}
template <const V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::SetColumnColors(const V3D &column, const V3D *color){
uint32_t columnHeight{this->getColumnHeight(static_cast<BOARD_TYPES::PLANE_NORMAL>(column.z))};
V3D position = column;
for(uint32_t z = 0; z < columnHeight; z++){
position.z = z;
this->board.SetCubeColor(position, color[z]);
}
this->updateBoardColors(column);
}
template <const V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::FillColumnColor(const V3D &column, const V3D &color){
uint32_t columnHeight{this->getColumnHeight(column.z)};
V3D position = column;
for(uint32_t z = 0; z < columnHeight; z++){
position.z = z;
this->board.SetCubeColor(position, color);
}
this->updateBoardColors(column);
}
template <const V3D &BOARD_DIMS>
bool BoardManager<BOARD_DIMS>::HasBoardChanged(){return this->hasBoardChanged;}
template <const V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::ClearBoardChanged(){this->hasBoardChanged = false;}
template <const V3D &BOARD_DIMS>
String &BoardManager<BOARD_DIMS>::Board2StackString(){
String message{};
this->board.ToStackString(message);
return message;
}

View File

@@ -2,9 +2,15 @@
#include <cstdint> #include <cstdint>
namespace BoardDriverTypes{ namespace BOARD_TYPES{
struct CubeStack{ struct CubeStack{
uint8_t adcPin; uint8_t adcPin;
uint8_t ledPin; uint8_t ledPin;
}; };
enum PLANE_NORMAL : uint32_t{
X = 0,
Y,
Z
};
}; };

View File

@@ -1,102 +0,0 @@
#pragma once
#include "Board.h"
#include "BoardDriver.h"
#include "Vector3D.h"
template <V3D &BOARD_DIMS>
class BoardManager{
public:
BoardManager(BoardDriver<BOARD_WIDTH*BOARD_LENGTH> &boardDriver):
driver(boardDriver){};
~BoardManager() = default;
void Init();
void Update();
void SetCubeColor(const V3D &position, const V3D &color);
void SetColumnColor(const V3D &position, const V3D &color);
/**
* @brief Fill a column along any axis with a color
* @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)
* @param color the color you want to fill the column with
*/
void FillColumnColor(const V3D &column, const V3D &color);
bool HasBoardChanged(){return this->hasBoardChanged;}
private:
BoardDriver<BOARD_WIDTH*BOARD_LENGTH> &driver;
Board<BOARD_DIMS> board{};
bool hasBoardChanged{false};
void updateBoardColors(const V3D &column);
};
template <V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::Init(){
this->driver.Init();
}
template <V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::Update(){
// update the occupied cubes on the board and the cube colors
for(uint32_t x = 0; x < BOARD_DIMS.x; x++){
for(uint32_t y = 0; y < BOARD_DIMS.y; y++){
uint32_t numCubes{this->driver.GetNumberCubes(i)};
for(uint32_t z = 0; z < BOARD_DIMS.z; z++){
V3D cubePosition{x, y, z};
bool isOccupied{z < numCubes};
if(this->board.SetCubeOccupation(cubePosition, i < numCubes) != isOccupied){
this->board.boardStateHasChanged = true;
}
cubePosition.z = Board::PLANE_NORMAL::Z;
this->driver.UpdateStackLEDs(i, this->board.SliceBoard(cubePosition), BOARD_DIMS.z);
}
}
}
// update the colors
for(uint32_t i = 0; i < BOARD_DIMS.x * BOARD_DIMS.y; i++){
}
}
template <V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::updateBoardColors(const V3D &column){
Cube * cubeSlice{this->board.SliceBoard(column)};
uint32_t numCubes{0};
switch(column.z){
case Board::PLANE_NORMAL::X:
numCubes = BOARD_DIMS.x;
break;
case Board::PLANE_NORMAL::Y:
numCubes = BOARD_DIMS.y;
break;
case Board::PLANE_NORMAL::Z:
numCubes = BOARD_DIMS.z;
break;
default:
break;
}
this->driver.UpdateStackLEDs(BOARD_DIMS.x, cubeSlice, numCubes);
}
template <V3D &BOARD_DIMS>
void BoardManager<BOARD_DIMS>::SetCubeColor(const V3D &position, const V3D &color){
this->board.SetCubeColor(position, color);
V3D slice{position.x, position.y, Board::PLANE_NORMAL::Z};
this->updateBoardColors(slice);
}

View File

@@ -2,6 +2,8 @@
#include <Arduino.h> #include <Arduino.h>
#include <BluetoothSerial.h> #include <BluetoothSerial.h>
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <Adafruit_NeoPixel.h>
#include <chrono>
// Static Defines // Static Defines
#include "PINOUT.h" #include "PINOUT.h"
@@ -11,23 +13,26 @@
// project specific libraries // project specific libraries
#include "BluetoothSerial.h" #include "BluetoothSerial.h"
#include "SerialMessage.h" #include "SerialMessage.h"
#include "Color.h"
#include "GlobalPrint.h" #include "GlobalPrint.h"
#include "BoardManager.h"
#include "BoardDriver.h"
#include "BoardTypes.h"
// -------------------------------------------------- // --------------------------------------------------
// ----------------- VARIABLES ---------------------- // ----------------- VARIABLES ----------------------
// -------------------------------------------------- // --------------------------------------------------
TaskHandle_t updateCommunicaitonTask; TaskHandle_t updateCommunicaitonTask;
TaskHandle_t updateBoardTask; TaskHandle_t updateBoardTask;
uint32_t boardStateTimer{0};
bool boardStateHasChanged{false};
uint32_t boardStateMaxUpdatePeriod{34}; // this is a little slower than 30fps
// BluetoothSerial SerialBT; // BluetoothSerial SerialBT;
// BluetoothSerialMessage serialMessageBT(&SerialBT); // BluetoothSerialMessage serialMessageBT(&SerialBT);
SerialMessage<500, 10> serialMessage(&Serial); SerialMessage<500, 10> serialMessage(&Serial);
Adafruit_NeoPixel pixelController{BOARD_HEIGHT*2, STACK1_LED_PIN, NEO_GRB + NEO_KHZ800};
BoardDriver<BOARD_WIDTH*BOARD_LENGTH> boardDriver{stacks, pixelController};
BoardManager<BOARD_DIMENSIONS> boardManager{boardDriver};
// -------------------------------------------------- // --------------------------------------------------
// ----------------- FUNCTIONS ---------------------- // ----------------- FUNCTIONS ----------------------
// -------------------------------------------------- // --------------------------------------------------
@@ -58,37 +63,30 @@ void SetupBluetoothModule(){
void printBoardState(){ void printBoardState(){
// create a buffer to hold the board state
uint16_t boardState[BOARD_WIDTH * BOARD_LENGTH];
// read in the board state
board.GetBoardState(boardState);
GlobalPrint::Print("!0,"); GlobalPrint::Print("!0,");
GlobalPrint::Print(boardManager.Board2StackString());
for(int i = 0; i < (BOARD_WIDTH * BOARD_LENGTH); i++){
GlobalPrint::Print(String(boardState[i]));
if(i == (BOARD_WIDTH * BOARD_LENGTH) - 1){
break;
}
GlobalPrint::Print(",");
}
GlobalPrint::Println(";"); GlobalPrint::Println(";");
} }
void SetStackColor(uint32_t * args, int argsLength){ void SetStackColor(uint32_t * args, int argsLength){
uint32_t stackNum = args[1]; uint32_t stackNum = args[1];
uint32_t X_COORD{stackNum};
while(X_COORD > BOARD_DIMENSIONS.x - 1){
X_COORD -= BOARD_DIMENSIONS.x;
}
uint32_t Y_COORD{(stackNum - X_COORD) / BOARD_DIMENSIONS.y};
uint32_t numColors = (argsLength - 2) / 3; uint32_t numColors = (argsLength - 2) / 3;
Color colors[numColors]; V3D colors[numColors];
for(int i = 0; i < numColors; i++){ for(int i = 0; i < numColors; i++){
int red = args[2 + (i * 3)]; int red = args[2 + (i * 3)];
int green = args[3 + (i * 3)]; int green = args[3 + (i * 3)];
int blue = args[4 + (i * 3)]; int blue = args[4 + (i * 3)];
colors[i] = Color(red, green, blue); colors[i] = V3D{red, green, blue};
} }
board.SetStackColors(stackNum, colors); boardManager.SetColumnColors(V3D{X_COORD, Y_COORD, BOARD_TYPES::PLANE_NORMAL::Z}, colors);
} }
void parseData(Message<500, 10> &message){ void parseData(Message<500, 10> &message){
@@ -104,12 +102,14 @@ void parseData(Message<500, 10> &message){
break; break;
case Commands::SetStackColors: case Commands::SetStackColors:
GlobalPrint::Println("!2;"); GlobalPrint::Println("!2;");
colorManager.Enable(false); // TODO: replace this with the animator
// colorManager.Enable(false);
SetStackColor(reinterpret_cast<uint32_t *>(args), argsLength); SetStackColor(reinterpret_cast<uint32_t *>(args), argsLength);
break; break;
case Commands::GoToIdle: case Commands::GoToIdle:
GlobalPrint::Println("!3;"); GlobalPrint::Println("!3;");
colorManager.Enable(true); // TODO: replace this with the animator
// colorManager.Enable(true);
break; break;
default: default:
GlobalPrint::Println("INVALID COMMAND"); GlobalPrint::Println("INVALID COMMAND");
@@ -144,20 +144,20 @@ void UpdateCommunication(void * params){
void UpdateBoard(void * params){ void UpdateBoard(void * params){
Serial.println("Spawning UpdateBoard task"); Serial.println("Spawning UpdateBoard task");
auto updateTickRate{std::chrono::milliseconds(8)};
auto boardStateTimer{std::chrono::milliseconds(0)};
auto boardStateMaxUpdatePeriod{std::chrono::milliseconds(34)}; // this is a little slower than 30fps
for(;;){ for(;;){
if(board.BoardStateHasChanged()){ if(boardStateTimer >= boardStateMaxUpdatePeriod && boardManager.HasBoardChanged()){
boardStateHasChanged = true;
}
if(millis() - boardStateTimer > boardStateMaxUpdatePeriod && boardStateHasChanged){
boardStateTimer = millis();
printBoardState(); printBoardState();
boardStateHasChanged = false; boardManager.ClearBoardChanged();
} }
colorManager.Update(); boardManager.Update();
vTaskDelay(5); boardStateTimer += updateTickRate;
vTaskDelay(updateTickRate.count());
} }
Serial.println("UpdateBoard task has ended unexpectedly!"); Serial.println("UpdateBoard task has ended unexpectedly!");
} }
@@ -183,10 +183,8 @@ void setup() {
xTaskCreate(UpdateCommunication, "UpdateCommunication", 10000, NULL, 0, &updateCommunicaitonTask); xTaskCreate(UpdateCommunication, "UpdateCommunication", 10000, NULL, 0, &updateCommunicaitonTask);
Serial.println("Beginning Board Initializaiton"); Serial.println("Beginning Board Initializaiton");
boardManager.Init();
xTaskCreate(UpdateBoard, "UpdateBoard", 10000, NULL, 0, &updateBoardTask); xTaskCreate(UpdateBoard, "UpdateBoard", 10000, NULL, 0, &updateBoardTask);
Color colors[] = {Color(255, 0, 0), Color(0, 0, 0), Color(0, 0, 0)};
board.SetStackColors(2, colors);
boardStateTimer = millis();
Serial.println("Setup Complete"); Serial.println("Setup Complete");
} }