/*
**
******************************************************************************
* @file : MESCApp.h
* @brief : Application specific code, such as for managing vehicle inputs for brake, stands...
******************************************************************************
* @attention
*
*
© Copyright (c) 2024 David Molony.
* All rights reserved.
*
* This software component is licensed under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*In addition to the usual 3 BSD clauses, it is explicitly noted that you
*do NOT have the right to take sections of this code for other projects
*without attribution and credit to the source. Specifically, if you copy into
*copyleft licenced code without attribution and retention of the permissive BSD
*3 clause licence, you grant a perpetual licence to do the same regarding turning sections of your code
*permissive, and lose any rights to use of this code previously granted or assumed.
*
*This code is intended to remain permissively licensed wherever it goes,
*maintaining the freedom to distribute compiled binaries WITHOUT a requirement to supply source.
*
*This is to ensure this code can at any point be used commercially, on products that may require
*such restriction to meet regulatory requirements, or to avoid damage to hardware, or to ensure
*warranties can reasonably be honoured.
******************************************************************************
* MESCfoc.h
*
* Created on: Oct 2024
* Author: David Molony
*/
#include "MESCApp.h"
#include "MESCfoc.h"
#include "MESCmotor_state.h"
#include "MESCerror.h"
#include "stm32fxxx_hal.h"
typedef struct {
uint32_t reverseState;
uint32_t sidestandState;
uint32_t brakeState;
}Vehicle_s;
Vehicle_s vehicle;
/////Macros to read inputs
#ifdef REVERSE_GPIO
#define getReverseState(...) ((REVERSE_GPIO->IDR >> (REVERSE_IONO)) & 0x1)
#else
#define getReverseState(...) (1) //Default forward
#endif
#ifdef SIDESTAND_GPIO
#define getSidestandState(...) ((SIDESTAND_GPIO->IDR >> (SIDESTAND_IONO)) & 0x1)
#else
#define getSidestandState(...) (1) //Default sidestand up, vehicle moves
#endif
#ifdef BRAKE_GPIO
#define getBrakeState(...) ((BRAKE_GPIO->IDR >> (BRAKE_IONO)) & 0x1)
#else
#define getBrakeState(...) (1) //Default no brake, vehicle moves
#endif
uint32_t vehicle_state = VEHICLE_IDLE;
uint32_t vehicle_direction = VEHICLE_FORWARD;
uint32_t debounce(uint32_t var, uint32_t input){
if((var>0) && (!input)){
var = var-1;
}else if(var == 0){
var = 100; //Reset it to far from the threshold
}else if((var<100)){
var = var+1;
}
return var;
}
void No_app(MESC_motor_typedef *_motor){
//Sum the inputs
//We just scale and sum the input current requests
_motor->FOC.Idq_prereq.q = _motor->input_vars.UART_req +
_motor->input_vars.max_request_Idq.q * (_motor->input_vars.ADC1_req + _motor->input_vars.ADC2_req +
_motor->input_vars.RCPWM_req + _motor->input_vars.ADC12_diff_req +
_motor->input_vars.remote_ADC1_req + _motor->input_vars.remote_ADC2_req );
//Clamp the Q component; d component is not directly requested
_motor->FOC.Idq_prereq.q = clamp(_motor->FOC.Idq_prereq.q, _motor->input_vars.min_request_Idq.q, _motor->input_vars.max_request_Idq.q);
}
void Vehicle_app(MESC_motor_typedef *_motor){
//Sum the inputs
//We just scale and sum the input current requests
_motor->FOC.Idq_prereq.q = _motor->input_vars.UART_req +
_motor->input_vars.max_request_Idq.q * (_motor->input_vars.ADC1_req + _motor->input_vars.ADC2_req +
_motor->input_vars.RCPWM_req + _motor->input_vars.ADC12_diff_req +
_motor->input_vars.remote_ADC1_req + _motor->input_vars.remote_ADC2_req );
//Clamp the Q component; d component is not directly requested
_motor->FOC.Idq_prereq.q = clamp(_motor->FOC.Idq_prereq.q, _motor->input_vars.min_request_Idq.q, _motor->input_vars.max_request_Idq.q);
vehicle.sidestandState = getSidestandState();
#ifdef MOMENTARY_REV
// vehicle.reverseState = getReverseState();
vehicle.reverseState = debounce(vehicle.reverseState, getReverseState());
if((!vehicle.reverseState)&&(fabsf(_motor->FOC.Idq_prereq.q)<5.0f)){
vehicle_direction = vehicle_direction+1;
vehicle_direction = vehicle_direction & 0x1;
}
if(vehicle_direction){
//Nothing
}else{
_motor->FOC.Idq_prereq.q *= -1.0f;
}
#else
vehicle.reverseState = getReverseState();
if(vehicle.reverseState == 0){
_motor->FOC.Idq_prereq.q *= -1.0f;
}
#endif
vehicle.brakeState = getBrakeState();
/////////////////////////////Vehicle State Machine
switch(vehicle_state){
case VEHICLE_IDLE:
_motor->key_bits |= APP_KEY; //Set the bit; lock the motor from current
//HACK
vehicle_state = VEHICLE_DRIVE; //Move direct to drive for testing, otherwise it will lock the vehicle...
//Add state machine logics
break;
case VEHICLE_PARKED:
_motor->key_bits |= APP_KEY; //Set the bit; lock the motor from current
//Add state machine logics
break;
case VEHICLE_DRIVE:
_motor->key_bits &= ~APP_KEY; //Clear the bit; allow motor current
//Add state machine logics
break;
case VEHICLE_x:
break;
case VEHICLE_y:
break;
default:
handleError(_motor,ERROR_APP);
_motor->key_bits |= APP_KEY; //Set the bit; lock the motor from current
}
// _motor->key_bits;
// _motor->key_bits |= APP_KEY; Set the bit; lock the motor from current
// _motor->key_bits &= ~APP_KEY; Clear the bit - allow current
}