jim herd / FPGA_bus
Revision:
0:9600ed6fd725
Child:
1:b819a72b3b5d
diff -r 000000000000 -r 9600ed6fd725 FPGA_bus.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FPGA_bus.cpp	Wed Feb 20 16:42:55 2019 +0000
@@ -0,0 +1,183 @@
+/*
+ * FPGA_bus : 8-bit bi-directional bus between uP and FPGA
+ */
+#include "mbed.h"
+#include "FPGA_bus.h"
+
+/** create a FPGA_bus object connecting uP to FPGA
+ *
+ * @param  nos_PWM      Number of PWM channels (default = 4)
+ * @param  nos_QE       Number of Quadrature Encoder channels (default = 4)
+ * @param  nos_servo    Number of RC servo channels (default = 8)
+ *
+ * Notes
+ *      You can only change the defaults by recompiling the SystemVerilog code
+ *      on the FPGA.
+ */  
+FPGA_bus::FPGA_bus(int nos_PWM   = NOS_PWM_CHANNELS, 
+                   int nos_QE    = NOS_QE_CHANNELS, 
+                   int nos_servo = NOS_RC_CHANNELS)
+                   
+                :   async_uP_start(ASYNC_UP_START_PIN), 
+                    async_uP_handshake_1(ASYNC_UP_HANDSHAKE_1_PIN),
+                    async_uP_RW(ASYNC_UP_RW_PIN),
+                    async_uP_reset(ASYNC_UP_RESET_PIN),
+                    uP_ack(ASYNC_UP_ACK_PIN),
+                    uP_handshake_2(ASYNC_UP_HANDSHAKE_2_PIN)                   
+{
+    _nos_PWM_units   = nos_PWM;
+    _nos_QE_units    = nos_QE;
+    _nos_servo_units = nos_servo;
+    
+    async_uP_start   = LOW;
+}
+
+FPGA_bus::FPGA_bus(void)
+                :   async_uP_start(ASYNC_UP_START_PIN), 
+                    async_uP_handshake_1(ASYNC_UP_HANDSHAKE_1_PIN),
+                    async_uP_RW(ASYNC_UP_RW_PIN),
+                    async_uP_reset(ASYNC_UP_RESET_PIN),
+                    uP_ack(ASYNC_UP_ACK_PIN),
+                    uP_handshake_2(ASYNC_UP_HANDSHAKE_2_PIN)                   
+{
+    _nos_PWM_units   = NOS_PWM_CHANNELS;
+    _nos_QE_units    = NOS_QE_CHANNELS;
+    _nos_servo_units = NOS_RC_CHANNELS;
+    
+    async_uP_start       = LOW;
+}
+
+
+
+void  FPGA_bus::initialise(void)
+{
+    // GPIOC Periph clock enable
+    
+    ENABLE_GPIO_SUBSYSTEM;
+    wait_us(2);
+    
+    async_uP_start       = LOW;
+    async_uP_reset       = HIGH;
+    async_uP_handshake_1 = LOW;
+    async_uP_RW          = LOW;
+    
+    async_uP_reset = LOW;       // generate low reset pulse
+    wait_us(20);
+    async_uP_reset = HIGH;
+    wait_us(20);
+}
+    
+void FPGA_bus::do_start(void)
+{
+    async_uP_start       = HIGH;
+    async_uP_handshake_1 = LOW;
+    async_uP_start       = LOW;
+}
+
+void FPGA_bus::do_end(void)
+{
+    while (uP_ack == HIGH)
+        ;
+    async_uP_start = LOW;
+}
+
+void FPGA_bus::write_byte(uint32_t byte_value)
+{
+    SET_BUS_OUTPUT;
+    OUTPUT_BYTE_TO_BUS(byte_value);
+    async_uP_RW = WRITE_BUS;
+    async_uP_handshake_1 = HIGH;
+    while (uP_handshake_2 == LOW)
+        ;
+    async_uP_handshake_1 = LOW;
+    while (uP_handshake_2 == HIGH)
+        ;
+}
+
+uint32_t FPGA_bus::read_byte(void)
+{
+    SET_BUS_INPUT;
+    async_uP_RW = READ_BUS;
+    while (uP_handshake_2 == LOW)
+        ;
+    data = INPUT_BYTE_FROM_BUS;
+    async_uP_handshake_1 = HIGH;
+    while (uP_handshake_2 == HIGH)
+        ;
+    async_uP_handshake_1 = LOW;
+    return data;
+}
+
+void FPGA_bus::do_write(uint32_t command, 
+              uint32_t register_address, 
+              uint32_t register_data)
+{
+    write_byte(command);
+    write_byte(register_address);
+    write_byte(register_data);
+    write_byte(register_data>>8);
+    write_byte(register_data>>16);
+    write_byte(register_data>>24);
+}
+
+void FPGA_bus::do_read(received_packet_t   *buffer)
+{
+    for (int i=0; i < (NOS_RECEIVED_PACKET_WORDS<<2) ; i++) {
+        buffer->byte_data[i] = (uint8_t)read_byte();
+    }
+}
+
+void FPGA_bus::do_transaction(uint32_t command, 
+                    uint32_t register_address, 
+                    uint32_t register_data,
+                    uint32_t *data,
+                    uint32_t *status)
+{
+    do_start();
+ //   pc.printf("\n1");
+    do_write(command, register_address, register_data);
+ //   pc.printf(" 2");
+    do_read(&in_pkt);
+ //   pc.printf(" 3");
+    do_end();
+ //   pc.printf(" 4\n");
+    *data = in_pkt.word_data[0];
+    *status = in_pkt.word_data[1];
+   // pc.printf("data = %#08X  :: status = %#08X\n", in_pkt.word_data[0], in_pkt.word_data[1]);
+}
+
+uint32_t  FPGA_bus::do_command(FPGA_packet_t cmd_packet)
+{
+    async_uP_start = LOW;
+    return 0;
+}
+    
+uint32_t FPGA_bus::set_PWM_period(uint32_t channel, float frequency)
+{
+    uint32_t period_value = (uint32_t)(1000000/(20 * frequency));
+    do_transaction(WRITE_REGISTER_CMD, (channel + PWM_PERIOD) , period_value, &data, &status); 
+    sys_data.PWM_period_value[channel] = period_value;
+    return status;
+}
+
+uint32_t FPGA_bus::set_PWM_duty(uint32_t channel, float percentage)
+{
+    uint32_t duty_value = (uint32_t)((sys_data.PWM_period_value[channel] * percentage) / 100);
+    do_transaction(WRITE_REGISTER_CMD, (channel + PWM_ON_TIME) , duty_value, &data, &status);
+    sys_data.PWM_duty_value[channel] = duty_value;
+    return status;
+}
+
+uint32_t FPGA_bus::PWM_enable(uint32_t channel)
+{
+    do_transaction(WRITE_REGISTER_CMD, (channel + PWM_CONFIG) , 1, &data, &status);
+ //   sys_data.PWM_duty_value[channel] = duty_value;
+    return status;
+}
+
+uint32_t FPGA_bus::PWM_config(uint32_t channel, uint32_t config_value)
+{
+    do_transaction(WRITE_REGISTER_CMD, (channel + PWM_CONFIG) , config_value, &data, &status);
+    sys_data.PWM_duty_value[channel] = config_value;
+    return status;
+}
\ No newline at end of file