/*
 * control_table.h
 *
 *  Created on: 2023/10/11
 */

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2023 Takayoshi Uemitsu (BestTechnology CO.,LTD.)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */

#ifndef CONTROL_TABLE_H_
#define CONTROL_TABLE_H_

#include "hal_data.h"

#include <stdint.h>
#include <stdbool.h>
#include <limits.h>

// Servo control mode
typedef enum { sm_none = 0, sm_angle = 1, sm_velocity = 2, sm_current = 4, sm_pwm = 8} tsevomode;
// Supported baudrate list
typedef enum { br_9600 = 0, br_19200, br_38400, br_57600, br_100k, br_115200, br_200k, br_230400, br_460800, br_500k, br_1M, br_2M, br_3M, br_4M } TBaudrate;

// Monitor mode
typedef enum { mdm_none = 0, mdm_withinrange, mdm_outofrange, mdm_match } tmondetectmode;
// Monitor procedure
typedef enum { mpc_idle = -1, mpc_none = 0, mpc_pwm75 = 1, mpc_pwm50, mpc_pwm25, mpc_pwm10, mpc_pwm0, mpc_free, mpc_stall} tmonproc;

// System status (mainly anomalies)
typedef union {
    uint32_t all;
    struct {
        uint32_t encoderstat        :8;
        uint32_t outoftemperature   :4;
        uint32_t encodererror       :1;
        uint32_t powmonerror        :1;
        uint32_t other              :18;
    } __PACKED bit;
} TSysStatus;

// PID control value
typedef struct {
    int32_t Kp;
    int32_t Ki;
    int32_t Kd;
    int32_t Kf;
    int32_t delta_t;
} /*__PACKED */TGainInt;

typedef struct {
    int32_t min;
    int32_t max;
} TAngleLimit;

typedef struct {
    int16_t ItemIndex;
    int32_t min;
    int32_t max;
    uint32_t time;
    uint8_t DetectMode;
    uint8_t ProcMode;
    uint32_t DurationTime;
} TMonInfo;

// Flexibility control value
typedef struct {
    int32_t p_compliance;
    int32_t p_deadzone;
    int32_t n_deadzone;
    int32_t n_compliance;
} /*__PACKED */TFlexibility;

// Internal Control table
typedef struct {
    uint8_t ID;
    uint8_t  Baudrate;
    int32_t OffsetPresentAngle;
    uint8_t LED;

    uint16_t ReturnDelayTime;

    TSysStatus SystemStatus;

    TGainInt AngleCtrlGain;
    TGainInt VelocityCtrlGain;
    TGainInt CurrentCtrlGain;

    TAngleLimit AngleLimit;
    TFlexibility AngleFlexibility;
    TFlexibility VelocityFlexibility;
    TFlexibility CurrentFlexibility;

    uint8_t Excitation;

    uint8_t TransitionMode;
    int32_t TransitionTime;

    int32_t TargetAngle;
    int32_t TargetVelocity;
    int32_t TargetCurrent;
    int32_t TargetPWM;
    int32_t OffsetTargetAngle;
    int32_t OffsetTargetVelocity;
    int32_t OffsetTargetCurrent;

    int32_t CurrentAngle;
    int32_t CurrentVelocity;
    int32_t CurrentCurrent;
    int32_t CurrentPWM;
    uint16_t CurrentRawPosition;
    int32_t AngleViation;
    int32_t VelocityViation;
    int32_t CurrentViation;

    uint16_t CurrentBusVoltage;
    int16_t CurrentMPUTemp;
    int16_t CurrentAMPTemp;
    int16_t CurrentMotorTemp;
    uint32_t SysTickTimee;
    uint32_t ControlDurationTime;
    uint32_t NoCommTime;

    uint16_t AngleCorrection[37];   // 31..67
    TMonInfo MonInfo[5];
} /*__PACKED */TControlTable;

// The index of items in the control table is not the order of elements defined in TControlTable, but the order of elements defined in ItemInfo.
#define _ITEM_IDX_ID                  0
#define _ITEM_IDX_BAUDRATE            1
#define _ITEM_IDX_OFFSETANGLE         2
#define _ITEM_IDX_LED                 3
#define _ITEM_IDX_SYSTEMSTATUS        5

#define _ITEM_IDX_ANGFLEX_NCOMP       6
#define _ITEM_IDX_ANGFLEX_NDEAD       7
#define _ITEM_IDX_ANGFLEX_PDEAD       8
#define _ITEM_IDX_ANGFLEX_PCOMP       9
#define _ITEM_IDX_CURFLEX_NCOMP       10
#define _ITEM_IDX_CURFLEX_NDEAD       11
#define _ITEM_IDX_CURFLEX_PDEAD       12
#define _ITEM_IDX_CURFLEX_PCOMP       13

#define _ITEM_IDX_ANGLELIMIT_MIN      18
#define _ITEM_IDX_ANGLELIMIT_MAX      19

#define _ITEM_IDX_ANGLECTRLGAIN       20
#define _ITEM_IDX_VELOCITYCTRLGAIN    25
#define _ITEM_IDX_CURRENTCTRLGAIN     30

#define _ITEM_IDX_TRANSITIONMODE      35
#define _ITEM_IDX_TRANSITIONTIME      36

#define _ITEM_IDX_EXCITATION          37

#define _ITEM_IDX_TARGETANGLE         38
#define _ITEM_IDX_TARGETVELOCITY      39
#define _ITEM_IDX_TARGETCURRENT       40
#define _ITEM_IDX_TARGETPWM           41

#define _ITEM_IDX_CURRENTANGLE        45
#define _ITEM_IDX_CURRENTVELOCITY     46
#define _ITEM_IDX_CURRENTCURRENT      47
#define _ITEM_IDX_CURRENTPWM          48
#define _ITEM_IDX_CURRENTRAWPOSITION  49

#define _ITEM_IDX_CURRENTBUSVOLTAGE   50
#define _ITEM_IDX_CURRENTMPUTEMP      51
#define _ITEM_IDX_CURRENTAMPTEMP      52
#define _ITEM_IDX_CURRENTMOTORTEMP    53

#define _ITEM_IDX_ANGLECORRECTION     60

#define _ITEM_IDX_MONINFO             97

typedef enum {
    dt_int8, dt_uint8, dt_int16, dt_uint16, dt_int32, dt_uint32
} Tdatatype;

typedef struct {
    void *offset;
    Tdatatype dtype;
    bool readonly;
    bool nvm;
    int min;
    int max;
} TItemInfo;

extern const uint32_t baudrate_list[15];
extern const TItemInfo ItemInfo[];

extern TControlTable ControlTable;
extern const TControlTable Default_ControlTable;

// Write control table back to default values
extern bool RestoreControlTable2FactoryDefaults (void);

// Writing to one item in the control table
// **index overflow is not determined
typedef void (*twitm_fp)(uint16_t index, int data);
extern bool write_item (uint16_t idx, int data, twitm_fp);
// Read from one item in the control table
// **index overflow is not determined
typedef void (*tritm_fp)(uint16_t index);
extern bool read_item (uint16_t idx, Tdatatype *dtype, int32_t *data, tritm_fp);
extern int get_iteminfosize (void);

extern bool SaveCcontroltableToNVM (void);
extern bool LoadCcontroltableFromNVM (void);

extern void dbg_p (void);

#endif /* CONTROL_TABLE_H_ */
