Comms between MAX 10 FPGA and ST uP

Committer:
jimherd
Date:
Fri May 22 22:53:46 2020 +0000
Revision:
15:6420b52d30cc
Parent:
14:b56473e54f6f
Child:
16:d69a36a541c5
FPGA unit base register pointers are now variables rather than #define constants

Who changed what in which revision?

UserRevisionLine numberNew 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 #include "mbed.h"
jimherd 0:9600ed6fd725 5 #include "FPGA_bus.h"
jimherd 0:9600ed6fd725 6
jimherd 0:9600ed6fd725 7 /** create a FPGA_bus object connecting uP to FPGA
jimherd 0:9600ed6fd725 8 *
jimherd 0:9600ed6fd725 9 * @param nos_PWM Number of PWM channels (default = 4)
jimherd 0:9600ed6fd725 10 * @param nos_QE Number of Quadrature Encoder channels (default = 4)
jimherd 0:9600ed6fd725 11 * @param nos_servo Number of RC servo channels (default = 8)
jimherd 0:9600ed6fd725 12 *
jimherd 0:9600ed6fd725 13 * Notes
jimherd 0:9600ed6fd725 14 * You can only change the defaults by recompiling the SystemVerilog code
jimherd 0:9600ed6fd725 15 * on the FPGA.
jimherd 7:c0bef9c1f5d5 16 */
jimherd 7:c0bef9c1f5d5 17
jimherd 14:b56473e54f6f 18 FPGA_bus::FPGA_bus(int nos_PWM /* = NOS_PWM_CHANNELS */,
jimherd 14:b56473e54f6f 19 int nos_QE /* = NOS_QE_CHANNELS */,
jimherd 14:b56473e54f6f 20 int nos_servo /* = NOS_RC_CHANNELS */ )
jimherd 0:9600ed6fd725 21
jimherd 14:b56473e54f6f 22 :
jimherd 14:b56473e54f6f 23 _nos_PWM_units(nos_PWM),
jimherd 14:b56473e54f6f 24 _nos_QE_units(nos_QE),
jimherd 14:b56473e54f6f 25 _nos_servo_units(nos_servo),
jimherd 14:b56473e54f6f 26
jimherd 14:b56473e54f6f 27 async_uP_start(ASYNC_UP_START_PIN),
jimherd 0:9600ed6fd725 28 async_uP_handshake_1(ASYNC_UP_HANDSHAKE_1_PIN),
jimherd 0:9600ed6fd725 29 async_uP_RW(ASYNC_UP_RW_PIN),
jimherd 0:9600ed6fd725 30 async_uP_reset(ASYNC_UP_RESET_PIN),
jimherd 0:9600ed6fd725 31 uP_ack(ASYNC_UP_ACK_PIN),
jimherd 9:6fe95fb0c7ea 32 uP_handshake_2(ASYNC_UP_HANDSHAKE_2_PIN),
jimherd 14:b56473e54f6f 33 log_pin(LOG_PIN)
jimherd 15:6420b52d30cc 34
jimherd 14:b56473e54f6f 35 {
jimherd 14:b56473e54f6f 36 async_uP_start = LOW;
jimherd 15:6420b52d30cc 37 PWM_base = 0;
jimherd 15:6420b52d30cc 38 QE_base = 0;
jimherd 15:6420b52d30cc 39 RC_base = 0;
jimherd 7:c0bef9c1f5d5 40 }
jimherd 0:9600ed6fd725 41
jimherd 0:9600ed6fd725 42
jimherd 0:9600ed6fd725 43 void FPGA_bus::initialise(void)
jimherd 0:9600ed6fd725 44 {
jimherd 15:6420b52d30cc 45
jimherd 15:6420b52d30cc 46 update_FPGA_register_pointers();
jimherd 15:6420b52d30cc 47
jimherd 0:9600ed6fd725 48 // GPIOC Periph clock enable
jimherd 0:9600ed6fd725 49
jimherd 0:9600ed6fd725 50 ENABLE_GPIO_SUBSYSTEM;
jimherd 0:9600ed6fd725 51 wait_us(2);
jimherd 0:9600ed6fd725 52
jimherd 0:9600ed6fd725 53 async_uP_start = LOW;
jimherd 0:9600ed6fd725 54 async_uP_reset = HIGH;
jimherd 0:9600ed6fd725 55 async_uP_handshake_1 = LOW;
jimherd 0:9600ed6fd725 56 async_uP_RW = LOW;
jimherd 0:9600ed6fd725 57
jimherd 0:9600ed6fd725 58 async_uP_reset = LOW; // generate low reset pulse
jimherd 0:9600ed6fd725 59 wait_us(20);
jimherd 0:9600ed6fd725 60 async_uP_reset = HIGH;
jimherd 0:9600ed6fd725 61 wait_us(20);
jimherd 1:b819a72b3b5d 62
jimherd 1:b819a72b3b5d 63 global_FPGA_unit_error_flag = NO_ERROR;
jimherd 9:6fe95fb0c7ea 64 log_pin = LOW;
jimherd 0:9600ed6fd725 65 }
jimherd 0:9600ed6fd725 66
jimherd 0:9600ed6fd725 67 void FPGA_bus::do_start(void)
jimherd 0:9600ed6fd725 68 {
jimherd 0:9600ed6fd725 69 async_uP_start = HIGH;
jimherd 0:9600ed6fd725 70 async_uP_handshake_1 = LOW;
jimherd 0:9600ed6fd725 71 async_uP_start = LOW;
jimherd 0:9600ed6fd725 72 }
jimherd 0:9600ed6fd725 73
jimherd 0:9600ed6fd725 74 void FPGA_bus::do_end(void)
jimherd 0:9600ed6fd725 75 {
jimherd 0:9600ed6fd725 76 while (uP_ack == HIGH)
jimherd 0:9600ed6fd725 77 ;
jimherd 0:9600ed6fd725 78 async_uP_start = LOW;
jimherd 0:9600ed6fd725 79 }
jimherd 0:9600ed6fd725 80
jimherd 0:9600ed6fd725 81 void FPGA_bus::write_byte(uint32_t byte_value)
jimherd 0:9600ed6fd725 82 {
jimherd 0:9600ed6fd725 83 SET_BUS_OUTPUT;
jimherd 0:9600ed6fd725 84 OUTPUT_BYTE_TO_BUS(byte_value);
jimherd 0:9600ed6fd725 85 async_uP_RW = WRITE_BUS;
jimherd 0:9600ed6fd725 86 async_uP_handshake_1 = HIGH;
jimherd 0:9600ed6fd725 87 while (uP_handshake_2 == LOW)
jimherd 0:9600ed6fd725 88 ;
jimherd 0:9600ed6fd725 89 async_uP_handshake_1 = LOW;
jimherd 0:9600ed6fd725 90 while (uP_handshake_2 == HIGH)
jimherd 0:9600ed6fd725 91 ;
jimherd 0:9600ed6fd725 92 }
jimherd 0:9600ed6fd725 93
jimherd 0:9600ed6fd725 94 uint32_t FPGA_bus::read_byte(void)
jimherd 0:9600ed6fd725 95 {
jimherd 0:9600ed6fd725 96 SET_BUS_INPUT;
jimherd 0:9600ed6fd725 97 async_uP_RW = READ_BUS;
jimherd 0:9600ed6fd725 98 while (uP_handshake_2 == LOW)
jimherd 0:9600ed6fd725 99 ;
jimherd 0:9600ed6fd725 100 data = INPUT_BYTE_FROM_BUS;
jimherd 0:9600ed6fd725 101 async_uP_handshake_1 = HIGH;
jimherd 0:9600ed6fd725 102 while (uP_handshake_2 == HIGH)
jimherd 0:9600ed6fd725 103 ;
jimherd 0:9600ed6fd725 104 async_uP_handshake_1 = LOW;
jimherd 0:9600ed6fd725 105 return data;
jimherd 0:9600ed6fd725 106 }
jimherd 0:9600ed6fd725 107
jimherd 0:9600ed6fd725 108 void FPGA_bus::do_write(uint32_t command,
jimherd 0:9600ed6fd725 109 uint32_t register_address,
jimherd 0:9600ed6fd725 110 uint32_t register_data)
jimherd 0:9600ed6fd725 111 {
jimherd 0:9600ed6fd725 112 write_byte(command);
jimherd 0:9600ed6fd725 113 write_byte(register_address);
jimherd 0:9600ed6fd725 114 write_byte(register_data);
jimherd 0:9600ed6fd725 115 write_byte(register_data>>8);
jimherd 0:9600ed6fd725 116 write_byte(register_data>>16);
jimherd 0:9600ed6fd725 117 write_byte(register_data>>24);
jimherd 0:9600ed6fd725 118 }
jimherd 0:9600ed6fd725 119
jimherd 0:9600ed6fd725 120 void FPGA_bus::do_read(received_packet_t *buffer)
jimherd 0:9600ed6fd725 121 {
jimherd 0:9600ed6fd725 122 for (int i=0; i < (NOS_RECEIVED_PACKET_WORDS<<2) ; i++) {
jimherd 0:9600ed6fd725 123 buffer->byte_data[i] = (uint8_t)read_byte();
jimherd 0:9600ed6fd725 124 }
jimherd 0:9600ed6fd725 125 }
jimherd 0:9600ed6fd725 126
jimherd 0:9600ed6fd725 127 void FPGA_bus::do_transaction(uint32_t command,
jimherd 0:9600ed6fd725 128 uint32_t register_address,
jimherd 0:9600ed6fd725 129 uint32_t register_data,
jimherd 0:9600ed6fd725 130 uint32_t *data,
jimherd 0:9600ed6fd725 131 uint32_t *status)
jimherd 0:9600ed6fd725 132 {
jimherd 9:6fe95fb0c7ea 133 log_pin = HIGH;
jimherd 0:9600ed6fd725 134 do_start();
jimherd 0:9600ed6fd725 135 do_write(command, register_address, register_data);
jimherd 0:9600ed6fd725 136 do_read(&in_pkt);
jimherd 0:9600ed6fd725 137 do_end();
jimherd 9:6fe95fb0c7ea 138 log_pin = LOW;
jimherd 0:9600ed6fd725 139 *data = in_pkt.word_data[0];
jimherd 0:9600ed6fd725 140 *status = in_pkt.word_data[1];
jimherd 0:9600ed6fd725 141 }
jimherd 0:9600ed6fd725 142
jimherd 0:9600ed6fd725 143 uint32_t FPGA_bus::do_command(FPGA_packet_t cmd_packet)
jimherd 0:9600ed6fd725 144 {
jimherd 0:9600ed6fd725 145 async_uP_start = LOW;
jimherd 0:9600ed6fd725 146 return 0;
jimherd 0:9600ed6fd725 147 }
jimherd 0:9600ed6fd725 148
jimherd 1:b819a72b3b5d 149 void FPGA_bus::set_PWM_period(uint32_t channel, float frequency)
jimherd 0:9600ed6fd725 150 {
jimherd 4:e5d36eee9245 151 uint32_t register_address = ((PWM_BASE + (channel * NOS_PWM_REGISTERS)) + PWM_PERIOD);
jimherd 0:9600ed6fd725 152 uint32_t period_value = (uint32_t)(1000000/(20 * frequency));
jimherd 4:e5d36eee9245 153 do_transaction(WRITE_REGISTER_CMD, register_address, period_value, &data, &status);
jimherd 0:9600ed6fd725 154 sys_data.PWM_period_value[channel] = period_value;
jimherd 1:b819a72b3b5d 155 global_FPGA_unit_error_flag = status;
jimherd 0:9600ed6fd725 156 }
jimherd 0:9600ed6fd725 157
jimherd 1:b819a72b3b5d 158 void FPGA_bus::set_PWM_duty(uint32_t channel, float percentage)
jimherd 0:9600ed6fd725 159 {
jimherd 4:e5d36eee9245 160 uint32_t register_address = ((PWM_BASE + (channel * NOS_PWM_REGISTERS)) + PWM_ON_TIME);
jimherd 0:9600ed6fd725 161 uint32_t duty_value = (uint32_t)((sys_data.PWM_period_value[channel] * percentage) / 100);
jimherd 4:e5d36eee9245 162 do_transaction(WRITE_REGISTER_CMD, register_address , duty_value, &data, &status);
jimherd 0:9600ed6fd725 163 sys_data.PWM_duty_value[channel] = duty_value;
jimherd 1:b819a72b3b5d 164 global_FPGA_unit_error_flag = status;;
jimherd 0:9600ed6fd725 165 }
jimherd 0:9600ed6fd725 166
jimherd 1:b819a72b3b5d 167 void FPGA_bus::PWM_enable(uint32_t channel)
jimherd 0:9600ed6fd725 168 {
jimherd 4:e5d36eee9245 169 uint32_t register_address = ((PWM_BASE + (channel * NOS_PWM_REGISTERS)) + PWM_CONFIG);
jimherd 4:e5d36eee9245 170 do_transaction(WRITE_REGISTER_CMD, register_address , 1, &data, &status);
jimherd 0:9600ed6fd725 171 // sys_data.PWM_duty_value[channel] = duty_value;
jimherd 1:b819a72b3b5d 172 global_FPGA_unit_error_flag = status;;
jimherd 0:9600ed6fd725 173 }
jimherd 0:9600ed6fd725 174
jimherd 1:b819a72b3b5d 175 void FPGA_bus::PWM_config(uint32_t channel, uint32_t config_value)
jimherd 0:9600ed6fd725 176 {
jimherd 4:e5d36eee9245 177 uint32_t register_address = ((PWM_BASE + (channel * NOS_PWM_REGISTERS)) + PWM_CONFIG);
jimherd 4:e5d36eee9245 178 do_transaction(WRITE_REGISTER_CMD, register_address , config_value, &data, &status);
jimherd 0:9600ed6fd725 179 sys_data.PWM_duty_value[channel] = config_value;
jimherd 1:b819a72b3b5d 180 global_FPGA_unit_error_flag = status;;
jimherd 1:b819a72b3b5d 181 }
jimherd 1:b819a72b3b5d 182
jimherd 4:e5d36eee9245 183 void FPGA_bus::set_RC_period(void)
jimherd 1:b819a72b3b5d 184 {
jimherd 4:e5d36eee9245 185 do_transaction(WRITE_REGISTER_CMD, (RC_BASE + RC_SERVO_PERIOD), 1000000, &data, &status);
jimherd 6:e68defb7b775 186 global_FPGA_unit_error_flag = status;
jimherd 1:b819a72b3b5d 187 }
jimherd 1:b819a72b3b5d 188
jimherd 4:e5d36eee9245 189 void FPGA_bus::set_RC_period(uint32_t duty_uS)
jimherd 1:b819a72b3b5d 190 {
jimherd 1:b819a72b3b5d 191 uint32_t nos_20nS_ticks = ((duty_uS * nS_IN_uS)/FPGA_CLOCK_PERIOD_nS);
jimherd 4:e5d36eee9245 192 do_transaction(WRITE_REGISTER_CMD, (RC_BASE + RC_SERVO_PERIOD), nos_20nS_ticks, &data, &status);
jimherd 6:e68defb7b775 193 global_FPGA_unit_error_flag = status;
jimherd 1:b819a72b3b5d 194 }
jimherd 1:b819a72b3b5d 195
jimherd 1:b819a72b3b5d 196 void FPGA_bus :: set_RC_pulse(uint32_t channel, uint32_t pulse_uS)
jimherd 1:b819a72b3b5d 197 {
jimherd 1:b819a72b3b5d 198 uint32_t nos_20nS_ticks = ((pulse_uS * nS_IN_uS)/FPGA_CLOCK_PERIOD_nS);
jimherd 4:e5d36eee9245 199 do_transaction(WRITE_REGISTER_CMD, (RC_BASE + RC_SERVO_ON_TIME + channel), nos_20nS_ticks, &data, &status);
jimherd 1:b819a72b3b5d 200 global_FPGA_unit_error_flag = status;;
jimherd 1:b819a72b3b5d 201 }
jimherd 1:b819a72b3b5d 202
jimherd 4:e5d36eee9245 203 void FPGA_bus::enable_RC_channel(uint32_t channel)
jimherd 1:b819a72b3b5d 204 {
jimherd 4:e5d36eee9245 205 do_transaction(READ_REGISTER_CMD, (RC_BASE + RC_SERVO_CONFIG), NULL, &data, &status);
jimherd 2:fd5c862b86db 206 int32_t config = (data || (0x01 << channel)) + GLOBAL_RC_ENABLE;
jimherd 4:e5d36eee9245 207 do_transaction(WRITE_REGISTER_CMD, (RC_BASE + RC_SERVO_CONFIG), config, &data, &status);
jimherd 3:cf36c2d4208f 208 global_FPGA_unit_error_flag = status;
jimherd 2:fd5c862b86db 209 }
jimherd 2:fd5c862b86db 210
jimherd 4:e5d36eee9245 211 void FPGA_bus::disable_RC_channel(uint32_t channel)
jimherd 2:fd5c862b86db 212 {
jimherd 4:e5d36eee9245 213 do_transaction(READ_REGISTER_CMD, (RC_BASE + RC_SERVO_CONFIG), NULL, &data, &status);
jimherd 4:e5d36eee9245 214 uint32_t config = data && ~(0x01 << channel);
jimherd 4:e5d36eee9245 215 do_transaction(WRITE_REGISTER_CMD, (RC_BASE + RC_SERVO_CONFIG), config, &data, &status);
jimherd 1:b819a72b3b5d 216 global_FPGA_unit_error_flag = status;
jimherd 4:e5d36eee9245 217 }
jimherd 4:e5d36eee9245 218
jimherd 9:6fe95fb0c7ea 219 void FPGA_bus::QE_config(uint32_t channel, uint32_t config_value)
jimherd 9:6fe95fb0c7ea 220 {
jimherd 9:6fe95fb0c7ea 221 uint32_t register_address = ((PWM_BASE + (channel * NOS_PWM_REGISTERS)) + PWM_CONFIG);
jimherd 9:6fe95fb0c7ea 222 do_transaction(WRITE_REGISTER_CMD, register_address , config_value, &data, &status);
jimherd 9:6fe95fb0c7ea 223 global_FPGA_unit_error_flag = status;;
jimherd 9:6fe95fb0c7ea 224 }
jimherd 9:6fe95fb0c7ea 225
jimherd 9:6fe95fb0c7ea 226 void FPGA_bus::enable_speed_measure(uint32_t channel, uint32_t config_value, uint32_t phase_time)
jimherd 4:e5d36eee9245 227 {
jimherd 9:6fe95fb0c7ea 228 uint32_t register_base = (QE_BASE + (channel * NOS_QE_REGISTERS));
jimherd 9:6fe95fb0c7ea 229 do_transaction(WRITE_REGISTER_CMD, (register_base + QE_SIM_PHASE_TIME), phase_time, &data, &status);
jimherd 5:64c677e9995c 230 global_FPGA_unit_error_flag = status;
jimherd 10:56a045a02047 231 if (status != NO_ERROR) {
jimherd 10:56a045a02047 232 return;
jimherd 10:56a045a02047 233 }
jimherd 10:56a045a02047 234 do_transaction(WRITE_REGISTER_CMD, (register_base + QE_CONFIG), config_value, &data, &status);
jimherd 10:56a045a02047 235 global_FPGA_unit_error_flag = status;
jimherd 5:64c677e9995c 236 }
jimherd 5:64c677e9995c 237
jimherd 5:64c677e9995c 238 uint32_t FPGA_bus::read_speed_measure(uint32_t channel)
jimherd 5:64c677e9995c 239 {
jimherd 8:65d1b1a7bfcc 240 uint32_t register_address = ((QE_BASE + (channel * NOS_QE_REGISTERS)) + QE_SPEED_BUFFER);
jimherd 5:64c677e9995c 241 do_transaction(READ_REGISTER_CMD, register_address, NULL, &data, &status);
jimherd 5:64c677e9995c 242 global_FPGA_unit_error_flag = status;
jimherd 5:64c677e9995c 243 return data;
jimherd 6:e68defb7b775 244 }
jimherd 6:e68defb7b775 245
jimherd 10:56a045a02047 246 uint32_t FPGA_bus::read_count_measure(uint32_t channel)
jimherd 10:56a045a02047 247 {
jimherd 10:56a045a02047 248 uint32_t register_address = ((QE_BASE + (channel * NOS_QE_REGISTERS)) + QE_COUNT_BUFFER);
jimherd 10:56a045a02047 249 do_transaction(READ_REGISTER_CMD, register_address, NULL, &data, &status);
jimherd 10:56a045a02047 250 global_FPGA_unit_error_flag = status;
jimherd 10:56a045a02047 251 return data;
jimherd 10:56a045a02047 252 }
jimherd 10:56a045a02047 253
jimherd 6:e68defb7b775 254 uint32_t FPGA_bus::get_SYS_data(void)
jimherd 6:e68defb7b775 255 {
jimherd 6:e68defb7b775 256 do_transaction(READ_REGISTER_CMD, SYS_DATA_REG_ADDR, NULL, &data, &status);
jimherd 6:e68defb7b775 257 sys_data.major_version = (data & 0x0000000F);
jimherd 6:e68defb7b775 258 sys_data.minor_version = (data >> 4) & 0x0000000F;
jimherd 6:e68defb7b775 259 sys_data.number_of_PWM_channels = (data >> 8) & 0x0000000F;
jimherd 6:e68defb7b775 260 sys_data.number_of_QE_channels = (data >> 8) & 0x0000000F;
jimherd 6:e68defb7b775 261 sys_data.number_of_RC_channels = (data >> 8) & 0x0000000F;
jimherd 6:e68defb7b775 262
jimherd 6:e68defb7b775 263 global_FPGA_unit_error_flag = status;
jimherd 6:e68defb7b775 264 return data;
jimherd 15:6420b52d30cc 265 }
jimherd 15:6420b52d30cc 266
jimherd 15:6420b52d30cc 267 void FPGA_bus::update_FPGA_register_pointers(void) {
jimherd 15:6420b52d30cc 268
jimherd 15:6420b52d30cc 269 PWM_base = 1;
jimherd 15:6420b52d30cc 270 QE_base = ((NOS_PWM_REGISTERS * _nos_PWM_units) + PWM_base);
jimherd 15:6420b52d30cc 271 RC_base = ((NOS_QE_REGISTERS * _nos_QE_units) + QE_base);
jimherd 0:9600ed6fd725 272 }