/*
   @copyright (C) 2024 Melexis <http://www.melexis.com>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

   Rev1.0: Creation, Mar 28th 2024, general serial to SPI interface.
   Rev1.1: SPI mode fixed to mode 0 (April 2025)
*/

#include <SPI.h>
uint8_t Nbytes = 0;
uint8_t toSend[8];
uint8_t receivedFrom[8];
uint32_t speedMaximum = 1000000;
uint8_t dataOrder = MSBFIRST;
uint8_t dataMode = SPI_MODE0;
SPISettings mySetting(speedMaximum, dataOrder, dataMode);
uint8_t charReceived;


void setup() {
  Serial.begin(115200);
  SPI.begin();
  SPI.beginTransaction(mySetting);
}

void loop() {
  if (Serial.available() > 0) {
    charReceived = Serial.read();
  }
  switch (charReceived) {
    case 'X':
      // What is length in bytes of SPI message?
      while (!Serial.available()) {}
      charReceived = hex2dec(Serial.read());
      while (!Serial.available()) {}
      charReceived = 16 * charReceived + hex2dec(Serial.read());
      Nbytes = charReceived;
      // What are the bytes of the SPI message?
      for (int i = 0; i < Nbytes; i++) {
        while (!Serial.available()) {}
        charReceived = hex2dec(Serial.read());
        while (!Serial.available()) {}
        charReceived = 16 * charReceived + hex2dec(Serial.read());
        toSend[i] = charReceived;
      }
      // Send the SPI message
      SPI.beginTransaction(mySetting);
      digitalWrite(PIN_SPI_SS, LOW);
      for (uint8_t i = 0; i < Nbytes; i++) {
        receivedFrom[i] = SPI.transfer(toSend[i]);
      }
      digitalWrite(PIN_SPI_SS, HIGH);
      SPI.endTransaction();
      // Return answer to PC
      for (int i = 0; i < Nbytes; i++) {
        if (receivedFrom[i] < 0x10) {
          Serial.print("0"); // Padding with 0
        }
        Serial.print(receivedFrom[i], HEX);
      }
      Serial.println();
      break;
    case 'Z':
      digitalWrite(PIN_SPI_SS, LOW);
      digitalWrite(PIN_SPI_SS, HIGH);
      Serial.println("OK");
      break;
  }
  charReceived = 0;
}

int hex2dec(char input)
{
  int result = 0;
  if (input >= 48 && input <= 57) {
    result = (int) input - 48;
  }
  if (input >= 65 && input <= 70) {
    result = (int) input - 55;
  }
  return result;
}