From 330a923847d4714e9cb911ebc9491615c2951c01 Mon Sep 17 00:00:00 2001 From: GhassanYusuf Date: Thu, 5 Jun 2025 16:47:58 +0300 Subject: [PATCH] first commit --- HaithamJoyStick.ino | 218 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 HaithamJoyStick.ino diff --git a/HaithamJoyStick.ino b/HaithamJoyStick.ino new file mode 100644 index 0000000..45ece87 --- /dev/null +++ b/HaithamJoyStick.ino @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include +#include +#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*)©, 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(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 +} \ No newline at end of file