/*

    Cute Useless Robot (´・ω・`)

    Developed by tobychui
    Idea come from Kairoshi

    Board Settings:
    ESP32 v2.014
    -> ESP32 Dev Module
*/

/* Libraries */
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <SD.h>
#include <ESP32Servo.h> //Require ESP32Servo

/* Pins Definations */
#define STP_DATA_PIN 4    // Stepper Shift Register DS
#define STP_CLOCK_PIN 16  // Stepper Shift Register SH_CP
#define STP_LATCH_PIN 17  // Stepper Shift Register ST_CP

#define SERVO_SWITCH 27  //Servo to push the switch
#define SERVO_COVER 14   //Servo to push the cover

#define DP_CLK_PIN 32   //Display CLK
#define DP_DATA_PIN 33  //Display DIN
#define DP_CS_PIN 25    //Display CS

#define SD_CS_PIN 5       //SD Card CS pin
#define TOGGLE_SWITCH 13  //Switch on top of the matrix display

/* Display settings generated by trial and error. Don't touch these */
#define HARDWARE_TYPE MD_MAX72XX::DR1CR0RR0_HW
#define MAX_DEVICES 8

/* Hardware Type Definations */
Servo servoSwitchPusher;
Servo servoCoverPusher;
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DP_DATA_PIN, DP_CLK_PIN, DP_CS_PIN, MAX_DEVICES);

/* Global Variables */
char animation = 'a';  //Animation ID to render

void setup() {
  Serial.begin(115200);

  // Allow allocation of all timers

  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);

  /* Stepper IO */
  pinMode(STP_DATA_PIN, OUTPUT);
  pinMode(STP_CLOCK_PIN, OUTPUT);
  pinMode(STP_LATCH_PIN, OUTPUT);
  standbySteppers();

  /* Servo IO */
  servoSwitchPusher.setPeriodHertz(50); 
  servoCoverPusher.setPeriodHertz(50); 
  servoSwitchPusher.attach(SERVO_SWITCH);
  servoCoverPusher.attach(SERVO_COVER);
  servoCoverPusher.write(0);
  servoSwitchPusher.write(0);

  /* SD Card */
  // Initialize SD card
  if (!SD.begin(SD_CS_PIN)) {
    Serial.println("[Error] Unable to mount SD card");
  }

  /* Display Module */
  mx.begin();
  setDisplayBrightness(0x4);
  renderFrame();  //Render the default frame to matrix
  delay(5000);

  /* Start Dual-core processes */
  createSemaphore();
  startCoreTasks();
}

void loop() {
  //Process has been handled in tasks.ino
  //Do not use this loop
}
