latest update

This commit is contained in:
Ghassan Yusuf 2025-06-10 22:28:08 +03:00
parent 8535212aa3
commit 6969c69368
13 changed files with 790 additions and 622 deletions

View File

@ -1,218 +0,0 @@
#include <FastLED.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_DotStarMatrix.h>
#include <Adafruit_DotStar.h>
#include <SPI.h>
#include <SparkFun_APDS9960.h>
#undef WAIT // Prevent macro conflict with FastLED
// ============ PIN DEFINITIONS ============
// PublicI2C (slave) pins
#define PUBLIC_I2C_SDA 21
#define PUBLIC_I2C_SCL 22
#define PUBLIC_I2C_ADDR 0x42 // Example slave address
// LocalI2C (master) pins
#define LOCAL_I2C_SDA 12
#define LOCAL_I2C_SCL 11
// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
// Joystick pins
#define JOY_X_PIN 1 // ADC1_CH0
#define JOY_Y_PIN 2 // ADC1_CH1
#define JOY_BTN_PIN 3 // Digital input
// FastLED (NeoPixel) settings
#define NUM_LEDS 16
#define LED_DATA_PIN 5 // Example GPIO for LED data
// DotStar HD 8x8 Grid settings
#define DOTSTAR_WIDTH 8
#define DOTSTAR_HEIGHT 8
#define DOTSTAR_DATA 6 // Example GPIO for DotStar data
#define DOTSTAR_CLK 7 // Example GPIO for DotStar clock
// ============ I2C BUS OBJECTS ============
TwoWire PublicI2C = TwoWire(0); // I2C0 (slave)
TwoWire LocalI2C = TwoWire(1); // I2C1 (master)
// ============ DEVICE OBJECTS =============
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &LocalI2C, OLED_RESET);
// Use a SparkFun_APDS9960 library that supports TwoWire
SparkFun_APDS9960 apds(&LocalI2C);
CRGB leds[NUM_LEDS];
Adafruit_DotStarMatrix dotstar = Adafruit_DotStarMatrix(
DOTSTAR_WIDTH, DOTSTAR_HEIGHT, DOTSTAR_DATA, DOTSTAR_CLK,
DS_MATRIX_TOP + DS_MATRIX_LEFT + DS_MATRIX_ROWS + DS_MATRIX_PROGRESSIVE,
DOTSTAR_BRG
);
// ============ DATA STRUCTURES ============
struct SensorData {
int8_t joystickDir; // -1=none, 0=up, 1=down, 2=left, 3=right
bool joystickBtn;
uint16_t colorR, colorG, colorB, colorC;
};
volatile SensorData latestData;
// ============ I2C SLAVE DATA HANDLERS =========
void receiveEvent(int numBytes) {
// Not used in this application, but required by Wire
}
void requestEvent() {
// Copy volatile to local to avoid race conditions
SensorData copy;
noInterrupts();
copy = latestData;
interrupts();
// Send as a binary buffer
PublicI2C.write((uint8_t*)&copy, sizeof(SensorData));
}
// ============ JOYSTICK INTERPRETATION =========
#define JOY_THRESHOLD_HIGH 3000
#define JOY_THRESHOLD_LOW 1000
void updateJoystick(SensorData &data) {
int joyX = analogRead(JOY_X_PIN);
int joyY = analogRead(JOY_Y_PIN);
bool joyBtn = digitalRead(JOY_BTN_PIN) == LOW;
// Default: no direction
data.joystickDir = -1;
if (joyY > JOY_THRESHOLD_HIGH) data.joystickDir = 0; // Up
else if (joyY < JOY_THRESHOLD_LOW) data.joystickDir = 1; // Down
else if (joyX < JOY_THRESHOLD_LOW) data.joystickDir = 2; // Left
else if (joyX > JOY_THRESHOLD_HIGH) data.joystickDir = 3; // Right
data.joystickBtn = joyBtn;
}
// ============ COLOR SENSOR READING =========
void updateColorSensor(SensorData &data) {
uint16_t r=0, g=0, b=0, c=0;
if (apds.readAmbientLight(c) &&
apds.readRedLight(r) &&
apds.readGreenLight(g) &&
apds.readBlueLight(b)) {
data.colorR = r;
data.colorG = g;
data.colorB = b;
data.colorC = c;
}
}
// ============ DISPLAY LOGIC =========
void updateDisplays(const SensorData &data) {
// DotStar: show direction as arrow or color as background
dotstar.fillScreen(0);
if (data.joystickDir == 0) dotstar.drawPixel(3, 0, dotstar.Color(0,0,255)); // Up
else if (data.joystickDir == 1) dotstar.drawPixel(3, 7, dotstar.Color(0,0,255)); // Down
else if (data.joystickDir == 2) dotstar.drawPixel(0, 3, dotstar.Color(0,0,255)); // Left
else if (data.joystickDir == 3) dotstar.drawPixel(7, 3, dotstar.Color(0,0,255)); // Right
else dotstar.fillScreen(dotstar.Color(data.colorR>>2, data.colorG>>2, data.colorB>>2)); // Show color
dotstar.show();
// FastLED: color bar with button brightness
uint8_t brightness = data.joystickBtn ? 255 : 64;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(data.colorR>>4, data.colorG>>4, data.colorB>>4);
leds[i].nscale8_video(brightness);
}
FastLED.show();
// OLED: show values
display.clearDisplay();
display.setCursor(0,0);
display.print("Dir: ");
switch (data.joystickDir) {
case 0: display.println("Up"); break;
case 1: display.println("Down"); break;
case 2: display.println("Left"); break;
case 3: display.println("Right"); break;
default: display.println("None"); break;
}
display.print("Btn: "); display.println(data.joystickBtn ? "Pressed" : "Released");
display.print("R: "); display.println(data.colorR);
display.print("G: "); display.println(data.colorG);
display.print("B: "); display.println(data.colorB);
display.print("C: "); display.println(data.colorC);
display.display();
}
// ============ SETUP FUNCTION =============
void setup() {
Serial.begin(115200);
// --- Initialize PublicI2C as Slave ---
PublicI2C.begin(PUBLIC_I2C_ADDR, PUBLIC_I2C_SDA, PUBLIC_I2C_SCL, 100000);
PublicI2C.onReceive(receiveEvent);
PublicI2C.onRequest(requestEvent);
Serial.println("PublicI2C (slave) initialized.");
// --- Initialize LocalI2C as Master ---
LocalI2C.begin(LOCAL_I2C_SDA, LOCAL_I2C_SCL, 100000);
Serial.println("LocalI2C (master) initialized.");
// --- Initialize OLED Display ---
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 allocation failed");
while (1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("OLED Ready!");
display.display();
// --- Initialize APDS-9960 (SparkFun) ---
if (!apds.init()) { // Uses LocalI2C if library supports it
Serial.println("APDS-9960 initialization failed");
display.println("No APDS-9960!");
display.display();
while (1);
}
display.println("APDS-9960 ready!");
display.display();
// Enable color sensing
apds.enableLightSensor(false);
// --- Initialize Joystick Pins ---
pinMode(JOY_BTN_PIN, INPUT_PULLUP); // Button is active LOW
// --- Initialize FastLED (NeoPixel) ---
FastLED.addLeds<NEOPIXEL, LED_DATA_PIN>(leds, NUM_LEDS);
FastLED.clear();
FastLED.show();
// --- Initialize DotStar Matrix ---
dotstar.begin();
dotstar.setBrightness(32); // Adjust as needed
dotstar.fillScreen(0);
dotstar.show();
}
// ============ MAIN LOOP ==================
void loop() {
SensorData tempData;
updateJoystick(tempData);
updateColorSensor(tempData);
// Copy to shared struct for I2C
noInterrupts();
latestData = tempData;
interrupts();
updateDisplays(tempData);
delay(50); // Adjust as needed
}

View File

@ -0,0 +1,117 @@
#include "dice.h" // Dice Function
#include "header.h" // Player Data Types
#include <Adafruit_NeoPixel.h>
#define LED_PIN 8 // Digital pin connected to the LED strip
#define NUM_LEDS 64 // 8x8 = 64 LEDs
#define BRIGHTNESS 100 // Default max brightness
#define sspacer Serial.println("--------------------------------------------")
#define dspacer Serial.println("============================================")
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
// Convert (row, col) to strip index
uint16_t getIndex(uint8_t row, uint8_t col) {
// Adjust depending on how your strip is wired
if (row % 2 == 0) {
return row * 8 + col; // Left to right
} else {
return row * 8 + (7 - col); // Right to left (zigzag)
}
}
// Set individual LED with row, col, color and brightness
void setPixelColorRC(uint8_t row, uint8_t col, uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) {
if(row >= 8 || col >= 8) return; // Bounds check
strip.setBrightness(brightness);
uint16_t index = getIndex(row, col);
strip.setPixelColor(index, strip.Color(r, g, b));
strip.show();
}
// Optional: set LED by index directly
void setPixelColorIndex(uint16_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) {
if (index >= NUM_LEDS) return;
strip.setBrightness(brightness);
strip.setPixelColor(index, strip.Color(r, g, b));
strip.show();
}
//================================================================
// SETUP
//================================================================
void setup() {
// I2C Communications
Wire.begin(); // For Master
// Start Serial And Message
Serial.begin(115200);
Serial.println();
dspacer;
// Starting LED Strip
strip.begin();
strip.setBrightness(BRIGHTNESS); // Initial brightness
strip.show(); // Initialize all pixels to 'off'
// Red Player
player[0].i2ca = 0x10;
player[0].position.x = 0;
player[0].position.y = 0;
player[0].color.r = 255;
player[0].color.i = 60;
// Paint The Strip Position For Red Player
setPixelColorRC(
player[0].position.x,
player[0].position.y,
player[0].color.r,
player[0].color.g,
player[0].color.b,
player[0].color.i
);
// Blue Player
player[1].i2ca = 0x20;
player[1].position.x = 7;
player[1].position.y = 7;
player[1].color.b = 255;
player[1].color.i = 60;
// Paint The Strip Position For Blue Player
setPixelColorRC(
player[1].position.x,
player[1].position.y,
player[1].color.r,
player[1].color.g,
player[1].color.b,
player[1].color.i
);
// Make Dicision
diceRoll();
// Make Spacer
dspacer;
}
//================================================================
// LOOP
//================================================================
void loop() {
for(int i=0; i<2; i++) {
movePlayers(i);
}
}
//================================================================
//
//================================================================

View File

@ -0,0 +1,6 @@
#include <esp_system.h> // For esp_random()
int roll_dice() {
uint32_t random_value = esp_random();
return (random_value % 6) + 1;
}

View File

@ -0,0 +1,127 @@
void diceRoll() {
dspacer;
Serial.println(" Dice Roll");
dspacer;
while(1) {
// Player turn decision
int redplayerdice = roll_dice();
int blueplayerdice = roll_dice();
// Display The Dice Values
Serial.println("Red Dice : " + String(redplayerdice));
Serial.println("Blue Dice : " + String(blueplayerdice));
// Swaping The Players
if(redplayerdice > blueplayerdice) {
Serial.println("Red Player Starts");
break;
} else if(redplayerdice < blueplayerdice) {
Serial.println("Blue Player Starts");
temp = player[0];
player[0] = player[1];
player[1] = temp;
break;
} else if(redplayerdice == blueplayerdice) {
Serial.println(" -X- Its A Draw, Do It Again");
}
}
}
//================================================================
//
//================================================================
String Question(Stream &serial, String Message) {
// Print On Serial
serial.print(Message + " : ");
// Wait Until User Input A Thing
while(!serial.available());
// Read User Input
String x = serial.readStringUntil('\n');
// Cleaning The Buffer
while(serial.available()) { serial.read(); }
// Remove Spaces
x.trim();
// Print Answer
serial.println(x);
// Return The Value Of x
return x;
}
//================================================================
//
//================================================================
void movePlayers(uint8_t num) {
// New Position Variables
uint8_t posX, posY;
// Select Player
if(player[num].color.r == 255) {
Serial.println("Red Player Turn > > >");
} else if(player[num].color.b == 255) {
Serial.println("Blue Player Turn > > >");
}
// Take User Input
while(1) {
// User Input
posX = Question(Serial, "Select X Position ").toInt();
posY = Question(Serial, "Select Y Position ").toInt();
// Boundries Check
if((posX >= 0 && posX <= 7) && (posY >= 0 && posY <= 7)) {
break;
} else {
Serial.println(" -> Wrong Input, Exceeding Boundries, Try Again");
}
}
// Seperator
Serial.println("--------------------------------------------");
// Clear Current Position
setPixelColorRC(
player[num].position.x,
player[num].position.y,
0,
0,
0,
60
);
// Update Positions Values
player[num].position.x = posX;
player[num].position.y = posY;
// Paint New Position
setPixelColorRC(
player[num].position.x,
player[num].position.y,
player[num].color.r,
player[num].color.g,
player[num].color.b,
player[num].color.i
);
}
//================================================================
//
//================================================================

View File

@ -0,0 +1,25 @@
// Player Position Data Type
struct _position {
uint8_t x;
uint8_t y;
};
// Color Of Any Thing
struct _color {
uint8_t r; // Red Color
uint8_t g; // Green Color
uint8_t b; // Blue Color
uint8_t i; // Intensity
};
// Player Data Type
struct _player {
_position position; // the current position of the player
_color color; // the color of the player light indicator
uint8_t health; // the health level of the player 0 - 7 => 8
uint8_t i2ca; // the i2c address of the joystic of the player
};
// Two Players Instences
_player player[2]; // The Two Contenders
_player temp; // For Swaping Purpose

View File

@ -0,0 +1,86 @@
int I2C_DiceCommand(uint8_t address) {
// Memory
int dice = 0;
// Call Slave Addrees
Wire.beginTransmission(address); // or 0x20
// Send Command 1 -> Roll A Dice
Wire.write(0x01);
// Stop Transmition
Wire.endTransmission();
// Request 1 byte from slave -> Contains A Number 1 to 6
Wire.requestFrom(0x10, 1);
// If Data Received
if(Wire.available()) {
// Read The Data
dice = Wire.read();
}
// Return The Value To Master
return dice
}
void I2C_PushData(uint8_t address, _player &pl1, _player &pl2) {
// Slave Address
Wire.beginTransmission(address);
// Command Number - Push Data
Wire.write(0x02);
// Player One Data
Wire.write(pl1.position.x);
Wire.write(pl1.position.y);
Wire.write(pl1.color.r);
Wire.write(pl1.color.g);
Wire.write(pl1.color.b);
Wire.write(pl1.color.i);
Wire.write(pl1.health);
// Player Two Data
Wire.write(pl1.position.x);
Wire.write(pl1.position.y);
Wire.write(pl1.color.r);
Wire.write(pl1.color.g);
Wire.write(pl1.color.b);
Wire.write(pl1.color.i);
Wire.write(pl1.health);
// Stop Transmition
Wire.endTransmission();
}
void I2C_Permission(uint8_t address) {
// Card Color
_color color;
// Direction
uint8_t Direction;
Wire.beginTransmission(address);
Wire.write(0x03); // permission to play command
Wire.endTransmission();
// Master waits for slave to send data
Wire.requestFrom(0x10, 4); // expecting 2 bytes: card color (R, G, B), direction (one byte)
// Receive Bytes
if(Wire.available()) {
color.r = Wire.read();
color.g = Wire.read();
color.b = Wire.read();
Direction = Wire.read();
}
}

View File

@ -1,218 +0,0 @@
#include <FastLED.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_DotStarMatrix.h>
#include <Adafruit_DotStar.h>
#include <SPI.h>
#include <SparkFun_APDS9960.h>
#undef WAIT // Prevent macro conflict with FastLED
// ============ PIN DEFINITIONS ============
// PublicI2C (slave) pins
#define PUBLIC_I2C_SDA 21
#define PUBLIC_I2C_SCL 22
#define PUBLIC_I2C_ADDR 0x42 // Example slave address
// LocalI2C (master) pins
#define LOCAL_I2C_SDA 12
#define LOCAL_I2C_SCL 11
// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
// Joystick pins
#define JOY_X_PIN 1 // ADC1_CH0
#define JOY_Y_PIN 2 // ADC1_CH1
#define JOY_BTN_PIN 3 // Digital input
// FastLED (NeoPixel) settings
#define NUM_LEDS 16
#define LED_DATA_PIN 5 // Example GPIO for LED data
// DotStar HD 8x8 Grid settings
#define DOTSTAR_WIDTH 8
#define DOTSTAR_HEIGHT 8
#define DOTSTAR_DATA 6 // Example GPIO for DotStar data
#define DOTSTAR_CLK 7 // Example GPIO for DotStar clock
// ============ I2C BUS OBJECTS ============
TwoWire PublicI2C = TwoWire(0); // I2C0 (slave)
TwoWire LocalI2C = TwoWire(1); // I2C1 (master)
// ============ DEVICE OBJECTS =============
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &LocalI2C, OLED_RESET);
// Use a SparkFun_APDS9960 library that supports TwoWire
SparkFun_APDS9960 apds(&LocalI2C);
CRGB leds[NUM_LEDS];
Adafruit_DotStarMatrix dotstar = Adafruit_DotStarMatrix(
DOTSTAR_WIDTH, DOTSTAR_HEIGHT, DOTSTAR_DATA, DOTSTAR_CLK,
DS_MATRIX_TOP + DS_MATRIX_LEFT + DS_MATRIX_ROWS + DS_MATRIX_PROGRESSIVE,
DOTSTAR_BRG
);
// ============ DATA STRUCTURES ============
struct SensorData {
int8_t joystickDir; // -1=none, 0=up, 1=down, 2=left, 3=right
bool joystickBtn;
uint16_t colorR, colorG, colorB, colorC;
};
volatile SensorData latestData;
// ============ I2C SLAVE DATA HANDLERS =========
void receiveEvent(int numBytes) {
// Not used in this application, but required by Wire
}
void requestEvent() {
// Copy volatile to local to avoid race conditions
SensorData copy;
noInterrupts();
copy = latestData;
interrupts();
// Send as a binary buffer
PublicI2C.write((uint8_t*)&copy, sizeof(SensorData));
}
// ============ JOYSTICK INTERPRETATION =========
#define JOY_THRESHOLD_HIGH 3000
#define JOY_THRESHOLD_LOW 1000
void updateJoystick(SensorData &data) {
int joyX = analogRead(JOY_X_PIN);
int joyY = analogRead(JOY_Y_PIN);
bool joyBtn = digitalRead(JOY_BTN_PIN) == LOW;
// Default: no direction
data.joystickDir = -1;
if (joyY > JOY_THRESHOLD_HIGH) data.joystickDir = 0; // Up
else if (joyY < JOY_THRESHOLD_LOW) data.joystickDir = 1; // Down
else if (joyX < JOY_THRESHOLD_LOW) data.joystickDir = 2; // Left
else if (joyX > JOY_THRESHOLD_HIGH) data.joystickDir = 3; // Right
data.joystickBtn = joyBtn;
}
// ============ COLOR SENSOR READING =========
void updateColorSensor(SensorData &data) {
uint16_t r=0, g=0, b=0, c=0;
if (apds.readAmbientLight(c) &&
apds.readRedLight(r) &&
apds.readGreenLight(g) &&
apds.readBlueLight(b)) {
data.colorR = r;
data.colorG = g;
data.colorB = b;
data.colorC = c;
}
}
// ============ DISPLAY LOGIC =========
void updateDisplays(const SensorData &data) {
// DotStar: show direction as arrow or color as background
dotstar.fillScreen(0);
if (data.joystickDir == 0) dotstar.drawPixel(3, 0, dotstar.Color(0,0,255)); // Up
else if (data.joystickDir == 1) dotstar.drawPixel(3, 7, dotstar.Color(0,0,255)); // Down
else if (data.joystickDir == 2) dotstar.drawPixel(0, 3, dotstar.Color(0,0,255)); // Left
else if (data.joystickDir == 3) dotstar.drawPixel(7, 3, dotstar.Color(0,0,255)); // Right
else dotstar.fillScreen(dotstar.Color(data.colorR>>2, data.colorG>>2, data.colorB>>2)); // Show color
dotstar.show();
// FastLED: color bar with button brightness
uint8_t brightness = data.joystickBtn ? 255 : 64;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(data.colorR>>4, data.colorG>>4, data.colorB>>4);
leds[i].nscale8_video(brightness);
}
FastLED.show();
// OLED: show values
display.clearDisplay();
display.setCursor(0,0);
display.print("Dir: ");
switch (data.joystickDir) {
case 0: display.println("Up"); break;
case 1: display.println("Down"); break;
case 2: display.println("Left"); break;
case 3: display.println("Right"); break;
default: display.println("None"); break;
}
display.print("Btn: "); display.println(data.joystickBtn ? "Pressed" : "Released");
display.print("R: "); display.println(data.colorR);
display.print("G: "); display.println(data.colorG);
display.print("B: "); display.println(data.colorB);
display.print("C: "); display.println(data.colorC);
display.display();
}
// ============ SETUP FUNCTION =============
void setup() {
Serial.begin(115200);
// --- Initialize PublicI2C as Slave ---
PublicI2C.begin(PUBLIC_I2C_ADDR, PUBLIC_I2C_SDA, PUBLIC_I2C_SCL, 100000);
PublicI2C.onReceive(receiveEvent);
PublicI2C.onRequest(requestEvent);
Serial.println("PublicI2C (slave) initialized.");
// --- Initialize LocalI2C as Master ---
LocalI2C.begin(LOCAL_I2C_SDA, LOCAL_I2C_SCL, 100000);
Serial.println("LocalI2C (master) initialized.");
// --- Initialize OLED Display ---
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 allocation failed");
while (1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("OLED Ready!");
display.display();
// --- Initialize APDS-9960 (SparkFun) ---
if (!apds.init()) { // Uses LocalI2C if library supports it
Serial.println("APDS-9960 initialization failed");
display.println("No APDS-9960!");
display.display();
while (1);
}
display.println("APDS-9960 ready!");
display.display();
// Enable color sensing
apds.enableLightSensor(false);
// --- Initialize Joystick Pins ---
pinMode(JOY_BTN_PIN, INPUT_PULLUP); // Button is active LOW
// --- Initialize FastLED (NeoPixel) ---
FastLED.addLeds<NEOPIXEL, LED_DATA_PIN>(leds, NUM_LEDS);
FastLED.clear();
FastLED.show();
// --- Initialize DotStar Matrix ---
dotstar.begin();
dotstar.setBrightness(32); // Adjust as needed
dotstar.fillScreen(0);
dotstar.show();
}
// ============ MAIN LOOP ==================
void loop() {
SensorData tempData;
updateJoystick(tempData);
updateColorSensor(tempData);
// Copy to shared struct for I2C
noInterrupts();
latestData = tempData;
interrupts();
updateDisplays(tempData);
delay(50); // Adjust as needed
}

View File

@ -0,0 +1,103 @@
#include "pins.h"
#include <Wire.h>
#include "healthbar.h"
#include "map.h"
#define X_PIN 1
#define Y_PIN 2
#define BUTTON_PIN 3
#define DEAD_ZONE 50 // Adjust this value for your joystick sensitivity
struct _location {
uint8_t x;
uint8_t y;
};
_location playerLocation;
void setup() {
playerLocation.x = 0;
playerLocation.y = 7;
Serial.begin(9600);
while (!Serial); // Wait for serial monitor on boards like Leonardo
map_begin();
// Display Helth
fastled_begin();
red_health(4, 5);
blue_health(2, 5);
fastled_show();
// map display - map_setDot(int x, int y, byte r, byte g, byte b)
map_setDot(0, 7, 255, 0, 0, 5);
map_setDot(7, 0, 0, 0, 255, 5);
map_show();
// // Initialize I2C buses (example for ESP32)
// Wire.begin(6, 7); // Public I2C (SDA 6, SCL 7)
// Wire1.begin(12, 11); // Local I2C (SDA 12, SCL 11) - remove if not available
}
void loop() {
// Serial.println(String(analogRead(X_PIN)) + " " + String(analogRead(Y_PIN)));
// delay(250);
String joymem = readJoystick();
Serial.println(joymem);
if(joymem == "up") {
if(playerLocation.y < 7) {
// Clear Previous playerLocation
map_setDot(playerLocation.x, playerLocation.y, 0, 0, 0, 0);
// New Value
playerLocation.y += 1;
// Draw On New playerLocation
map_setDot(playerLocation.x, playerLocation.y, 255, 0, 0, 50);
// Display On Map
map_show();
delay(500);
}
} else if(joymem == "down") {
if(playerLocation.y > 0) {
// Clear Previous playerLocation
map_setDot(playerLocation.x, playerLocation.y, 0, 0, 0, 0);
// New Value
playerLocation.y -= 1;
// Draw On New playerLocation
map_setDot(playerLocation.x, playerLocation.y, 255, 0, 0, 50);
// Display On Map
map_show();
delay(500);
}
} else if(joymem == "left") {
if(playerLocation.x > 0) {
// Clear Previous playerLocation
map_setDot(playerLocation.x, playerLocation.y, 0, 0, 0, 0);
// New Value
playerLocation.x -= 1;
// Draw On New playerLocation
map_setDot(playerLocation.x, playerLocation.y, 255, 0, 0, 50);
// Display On Map
map_show();
delay(500);
}
} else if(joymem == "right") {
if(playerLocation.x < 7) {
// Clear Previous playerLocation
map_setDot(playerLocation.x, playerLocation.y, 0, 0, 0, 0);
// New Value
playerLocation.x += 1;
// Draw On New playerLocation
map_setDot(playerLocation.x, playerLocation.y, 255, 0, 0, 50);
// Display On Map
map_show();
delay(500);
}
}
}

View File

@ -0,0 +1,97 @@
// I2C scanner function
void scanI2CBus(TwoWire &wire, const char* busName) {
byte error, address;
int nDevices = 0;
Serial.print("Scanning I2C bus: ");
Serial.println(busName);
for(address = 1; address < 127; address++) {
wire.beginTransmission(address);
error = wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) Serial.print("0");
Serial.print(address, HEX);
Serial.println(" !");
nDevices++;
} else if (error == 4) {
Serial.print("Unknown error at address 0x");
if (address < 16) Serial.print("0");
Serial.println(address, HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
}
//================================================================
//
//================================================================
String readJoystick() {
// const int X_PIN = A0;
// const int Y_PIN = A1;
int xVal = analogRead(X_PIN);
int yVal = analogRead(Y_PIN);
// Deadzone centers and ranges (after increasing by 50)
const int X_DEADZONE_MIN = 1975;
const int X_DEADZONE_MAX = 2065;
const int Y_DEADZONE_MIN = 1875;
const int Y_DEADZONE_MAX = 1965;
// Deadzone centers (can be calculated as (min+max)/2)
const int X_CENTER = (X_DEADZONE_MIN + X_DEADZONE_MAX) / 2; // 2020
const int Y_CENTER = (Y_DEADZONE_MIN + Y_DEADZONE_MAX) / 2; // 1920
bool xInDeadzone = (xVal >= X_DEADZONE_MIN && xVal <= X_DEADZONE_MAX);
bool yInDeadzone = (yVal >= Y_DEADZONE_MIN && yVal <= Y_DEADZONE_MAX);
if (xInDeadzone && yInDeadzone) return "center";
// Calculate how far each axis is from its deadzone center
int xDist = abs(xVal - X_CENTER);
int yDist = abs(yVal - Y_CENTER);
// If both axes are outside their deadzones, choose the one with the greater movement
if (!xInDeadzone && !yInDeadzone) {
if (xDist > yDist) {
if (xVal < X_CENTER) return "left";
else return "right";
} else {
if (yVal < Y_CENTER) return "up";
else return "down";
}
}
// If only one axis is outside, return its direction
else if (!yInDeadzone) {
if (yVal < Y_CENTER) return "up";
else return "down";
}
else if (!xInDeadzone) {
if (xVal < X_CENTER) return "left";
else return "right";
}
return "center";
}
//================================================================
//
//================================================================
int analogReadAVG(uint8_t pin, uint8_t times) {
int value;
for(int i=0; i<times; i++) {
}
}

View File

@ -0,0 +1,53 @@
#include <FastLED.h>
#define NUM_LEDS 16
#define DATA_PIN 8 // Change to your actual data pin
CRGB leds[NUM_LEDS];
void fastled_color(int start, int end, byte r, byte g, byte b, byte brightness) {
if (start < 0) start = 0;
if (end >= NUM_LEDS) end = NUM_LEDS - 1;
CHSV hsv = rgb2hsv_approximate(CRGB(r, g, b));
hsv.value = brightness;
for (int i = start; i <= end; i++) {
leds[i] = hsv;
}
}
void fastled_begin() {
FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
FastLED.clear();
FastLED.show();
}
void fastled_show() {
FastLED.show();
}
// Example health bar functions
void red_health(uint8_t value, uint8_t brightness) {
fastled_color(0, value-1, 255, 0, 0, brightness);
}
void blue_health(uint8_t value, uint8_t brightness) {
fastled_color(8, 8+value-1, 0, 0, 255, brightness); // Adjust if you want a different range
}
void crossfade_red() {
for(int i=10; i<=60; i++){
red_health(4, i);
fastled_show();
delay(20);
}
for(int i=60; i>=10; i--) {
red_health(4, i);
fastled_show();
delay(20);
}
}

View File

@ -0,0 +1,31 @@
#include <Adafruit_DotStar.h>
#define DATAPIN 10 // Change to your data pin
#define CLOCKPIN 9 // Change to your clock pin
#define NUMPIXELS 64 // 8x8 matrix
Adafruit_DotStar matrix(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BGR);
// Function to set a single dot (x, y) to a color (r, g, b)
void map_setDot(int x, int y, byte r, byte g, byte b, byte brightness) {
if (x < 0 || x > 7 || y < 0 || y > 7) return; // Out of bounds
int index = x + y * 8; // Convert (x,y) to strip index
// Scale the color by brightness (0255)
uint32_t color = matrix.Color(
(uint8_t)(r * brightness / 255),
(uint8_t)(g * brightness / 255),
(uint8_t)(b * brightness / 255)
);
matrix.setPixelColor(index, color);
}
void map_begin() {
matrix.begin();
matrix.clear();
matrix.show();
}
void map_show() {
matrix.show();
}

View File

View File

@ -1,218 +1,177 @@
#include <FastLED.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_DotStarMatrix.h>
#include <Adafruit_DotStar.h>
#include <SPI.h>
#include <SparkFun_APDS9960.h>
#undef WAIT // Prevent macro conflict with FastLED
#include <Wire.h>
#include <FastLED.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_DotStarMatrix.h>
#include <Adafruit_DotStar.h>
#include <SPI.h>
// ============ PIN DEFINITIONS ============
// PublicI2C (slave) pins
#define PUBLIC_I2C_SDA 21
#define PUBLIC_I2C_SCL 22
#define PUBLIC_I2C_ADDR 0x42 // Example slave address
// ============ PIN DEFINITIONS (ESP32-S3 Super Mini) ============
// LocalI2C (master) pins
#define LOCAL_I2C_SDA 12
#define LOCAL_I2C_SCL 11
#define JOY_X_PIN A1 // Example: GP2, adjust to your wiring
#define JOY_Y_PIN A2 // Example: GP3, adjust to your wiring
#define JOY_BTN_PIN 3 // Example: GP8, adjust to your wiring
// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define LOCAL_I2C_SDA 12 // Example: GP9, SDA for OLED/APDS
#define LOCAL_I2C_SCL 11 // Example: GP10, SCL for OLED/APDS
// Joystick pins
#define JOY_X_PIN 1 // ADC1_CH0
#define JOY_Y_PIN 2 // ADC1_CH1
#define JOY_BTN_PIN 3 // Digital input
#define NUM_LEDS 16
#define LED_DATA_PIN 8 // Example: GP11, adjust to your wiring
// FastLED (NeoPixel) settings
#define NUM_LEDS 16
#define LED_DATA_PIN 5 // Example GPIO for LED data
#define DOTSTAR_WIDTH 8
#define DOTSTAR_HEIGHT 8
#define DOTSTAR_DATA 10 // Example: GP12, adjust to your wiring
#define DOTSTAR_CLK 9 // Example: GP13, adjust to your wiring
// DotStar HD 8x8 Grid settings
#define DOTSTAR_WIDTH 8
#define DOTSTAR_HEIGHT 8
#define DOTSTAR_DATA 6 // Example GPIO for DotStar data
#define DOTSTAR_CLK 7 // Example GPIO for DotStar clock
// ============ I2C BUS OBJECTS ============
TwoWire PublicI2C = TwoWire(0); // I2C0 (slave)
TwoWire LocalI2C = TwoWire(1); // I2C1 (master)
#define ONBOARD_RGB_LED 48 // Onboard WS2812 RGB LED on GP48
// ============ DEVICE OBJECTS =============
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &LocalI2C, OLED_RESET);
// Use a SparkFun_APDS9960 library that supports TwoWire
SparkFun_APDS9960 apds(&LocalI2C);
CRGB leds[NUM_LEDS];
Adafruit_DotStarMatrix dotstar = Adafruit_DotStarMatrix(
DOTSTAR_WIDTH, DOTSTAR_HEIGHT, DOTSTAR_DATA, DOTSTAR_CLK,
DS_MATRIX_TOP + DS_MATRIX_LEFT + DS_MATRIX_ROWS + DS_MATRIX_PROGRESSIVE,
DOTSTAR_BRG
);
// ============ DATA STRUCTURES ============
struct SensorData {
int8_t joystickDir; // -1=none, 0=up, 1=down, 2=left, 3=right
bool joystickBtn;
uint16_t colorR, colorG, colorB, colorC;
};
volatile SensorData latestData;
Adafruit_SSD1306 display(128, 64, &Wire, -1);
CRGB leds[NUM_LEDS];
// ============ I2C SLAVE DATA HANDLERS =========
void receiveEvent(int numBytes) {
// Not used in this application, but required by Wire
}
Adafruit_DotStarMatrix dotstar = Adafruit_DotStarMatrix(
DOTSTAR_WIDTH, DOTSTAR_HEIGHT, DOTSTAR_DATA, DOTSTAR_CLK,
DS_MATRIX_TOP + DS_MATRIX_LEFT + DS_MATRIX_ROWS + DS_MATRIX_PROGRESSIVE,
DOTSTAR_BRG
);
void requestEvent() {
// Copy volatile to local to avoid race conditions
SensorData copy;
noInterrupts();
copy = latestData;
interrupts();
// Send as a binary buffer
PublicI2C.write((uint8_t*)&copy, sizeof(SensorData));
}
// ============ I2C SCAN FUNCTION =========
// ============ JOYSTICK INTERPRETATION =========
#define JOY_THRESHOLD_HIGH 3000
#define JOY_THRESHOLD_LOW 1000
void updateJoystick(SensorData &data) {
int joyX = analogRead(JOY_X_PIN);
int joyY = analogRead(JOY_Y_PIN);
bool joyBtn = digitalRead(JOY_BTN_PIN) == LOW;
// Default: no direction
data.joystickDir = -1;
if (joyY > JOY_THRESHOLD_HIGH) data.joystickDir = 0; // Up
else if (joyY < JOY_THRESHOLD_LOW) data.joystickDir = 1; // Down
else if (joyX < JOY_THRESHOLD_LOW) data.joystickDir = 2; // Left
else if (joyX > JOY_THRESHOLD_HIGH) data.joystickDir = 3; // Right
data.joystickBtn = joyBtn;
}
// ============ COLOR SENSOR READING =========
void updateColorSensor(SensorData &data) {
uint16_t r=0, g=0, b=0, c=0;
if (apds.readAmbientLight(c) &&
apds.readRedLight(r) &&
apds.readGreenLight(g) &&
apds.readBlueLight(b)) {
data.colorR = r;
data.colorG = g;
data.colorB = b;
data.colorC = c;
void scanI2CDevices(TwoWire &bus) {
byte error, address;
int nDevices = 0;
Serial.println("Scanning...");
for (address = 1; address < 127; address++) {
bus.beginTransmission(address);
error = bus.endTransmission();
if (error == 0) {
Serial.print("I2C device found at address 0x");
if (address < 16) Serial.print("0");
Serial.println(address, HEX);
nDevices++;
}
delay(1);
}
if (nDevices > 0) {
Serial.println("done");
}
}
}
// ============ DISPLAY LOGIC =========
void updateDisplays(const SensorData &data) {
// DotStar: show direction as arrow or color as background
dotstar.fillScreen(0);
if (data.joystickDir == 0) dotstar.drawPixel(3, 0, dotstar.Color(0,0,255)); // Up
else if (data.joystickDir == 1) dotstar.drawPixel(3, 7, dotstar.Color(0,0,255)); // Down
else if (data.joystickDir == 2) dotstar.drawPixel(0, 3, dotstar.Color(0,0,255)); // Left
else if (data.joystickDir == 3) dotstar.drawPixel(7, 3, dotstar.Color(0,0,255)); // Right
else dotstar.fillScreen(dotstar.Color(data.colorR>>2, data.colorG>>2, data.colorB>>2)); // Show color
dotstar.show();
// ============ ONBOARD RGB LED TEST =========
// FastLED: color bar with button brightness
uint8_t brightness = data.joystickBtn ? 255 : 64;
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(data.colorR>>4, data.colorG>>4, data.colorB>>4);
leds[i].nscale8_video(brightness);
void testOnboardRGB() {
// Note: Onboard RGB LED is a WS2812 on GP48
FastLED.addLeds<NEOPIXEL, ONBOARD_RGB_LED>(leds, 1); // Use just 1 LED
leds[0] = CRGB::Red;
FastLED.show();
delay(500);
leds[0] = CRGB::Blue;
FastLED.show();
delay(500);
leds[0] = CRGB::Green;
FastLED.show();
delay(500);
FastLED.clear();
FastLED.show();
FastLED.clear(true); // Clear LED data and reset FastLED for main NeoPixel strip
}
FastLED.show();
// OLED: show values
display.clearDisplay();
display.setCursor(0,0);
display.print("Dir: ");
switch (data.joystickDir) {
case 0: display.println("Up"); break;
case 1: display.println("Down"); break;
case 2: display.println("Left"); break;
case 3: display.println("Right"); break;
default: display.println("None"); break;
}
display.print("Btn: "); display.println(data.joystickBtn ? "Pressed" : "Released");
display.print("R: "); display.println(data.colorR);
display.print("G: "); display.println(data.colorG);
display.print("B: "); display.println(data.colorB);
display.print("C: "); display.println(data.colorC);
display.display();
}
// ============ SYSTEM TEST =========
// ============ SETUP FUNCTION =============
void setup() {
Serial.begin(115200);
void runSystemTest() {
// --- Initialize PublicI2C as Slave ---
PublicI2C.begin(PUBLIC_I2C_ADDR, PUBLIC_I2C_SDA, PUBLIC_I2C_SCL, 100000);
PublicI2C.onReceive(receiveEvent);
PublicI2C.onRequest(requestEvent);
Serial.println("PublicI2C (slave) initialized.");
Serial.println("\n===== SYSTEM TEST =====\n");
// --- Initialize LocalI2C as Master ---
LocalI2C.begin(LOCAL_I2C_SDA, LOCAL_I2C_SCL, 100000);
Serial.println("LocalI2C (master) initialized.");
// --- Onboard RGB LED Test ---
// --- Initialize OLED Display ---
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 allocation failed");
while (1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("OLED Ready!");
display.display();
Serial.println("Testing onboard RGB LED...");
testOnboardRGB();
Serial.println("Onboard RGB LED: OK");
// --- Initialize APDS-9960 (SparkFun) ---
if (!apds.init()) { // Uses LocalI2C if library supports it
Serial.println("APDS-9960 initialization failed");
display.println("No APDS-9960!");
// --- Joystick Test ---
int joyX = analogRead(JOY_X_PIN);
int joyY = analogRead(JOY_Y_PIN);
int joyBtn = digitalRead(JOY_BTN_PIN);
Serial.print("Joystick X: "); Serial.println(joyX);
Serial.print("Joystick Y: "); Serial.println(joyY);
Serial.print("Button: "); Serial.println(joyBtn ? "Released" : "Pressed");
Serial.println("Joystick: OK");
// --- I2C Device Scan ---
Serial.println("Scanning I2C devices...");
scanI2CDevices(Wire);
// --- OLED Test ---
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED: FAIL");
while(1);
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("SYSTEM TEST");
display.println("Joystick OK");
display.println("I2C OK");
display.println("FastLED OK");
display.println("DotStar OK");
display.display();
while (1);
Serial.println("OLED: OK");
// --- FastLED (NeoPixel) Test ---
FastLED.addLeds<NEOPIXEL, LED_DATA_PIN>(leds, NUM_LEDS);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(0, 255, 0); // Green
}
FastLED.show();
delay(1000);
FastLED.clear();
FastLED.show();
Serial.println("FastLED: OK");
// --- DotStar (APA102) Test ---
dotstar.begin();
dotstar.setBrightness(32);
dotstar.fillScreen(dotstar.Color(255, 0, 0)); // Red
dotstar.show();
delay(1000);
dotstar.fillScreen(0);
dotstar.show();
Serial.println("DotStar: OK");
Serial.println("===== SYSTEM TEST COMPLETE =====");
}
display.println("APDS-9960 ready!");
display.display();
// Enable color sensing
apds.enableLightSensor(false);
// ============ SETUP =============
// --- Initialize Joystick Pins ---
pinMode(JOY_BTN_PIN, INPUT_PULLUP); // Button is active LOW
void setup() {
// --- Initialize FastLED (NeoPixel) ---
FastLED.addLeds<NEOPIXEL, LED_DATA_PIN>(leds, NUM_LEDS);
FastLED.clear();
FastLED.show();
Serial.begin(115200);
// --- Initialize DotStar Matrix ---
dotstar.begin();
dotstar.setBrightness(32); // Adjust as needed
dotstar.fillScreen(0);
dotstar.show();
}
while(!Serial) { delay(10); }
// ============ MAIN LOOP ==================
void loop() {
SensorData tempData;
updateJoystick(tempData);
updateColorSensor(tempData);
// Initialize I2C
Wire.begin(LOCAL_I2C_SDA, LOCAL_I2C_SCL, 100000);
// Copy to shared struct for I2C
noInterrupts();
latestData = tempData;
interrupts();
// Initialize joystick button
pinMode(JOY_BTN_PIN, INPUT_PULLUP);
updateDisplays(tempData);
// Run system test
runSystemTest();
delay(50); // Adjust as needed
}
// Keep the loop empty as recommended for ESP32-S3 Super Mini
while(true) {}
}
// ============ LOOP =============
void loop() {
// Leave empty to avoid crashes on ESP32-S3 Super Mini
}