// data_structures.h

#define BASE_RATE 98.304                // units of Mbits/sec

// constants used in the main arbitration state machine

enum Legacy_wait_times { // set to values corresponding to the tables in text, in Legacy_time units (2/BASE_RATE)
  SPEED_SIGNAL_LENGTH = 5, 
  DATA_PREFIX_HOLD = 2, 
  DATA_END_TIME = 12,
  MIN_IDLE_TIME = 2,
  CONCATENATION_PREFIX_TIME = 8, 
  MIN_DELETABLE_SYMBOL_TIME = 2}; 
enum wait_times { // set to values corresponding to the tables in text, scaled to seconds
  SHORT_RESET_TIME, RESET_TIME, RESET_WAIT, ROOT_CONTEND_SLOW, ROOT_CONTEND_FAST, FORCE_ROOT_TIMEOUT,
  CONFIG_TIMEOUT, CM_MIN_IDLE_TIME, MAX_ARB_STATE_TIME}; 
enum Beta_times {BOSS_RESTART_TIME}; 

// constant used in background processing
enum Background_Beta_times {MAX_BETA_TIME}; 

// constants used in node-level connection management - times are given in Table 11-3
enum node_wait_times {BIAS_FILTER_TIME};
enum Beta_node_wait_times {TEST_INTERVAL};

// constants used in port-level connection management - times are given in Table 11-3
enum port_wait_times {DISCONNECTED_TONE_INTERVAL, TONE_DURATION, SPEEDCODE_BIT_INTERVAL, 
 RECEIVER_INIT_TIME, RESET_DETECT, CONNECT_TIMEOUT, 
 RECEIVE_OK_HANDSHAKE, PORT_ENABLE_TIME, MAX_OCCUPANCY_TIME};

#define TONE_GAP 8
#define TONE_INTERVAL 16
#define NUM_OF_TRIES 4
#define RESUME_CHECKS 65
#define SYNCHRONIZATION_LENGTH 16384

// data structures

typedef enum { S100 = 0, S200 = 1, S400 = 2, S800 = 3, S1600 = 4, S3200 = 5, 
                    NO_SPEED = 6, DEFAULT = 7} speedCode;
typedef enum {                          // Types of bus requests made by link across PHY/link interface
                                        // the boolean "immediate_request" replaces use of IMMED_REQ
  NO_REQ, ISOCH_REQ, PRIORITY_REQ, FAIR_REQ} breq_type;

typedef enum {                         // Tracks the PHY state (names per state diagrams)
  R0, R1, T0, T1, T2, T3, S0, S1, S2, S3, S4, A0, A1, A2, RX, TX, PH} PHY_state_type;
typedef enum {P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12} port_state_type;
typedef enum {L, H} tpSig;           // Differential signal on twisted pair
typedef enum {GND, Bias_On, ZZ} tpBiasSig;
typedef struct {tpSig TpA; tpSig TpB;} portData;    // Port data structure
typedef enum {RX_IDLE = 0, RX_PARENT_NOTIFY = 1, RX_REQUEST_CANCEL = 1,
  RX_IDENT_DONE = 2, RX_SELF_ID_GRANT = 3, RX_REQUEST = 3,
  RX_ROOT_CONTENTION = 4, RX_GRANT = 4, RX_SUSPEND = 4,
  RX_PARENT_HANDSHAKE = 5, RX_DATA_END = 5,
  RX_CHILD_HANDSHAKE = 6, RX_DISABLE_NOTIFY = 6,
  RX_DATA_PREFIX = 7, RX_BUS_RESET = 8} RX_arbstate;
typedef enum {TX_IDLE = 0, TX_REQUEST = 1, TX_GRANT = 1, TX_DISABLE_NOTIFY = 2, TX_PARENT_NOTIFY = 3,
  TX_SUSPEND = 4, TX_DATA_PREFIX = 5, TX_CHILD_NOTIFY = 6, TX_IDENT_DONE = 6,
  TX_DATA_END = 7,  TX_BUS_RESET = 8} TX_arbstate;  
typedef struct {RX_arbstate RX_arb; portData data;} RX_signal;

typedef enum {LTP_TEST = 0, ATTACH_IN_PROGRESS = 1} LTP_mode_type;
#define COLLISION_LIMIT 7

typedef enum {B_Link, Legacy_Link} linkType;
typedef enum {grant_senior, grant_link, grant_null, grant_junior, boss_management_actions}
                boss_eop_status; 

// CTRL, CONFIG_REQUEST and INVALID are used internally within the port machines
// DATA and ARB_STATE are used for communicating to the arb state machine
// DS_RAW_ARB is used to pass the overloaded received Legacy arb states to the process_request block
// for filtering based on the current PHY state
typedef enum { DATA, CTRL, ARB_REQUEST, CONFIG_REQUEST, INVALID, ARB_STATE, DS_RAW_ARB} portTag;

typedef enum { LEGACY, BETA, UNSPECIFIED } pktType;

typedef enum {  // first the arb-states corresponding to CTRL symbols
   // SPEEDa, SPEEDb and SPEEDc are used only internally in the port
  ASYNC_START = 0, CYCLE_START_EVEN = 1, CYCLE_START_ODD = 2, ATTACH_REQUEST = 3, 
  ARB_CONTEXT = 3, SPEEDa = 4, DATA_END = 5, DATA_NULL = 6, SPEEDb = 7, 
  // note GRANT and SELF_ID_GRANT are the same code
  GRANT = 8, SELF_ID_GRANT = 8,
  DATA_PREFIX = 9, GRANT_ISOCH = 10, SPEEDc = 11, ARB_RESET_EVEN = 12, ARB_RESET_ODD = 13, 
  BUS_RESET = 14, IDLE = 15, SPEED = 16, SPEED_RAW = 17,
  
  // then the arb-states corresponding to CONFIG_REQUEST symbols
  // note, CHILD_NOTIFY, PARENT_HANDSHAKE and IDENT_DONE are the same code
  // note TRAINING is the lowest value of these enum types
  TRAINING = 18, STANDBY = 19, CHILD_NOTIFY = 20, IDENT_DONE = 20, PARENT_HANDSHAKE = 20, 
  // note PARENT_NOTIFY and ROOT_CONTENTION are the same code
  PARENT_NOTIFY = 21, ROOT_CONTENTION = 21,
  DISABLE_NOTIFY = 22, SUSPEND = 23, OPERATION = 24, LEGACY_REQUEST = 25,
  CHILD_HANDSHAKE = 26, REQUEST_CANCEL = 27,
  
  // DATA_BYTE is only used in the arb state machine
  DATA_BYTE = 28
} ArbState;

// encode the two types of priority as two nibbles, high order for odd phase
typedef enum { A_NONE = 0, NONE_ODD = 0x13, NEXT_EVEN = 0x25, NONE_EVEN = 0x31, 
  CURRENT = 0x44, NEXT_ODD = 0x52, CYCLE_START_REQ = 0x66, BORDER = 0x77} asyncReqType;

typedef enum { I_NONE = 0, ISOCH_NONE = 0x11, ISOCH_ODD = 0x42, ISOCH_EVEN = 0x24,
               ISOCH_IN_PHASE = 0x33, ISOCH_CURRENT = 0x55} isochReqType;
               // Note, ISOCH_IN_PHASE is defined for simple comparisons to determine
               // if a particular request is for the current phase.  Is does not appear
               // on the serial bus

typedef enum { negative_rd = 0, positive_rd = 1  } disparityType;

typedef struct {
  asyncReqType async;
  isochReqType isoch;
} BetaRequestCode;

typedef struct {         // This type holds any port symbol
  portTag tag;             // The type of symbol
  union {                  // This part holds symbol data
    byte data;               // valid if tag is DATA
    ArbState arb;            // valid if tag is CTRL, CONFIG_REQUEST, or ARB_STATE
    RX_arbstate rx_dsarb;    // valid if tag is DS_RAW_ARB
    BetaRequestCode req;     // valid if tag is ARB_REQUEST (only used internally in the port)
  };
  speedCode speed;         // the effective speed at which the current info is to be sent
  pktType pkt;             // valid if arb is SPEED
} portSymbol;

typedef struct {
  union {
    byte dataBytes[8];
    struct {
      union {
        quadlet dataQuadlet;
        struct {   // First self_ID packet
          quadlet phy_pktType:2;
          quadlet phy_ID:6; // Physical_ID
          quadlet :1; // Always 0 for first self_ID packet
          quadlet L:1; // Link active
          quadlet gap_cnt:6; // Gap count
          quadlet sp:2; // Speed code
          quadlet :2;
          quadlet c:1; // Isochronous resource manager contender
          quadlet pwr:3; // Power class
          quadlet p0:2; // Port 0 connection status
          quadlet p1:2; // Port 1 connection status
          quadlet p2:2; // Port 2 connection status
          quadlet i:1; // Initiated reset
          quadlet m:1; // More self_ID packets...
        } ; //self_ID_first
        struct { // Subsequent self_ID packets
          quadlet :8;
          quadlet ext:1; // Nonzero for second and subsequent self_ID packets
          quadlet n:3; // Sequence number
          quadlet :2;
          quadlet pa:2; // Port connection status...
          quadlet pb:2; // pa pb pc pd pe pf pg ph
          quadlet pc:2; // self_ID packet 2 P3 P4 P5 P6 P7 P8 P9 P10
          quadlet pd:2; // self_ID packet 3 P11 P12 P13 P14 P15 --- --- ---
          quadlet pe:2;
          quadlet pf:2;
          quadlet pg:2;
          quadlet ph:2;
          quadlet :2;
        } ; // self_ID;
        struct { // PHY configuration packet, also used as restore packet
          quadlet :2;
          quadlet root_ID:6; // Intended root
          quadlet R:1; // If set, root_ID field is valid
          quadlet T:1; // If set, gap_cnt field is valid
          quadlet gap_count:6; // Gap count
          union {
            struct {    // for a restore packet
              quadlet:12;
              quadlet Q;
              quadlet P;
              quadlet notify_odd_async_phase:1;
              quadlet notify_reset:1;
            };
            quadlet :16;
          };
        } ; // phy_config;
        struct { // Extended PHY packets (ping and other remote packets)
          quadlet :2;
          quadlet :6; // Physical_ID
          quadlet :2; // Always 0, identifies Exended PHY packet
          quadlet ext_type:4; // Extended type
          union {
            struct {
              union {
                quadlet page:3; // Page_select
                quadlet e_cmnd:3; // Extended command
              };
              quadlet port_num:4; // Port_select
              union {
                struct {
                  quadlet reg:3; // Register address (add 0b1000 if paged register)
                  quadlet data:8; // Register data (remote reply)
                };
                struct { // Remote confirmation
                  quadlet :2;
                  quadlet standby_fault:1; // Copies of equivalent PHY register bits...
                  quadlet fault:1; 
                  quadlet connected:1;
                  quadlet bias:1;
                  quadlet disabled:1;
                  quadlet ok:1; // Confirm command accepted or not
                  quadlet cmnd:3; // Remote command
                } ; // remote_cnfrm;
              };
            };
            struct { // fields for Loop Test Packet
              quadlet :10;
              quadlet mode:1; // LTP mode
              quadlet G:1;    // Generation number
              quadlet test_value:6;   // Loop Test Packet comparison value
            };
          };
        } ; // ext_phy;
      };
      quadlet checkQuadlet;
    };
  };
} PHY_PKT;

// implementation dependent constants
#define CONTENDER 1                     // IMPLEMENTATION DEPENDENT
#define POWER_CLASS 0b000               // IMPLEMENTATION DEPENDENT

#define NPORT 4                         // number of ports - IMPLEMENTATION DEPENDENT

#define PHY_SPEED S800                  // PHY speed - IMPLEMENTATION DEPENDENT
#define DS_PHY_SPEED S400               // PHY speed for DS ports - IMPLEMENTATION DEPENDENT

const speedCode DS_port_speed[NPORT];   // Speed of each DS capable port - IMPLEMENTATION DEPENDENT
