Comms between MAX 10 FPGA and ST uP
FPGA_bus.h@24:551a996eb5c2, 2020-06-28 (annotated)
- Committer:
- jimherd
- Date:
- Sun Jun 28 13:51:17 2020 +0000
- Revision:
- 24:551a996eb5c2
- Parent:
- 23:4b391cfd4f2d
- Child:
- 26:1837bc6df8ef
motor command config values fixed
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jimherd | 0:9600ed6fd725 | 1 | /* |
jimherd | 0:9600ed6fd725 | 2 | * FPGA_bus : 8-bit bi-directional bus between uP and FPGA |
jimherd | 0:9600ed6fd725 | 3 | * |
jimherd | 0:9600ed6fd725 | 4 | * Author : Jim Herd |
jimherd | 0:9600ed6fd725 | 5 | * |
jimherd | 0:9600ed6fd725 | 6 | * Version 0.1 : initial release |
jimherd | 0:9600ed6fd725 | 7 | */ |
jimherd | 0:9600ed6fd725 | 8 | #include "mbed.h" |
jimherd | 17:928b755cba80 | 9 | |
jimherd | 0:9600ed6fd725 | 10 | #ifndef FPGA_bus_H |
jimherd | 0:9600ed6fd725 | 11 | #define FPGA_bus_H |
jimherd | 0:9600ed6fd725 | 12 | |
jimherd | 20:aacf2ebd93ff | 13 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 20:aacf2ebd93ff | 14 | // MACROS |
jimherd | 20:aacf2ebd93ff | 15 | |
jimherd | 20:aacf2ebd93ff | 16 | #define LOOP_HERE for(;;) |
jimherd | 20:aacf2ebd93ff | 17 | |
jimherd | 20:aacf2ebd93ff | 18 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 0:9600ed6fd725 | 19 | // Pin definitions |
jimherd | 0:9600ed6fd725 | 20 | |
jimherd | 0:9600ed6fd725 | 21 | #define ASYNC_UP_RW_PIN PB_0 |
jimherd | 0:9600ed6fd725 | 22 | #define ASYNC_UP_HANDSHAKE_1_PIN PB_1 |
jimherd | 0:9600ed6fd725 | 23 | #define ASYNC_UP_HANDSHAKE_2_PIN PB_2 |
jimherd | 0:9600ed6fd725 | 24 | #define ASYNC_UP_START_PIN PB_3 |
jimherd | 0:9600ed6fd725 | 25 | #define ASYNC_UP_ACK_PIN PB_4 |
jimherd | 0:9600ed6fd725 | 26 | #define ASYNC_UP_RESET_PIN PB_5 |
jimherd | 0:9600ed6fd725 | 27 | |
jimherd | 9:6fe95fb0c7ea | 28 | #define LOG_PIN PB_8 |
jimherd | 9:6fe95fb0c7ea | 29 | |
jimherd | 0:9600ed6fd725 | 30 | // |
jimherd | 16:d69a36a541c5 | 31 | //#define PWM_BASE 1 |
jimherd | 0:9600ed6fd725 | 32 | #define NOS_PWM_REGISTERS 4 |
jimherd | 14:b56473e54f6f | 33 | #define NOS_PWM_CHANNELS 1 |
jimherd | 0:9600ed6fd725 | 34 | |
jimherd | 16:d69a36a541c5 | 35 | //#define QE_BASE ((NOS_PWM_REGISTERS * NOS_PWM_CHANNELS) + PWM_BASE) |
jimherd | 0:9600ed6fd725 | 36 | #define NOS_QE_REGISTERS 7 |
jimherd | 14:b56473e54f6f | 37 | #define NOS_QE_CHANNELS 1 |
jimherd | 0:9600ed6fd725 | 38 | |
jimherd | 16:d69a36a541c5 | 39 | //#define RC_BASE ((NOS_QE_REGISTERS * NOS_QE_CHANNELS) + QE_BASE) |
jimherd | 0:9600ed6fd725 | 40 | #define NOS_RC_CHANNELS 8 |
jimherd | 2:fd5c862b86db | 41 | #define GLOBAL_RC_ENABLE 0x80000000 |
jimherd | 0:9600ed6fd725 | 42 | |
jimherd | 16:d69a36a541c5 | 43 | #define PWM_ch0 (PWM_base + (0 * NOS_PWM_REGISTERS)) |
jimherd | 16:d69a36a541c5 | 44 | #define PWM_ch1 (PWM_base + (1 * NOS_PWM_REGISTERS)) |
jimherd | 16:d69a36a541c5 | 45 | #define PWM_ch3 (PWM_base + (3 * NOS_PWM_REGISTERS)) |
jimherd | 0:9600ed6fd725 | 46 | |
jimherd | 0:9600ed6fd725 | 47 | #define RC_0 RC_BASE |
jimherd | 0:9600ed6fd725 | 48 | |
jimherd | 9:6fe95fb0c7ea | 49 | // |
jimherd | 9:6fe95fb0c7ea | 50 | // System can be configured to return ONE or TWO 32-bit values from the FPGA. |
jimherd | 9:6fe95fb0c7ea | 51 | // |
jimherd | 9:6fe95fb0c7ea | 52 | // first value : 32-bit data value |
jimherd | 9:6fe95fb0c7ea | 53 | // second value : 32-bit status value |
jimherd | 9:6fe95fb0c7ea | 54 | // |
jimherd | 9:6fe95fb0c7ea | 55 | // In practice, the status word carries little or no information but consumes |
jimherd | 9:6fe95fb0c7ea | 56 | // four 8-bit transactions between the FPGA and the uP. |
jimherd | 9:6fe95fb0c7ea | 57 | // |
jimherd | 9:6fe95fb0c7ea | 58 | // Uncomment following #define to enable status word to be returned. |
jimherd | 9:6fe95fb0c7ea | 59 | |
jimherd | 9:6fe95fb0c7ea | 60 | //#define INCLUDE_32_BIT_STATUS_RETURN |
jimherd | 9:6fe95fb0c7ea | 61 | |
jimherd | 9:6fe95fb0c7ea | 62 | #ifdef INCLUDE_32_BIT_STATUS_RETURN |
jimherd | 9:6fe95fb0c7ea | 63 | #define NOS_RECEIVED_PACKET_WORDS 2 |
jimherd | 9:6fe95fb0c7ea | 64 | #else |
jimherd | 9:6fe95fb0c7ea | 65 | #define NOS_RECEIVED_PACKET_WORDS 1 |
jimherd | 9:6fe95fb0c7ea | 66 | #endif |
jimherd | 0:9600ed6fd725 | 67 | |
jimherd | 0:9600ed6fd725 | 68 | #define SET_BUS_INPUT (GPIOC->MODER = (GPIOC->MODER & 0xFFFF0000)) |
jimherd | 0:9600ed6fd725 | 69 | #define SET_BUS_OUTPUT (GPIOC->MODER = ((GPIOC->MODER & 0xFFFF0000) | 0x00005555)) |
jimherd | 0:9600ed6fd725 | 70 | #define OUTPUT_BYTE_TO_BUS(value) (GPIOC->ODR = ((GPIOC->ODR & 0x0000FF00) | (value & 0x000000FF))) |
jimherd | 0:9600ed6fd725 | 71 | #define INPUT_BYTE_FROM_BUS (GPIOC->IDR & 0x000000FF) |
jimherd | 0:9600ed6fd725 | 72 | #define ENABLE_GPIO_SUBSYSTEM (RCC->AHBENR |= RCC_AHBENR_GPIOCEN) |
jimherd | 0:9600ed6fd725 | 73 | |
jimherd | 20:aacf2ebd93ff | 74 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 1:b819a72b3b5d | 75 | // FPGA constants |
jimherd | 1:b819a72b3b5d | 76 | |
jimherd | 1:b819a72b3b5d | 77 | #define nS_IN_uS 1000 |
jimherd | 20:aacf2ebd93ff | 78 | #define FPGA_CLOCK_PERIOD_nS 20 |
jimherd | 21:6b2b7a0e2d9a | 79 | #define uS_DELAY_BEFORE_TEST_HANDSHAKE 25 |
jimherd | 22:c47d4177d59c | 80 | #define HANDSHAKE_TIMEOUT_COUNT 10000 |
jimherd | 1:b819a72b3b5d | 81 | |
jimherd | 20:aacf2ebd93ff | 82 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 1:b819a72b3b5d | 83 | // error codes |
jimherd | 1:b819a72b3b5d | 84 | |
jimherd | 21:6b2b7a0e2d9a | 85 | #define NO_ERROR 0 |
jimherd | 23:4b391cfd4f2d | 86 | #define BUS_FAIL_1 -31 // handshake_2 initially HIGH but should be LOW |
jimherd | 23:4b391cfd4f2d | 87 | #define BUS_FAIL_2 -32 // handshake_2 not transitioned to HIGH |
jimherd | 23:4b391cfd4f2d | 88 | #define BUS_FAIL_3 -33 // handshake_2 not transitioned to HIGH |
jimherd | 1:b819a72b3b5d | 89 | |
jimherd | 20:aacf2ebd93ff | 90 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 20:aacf2ebd93ff | 91 | // typedef structures |
jimherd | 0:9600ed6fd725 | 92 | |
jimherd | 0:9600ed6fd725 | 93 | typedef struct { |
jimherd | 0:9600ed6fd725 | 94 | uint8_t command; |
jimherd | 0:9600ed6fd725 | 95 | uint8_t register_no; |
jimherd | 0:9600ed6fd725 | 96 | uint32_t cmd_data; |
jimherd | 0:9600ed6fd725 | 97 | uint32_t reply_data; |
jimherd | 0:9600ed6fd725 | 98 | uint32_t reply_status; |
jimherd | 0:9600ed6fd725 | 99 | } FPGA_packet_t; |
jimherd | 0:9600ed6fd725 | 100 | |
jimherd | 0:9600ed6fd725 | 101 | typedef union { |
jimherd | 9:6fe95fb0c7ea | 102 | uint32_t word_data[2]; // NOS_RECEIVED_PACKET_WORDS]; |
jimherd | 9:6fe95fb0c7ea | 103 | uint8_t byte_data[8]; // NOS_RECEIVED_PACKET_WORDS << 2]; |
jimherd | 0:9600ed6fd725 | 104 | } received_packet_t; |
jimherd | 0:9600ed6fd725 | 105 | |
jimherd | 0:9600ed6fd725 | 106 | enum {READ_REGISTER_CMD=0, WRITE_REGISTER_CMD=1}; |
jimherd | 0:9600ed6fd725 | 107 | enum {READ_BUS=0, WRITE_BUS=1}; |
jimherd | 0:9600ed6fd725 | 108 | enum {LOW=0, HIGH=1}; |
jimherd | 4:e5d36eee9245 | 109 | |
jimherd | 20:aacf2ebd93ff | 110 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 6:e68defb7b775 | 111 | // SYS_data registers |
jimherd | 6:e68defb7b775 | 112 | |
jimherd | 6:e68defb7b775 | 113 | enum {SYS_DATA_REG_ADDR=0}; |
jimherd | 6:e68defb7b775 | 114 | |
jimherd | 20:aacf2ebd93ff | 115 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 20:aacf2ebd93ff | 116 | // PWM registers with relative addresses |
jimherd | 4:e5d36eee9245 | 117 | // |
jimherd | 0:9600ed6fd725 | 118 | enum {PWM_PERIOD=0, PWM_ON_TIME=1, PWM_CONFIG=2, PWM_STATUS=3}; |
jimherd | 20:aacf2ebd93ff | 119 | // |
jimherd | 20:aacf2ebd93ff | 120 | // constants to define bits in PWM config register |
jimherd | 0:9600ed6fd725 | 121 | |
jimherd | 20:aacf2ebd93ff | 122 | #define PWM_CONFIG_DEFAULT 0x00 |
jimherd | 20:aacf2ebd93ff | 123 | enum {PWM_OFF=0x0, PWM_ON=0x1}; |
jimherd | 20:aacf2ebd93ff | 124 | enum {INT_H_BRIDGE_OFF=0x0, INT_H_BRIDGE_ON=0x10000}; |
jimherd | 20:aacf2ebd93ff | 125 | enum {EXT_H_BRIDGE_OFF=0x0, EXT_H_BRIDGE_ON=0x20000}; |
jimherd | 20:aacf2ebd93ff | 126 | enum {MODE_PWM_CONTROL=0x0, MODE_DIR_CONTROL=0x40000}; |
jimherd | 24:551a996eb5c2 | 127 | enum {MOTOR_COAST=0x0, MOTOR_FORWARD=0x100000, MOTOR_BACKWARD=0x200000, MOTOR_BRAKE=0x300000}; |
jimherd | 20:aacf2ebd93ff | 128 | enum {NO_SWAP=0x0, YES_SWAP=0x1000000}; |
jimherd | 20:aacf2ebd93ff | 129 | enum {PWM_BRAKE_DWELL=0x0, PWM_COAST_DWELL=0x2000000}; |
jimherd | 20:aacf2ebd93ff | 130 | enum {NO_INVERT = 0x0, H_BRIDGE_1_INVERT=0x4000000, H_BRIDGE_2_INVERT=0x8000000, ALL_INVERT=0xC000000}; |
jimherd | 20:aacf2ebd93ff | 131 | enum {BACKWARD, FORWARD}; |
jimherd | 20:aacf2ebd93ff | 132 | |
jimherd | 20:aacf2ebd93ff | 133 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 20:aacf2ebd93ff | 134 | // QE registers with relative addresses |
jimherd | 4:e5d36eee9245 | 135 | // |
jimherd | 4:e5d36eee9245 | 136 | enum {QE_COUNT_BUFFER=0, QE_TURN_BUFFER=1, QE_SPEED_BUFFER=2, QE_SIM_PHASE_TIME=3, |
jimherd | 4:e5d36eee9245 | 137 | QE_COUNTS_PER_REV=4, QE_CONFIG=5, QE_STATUS=6}; |
jimherd | 8:65d1b1a7bfcc | 138 | // |
jimherd | 8:65d1b1a7bfcc | 139 | // constants to define bits in QE config register |
jimherd | 4:e5d36eee9245 | 140 | |
jimherd | 9:6fe95fb0c7ea | 141 | #define QE_CONFIG_DEFAULT 0x00 |
jimherd | 8:65d1b1a7bfcc | 142 | enum {QE_SIG_EXT=0x00, QE_SIG_INT_SIM=0x02}; |
jimherd | 8:65d1b1a7bfcc | 143 | enum {QE_INT_SIM_DISABLE=0x0, QE_INT_SIM_ENABLE=0x04}; |
jimherd | 8:65d1b1a7bfcc | 144 | enum {QE_SIM_DIR_FORWARD=0x0, QE_SIM_DIR_BACKWARD=0x08}; |
jimherd | 8:65d1b1a7bfcc | 145 | enum {QE_NO_SWAP_AB=0x00, QE_SWAP_AB=0x10}; |
jimherd | 8:65d1b1a7bfcc | 146 | enum {QE_SPEED_CALC_DISABLE=0x00, QE_SPEED_CALC_ENABLE=0x10000}; |
jimherd | 8:65d1b1a7bfcc | 147 | enum {QE_SPEED_CALC_FILTER_DISABLE=0x00, QE_SPEED_CALC_FILTER_ENABLE=0x20000}; |
jimherd | 10:56a045a02047 | 148 | enum {QE_FILTER_SAMPLE_2=0x00, QE_FILTER_SAMPLE_4=0x100000, QE_FILTER_SAMPLE_8=0x200000, |
jimherd | 10:56a045a02047 | 149 | QE_FILTER_SAMPLE_16=0x300000, QE_FILTER_SAMPLE_32=0x400000}; |
jimherd | 20:aacf2ebd93ff | 150 | |
jimherd | 20:aacf2ebd93ff | 151 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 20:aacf2ebd93ff | 152 | // RC servo registers with relative addresses |
jimherd | 4:e5d36eee9245 | 153 | // |
jimherd | 0:9600ed6fd725 | 154 | enum {RC_SERVO_PERIOD=0, RC_SERVO_CONFIG=1, RC_SERVO_STATUS=2, RC_SERVO_ON_TIME=3}; |
jimherd | 0:9600ed6fd725 | 155 | |
jimherd | 20:aacf2ebd93ff | 156 | ////////////////////////////////////////////////////////////////////////// |
jimherd | 20:aacf2ebd93ff | 157 | // FPGA_bus class |
jimherd | 20:aacf2ebd93ff | 158 | // ============== |
jimherd | 9:6fe95fb0c7ea | 159 | |
jimherd | 0:9600ed6fd725 | 160 | class FPGA_bus { |
jimherd | 0:9600ed6fd725 | 161 | public: |
jimherd | 7:c0bef9c1f5d5 | 162 | FPGA_bus(int nos_PWM = NOS_PWM_CHANNELS , |
jimherd | 7:c0bef9c1f5d5 | 163 | int nos_QE = NOS_QE_CHANNELS , |
jimherd | 14:b56473e54f6f | 164 | int nos_servo = NOS_RC_CHANNELS ); // constructor |
jimherd | 20:aacf2ebd93ff | 165 | // |
jimherd | 20:aacf2ebd93ff | 166 | // functions |
jimherd | 20:aacf2ebd93ff | 167 | // |
jimherd | 20:aacf2ebd93ff | 168 | int32_t initialise(void); |
jimherd | 20:aacf2ebd93ff | 169 | void do_transaction(uint32_t command, |
jimherd | 20:aacf2ebd93ff | 170 | uint32_t register_address, |
jimherd | 20:aacf2ebd93ff | 171 | uint32_t register_data, |
jimherd | 20:aacf2ebd93ff | 172 | uint32_t *data, |
jimherd | 20:aacf2ebd93ff | 173 | uint32_t *status); |
jimherd | 20:aacf2ebd93ff | 174 | void write_register(uint32_t register_addr, uint32_t value); |
jimherd | 20:aacf2ebd93ff | 175 | void set_PWM_period(uint32_t channel, float frequency); |
jimherd | 20:aacf2ebd93ff | 176 | void set_PWM_duty(uint32_t channel, float percentage); |
jimherd | 20:aacf2ebd93ff | 177 | void PWM_enable(uint32_t channel); |
jimherd | 20:aacf2ebd93ff | 178 | void PWM_config(uint32_t channel, uint32_t config_value); |
jimherd | 20:aacf2ebd93ff | 179 | void set_RC_period(void); |
jimherd | 20:aacf2ebd93ff | 180 | void set_RC_period(uint32_t duty_uS); |
jimherd | 20:aacf2ebd93ff | 181 | void set_RC_pulse(uint32_t channel, uint32_t pulse_uS); |
jimherd | 20:aacf2ebd93ff | 182 | void enable_RC_channel(uint32_t channel); |
jimherd | 20:aacf2ebd93ff | 183 | void disable_RC_channel(uint32_t channel); |
jimherd | 20:aacf2ebd93ff | 184 | void QE_config(uint32_t channel, uint32_t config_value); |
jimherd | 20:aacf2ebd93ff | 185 | void enable_speed_measure(uint32_t channel, uint32_t config_value, uint32_t phase_time); |
jimherd | 5:64c677e9995c | 186 | uint32_t read_speed_measure(uint32_t channel); |
jimherd | 10:56a045a02047 | 187 | uint32_t read_count_measure(uint32_t channel); |
jimherd | 6:e68defb7b775 | 188 | uint32_t get_SYS_data(void); |
jimherd | 22:c47d4177d59c | 189 | int32_t soft_check_bus(void); |
jimherd | 20:aacf2ebd93ff | 190 | // |
jimherd | 20:aacf2ebd93ff | 191 | // data |
jimherd | 20:aacf2ebd93ff | 192 | // |
jimherd | 1:b819a72b3b5d | 193 | int32_t global_FPGA_unit_error_flag; |
jimherd | 20:aacf2ebd93ff | 194 | // |
jimherd | 20:aacf2ebd93ff | 195 | // persistant system data |
jimherd | 20:aacf2ebd93ff | 196 | // |
jimherd | 20:aacf2ebd93ff | 197 | struct SYS_data { |
jimherd | 20:aacf2ebd93ff | 198 | uint8_t major_version; |
jimherd | 20:aacf2ebd93ff | 199 | uint8_t minor_version; |
jimherd | 20:aacf2ebd93ff | 200 | uint8_t number_of_PWM_channels; |
jimherd | 20:aacf2ebd93ff | 201 | uint8_t number_of_QE_channels; |
jimherd | 20:aacf2ebd93ff | 202 | uint8_t number_of_RC_channels; |
jimherd | 20:aacf2ebd93ff | 203 | uint32_t PWM_period_value[NOS_PWM_CHANNELS]; |
jimherd | 20:aacf2ebd93ff | 204 | uint32_t PWM_duty_value[NOS_PWM_CHANNELS]; |
jimherd | 20:aacf2ebd93ff | 205 | } sys_data; |
jimherd | 0:9600ed6fd725 | 206 | |
jimherd | 15:6420b52d30cc | 207 | private: |
jimherd | 20:aacf2ebd93ff | 208 | // |
jimherd | 20:aacf2ebd93ff | 209 | // data |
jimherd | 20:aacf2ebd93ff | 210 | // |
jimherd | 0:9600ed6fd725 | 211 | uint32_t _nos_PWM_units; |
jimherd | 0:9600ed6fd725 | 212 | uint32_t _nos_QE_units; |
jimherd | 0:9600ed6fd725 | 213 | uint32_t _nos_servo_units; |
jimherd | 0:9600ed6fd725 | 214 | |
jimherd | 15:6420b52d30cc | 215 | uint32_t PWM_base, QE_base, RC_base; |
jimherd | 15:6420b52d30cc | 216 | |
jimherd | 0:9600ed6fd725 | 217 | uint32_t data, status, tmp_config; |
jimherd | 0:9600ed6fd725 | 218 | received_packet_t in_pkt; |
jimherd | 20:aacf2ebd93ff | 219 | // |
jimherd | 20:aacf2ebd93ff | 220 | // functions |
jimherd | 20:aacf2ebd93ff | 221 | // |
jimherd | 20:aacf2ebd93ff | 222 | void do_start(void); |
jimherd | 20:aacf2ebd93ff | 223 | void do_end(void); |
jimherd | 20:aacf2ebd93ff | 224 | void write_byte(uint32_t byte_value); |
jimherd | 0:9600ed6fd725 | 225 | uint32_t read_byte(void); |
jimherd | 20:aacf2ebd93ff | 226 | void do_write( uint32_t command, |
jimherd | 20:aacf2ebd93ff | 227 | uint32_t register_address, |
jimherd | 20:aacf2ebd93ff | 228 | uint32_t register_data); |
jimherd | 20:aacf2ebd93ff | 229 | void do_read(received_packet_t *buffer); |
jimherd | 20:aacf2ebd93ff | 230 | void do_reset(void); |
jimherd | 22:c47d4177d59c | 231 | int32_t hard_check_bus(void); |
jimherd | 20:aacf2ebd93ff | 232 | void update_FPGA_register_pointers(void); |
jimherd | 20:aacf2ebd93ff | 233 | // |
jimherd | 20:aacf2ebd93ff | 234 | // Hardware digital I/O lines |
jimherd | 20:aacf2ebd93ff | 235 | // |
jimherd | 0:9600ed6fd725 | 236 | DigitalOut async_uP_start; |
jimherd | 0:9600ed6fd725 | 237 | DigitalOut async_uP_handshake_1; |
jimherd | 0:9600ed6fd725 | 238 | DigitalOut async_uP_RW; |
jimherd | 0:9600ed6fd725 | 239 | DigitalOut async_uP_reset; |
jimherd | 0:9600ed6fd725 | 240 | DigitalIn uP_ack; |
jimherd | 0:9600ed6fd725 | 241 | DigitalIn uP_handshake_2; |
jimherd | 0:9600ed6fd725 | 242 | |
jimherd | 9:6fe95fb0c7ea | 243 | DigitalOut log_pin; |
jimherd | 9:6fe95fb0c7ea | 244 | |
jimherd | 0:9600ed6fd725 | 245 | }; |
jimherd | 0:9600ed6fd725 | 246 | |
jimherd | 0:9600ed6fd725 | 247 | #endif |
jimherd | 0:9600ed6fd725 | 248 |