From b4e74a5e7204030467db1de43df4fb09d97eb4f0 Mon Sep 17 00:00:00 2001 From: Nicolas Trimborn Date: Mon, 6 Sep 2021 22:12:59 +0200 Subject: [PATCH] Merged master and slave --- .../.atmelstart/AtmelStart.gpdsc | 3 + .../.atmelstart/atmel_start_config.atstart | 41 +- .../Two_Motor_D51/Config/hpl_sercom_config.h | 148 +++++ .../Config/peripheral_clk_config.h | 80 +++ .../Two_Motor_D51/Two_Motor_D51/Debug.xml | 126 +++++ .../Two_Motor_D51/Two_Motor_D51/MSIF_slave.h | 285 ++++++++++ .../Two_Motor_D51/Two_Motor_D51/Release.xml | 121 +++++ .../Two_Motor_D51/Two_Motor_D51.cproj | 512 +++++++++--------- .../Two_Motor_D51/configuration.h | 296 +++++++--- .../Two_Motor_D51/Two_Motor_D51/driver_init.c | 39 +- .../Two_Motor_D51/Two_Motor_D51/driver_init.h | 17 +- .../Two_Motor_D51/examples/driver_examples.c | 30 +- .../Two_Motor_D51/examples/driver_examples.h | 2 +- .../hal/documentation/spi_slave_sync.rst | 60 ++ .../hal/include/hal_spi_s_sync.h | 204 +++++++ .../Two_Motor_D51/hal/src/hal_spi_s_sync.c | 262 +++++++++ .../Two_Motor_D51/Two_Motor_D51/interrupts.h | 2 + .../Two_Motor_D51/Two_Motor_D51/main.c | 109 ++-- Screenshots/Event Manual Config/CH0.PNG | Bin 0 -> 11381 bytes Screenshots/Event Manual Config/CH1.PNG | Bin 0 -> 12528 bytes Screenshots/Event Manual Config/CH11.PNG | Bin 0 -> 12333 bytes Screenshots/Event Manual Config/CH12.PNG | Bin 0 -> 12354 bytes Screenshots/Event Manual Config/CH2.PNG | Bin 0 -> 12384 bytes Screenshots/Event Manual Config/CH3.PNG | Bin 0 -> 12490 bytes Screenshots/Event Manual Config/CH4.PNG | Bin 0 -> 11975 bytes Twincat/MotorData/.vs/MotorData/v15/.suo | Bin 42496 -> 66048 bytes 26 files changed, 1931 insertions(+), 406 deletions(-) create mode 100644 2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Debug.xml create mode 100644 2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/MSIF_slave.h create mode 100644 2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Release.xml create mode 100644 2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/documentation/spi_slave_sync.rst create mode 100644 2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/include/hal_spi_s_sync.h create mode 100644 2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/src/hal_spi_s_sync.c create mode 100644 Screenshots/Event Manual Config/CH0.PNG create mode 100644 Screenshots/Event Manual Config/CH1.PNG create mode 100644 Screenshots/Event Manual Config/CH11.PNG create mode 100644 Screenshots/Event Manual Config/CH12.PNG create mode 100644 Screenshots/Event Manual Config/CH2.PNG create mode 100644 Screenshots/Event Manual Config/CH3.PNG create mode 100644 Screenshots/Event Manual Config/CH4.PNG diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/.atmelstart/AtmelStart.gpdsc b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/.atmelstart/AtmelStart.gpdsc index 4f2fef4..f61ba3d 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/.atmelstart/AtmelStart.gpdsc +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/.atmelstart/AtmelStart.gpdsc @@ -51,6 +51,7 @@ + @@ -65,6 +66,7 @@ + @@ -177,6 +179,7 @@ + diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/.atmelstart/atmel_start_config.atstart b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/.atmelstart/atmel_start_config.atstart index 98ef807..3a4b4b1 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/.atmelstart/atmel_start_config.atstart +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/.atmelstart/atmel_start_config.atstart @@ -1822,8 +1822,8 @@ drivers: configuration: core_gclk_selection: Generic clock generator 0 slow_gclk_selection: Generic clock generator 3 - SPI_1_MSIF: - user_label: SPI_1_MSIF + SPI_1_MSIF_M: + user_label: SPI_1_MSIF_M definition: Atmel:SAMD51_Drivers:0.0.1::SAMD51J18A-MF::SERCOM1::driver_config_definition::SPI.Master::HAL:Driver:SPI.Master.DMA functionality: SPI api: HAL:Driver:SPI_Master_DMA @@ -1913,6 +1913,43 @@ drivers: configuration: core_gclk_selection: Generic clock generator 0 slow_gclk_selection: Generic clock generator 3 + SPI_1_MSIF_S: + user_label: SPI_1_MSIF_S + definition: Atmel:SAMD51_Drivers:0.0.1::SAMD51J18A-MF::SERCOM3::driver_config_definition::SPI.Slave::HAL:Driver:SPI.Slave.Sync + functionality: SPI + api: HAL:Driver:SPI_Slave_Sync + configuration: + spi_slave_advanced: false + spi_slave_arch_addr: 0 + spi_slave_arch_addrmask: 0 + spi_slave_arch_amode: Address mask + spi_slave_arch_amode_en: false + spi_slave_arch_cpha: Sample input on trailing edge + spi_slave_arch_cpol: SCK is low when idle + spi_slave_arch_dbgstop: Keep running + spi_slave_arch_dord: MSB first + spi_slave_arch_ibon: In data stream + spi_slave_arch_ploaden: false + spi_slave_arch_runstdby: false + spi_slave_arch_ssde: false + spi_slave_character_size: 8 bits + spi_slave_rx_enable: true + optional_signals: [] + variant: null + clocks: + domain_group: + nodes: + - name: Core + input: Generic clock generator 0 + external: false + external_frequency: 0 + - name: Slow + input: Generic clock generator 3 + external: false + external_frequency: 0 + configuration: + core_gclk_selection: Generic clock generator 0 + slow_gclk_selection: Generic clock generator 3 SPI_3: user_label: SPI_3 definition: Atmel:SAMD51_Drivers:0.0.1::SAMD51J18A-MF::SERCOM5::driver_config_definition::SPI.Master::HAL:Driver:SPI.Master.Sync diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Config/hpl_sercom_config.h b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Config/hpl_sercom_config.h index 1d01fe3..7d87f2a 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Config/hpl_sercom_config.h +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Config/hpl_sercom_config.h @@ -479,6 +479,154 @@ #define CONF_SERCOM_2_SPI_BAUD_RATE ((float)CONF_GCLK_SERCOM2_CORE_FREQUENCY / (float)(2 * CONF_SERCOM_2_SPI_BAUD)) - 1 #endif +// Enable configuration of module +#ifndef CONF_SERCOM_3_SPI_ENABLE +#define CONF_SERCOM_3_SPI_ENABLE 0 +#endif + +// Set module in SPI Slave mode +#ifndef CONF_SERCOM_3_SPI_MODE +#define CONF_SERCOM_3_SPI_MODE 0x02 +#endif + +// Basic Configuration + +// Receive buffer enable +// Enable receive buffer to receive data from slave. (RXEN) +// spi_slave_rx_enable +#ifndef CONF_SERCOM_3_SPI_RXEN +#define CONF_SERCOM_3_SPI_RXEN 0x1 +#endif + +// Character Size +// Bit size for all characters sent over the SPI bus. (CHSIZE) +// <0x0=>8 bits +// <0x1=>9 bits +// spi_slave_character_size +#ifndef CONF_SERCOM_3_SPI_CHSIZE +#define CONF_SERCOM_3_SPI_CHSIZE 0x0 +#endif + +// + +// Advanced Configuration +// spi_slave_advanced +#ifndef CONF_SERCOM_3_SPI_ADVANCED +#define CONF_SERCOM_3_SPI_ADVANCED 0 +#endif + +// Data Order +// <0=>MSB first +// <1=>LSB first +// I least significant or most significant bit is shifted out first. (DORD) +// spi_slave_arch_dord +#ifndef CONF_SERCOM_3_SPI_DORD +#define CONF_SERCOM_3_SPI_DORD 0x0 +#endif + +// Clock Polarity +// <0=>SCK is low when idle +// <1=>SCK is high when idle +// Determines if the leading edge is rising or falling with a corresponding opposite edge at the trailing edge. (CPOL) +// spi_slave_arch_cpol +#ifndef CONF_SERCOM_3_SPI_CPOL +#define CONF_SERCOM_3_SPI_CPOL 0x0 +#endif + +// Clock Phase +// <0x0=>Sample input on leading edge +// <0x1=>Sample input on trailing edge +// Determines if input data is sampled on leading or trailing SCK edge. (CPHA) +// spi_slave_arch_cpha +#ifndef CONF_SERCOM_3_SPI_CPHA +#define CONF_SERCOM_3_SPI_CPHA 0x1 +#endif + +// Immediate Buffer Overflow Notification +// Controls when OVF is asserted. (IBON) +// <0x0=>In data stream +// <0x1=>On buffer overflow +// spi_slave_arch_ibon +#ifndef CONF_SERCOM_3_SPI_IBON +#define CONF_SERCOM_3_SPI_IBON 0x0 +#endif + +// Slave Select Low Detect Enable +// This bit enables wake up when the slave select (_SS) pin transitions from high to low. (SSDE) +// spi_slave_arch_ssde +#ifndef CONF_SERCOM_3_SPI_SSDE +#define CONF_SERCOM_3_SPI_SSDE 0 +#endif + +// Slave Detect Preload Enable +// Setting this bit will enable preloading of the slave shift register when there is no transfer in progress. (PLOADEN) +// spi_slave_arch_ploaden +#ifndef CONF_SERCOM_3_SPI_PLOADEN +#define CONF_SERCOM_3_SPI_PLOADEN 0 +#endif + +// Enable SPI address mode +// This will enable SPI frames with address, first received character is treated as address. (FORM=SPI_ADDR) +// spi_slave_arch_amode_en +#ifndef CONF_SERCOM_3_SPI_AMODE_EN +#define CONF_SERCOM_3_SPI_AMODE_EN 0 +#endif + +// Address Mode +// <0x0=>Address mask +// <0x1=>Two unique addresses +// <0x2=>Address range +// These bits set the slave addressing mode when the frame format with address is used. (AMODE) +// spi_slave_arch_amode +#ifndef CONF_SERCOM_3_SPI_AMODE +#define CONF_SERCOM_3_SPI_AMODE 0 +#endif + +// Address <0-255> +// These bits hold the address when SPI address modes is enabled. (ADDR) +// spi_slave_arch_addr +#ifndef CONF_SERCOM_3_SPI_ADDR +#define CONF_SERCOM_3_SPI_ADDR 0 +#endif + +// Address mask <0-255> +// These bits hold the address mask when SPI address mode is enabled. (ADDRMASK) +// spi_slave_arch_addrmask +#ifndef CONF_SERCOM_3_SPI_ADDRMASK +#define CONF_SERCOM_3_SPI_ADDRMASK 0 +#endif + +// Run in stand-by +// Module stays active in stand-by sleep mode. (RUNSTDBY) +// spi_slave_arch_runstdby +#ifndef CONF_SERCOM_3_SPI_RUNSTDBY +#define CONF_SERCOM_3_SPI_RUNSTDBY 0x0 +#endif + +// Debug Stop Mode +// Behavior of the baud-rate generator when CPU is halted by external debugger. (DBGSTOP) +// <0=>Keep running +// <1=>Halt +// spi_slave_arch_dbgstop +#ifndef CONF_SERCOM_3_SPI_DBGSTOP +#define CONF_SERCOM_3_SPI_DBGSTOP 0 +#endif + +// + +// This bit is not applicable in slave mode +#ifndef CONF_SERCOM_3_SPI_MSSEN +#define CONF_SERCOM_3_SPI_MSSEN 0x0 +#endif + +#ifndef CONF_SERCOM_3_SPI_BAUD_RATE +#define CONF_SERCOM_3_SPI_BAUD_RATE 0 +#endif + +#ifndef CONF_SERCOM_3_SPI_DUMMYBYTE +#define CONF_SERCOM_3_SPI_DUMMYBYTE 0x0 +#endif + #include // Enable configuration of module diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Config/peripheral_clk_config.h b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Config/peripheral_clk_config.h index 5fb0e21..756808f 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Config/peripheral_clk_config.h +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Config/peripheral_clk_config.h @@ -931,6 +931,86 @@ // Generic clock generator 11 +// Select the clock source for CORE. +#ifndef CONF_GCLK_SERCOM3_CORE_SRC +#define CONF_GCLK_SERCOM3_CORE_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#endif + +// Slow Clock Source +// slow_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Generic clock generator 8 + +// Generic clock generator 9 + +// Generic clock generator 10 + +// Generic clock generator 11 + +// Select the slow clock source. +#ifndef CONF_GCLK_SERCOM3_SLOW_SRC +#define CONF_GCLK_SERCOM3_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK3_Val +#endif + +/** + * \def CONF_GCLK_SERCOM3_CORE_FREQUENCY + * \brief SERCOM3's Core Clock frequency + */ +#ifndef CONF_GCLK_SERCOM3_CORE_FREQUENCY +#define CONF_GCLK_SERCOM3_CORE_FREQUENCY 100000000 +#endif + +/** + * \def CONF_GCLK_SERCOM3_SLOW_FREQUENCY + * \brief SERCOM3's Slow Clock frequency + */ +#ifndef CONF_GCLK_SERCOM3_SLOW_FREQUENCY +#define CONF_GCLK_SERCOM3_SLOW_FREQUENCY 32768 +#endif + +// Core Clock Source +// core_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Generic clock generator 8 + +// Generic clock generator 9 + +// Generic clock generator 10 + +// Generic clock generator 11 + // Select the clock source for CORE. #ifndef CONF_GCLK_SERCOM5_CORE_SRC #define CONF_GCLK_SERCOM5_CORE_SRC GCLK_PCHCTRL_GEN_GCLK0_Val diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Debug.xml b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Debug.xml new file mode 100644 index 0000000..f2260ea --- /dev/null +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Debug.xml @@ -0,0 +1,126 @@ + + True + True + True + True + True + + + DEBUG + ARM_MATH_CM4=1 + + + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + + + Optimize debugging experience (-Og) + True + Maximum (-g3) + True + -std=gnu11 -mfloat-abi=hard -mfpu=fpv4-sp-d16 + True + + + libm + libarm_cortexM4lf_math.a + + + + + C:\Users\ge37vez\Documents\Git Repos\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master_D51\Two_Motor_D51\Two_Motor_D51\cmsis + %24(ProjectDir)\Device_Startup + + + True + + -Tsamd51j18a_flash.ld -std=gnu99 -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mfp16-format=ieee + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + + + Default (-g) + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + + + Default (-Wa,-g) + \ No newline at end of file diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/MSIF_slave.h b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/MSIF_slave.h new file mode 100644 index 0000000..a81bf72 --- /dev/null +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/MSIF_slave.h @@ -0,0 +1,285 @@ +/* + * master_slave_IF.h + * + * Created: 8/18/2021 4:32:19 PM + * Author: ge37vez + */ + + +#ifndef MASTER_SLAVE_IF_H_ +#define MASTER_SLAVE_IF_H_ + +#define SLAVE_BUFFER_SIZE_BYTES 64 +#define SLAVE_BUFFER_SIZE_LONG SLAVE_BUFFER_SIZE_BYTES/4 + +static uint32_t SPI_rx_buffer[SLAVE_BUFFER_SIZE_LONG] = {0}; +static uint32_t SPI_tx_buffer[SLAVE_BUFFER_SIZE_LONG] = {0}; + +//static uint8_t SPI_tx_buffer[SLAVE_BUFFER_SIZE] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17, + //18,19,20,21,22,23,24,25,26,27,28,29,30,31}; + +//tx_buffer +/* Motor 3*/ +static volatile uint8_t *M3_Status = (uint8_t *)&SPI_tx_buffer[0]; +static volatile uint8_t *M3_Mode = (((uint8_t *)&SPI_tx_buffer[0])+1); +static volatile int16_t *M3_Joint_rel_position = (((int16_t *)&SPI_tx_buffer[0])+1); +static volatile int16_t *M3_Joint_abs_position = ((int16_t *)&SPI_tx_buffer[1]); +static volatile int16_t *M3_Motor_speed = (((int16_t *)&SPI_tx_buffer[1])+1); +static volatile int16_t *M3_Motor_current_bus = ((int16_t *)&SPI_tx_buffer[2]); +static volatile int16_t *M3_Motor_currentPhA = (((int16_t *)&SPI_tx_buffer[2])+1); +static volatile int16_t *M3_Motor_currentPhB = ((int16_t *)&SPI_tx_buffer[3]); +static volatile int16_t *M3_Motor_currentPhC = (((int16_t *)&SPI_tx_buffer[3])+1); +static volatile int16_t *M3_Motor__hallState = ((int16_t *)&SPI_tx_buffer[4]); +static volatile int16_t *M3_Motor_dutyCycle = (((int16_t *)&SPI_tx_buffer[4])+1); +/* Motor 4*/ +static volatile uint8_t *M4_Status = (uint8_t *)&SPI_tx_buffer[5]; +static volatile uint8_t *M4_Mode = (((uint8_t *)&SPI_tx_buffer[5])+1); +static volatile int16_t *M4_Joint_rel_position = (((int16_t *)&SPI_tx_buffer[5])+1); +static volatile int16_t *M4_Joint_abs_position = ((int16_t *)&SPI_tx_buffer[6]); +static volatile int16_t *M4_Motor_speed = (((int16_t *)&SPI_tx_buffer[6])+1); +static volatile int16_t *M4_Motor_current_bus = ((int16_t *)&SPI_tx_buffer[7]); +static volatile int16_t *M4_Motor_currentPhA = (((int16_t *)&SPI_tx_buffer[7])+1); +static volatile int16_t *M4_Motor_currentPhB = ((int16_t *)&SPI_tx_buffer[8]); +static volatile int16_t *M4_Motor_currentPhC = (((int16_t *)&SPI_tx_buffer[8])+1); +static volatile int16_t *M4_Motor__hallState = ((int16_t *)&SPI_tx_buffer[9]); +static volatile int16_t *M4_Motor_dutyCycle = (((int16_t *)&SPI_tx_buffer[9])+1); +/* IMU */ +static volatile int16_t *q_x0 = (int16_t *)&SPI_tx_buffer[10]; +static volatile int16_t *q_y0 = (((int16_t *)&SPI_tx_buffer[10])+1); +static volatile int16_t *q_z0 = (int16_t *)&SPI_tx_buffer[11]; +static volatile int16_t *q_w0 = (((int16_t *)&SPI_tx_buffer[11])+1); +/* EMG */ +static volatile int16_t *FSR_CH1 = (int16_t *)&SPI_tx_buffer[12]; //2 byte - 48 of 64 +static volatile int16_t *FSR_CH2 = (((int16_t *)&SPI_tx_buffer[12])+1); +static volatile int16_t *FSR_CH3 = (int16_t *)&SPI_tx_buffer[13]; //2 byte - 52 of 64 +static volatile int16_t *FSR_CH4 = (((int16_t *)&SPI_tx_buffer[13])+1); +static volatile int16_t *FSR_CH5 = (int16_t *)&SPI_tx_buffer[14]; //2 byte - 56 of 64 +static volatile int16_t *Pressure_CH1 = (((int16_t *)&SPI_tx_buffer[14])+1); +static volatile int16_t *Pressure_CH2 = (int16_t *)&SPI_tx_buffer[15]; //2 byte - 60 of 64 +static volatile int16_t *Pressure_CH3 = (((int16_t *)&SPI_tx_buffer[15])+1); + +//rx_buffer +///* Motor 3*/ +static volatile uint8_t *M3_Control_mode = (uint8_t *)&SPI_rx_buffer[0]; //1 byte - 0 of 32 +static volatile uint8_t *M3_Control_set = (((uint8_t *)&SPI_rx_buffer[0])+1); //1 byte - 1 of 32 +static volatile int16_t *M3_Desired_pos = ((int16_t *)&SPI_rx_buffer[0]+1); //2 byte - 2 of 32 +static volatile int16_t *M3_Desired_speed = (int16_t *)&SPI_rx_buffer[1]; //2 byte - 4 of 32 +static volatile int16_t *M3_Desired_current = ((int16_t *)&SPI_rx_buffer[1]+1); //2 byte - 6 of 32 +static volatile int16_t *M3_Max_pos = (int16_t *)&SPI_rx_buffer[2]; //2 byte - 8 of 32 +static volatile int16_t *M3_Max_velocity = ((int16_t *)&SPI_rx_buffer[2]+1); //2 byte - 10 of 32 +static volatile int16_t *M3_Max_current = (int16_t *)&SPI_rx_buffer[3]; //2 byte - 12 of 32 +static volatile int16_t *M3_Spare = ((int16_t *)&SPI_rx_buffer[3]+1); //2 byte - 14 of 32 +///* Motor 4*/ +static volatile uint8_t *M4_Control_mode = (uint8_t *)&SPI_rx_buffer[4]; //1 byte - 16 of 32 +static volatile uint8_t *M4_Control_set = (((uint8_t *)&SPI_rx_buffer[4])+1); //1 byte - 17 of 32 +static volatile int16_t *M4_Desired_pos = ((int16_t *)&SPI_rx_buffer[4]+1); //2 byte - 18 of 32 +static volatile int16_t *M4_Desired_speed = (int16_t *)&SPI_rx_buffer[5]; //2 byte - 20 of 32 +static volatile int16_t *M4_Desired_current = ((int16_t *)&SPI_rx_buffer[5]+1); //2 byte - 22 of 32 +static volatile int16_t *M4_Max_pos = (int16_t *)&SPI_rx_buffer[6]; //2 byte - 24 of 32 +static volatile int16_t *M4_Max_velocity = ((int16_t *)&SPI_rx_buffer[6]+1); //2 byte - 26 of 32 +static volatile int16_t *M4_Max_current = (int16_t *)&SPI_rx_buffer[7]; //2 byte - 28 of 32 +static volatile int16_t *M4_Spare = ((int16_t *)&SPI_rx_buffer[7]+1); //2 byte - 30 of 32 + + +////tx_buffer +///* Motor 3*/ +//static volatile uint8_t *M3_Status = (uint8_t *)&SPI_tx_buffer[0]; //1 byte - 0 of 64 +//static volatile uint8_t *M3_Mode = (uint8_t *)&SPI_tx_buffer[1]; //1 byte - 1 of 64 +//static volatile int16_t *M3_Joint_rel_position = (int16_t *)&SPI_tx_buffer[2]; //2 byte - 2 of 64 +//static volatile int16_t *M3_Joint_abs_position = (int16_t *)&SPI_tx_buffer[4]; //2 byte - 4 of 64 +//static volatile int16_t *M3_Motor_speed = (int16_t *)&SPI_tx_buffer[6]; //2 byte - 6 of 64 +//static volatile int16_t *M3_Motor_current_bus = (int16_t *)&SPI_tx_buffer[8]; //2 byte - 8 of 64 +//static volatile int16_t *M3_Motor_currentPhA = (int16_t *)&SPI_tx_buffer[10]; //2 byte - 10 of 64 +//static volatile int16_t *M3_Motor_currentPhB = (int16_t *)&SPI_tx_buffer[12]; //2 byte - 12 of 64 +//static volatile int16_t *M3_Motor_currentPhC = (int16_t *)&SPI_tx_buffer[14]; //2 byte - 14 of 64 +//static volatile int16_t *M3_Motor__hallState = (int16_t *)&SPI_tx_buffer[16]; //2 byte - 16 of 64 +//static volatile int16_t *M3_Motor_dutyCycle = (int16_t *)&SPI_tx_buffer[18]; //2 byte - 18 of 64 +///* Motor 4*/ +//static volatile uint8_t *M4_Status = (uint8_t *)&SPI_tx_buffer[20]; //1 byte - 20 of 64 +//static volatile uint8_t *M4_Mode = (uint8_t *)&SPI_tx_buffer[21]; //1 byte - 21 of 64 +//static volatile int16_t *M4_Joint_rel_position = (int16_t *)&SPI_tx_buffer[22]; //2 byte - 22 of 64 +//static volatile int16_t *M4_Joint_abs_position = (int16_t *)&SPI_tx_buffer[24]; //2 byte - 24 of 64 +//static volatile int16_t *M4_Motor_speed = (int16_t *)&SPI_tx_buffer[26]; //2 byte - 26 of 64 +//static volatile int16_t *M4_Motor_current_bus = (int16_t *)&SPI_tx_buffer[28]; //2 byte - 28 of 64 +//static volatile int16_t *M4_Motor_currentPhA = (int16_t *)&SPI_tx_buffer[30]; //2 byte - 30 of 64 +//static volatile int16_t *M4_Motor_currentPhB = (int16_t *)&SPI_tx_buffer[32]; //2 byte - 32 of 64 +//static volatile int16_t *M4_Motor_currentPhC = (int16_t *)&SPI_tx_buffer[34]; //2 byte - 34 of 64 +//static volatile int16_t *M4_Motor__hallState = (int16_t *)&SPI_tx_buffer[36]; //2 byte - 36 of 64 +//static volatile int16_t *M4_Motor_dutyCycle = (int16_t *)&SPI_tx_buffer[38]; //2 byte - 38 of 64 +///* IMU */ +//static volatile int16_t *q_x0 = (int16_t *)&SPI_tx_buffer[40]; //2 byte - 40 of 64 +//static volatile int16_t *q_y0 = (int16_t *)&SPI_tx_buffer[42]; //2 byte - 42 of 64 +//static volatile int16_t *q_z0 = (int16_t *)&SPI_tx_buffer[44]; //2 byte - 44 of 64 +//static volatile int16_t *q_w0 = (int16_t *)&SPI_tx_buffer[46]; //2 byte - 46 of 64 +///* EMG */ +//static volatile int16_t *FSR_CH1 = (int16_t *)&SPI_tx_buffer[48]; //2 byte - 48 of 64 +//static volatile int16_t *FSR_CH2 = (int16_t *)&SPI_tx_buffer[50]; //2 byte - 50 of 64 +//static volatile int16_t *FSR_CH3 = (int16_t *)&SPI_tx_buffer[52]; //2 byte - 52 of 64 +//static volatile int16_t *FSR_CH4 = (int16_t *)&SPI_tx_buffer[54]; //2 byte - 54 of 64 +//static volatile int16_t *FSR_CH5 = (int16_t *)&SPI_tx_buffer[56]; //2 byte - 56 of 64 +//static volatile int16_t *Pressure_CH1 = (int16_t *)&SPI_tx_buffer[58]; //2 byte - 58 of 64 +//static volatile int16_t *Pressure_CH2 = (int16_t *)&SPI_tx_buffer[60]; //2 byte - 60 of 64 +//static volatile int16_t *Pressure_CH3 = (int16_t *)&SPI_tx_buffer[62]; //2 byte - 62 of 64 +// +////rx_buffer +/////* Motor 3*/ +//static volatile uint8_t *M3_Control_mode = (uint8_t *)&SPI_rx_buffer[0]; //1 byte - 0 of 32 +//static volatile uint8_t *M3_Control_set = (uint8_t *)&SPI_rx_buffer[1]; //1 byte - 1 of 32 +//static volatile int16_t *M3_Desired_pos = (int16_t *)&SPI_rx_buffer[2]; //2 byte - 2 of 32 +//static volatile int16_t *M3_Desired_speed = (int16_t *)&SPI_rx_buffer[4]; //2 byte - 4 of 32 +//static volatile int16_t *M3_Desired_current = (int16_t *)&SPI_rx_buffer[6]; //2 byte - 6 of 32 +//static volatile int16_t *M3_Max_pos = (int16_t *)&SPI_rx_buffer[8]; //2 byte - 8 of 32 +//static volatile int16_t *M3_Max_velocity = (int16_t *)&SPI_rx_buffer[10]; //2 byte - 10 of 32 +//static volatile int16_t *M3_Max_current = (int16_t *)&SPI_rx_buffer[12]; //2 byte - 12 of 32 +//static volatile int16_t *M3_Spare = (int16_t *)&SPI_rx_buffer[14]; //2 byte - 14 of 32 +/////* Motor 4*/ +//static volatile uint8_t *M4_Control_mode = (int16_t *)&SPI_rx_buffer[16]; //1 byte - 16 of 32 +//static volatile uint8_t *M4_Control_set = (int16_t *)&SPI_rx_buffer[17]; //1 byte - 17 of 32 +//static volatile int16_t *M4_Desired_pos = (int16_t *)&SPI_rx_buffer[18]; //2 byte - 18 of 32 +//static volatile int16_t *M4_Desired_speed = (int16_t *)&SPI_rx_buffer[20]; //2 byte - 20 of 32 +//static volatile int16_t *M4_Desired_current = (int16_t *)&SPI_rx_buffer[22]; //2 byte - 22 of 32 +//static volatile int16_t *M4_Max_pos = (int16_t *)&SPI_rx_buffer[24]; //2 byte - 24 of 32 +//static volatile int16_t *M4_Max_velocity = (int16_t *)&SPI_rx_buffer[26]; //2 byte - 26 of 32 +//static volatile int16_t *M4_Max_current = (int16_t *)&SPI_rx_buffer[28]; //2 byte - 28 of 32 +//static volatile int16_t *M4_Spare = (int16_t *)&SPI_rx_buffer[30]; //2 byte - 30 of 32 + + + + +static void update_telemetry(void) +{ + inline int16_t convert_to_mA(volatile float32_t current_PU) + { + return (int16_t)(current_PU*1000.0f); + } + // + //*M3_Status = 0; + //*M3_Mode = 0; + + /* Motor 1 */ + *M3_Status = Motor1.motor_state.fault; + *M3_Mode = Motor1.motor_state.currentstate; + *M3_Joint_rel_position = Motor1.motor_status.Num_Steps; + *M3_Joint_abs_position = Motor1.motor_setpoints.desired_position + 1 ; + //*M3_Motor_speed = (((int16_t *)&QSPI_tx_buffer[1]+1); + *M3_Motor_current_bus = convert_to_mA(Motor1.Iphase_pu.Bus); + *M3_Motor_currentPhA = convert_to_mA(Motor1.Iphase_pu.A); + *M3_Motor_currentPhB = convert_to_mA(Motor1.Iphase_pu.B); + *M3_Motor_currentPhC = convert_to_mA(Motor1.Iphase_pu.C); + *M3_Motor__hallState = Motor1.motor_status.currentHallPattern; + *M3_Motor_dutyCycle = Motor1.motor_status.duty_cycle; + *M3_Motor_speed = (int16_t)Motor1.motor_status.calc_rpm; + //*M3_Joint_abs_position = ; + /* Motor 2 */ + *M4_Status = Motor2.motor_state.fault; + *M4_Mode = Motor2.motor_state.currentstate; + *M4_Joint_rel_position = Motor2.motor_status.Num_Steps; + *M4_Joint_abs_position = Motor2.motor_setpoints.desired_position + 1 ; + //*M3_Motor_speed = (((int16_t *)&QSPI_tx_buffer[1]+1); + *M4_Motor_current_bus = convert_to_mA( Motor2.Iphase_pu.Bus); + *M4_Motor_currentPhA = convert_to_mA( Motor2.Iphase_pu.A); + *M4_Motor_currentPhB = convert_to_mA( Motor2.Iphase_pu.B); + *M4_Motor_currentPhC = convert_to_mA(Motor2.Iphase_pu.C); + *M4_Motor__hallState = Motor2.motor_status.currentHallPattern; + *M4_Motor_dutyCycle = Motor2.motor_status.duty_cycle; + *M4_Motor_speed = (int16_t)Motor2.motor_status.calc_rpm; + //*M4_Joint_abs_position = Motor2.motor_status.actualDirection; +} + +static void update_setpoints(void) +{ + Motor1.motor_setpoints.desired_position = *M3_Desired_pos; + Motor1.motor_setpoints.desired_speed = *M3_Desired_speed; + Motor1.motor_setpoints.desired_torque = *M3_Desired_current; + Motor1.motor_setpoints.max_current = *M3_Max_current; + Motor1.motor_setpoints.max_torque = *M3_Max_current; + Motor1.motor_setpoints.max_velocity = *M3_Max_velocity; + + Motor2.motor_setpoints.desired_position = *M4_Desired_pos; + Motor2.motor_setpoints.desired_speed = *M4_Desired_speed; + Motor2.motor_setpoints.desired_torque = *M4_Desired_current; + Motor2.motor_setpoints.max_current = *M4_Max_current; + Motor2.motor_setpoints.max_torque = *M4_Max_current; + Motor2.motor_setpoints.max_velocity = *M4_Max_velocity; + + volatile int y = 0; + //volatile uint8_t a = *M3_Control_mode; + //volatile uint8_t b = *M3_Control_set; + //volatile int16_t c = *M3_Desired_pos; + //volatile int16_t d = *M3_Desired_speed; + //volatile int16_t e = *M3_Desired_current; + //volatile int16_t f = *M3_Max_pos; + //volatile int16_t g = *M3_Max_velocity; + //volatile int16_t h = *M3_Max_current; + //volatile int16_t i = *M3_Spare; + //inline float32_t convert_int_to_PU(volatile int16_t input) + //{ + //return ((float32_t)(input/1000.0f)); + //} + ////Motor1.des_mode = 0; + ////Motor1.set = 0; + //Motor1.motor_setpoints.desired_position = *desired_position; + //Motor1.motor_setpoints.desired_speed = *desired_speed; + ////Motor1.desired_speed = 1500; + //Motor1.motor_setpoints.desired_torque = convert_int_to_PU(*desired_torque); + ////Motor1.controllerParam.I_kp = 0; + ////Motor1.controllerParam.I_ki = 0; + ////Motor1.controllerParam.V_kp = 0; + ////Motor1.controllerParam.V_kd = 0; + ////Motor1.controllerParam.V_kd = 0; + ////Motor1.controllerParam.P_kp = 0; + ////Motor1.controllerParam.P_ki = 0; + ////Motor1.reductionRatio = 0; + //Motor1.motor_setpoints.max_velocity = *max_velocity; + //Motor1.motor_setpoints.max_current = convert_int_to_PU(*max_current); + //Motor1.motor_setpoints.max_torque = convert_int_to_PU(*max_torque); + ////Motor1.Spare1 = 0; + ////Motor1.Spare2 = 0; + ////Motor1.Spare3 = 0; + ////Motor1.Spare4 = 0; +} + +static inline void comms_check(void) +{ + /* Motor 1*/ + *M3_Status = 1; + *M3_Mode = 2; + *M3_Joint_rel_position = -3; + *M3_Joint_abs_position = 4; + *M3_Motor_speed = -5; + *M3_Motor_current_bus = 6; + *M3_Motor_currentPhA = -7; + *M3_Motor_currentPhB = 8; + *M3_Motor_currentPhC = -9; + *M3_Motor__hallState = 10; + *M3_Motor_dutyCycle = -11; + /* Motor 2*/ + *M4_Status = 12; + *M4_Mode = 13; + *M4_Joint_rel_position = 14; + *M4_Joint_abs_position = -15; + *M4_Motor_speed = 16; + *M4_Motor_current_bus = -17; + *M4_Motor_currentPhA = 18; + *M4_Motor_currentPhB = -19; + *M4_Motor_currentPhC = 20; + *M4_Motor__hallState = -21; + *M4_Motor_dutyCycle = 22; + + /* IMU */ + *q_x0 = 23; + *q_y0 = -24; + *q_z0 = 25; + *q_w0 = -26; + /* EMG */ + *FSR_CH1 = 27; + *FSR_CH2 = -28; + *FSR_CH3 = 29; + *FSR_CH4 = -30; + *FSR_CH5 = 31; + *Pressure_CH1 = -32; + *Pressure_CH2 = 33; + *Pressure_CH3 = -34; +} + +#endif /* MASTER_SLAVE_IF_H_ */ \ No newline at end of file diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Release.xml b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Release.xml new file mode 100644 index 0000000..084e2d1 --- /dev/null +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Release.xml @@ -0,0 +1,121 @@ + + True + True + True + True + True + + + NDEBUG + + + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + Optimize for size (-Os) + True + True + -std=gnu99 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 + True + + + libm + libarm_cortexM4lf_math.a + + + + + C:\Users\ge37vez\Documents\Git Repos\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master_D51\Two_Motor_D51\Two_Motor_D51\cmsis + %24(ProjectDir)\Device_Startup + + + True + -Tsamd51j18a_flash.ld + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + \ No newline at end of file diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Two_Motor_D51.cproj b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Two_Motor_D51.cproj index f08b2bb..6c68523 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Two_Motor_D51.cproj +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/Two_Motor_D51.cproj @@ -65,6 +65,7 @@ + @@ -154,8 +155,8 @@ - - + + @@ -176,6 +177,7 @@ + @@ -216,9 +218,9 @@ - + - + @@ -243,256 +245,256 @@ - True - True - True - True - True - - - NDEBUG - - - - - %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ - ../Config - ../ - ../examples - ../hal/include - ../hal/utils/include - ../hpl/adc - ../hpl/ccl - ../hpl/cmcc - ../hpl/core - ../hpl/dmac - ../hpl/eic - ../hpl/evsys - ../hpl/gclk - ../hpl/mclk - ../hpl/osc32kctrl - ../hpl/oscctrl - ../hpl/pm - ../hpl/port - ../hpl/qspi - ../hpl/ramecc - ../hpl/sercom - ../hpl/tc - ../hpl/tcc - ../hri - %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include - - - Optimize for size (-Os) - True - True - -std=gnu99 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 - True - - - libm - libarm_cortexM4lf_math.a - - - - - C:\Users\ge37vez\Documents\Git Repos\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master_D51\Two_Motor_D51\Two_Motor_D51\cmsis - %24(ProjectDir)\Device_Startup - - - True - -Tsamd51j18a_flash.ld - - - %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ - ../Config - ../ - ../examples - ../hal/include - ../hal/utils/include - ../hpl/adc - ../hpl/ccl - ../hpl/cmcc - ../hpl/core - ../hpl/dmac - ../hpl/eic - ../hpl/evsys - ../hpl/gclk - ../hpl/mclk - ../hpl/osc32kctrl - ../hpl/oscctrl - ../hpl/pm - ../hpl/port - ../hpl/qspi - ../hpl/ramecc - ../hpl/sercom - ../hpl/tc - ../hpl/tcc - ../hri - %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include - - - - - %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ - ../Config - ../ - ../examples - ../hal/include - ../hal/utils/include - ../hpl/adc - ../hpl/ccl - ../hpl/cmcc - ../hpl/core - ../hpl/dmac - ../hpl/eic - ../hpl/evsys - ../hpl/gclk - ../hpl/mclk - ../hpl/osc32kctrl - ../hpl/oscctrl - ../hpl/pm - ../hpl/port - ../hpl/qspi - ../hpl/ramecc - ../hpl/sercom - ../hpl/tc - ../hpl/tcc - ../hri - %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include - - - + True + True + True + True + True + + + NDEBUG + + + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + Optimize for size (-Os) + True + True + -std=gnu99 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 + True + + + libm + libarm_cortexM4lf_math.a + + + + + C:\Users\ge37vez\Documents\Git Repos\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master_D51\Two_Motor_D51\Two_Motor_D51\cmsis + %24(ProjectDir)\Device_Startup + + + True + -Tsamd51j18a_flash.ld + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + - True - True - True - True - True - - - DEBUG - ARM_MATH_CM4=1 - - - - - %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ - %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include - ../Config - ../ - ../examples - ../hal/include - ../hal/utils/include - ../hpl/adc - ../hpl/ccl - ../hpl/cmcc - ../hpl/core - ../hpl/dmac - ../hpl/eic - ../hpl/evsys - ../hpl/gclk - ../hpl/mclk - ../hpl/osc32kctrl - ../hpl/oscctrl - ../hpl/pm - ../hpl/port - ../hpl/qspi - ../hpl/ramecc - ../hpl/sercom - ../hpl/tc - ../hpl/tcc - ../hri - - - Optimize debugging experience (-Og) - True - Maximum (-g3) - True - -std=gnu99 -mfloat-abi=hard -mfpu=fpv4-sp-d16 - True - - - libm - libarm_cortexM4lf_math.a - - - - - C:\Users\ge37vez\Documents\Git Repos\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master_D51\Two_Motor_D51\Two_Motor_D51\cmsis - %24(ProjectDir)\Device_Startup - - - True - - -Tsamd51j18a_flash.ld -std=gnu99 -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mfp16-format=ieee - - - %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ - %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include - ../Config - ../ - ../examples - ../hal/include - ../hal/utils/include - ../hpl/adc - ../hpl/ccl - ../hpl/cmcc - ../hpl/core - ../hpl/dmac - ../hpl/eic - ../hpl/evsys - ../hpl/gclk - ../hpl/mclk - ../hpl/osc32kctrl - ../hpl/oscctrl - ../hpl/pm - ../hpl/port - ../hpl/qspi - ../hpl/ramecc - ../hpl/sercom - ../hpl/tc - ../hpl/tcc - ../hri - - - Default (-g) - - - %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ - %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include - ../Config - ../ - ../examples - ../hal/include - ../hal/utils/include - ../hpl/adc - ../hpl/ccl - ../hpl/cmcc - ../hpl/core - ../hpl/dmac - ../hpl/eic - ../hpl/evsys - ../hpl/gclk - ../hpl/mclk - ../hpl/osc32kctrl - ../hpl/oscctrl - ../hpl/pm - ../hpl/port - ../hpl/qspi - ../hpl/ramecc - ../hpl/sercom - ../hpl/tc - ../hpl/tcc - ../hri - - - Default (-Wa,-g) - + True + True + True + True + True + + + DEBUG + ARM_MATH_CM4=1 + + + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + Optimize debugging experience (-Og) + True + Maximum (-g3) + True + -std=gnu99 -mfloat-abi=hard -mfpu=fpv4-sp-d16 + True + + + libm + libarm_cortexM4lf_math.a + + + + + C:\Users\ge37vez\Documents\Git Repos\bldc_control_thesis\bldc_firmware_thesis\2_Motor_Master_D51\Two_Motor_D51\Two_Motor_D51\cmsis + %24(ProjectDir)\Device_Startup + + + True + + -Tsamd51j18a_flash.ld -std=gnu99 -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mfp16-format=ieee + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + Default (-g) + + + %24(PackRepoDir)\arm\CMSIS\5.4.0\CMSIS\Core\Include\ + ../Config + ../ + ../examples + ../hal/include + ../hal/utils/include + ../hpl/adc + ../hpl/ccl + ../hpl/cmcc + ../hpl/core + ../hpl/dmac + ../hpl/eic + ../hpl/evsys + ../hpl/gclk + ../hpl/mclk + ../hpl/osc32kctrl + ../hpl/oscctrl + ../hpl/pm + ../hpl/port + ../hpl/qspi + ../hpl/ramecc + ../hpl/sercom + ../hpl/tc + ../hpl/tcc + ../hri + %24(PackRepoDir)\atmel\SAMD51_DFP\1.2.139\samd51a\include + + + Default (-Wa,-g) + @@ -655,6 +657,9 @@ compile + + compile + compile @@ -814,6 +819,9 @@ compile + + compile + compile @@ -1051,6 +1059,9 @@ compile + + compile + compile @@ -1125,6 +1136,9 @@ compile + + compile + compile diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/configuration.h b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/configuration.h index ea10d7c..dec4c31 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/configuration.h +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/configuration.h @@ -5,10 +5,17 @@ * Author: Nick-XMG */ - #ifndef CONFIGURATION_H_ #define CONFIGURATION_H_ +// Conditional Inclusion Only Select One +#define _MASTER +//#define _SLAVE + +#ifdef _MASTER +#include "EtherCAT_QSPI.h" +#endif // MASTER + // ---------------------------------------------------------------------- // Header Files // ---------------------------------------------------------------------- @@ -19,6 +26,31 @@ #include "ADS1299.h" #include "hpl_spi_m_dma.h" +#ifdef _SLAVE +#include "hal_spi_s_sync.h" +#include "hpl_spi_s_sync.h" +#endif // SLAVE + +/* DMA channel Descriptor */ +extern DmacDescriptor _descriptor_section[DMAC_CH_NUM]; +extern DmacDescriptor _write_back_section[DMAC_CH_NUM]; + +// ---------------------------------------------------------------------- +// DMA CHANNEL NUMBER CONFIGURATION +// ---------------------------------------------------------------------- +#define CONF_SERCOM_1_SPI_DMA_RX_CHANNEL 0U +#define CONF_SERCOM_1_SPI_DMA_TX_CHANNEL 7U +#define CONF_ADC_1_ADC_RES_READY_CHANNEL 3U +#define CONF_ADC_1_SEQUENCER_CHANNEL 4U + +#ifdef _MASTER + #define CONF_SERCOM_2_SPI_DMA_RX_CHANNEL 2U + #define CONF_SERCOM_2_SPI_DMA_TX_CHANNEL 5U +#else + #define CONF_ADC_0_ADC_RES_READY_CHANNEL 2U + #define CONF_ADC_0_SEQUENCER_CHANNEL 5U +#endif + // ---------------------------------------------------------------------- // PWM Timer Initialization // ---------------------------------------------------------------------- @@ -76,12 +108,6 @@ static void configure_tcc_pwm(void) // ADC DMA Initialization // M1_IA=ADC1_AIN[9], M1_IB=ADC1_AIN[8], M2_IA=ADC1_AIN[7], M2_IB=ADC1_AIN[6] // ---------------------------------------------------------------------- - -//#define CONF_ADC_0_ADC_RES_READY_CHANNEL 4U -#define CONF_ADC_1_ADC_RES_READY_CHANNEL 3U -//#define CONF_ADC_0_SEQUENCER_CHANNEL 6U -#define CONF_ADC_1_SEQUENCER_CHANNEL 4U - const uint32_t adc0_seq_regs[4] = {0}; const uint32_t adc1_seq_regs[4] = {0x0089, 0x0088, 0x0087, 0x0086}; /* Differential */ //const uint32_t adc1_seq_regs[4] = {0x1807, 0x1806, 0x1809, 0x1808}; /* Single Ended */ @@ -91,8 +117,6 @@ volatile int16_t adc1_res[4] = {0}; struct _dma_resource *adc_sram_dma_resource; struct _dma_resource *adc_dmac_sequence_resource; - - static void adc_dmac_sequence_init() { /* Configure the DMAC source address, destination address, @@ -122,7 +146,7 @@ static void adc_sram_dmac_init() // ---------------------------------------------------------------------- // ADC Initialization // ---------------------------------------------------------------------- -static void adc_init_dma_descriptors(void) +static void adc1_init_dma_descriptors(void) { adc_sram_dmac_init(); adc_dmac_sequence_init(); @@ -131,51 +155,120 @@ static void adc_init_dma_descriptors(void) } + // ---------------------------------------------------------------------- // SPI DMA communication between Master & Slave Board // ---------------------------------------------------------------------- - -#define MASTER_BUFFER_SIZE 64 -#define MASTER_BUFFER_SIZE_LONG MASTER_BUFFER_SIZE/4 - -/* DMA channel Descriptor */ -extern DmacDescriptor _descriptor_section[DMAC_CH_NUM]; -extern DmacDescriptor _write_back_section[DMAC_CH_NUM]; +#define MASTER_SLAVE_BUFFER_SIZE 64 +#define MASTER_SLAVE_BUFFER_SIZE_LONG MASTER_SLAVE_BUFFER_SIZE/4 static void boardToBoardTransferInit(void) { - struct io_descriptor *io; - spi_m_dma_get_io_descriptor(&SPI_1_MSIF, &io); - //spi_m_dma_register_callback(&SPI_1_MSIF, SPI_M_DMA_CB_RX_DONE, b2bTransferComplete_cb); - //SERCOM4->SPI.CTRLC.bit.DATA32B = true; - //SERCOM1->SPI.LENGTH.bit.LENEN = true; - //SERCOM1->SPI.LENGTH.bit.LEN = 64; + #ifdef _MASTER + struct io_descriptor *io; + spi_m_dma_get_io_descriptor(&SPI_1_MSIF_M, &io); + //spi_m_dma_register_callback(&SPI_1_MSIF, SPI_M_DMA_CB_RX_DONE, b2bTransferComplete_cb); + //SERCOM4->SPI.CTRLC.bit.DATA32B = true; + //SERCOM1->SPI.LENGTH.bit.LENEN = true; + //SERCOM1->SPI.LENGTH.bit.LEN = 64; - SERCOM1->SPI.CTRLC.bit.ICSPACE = 4; - SERCOM1->SPI.CTRLC.bit.DATA32B= true; - gpio_set_pin_level(SPI1_CS, true); - spi_m_dma_enable(&SPI_1_MSIF); + SERCOM1->SPI.CTRLC.bit.ICSPACE = 4; + SERCOM1->SPI.CTRLC.bit.DATA32B= true; + gpio_set_pin_level(SPI1_CS, true); + spi_m_dma_enable(&SPI_1_MSIF_M); + #endif //MASTER + #ifdef _SLAVE + spi_m_dma_deinit(&SPI_1_MSIF_M); + spi_s_sync_init(&SPI_1_MSIF_S, SERCOM1); + SPI_1_MSIF_Slave_PORT_init(); + SERCOM1->SPI.CTRLC.bit.DATA32B = true; + hri_sercomspi_set_CTRLB_PLOADEN_bit(SERCOM1); + hri_sercomspi_write_CTRLA_MODE_bf(SERCOM1, 0x02); + hri_sercomspi_write_CTRLB_MSSEN_bit(SERCOM1, true); + spi_s_sync_enable(&SPI_1_MSIF_S); + + NVIC_DisableIRQ((IRQn_Type)SERCOM1_1_IRQn); + NVIC_ClearPendingIRQ((IRQn_Type)SERCOM1_1_IRQn); + NVIC_EnableIRQ((IRQn_Type)SERCOM1_1_IRQn); + hri_sercomspi_set_INTEN_TXC_bit(SERCOM1); + hri_sercomspi_set_INTEN_SSL_bit(SERCOM1); + #endif //SLAVE } -static void spi_master_init_dma_descriptors() +void SPI_1_MSIF_Slave_PORT_init(void) { - _dma_set_source_address(CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL, - (uint32_t *)&(((SercomSpi *)(SPI_1_MSIF.dev.prvt))->DATA.reg)); - _dma_set_destination_address(CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL, &QSPI_tx_buffer[16]); - _dma_set_data_amount(CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL, MASTER_BUFFER_SIZE_LONG); - _dma_set_next_descriptor(CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL, CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL); + + // Set pin direction to input + gpio_set_pin_direction(SPI1_MOSI, GPIO_DIRECTION_IN); + + gpio_set_pin_pull_mode(SPI1_MOSI, + // Pull configuration + // pad_pull_config + // Off + // Pull-up + // Pull-down + GPIO_PULL_OFF); + + gpio_set_pin_function(SPI1_MOSI, PINMUX_PA00D_SERCOM1_PAD0); + + gpio_set_pin_level(SPI1_SCK, + // Initial level + // pad_initial_level + // Low + // High + false); + + // Set pin direction to output + gpio_set_pin_direction(SPI1_SCK, GPIO_DIRECTION_OUT); + + gpio_set_pin_function(SPI1_SCK, PINMUX_PA01D_SERCOM1_PAD1); + + // Set pin direction to input + gpio_set_pin_direction(SPI1_CS, GPIO_DIRECTION_IN); + + gpio_set_pin_pull_mode(SPI1_CS, + // Pull configuration + // pad_pull_config + // Off + // Pull-up + // Pull-down + GPIO_PULL_OFF); + + gpio_set_pin_function(SPI1_CS, PINMUX_PB22C_SERCOM1_PAD2); + + gpio_set_pin_level(SPI1_MISO, + // Initial level + // pad_initial_level + // Low + // High + false); + + // Set pin direction to output + gpio_set_pin_direction(SPI1_MISO, GPIO_DIRECTION_OUT); + + gpio_set_pin_function(SPI1_MISO, PINMUX_PB23C_SERCOM1_PAD3); +} + + +static void spi_master_slave_if_dma_descriptor_init() +{ + #ifdef _MASTER + _dma_set_source_address(CONF_SERCOM_1_SPI_DMA_RX_CHANNEL, + (uint32_t *)&(((SercomSpi *)(SPI_1_MSIF_M.dev.prvt))->DATA.reg)); + _dma_set_destination_address(CONF_SERCOM_1_SPI_DMA_RX_CHANNEL, &QSPI_tx_buffer[16]); + _dma_set_data_amount(CONF_SERCOM_1_SPI_DMA_RX_CHANNEL, MASTER_SLAVE_BUFFER_SIZE_LONG); + _dma_set_next_descriptor(CONF_SERCOM_1_SPI_DMA_RX_CHANNEL, CONF_SERCOM_1_SPI_DMA_RX_CHANNEL); - _dma_set_source_address(CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL, &QSPI_rx_buffer[16]); - _dma_set_destination_address(CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL, - (uint32_t *)&(((SercomSpi *)(SPI_1_MSIF.dev.prvt))->DATA.reg)); - _dma_set_data_amount(CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL, MASTER_BUFFER_SIZE_LONG); - _dma_set_next_descriptor(CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL, CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL); + _dma_set_source_address(CONF_SERCOM_1_SPI_DMA_TX_CHANNEL, &QSPI_rx_buffer[16]); + _dma_set_destination_address(CONF_SERCOM_1_SPI_DMA_TX_CHANNEL, + (uint32_t *)&(((SercomSpi *)(SPI_1_MSIF_M.dev.prvt))->DATA.reg)); + _dma_set_data_amount(CONF_SERCOM_1_SPI_DMA_TX_CHANNEL, MASTER_SLAVE_BUFFER_SIZE_LONG); + _dma_set_next_descriptor(CONF_SERCOM_1_SPI_DMA_TX_CHANNEL, CONF_SERCOM_1_SPI_DMA_TX_CHANNEL); - hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL]); - hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL]); - + hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[CONF_SERCOM_1_SPI_DMA_TX_CHANNEL]); + hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[CONF_SERCOM_1_SPI_DMA_RX_CHANNEL]); /* callback */ //struct _dma_resource *resource_rx, *resource_tx; @@ -186,18 +279,12 @@ static void spi_master_init_dma_descriptors() /* Enable DMA transfer complete interrupt */ //_dma_set_irq_state(DMAC_CHANNEL_CONF_SERCOM_1_RECEIVE, DMA_TRANSFER_COMPLETE_CB, true); - + #endif //MASTER } -// ---------------------------------------------------------------------- -// SPI DMA communication ADS1299 -// ---------------------------------------------------------------------- -// - -#define CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL 2U -#define CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL 5U +#ifdef _MASTER /* 219 Bites total * Number format is 24 bit * 7 (uint_32) - 24 bits @@ -206,47 +293,43 @@ extern volatile uint32_t ads1299_buffer[ADS_BUFFER_SIZE]; // static void spi_ads1299_init_dma_descriptors() { - _dma_set_source_address(CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL, + _dma_set_source_address(CONF_SERCOM_2_SPI_DMA_RX_CHANNEL, (uint32_t *)&(((SercomSpi *)(SPI_2.dev.prvt))->DATA.reg)); - _dma_set_destination_address(CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL, &_ads1299_channel_data[0]); - _dma_set_data_amount(CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL, ADS_BUFFER_SIZE); - _dma_set_next_descriptor(CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL, CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL); + _dma_set_destination_address(CONF_SERCOM_2_SPI_DMA_RX_CHANNEL, &_ads1299_channel_data[0]); + _dma_set_data_amount(CONF_SERCOM_2_SPI_DMA_RX_CHANNEL, ADS_BUFFER_SIZE); + _dma_set_next_descriptor(CONF_SERCOM_2_SPI_DMA_RX_CHANNEL, CONF_SERCOM_2_SPI_DMA_RX_CHANNEL); - _dma_set_source_address(CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL, &ads1299_buffer[0]); - _dma_set_destination_address(CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL, + _dma_set_source_address(CONF_SERCOM_2_SPI_DMA_TX_CHANNEL, &ads1299_buffer[0]); + _dma_set_destination_address(CONF_SERCOM_2_SPI_DMA_TX_CHANNEL, (uint32_t *)&(((SercomSpi *)(SPI_2.dev.prvt))->DATA.reg)); - _dma_set_data_amount(CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL, ADS_BUFFER_SIZE); - _dma_set_next_descriptor(CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL, CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL); + _dma_set_data_amount(CONF_SERCOM_2_SPI_DMA_TX_CHANNEL, ADS_BUFFER_SIZE); + _dma_set_next_descriptor(CONF_SERCOM_2_SPI_DMA_TX_CHANNEL, CONF_SERCOM_2_SPI_DMA_TX_CHANNEL); - hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL]); - hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL]); + hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[CONF_SERCOM_2_SPI_DMA_RX_CHANNEL]); + hri_dmacdescriptor_set_BTCTRL_VALID_bit(&_descriptor_section[CONF_SERCOM_2_SPI_DMA_TX_CHANNEL]); /* callback */ struct _dma_resource *resource_rx, *resource_tx; - _dma_get_channel_resource(&resource_rx, CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL); - _dma_get_channel_resource(&resource_tx, CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL); + _dma_get_channel_resource(&resource_rx, CONF_SERCOM_2_SPI_DMA_RX_CHANNEL); + _dma_get_channel_resource(&resource_tx, CONF_SERCOM_2_SPI_DMA_TX_CHANNEL); resource_rx->dma_cb.transfer_done = ADS1299_Transfer_Complete_cb; resource_rx->dma_cb.error = ADS1299_Transfer_error_cb; resource_tx->dma_cb.transfer_done = ADS1299_Transfer_Complete_cb; /* Enable DMA transfer complete interrupt */ - _dma_set_irq_state(CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL, DMA_TRANSFER_COMPLETE_CB, true); - _dma_set_irq_state(CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL, DMA_TRANSFER_COMPLETE_CB, true); - //_dma_set_irq_state(CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL, DMA_TRANSFER_ERROR_CB, true); - - - - + _dma_set_irq_state(CONF_SERCOM_2_SPI_DMA_RX_CHANNEL, DMA_TRANSFER_COMPLETE_CB, true); + _dma_set_irq_state(CONF_SERCOM_2_SPI_DMA_TX_CHANNEL, DMA_TRANSFER_COMPLETE_CB, true); + //_dma_set_irq_state(CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL, DMA_TRANSFER_ERROR_CB, true); } +#endif //MASTER // ---------------------------------------------------------------------- // Overall DMA Init // ---------------------------------------------------------------------- - -/* Peripherals should be configured before interacting with dma +/* MASTER * CH0 - SERCOM1_RX(SPI1) - Master-Slave IF - Beat Transfer Event Drives CS Pin * CH1 - SERCOM5_RX(SPI3) - Angle Sensor * CH2 - SERCOM2_RX(SPI2) - Expansion IF (EMG) - Beat Transfer Event Drives CS Pin @@ -257,12 +340,24 @@ static void spi_ads1299_init_dma_descriptors() * CH7 - SERCOM1_TX(SPI1) - Master-Slave IF */ +/* SLAVE +* CH0 - SERCOM1_RX(SPI1) - Master-Slave IF - Beat Transfer Event Drives CS Pin +* CH1 - SERCOM5_RX(SPI3) - Angle Sensor +* CH2 - ADC0 - Result Ready +* CH3 - ADC1 - Result Ready +* CH4 - ADC1 - Sequencer - Triggered by TCC0 overflow event +* CH5 - ADC0 - Sequencer +* CH6 - SERCOM5_TX(SPI3) - Angle Sensor +* CH7 - SERCOM1_TX(SPI1) - Master-Slave IF +*/ + static void init_dma(void) { - spi_master_init_dma_descriptors(); + spi_master_slave_if_dma_descriptor_init(); + adc1_init_dma_descriptors(); + #ifdef _MASTER spi_ads1299_init_dma_descriptors(); - adc_init_dma_descriptors(); - + #endif // _MASTER } @@ -270,19 +365,48 @@ static void init_dma(void) // Overall DMA Init // ---------------------------------------------------------------------- -/* Peripherals should be configured before interacting with dma -* CH0 - QSPI_RX - For ECAT DMA Mode - Currently Disabled in ASTART -* CH1 - SERCOM1_RX(SPI1) - Master-Slave IF - Beat Transfer Event Drives CS Pin -* CH2 - SERCOM2_RX(SPI2) - Expansion IF (EMG) - Beat Transfer Event Drives CS Pin -* CH3 - SERCOM5_RX(SPI3) - Angle Sensor -* CH4 - ADC0 - Result Ready (Unused on master) - Currently Disabled in ASTART -* CH5 - ADC1 - Result Ready -* CH6 - ADC0 - Sequencer (Unused on master) - Currently Disabled in ASTART -* CH7 - ADC1 - Sequencer - Triggered by TCC0 overflow event -* CH8 - SERCOM2_TX(SPI2) - Expansion IF (EMG) -* CH9 - SERCOM5_TX(SPI3) - Angle Sensor -* CH10 - SERCOM1_TX(SPI1) - Master-Slave IF -* CH11 - QSPI_TX - For ECAT DMA Mode - Currently Disabled in ASTART +/* Master Event System Configured in ATMEL START. Slave retains some of +the same events which are reconfigured and enabled +* CH0 - TCC0 OVF +* CH1 - TC0 OVF (1ms) - telemetry +* CH2 - TC1 OVF (1ms) - Angle Sensor +* CH3 - CCL output 0 +* CH4 - CCL output 2 */ +void slave_event_system_config(void) +{ + event_system_deinit(); + + uint16_t slave_channel_confs[5] = + { + 0x0229, /* EVGEN = 29(TCC0_OVF) , Path = 2(ASYNCHRONOUS), Edgesel = 0(NO_EVT_OUTPUT)*/ + 0x0000, //0x0649, /* EVGEN = 49(TC0_OVF) , Path = 2(ASYNCHRONOUS), Edgesel = 1(RISING_EDGE) */ + 0x0000, //0x044C, /* EVGEN = 4C(TC1_OVF) , Path = 2(ASYNCHRONOUS), Edgesel = 1(RISING_EDGE) */ + 0x0674, /* EVGEN = 74(CCL_LUTOUT0) , Path = 2(ASYNCHRONOUS), Edgesel = 1(RISING_EDGE) */ + 0x0276 /* EVGEN = 76(CCL_LUTOUT2), Path = 2(ASYNCHRONOUS), Edgesel = 1(RISING_EDGE) */ + }; + uint32_t slave_interrupt_cfg[5] = + { + 0x00 /* The Event Detected Channel interrupt is disabled, The Overrun Channel interrupt is disabled. */ + }; + + /* USER_ID, Channel n-1 */ + //hri_evsys_write_USER_reg(EVSYS, 0x01, 0x02); /*PORT_EV0 - CH1*/ + //hri_evsys_write_USER_reg(EVSYS, 0x02, 0x07); /*PORT_EV1 - CH6*/ + //hri_evsys_write_USER_reg(EVSYS, 0x03, 0x06); /*PORT_EV2 - CH5*/ + //hri_evsys_write_USER_reg(EVSYS, 0x04, 0x09); /*PORT_EV3 - CH8*/ + hri_evsys_write_USER_reg(EVSYS, 0x09, 0x01); /*DMAC_CH4 - CH0 */ + //hri_evsys_write_USER_reg(EVSYS, 0x10, 0x06); /*DMAC_CH5 - CH1*/ + //hri_evsys_write_USER_reg(EVSYS, 0x12, 0x03); /*DMAC_CH7 - CH2*/ + hri_evsys_write_USER_reg(EVSYS, 0x46, 0x0c); /*TC2 - CH11*/ + hri_evsys_write_USER_reg(EVSYS, 0x48, 0x0d); /*TC4 - CH12 */ + + uint8_t i; + for (i = 0; i < 5; i++) { + hri_evsys_write_CHANNEL_reg(EVSYS, i, slave_channel_confs[i]); + hri_evsys_write_CHINTEN_reg(EVSYS, i, slave_interrupt_cfg[i]); + } +} + #endif /* CONFIGURATION_H_ */ \ No newline at end of file diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/driver_init.c b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/driver_init.c index 037d81d..06759c9 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/driver_init.c +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/driver_init.c @@ -25,7 +25,9 @@ struct qspi_dma_descriptor ECAT_QSPI; struct i2c_m_async_desc I2C_0; -struct spi_m_dma_descriptor SPI_1_MSIF; +struct spi_m_dma_descriptor SPI_1_MSIF_M; + +struct spi_s_sync_descriptor SPI_1_MSIF_S; struct pwm_descriptor PWM_0; @@ -439,7 +441,7 @@ void I2C_0_init(void) I2C_0_PORT_init(); } -void SPI_1_MSIF_PORT_init(void) +void SPI_1_MSIF_M_PORT_init(void) { gpio_set_pin_level(SPI1_MOSI, @@ -480,7 +482,7 @@ void SPI_1_MSIF_PORT_init(void) gpio_set_pin_function(SPI1_MISO, PINMUX_PB23C_SERCOM1_PAD3); } -void SPI_1_MSIF_CLOCK_init(void) +void SPI_1_MSIF_M_CLOCK_init(void) { hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM1_GCLK_ID_CORE, CONF_GCLK_SERCOM1_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM1_GCLK_ID_SLOW, CONF_GCLK_SERCOM1_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); @@ -488,11 +490,11 @@ void SPI_1_MSIF_CLOCK_init(void) hri_mclk_set_APBAMASK_SERCOM1_bit(MCLK); } -void SPI_1_MSIF_init(void) +void SPI_1_MSIF_M_init(void) { - SPI_1_MSIF_CLOCK_init(); - spi_m_dma_init(&SPI_1_MSIF, SERCOM1); - SPI_1_MSIF_PORT_init(); + SPI_1_MSIF_M_CLOCK_init(); + spi_m_dma_init(&SPI_1_MSIF_M, SERCOM1); + SPI_1_MSIF_M_PORT_init(); } void SPI_2_PORT_init(void) @@ -551,6 +553,25 @@ void SPI_2_init(void) SPI_2_PORT_init(); } +void SPI_1_MSIF_S_PORT_init(void) +{ +} + +void SPI_1_MSIF_S_CLOCK_init(void) +{ + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_CORE, CONF_GCLK_SERCOM3_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM3_GCLK_ID_SLOW, CONF_GCLK_SERCOM3_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + + hri_mclk_set_APBBMASK_SERCOM3_bit(MCLK); +} + +void SPI_1_MSIF_S_init(void) +{ + //SPI_1_MSIF_S_CLOCK_init(); + //spi_s_sync_init(&SPI_1_MSIF_S, SERCOM3); + //SPI_1_MSIF_S_PORT_init(); +} + void SPI_3_PORT_init(void) { @@ -805,10 +826,12 @@ void system_init(void) I2C_0_init(); - SPI_1_MSIF_init(); + SPI_1_MSIF_M_init(); SPI_2_init(); + SPI_1_MSIF_S_init(); + SPI_3_init(); TIMER_0_CLOCK_init(); diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/driver_init.h b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/driver_init.h index bab8991..00edc6a 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/driver_init.h +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/driver_init.h @@ -37,6 +37,8 @@ extern "C" { #include #include + +#include #include #include #include @@ -57,8 +59,10 @@ extern struct qspi_dma_descriptor ECAT_QSPI; extern struct i2c_m_async_desc I2C_0; -extern struct spi_m_dma_descriptor SPI_1_MSIF; +extern struct spi_m_dma_descriptor SPI_1_MSIF_M; extern struct spi_m_sync_descriptor SPI_2; + +extern struct spi_s_sync_descriptor SPI_1_MSIF_S; extern struct spi_m_sync_descriptor SPI_3; extern struct pwm_descriptor PWM_0; @@ -85,14 +89,19 @@ void I2C_0_PORT_init(void); void I2C_0_CLOCK_init(void); void I2C_0_init(void); -void SPI_1_MSIF_PORT_init(void); -void SPI_1_MSIF_CLOCK_init(void); -void SPI_1_MSIF_init(void); +void SPI_1_MSIF_M_PORT_init(void); +void SPI_1_MSIF_M_CLOCK_init(void); +void SPI_1_MSIF_M_init(void); void SPI_2_PORT_init(void); void SPI_2_CLOCK_init(void); void SPI_2_init(void); +void SPI_1_MSIF_S_PORT_init(void); +void SPI_1_MSIF_S_CLOCK_init(void); +void SPI_1_MSIF_S_init(void); +void SPI_1_MSIF_S_example(void); + void SPI_3_PORT_init(void); void SPI_3_CLOCK_init(void); void SPI_3_init(void); diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/examples/driver_examples.c b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/examples/driver_examples.c index 2adbb38..98b7011 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/examples/driver_examples.c +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/examples/driver_examples.c @@ -124,7 +124,7 @@ void I2C_0_example(void) } /** - * Example of using SPI_1_MSIF to write "Hello World" using the IO abstraction. + * Example of using SPI_1_MSIF_M to write "Hello World" using the IO abstraction. * * Since the driver is asynchronous we need to use statically allocated memory for string * because driver initiates transfer and then returns before the transmission is completed. @@ -132,21 +132,21 @@ void I2C_0_example(void) * Once transfer has been completed the tx_cb function will be called. */ -static uint8_t example_SPI_1_MSIF[12] = "Hello World!"; +static uint8_t example_SPI_1_MSIF_M[12] = "Hello World!"; -static void tx_complete_cb_SPI_1_MSIF(struct _dma_resource *resource) +static void tx_complete_cb_SPI_1_MSIF_M(struct _dma_resource *resource) { /* Transfer completed */ } -void SPI_1_MSIF_example(void) +void SPI_1_MSIF_M_example(void) { struct io_descriptor *io; - spi_m_dma_get_io_descriptor(&SPI_1_MSIF, &io); + spi_m_dma_get_io_descriptor(&SPI_1_MSIF_M, &io); - spi_m_dma_register_callback(&SPI_1_MSIF, SPI_M_DMA_CB_TX_DONE, tx_complete_cb_SPI_1_MSIF); - spi_m_dma_enable(&SPI_1_MSIF); - io_write(io, example_SPI_1_MSIF, 12); + spi_m_dma_register_callback(&SPI_1_MSIF_M, SPI_M_DMA_CB_TX_DONE, tx_complete_cb_SPI_1_MSIF_M); + spi_m_dma_enable(&SPI_1_MSIF_M); + io_write(io, example_SPI_1_MSIF_M, 12); } /** @@ -163,6 +163,20 @@ void SPI_2_example(void) io_write(io, example_SPI_2, 12); } +/** + * Example of using SPI_1_MSIF_S to write "Hello World" using the IO abstraction. + */ +static uint8_t example_SPI_1_MSIF_S[12] = "Hello World!"; + +void SPI_1_MSIF_S_example(void) +{ + struct io_descriptor *io; + spi_s_sync_get_io_descriptor(&SPI_1_MSIF_S, &io); + + spi_s_sync_enable(&SPI_1_MSIF_S); + io_write(io, example_SPI_1_MSIF_S, 12); +} + /** * Example of using SPI_3 to write "Hello World" using the IO abstraction. */ diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/examples/driver_examples.h b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/examples/driver_examples.h index 9defce7..d009c83 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/examples/driver_examples.h +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/examples/driver_examples.h @@ -24,7 +24,7 @@ void ECAT_QSPI_example(void); void I2C_0_example(void); -void SPI_1_MSIF_example(void); +void SPI_1_MSIF_M_example(void); void PWM_0_example(void); diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/documentation/spi_slave_sync.rst b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/documentation/spi_slave_sync.rst new file mode 100644 index 0000000..226eb8a --- /dev/null +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/documentation/spi_slave_sync.rst @@ -0,0 +1,60 @@ +The SPI Slave Synchronous Driver +================================ + +The serial peripheral interface (SPI) is a synchronous serial communication +interface. + +SPI devices communicate in full duplex mode using a master-slave +architecture with a single master. The slave device uses the control signal +and clocks from master for reading and writing. Slave device is selected through +slave select (SS) line. + +When data is read or written through the I/O writing function, the driver keeps +polling until amount of characters achieved. Also it's possible to perform +full-duplex read and write through transfer function, which process read and +write at the same time. + +When SS detection is considered, a "break on SS detection" option can be enabled +to make it possible to terminate the read/write/transfer on SS desertion. + +Features +-------- + +* Initialization/de-initialization +* Enabling/disabling +* Control of the following settings: + + * SPI mode + * Character size + * Data order +* Data transfer: transmission, reception and full-duplex + +Applications +------------ + +* SPI to I2C bridge that bridges SPI commands to I2C interface. + +Dependencies +------------ + +SPI slave capable hardware + +Concurrency +----------- + +N/A + +Limitations +----------- + +N/A + +Known issues and workarounds +---------------------------- + +When writing data through SPI slave, the time that the data appears on data line +depends on the SPI hardware, and previous writing state, since there can be +data in output fifo filled by previous broken transmitting. The number of such +dummy/broken characters is limited by hardware. Whether these dummy/broken +characters can be flushed is also limited by hardware. + diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/include/hal_spi_s_sync.h b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/include/hal_spi_s_sync.h new file mode 100644 index 0000000..2cdc43d --- /dev/null +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/include/hal_spi_s_sync.h @@ -0,0 +1,204 @@ +/** + * \file + * + * \brief SPI Slave functionality declaration. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_SPI_S_SYNC_H_INCLUDED +#define _HAL_SPI_S_SYNC_H_INCLUDED + +#include "hpl_spi_s_sync.h" +#include "utils.h" +#include "hal_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_spi_slave_sync + * + * @{ + */ + +/** \brief SPI Slave HAL driver struct for synchronous access + */ +struct spi_s_sync_descriptor { + struct _spi_s_sync_hpl_interface *func; + /** SPI device instance */ + struct _spi_sync_dev dev; + /** I/O read/write */ + struct io_descriptor io; + /** Break on SS desert detection. */ + uint8_t break_on_ss_det; +}; + +/** \brief Set the SPI HAL instance function pointer for HPL APIs. + * + * Set SPI HAL instance function pointer for HPL APIs. + * + * \param[in] spi Pointer to the HAL SPI instance. + * \param[in] func Pointer to the HPL api structure. + * + */ +void spi_s_sync_set_func_ptr(struct spi_s_sync_descriptor *spi, void *const func); + +/** \brief Initialize the SPI Slave HAL instance and hardware + * + * Initialize SPI Slave HAL with polling mode. + * + * \param[in, out] spi Pointer to the SPI Slave HAL instance. + * \param[in] hw Pointer to the hardware base. + * + * \return Operation status. + * \retval 0 Success. + * \retval <0 Error. + */ +int32_t spi_s_sync_init(struct spi_s_sync_descriptor *spi, void *const hw); + +/** \brief Deinitialize the SPI HAL instance + * + * Disable and reset SPI, de-init software. + * + * \param[in,out] spi Pointer to the SPI Slave HAL instance. + */ +void spi_s_sync_deinit(struct spi_s_sync_descriptor *spi); + +/** \brief Enable SPI + * + * \param[in,out] spi Pointer to the SPI Slave HAL instance. + */ +void spi_s_sync_enable(struct spi_s_sync_descriptor *spi); + +/** \brief Disable SPI + * + * \param[in,out] spi Pointer to the SPI Slave HAL instance. + */ +void spi_s_sync_disable(struct spi_s_sync_descriptor *spi); + +/** \brief Set SPI mode + * + * Set the SPI transfer mode (\ref spi_transfer_mode_t), + * which controls the clock polarity and clock phase: + * - Mode 0: leading edge is rising edge, data sample on leading edge. + * - Mode 1: leading edge is rising edge, data sample on trailing edge. + * - Mode 2: leading edge is falling edge, data sample on leading edge. + * - Mode 3: leading edge is falling edge, data sample on trailing edge. + * Note that SPI must be disabled to change mode. + * + * \param[in,out] spi Pointer to the HAL SPI instance. + * \param[in] mode The mode (\ref spi_transfer_mode_t). + * + * \return Operation status. + * \retval 0 Success. + * \retval <0 Error. + */ +int32_t spi_s_sync_set_mode(struct spi_s_sync_descriptor *spi, const enum spi_transfer_mode mode); + +/** \brief Set SPI transfer character size in number of bits + * + * The character size (\ref spi_char_size_t) influence the way the data is + * sent/received. + * For char size <= 8-bit, data is stored byte by byte. + * For char size between 9-bit ~ 16-bit, data is stored in 2-byte length. + * Note that the default and recommended char size is 8-bit since it's + * supported by all system. + * Note that the SPI must be disabled to change character size. Also it affects + * buffer accessing, the ring buffer should be flushed before changing it to + * avoid conflicts. + * + * \param[in,out] spi Pointer to the HAL SPI instance. + * \param[in] char_size The char size (~32, recommended 8). + * + * \return Operation status. + * \retval 0 Success. + * \retval <0 Error. + */ +int32_t spi_s_sync_set_char_size(struct spi_s_sync_descriptor *spi, const enum spi_char_size char_size); + +/** \brief Set SPI transfer data order + * + * Note that the SPI must be disabled to change data order. + * + * \param[in,out] spi Pointer to the HAL SPI instance. + * \param[in] dord The data order: send LSB/MSB first. + * + * \return Operation status. + * \retval 0 Success. + * \retval <0 Error. + */ +int32_t spi_s_sync_set_data_order(struct spi_s_sync_descriptor *spi, const enum spi_data_order dord); + +/** \brief Enable/disable break on SS desert detection + * + * \param[in,out] spi Pointer to the HAL SPI instance. + * \param[in] enable Set to \c true to break R/W loop on SS desert. + */ +void spi_s_sync_break_on_ss_detect(struct spi_s_sync_descriptor *spi, const bool enable); + +/** \brief Write/read at the same time + * + * \param[in,out] spi Pointer to the HAL SPI instance. + * \param[in] xfer Pointer to the transfer information (\ref spi_xfer). + * + * \return Operation result. + * \retval <0 Error. + * \retval >=0 Number of characters transferred. + */ +int32_t spi_s_sync_transfer(struct spi_s_sync_descriptor *spi, const struct spi_xfer *xfer); + +/** + * \brief Return I/O descriptor for this SPI instance + * + * This function will return an I/O instance for this SPI driver instance + * + * \param[in] spi An SPI slave descriptor, which is used to communicate through + * SPI + * \param[in] io A pointer to an I/O descriptor pointer type + * + * \return Error code. + * \retval 0 No error detected + * \retval <0 Error code + */ +int32_t spi_s_sync_get_io_descriptor(struct spi_s_sync_descriptor *spi, struct io_descriptor **io); + +/** \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t spi_s_sync_get_version(void); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* _HAL_SPI_S_SYNC_H_INCLUDED */ diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/src/hal_spi_s_sync.c b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/src/hal_spi_s_sync.c new file mode 100644 index 0000000..0498769 --- /dev/null +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/hal/src/hal_spi_s_sync.c @@ -0,0 +1,262 @@ +/** + * \file + * + * \brief I/O SPI related functionality implementation. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_atomic.h" +#include "hal_spi_s_sync.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Driver version + */ +#define SPI_S_SYNC_DRIVER_VERSION 0x00000001u + +/** Enable TX in transfer. */ +#define SPI_XFER_TX_EN (1u << 0) +/** Enable RX in transfer. */ +#define SPI_XFER_RX_EN (1u << 1) + +/** + * \brief Transfer data + * \param[in, out] dev Pointer to the SPI device instance. + * \param[in] xfer Pointer to the transfer struct instance. + * \param[in] flags control options. + * \return Error or number of characters transferred. + * \retval <0 Error. + * \retval >=0 Number of characters transferred. + */ +static int32_t _spi_s_sync_xfer(struct spi_s_sync_descriptor *spi, const struct spi_xfer *xfer, const uint8_t flags) +{ + uint32_t txcnt, rxcnt; + union { + uint16_t u16; + uint8_t u8[4]; + } tmp; + uint32_t n_bytes; + + ASSERT(spi && xfer); + + if (xfer->size == 0) { + return 0; + } + + n_bytes = xfer->size; + if (spi->dev.char_size > 1) { + n_bytes <<= 1; + } + + tmp.u16 = 0; + for (txcnt = 0, rxcnt = 0; txcnt < n_bytes && rxcnt < n_bytes;) { + if (_spi_s_sync_is_error(&spi->dev)) { + return ERR_IO; + } + if ((flags & SPI_XFER_TX_EN) && _spi_s_sync_is_tx_ready(&spi->dev)) { + tmp.u8[0] = xfer->txbuf[txcnt++]; + if (spi->dev.char_size > 1) { + tmp.u8[1] = xfer->txbuf[txcnt++]; + } + _spi_s_sync_write_one(&spi->dev, tmp.u16); + } + if ((flags & SPI_XFER_RX_EN) && _spi_s_sync_is_rx_ready(&spi->dev)) { + tmp.u16 = _spi_s_sync_read_one(&spi->dev); + + if (xfer->rxbuf) { + xfer->rxbuf[rxcnt++] = tmp.u8[0]; + if (spi->dev.char_size > 1) { + xfer->rxbuf[rxcnt++] = tmp.u8[1]; + } + } + } + if (spi->break_on_ss_det && _spi_s_sync_is_ss_deactivated(&spi->dev)) { + break; + } + } + + if (spi->dev.char_size <= 1) { + return (flags & SPI_XFER_RX_EN) ? rxcnt : txcnt; + } + return ((flags & SPI_XFER_RX_EN) ? rxcnt : txcnt) >> 1; +} + +/** \brief Do SPI data write + * + * Register background buffer to transmit data. + * + * It never blocks and return quickly, user check status or set callback to + * know when data is sent. + * + * \param[in] io Pointer to the I/O descriptor. + * \param[in] buf Pointer to the buffer to store data to write. + * \param[in] size Size of the data in number of characters. + * \return Operation status. + * \retval 0 Success. + * \retval -1 Busy, transfer in progress. + * \retval -3 Parameter error. + */ +static int32_t _spi_s_sync_io_write(struct io_descriptor *const io, const uint8_t *const buf, const uint16_t size) +{ + struct spi_s_sync_descriptor *spi; + struct spi_xfer xfer; + + ASSERT(io); + + spi = CONTAINER_OF(io, struct spi_s_sync_descriptor, io); + + xfer.txbuf = (uint8_t *)buf; + xfer.size = size; + return _spi_s_sync_xfer(spi, &xfer, SPI_XFER_TX_EN); +} + +/** \brief Do SPI read from ring-buffer (asynchronously) + * + * Read available characters from ring-buffer and return number of characters + * read. + * + * It never blocks and return quickly, user check status or set callback to + * know when data is ready. + * + * \param[in] io Pointer to the I/O descriptor. + * \param[out] buf Pointer to the buffer to store read data, + NULL to discard data. + * \param[in] size Size of the data in number of characters. + * \return Read result. + * \retval n Number of characters read. + * \retval <0 Error. + */ +static int32_t _spi_s_sync_io_read(struct io_descriptor *const io, uint8_t *const buf, const uint16_t size) +{ + struct spi_s_sync_descriptor *spi; + struct spi_xfer xfer; + + ASSERT(io); + + spi = CONTAINER_OF(io, struct spi_s_sync_descriptor, io); + + xfer.rxbuf = (uint8_t *)buf; + xfer.size = size; + return _spi_s_sync_xfer(spi, &xfer, SPI_XFER_RX_EN); +} + +/** + * \brief Initialize the SPI HAL instance function pointer for HPL APIs. + */ +void spi_s_sync_set_func_ptr(struct spi_s_sync_descriptor *spi, void *const func) +{ + ASSERT(spi); + spi->func = (struct _spi_s_sync_hpl_interface *)func; +} + +int32_t spi_s_sync_init(struct spi_s_sync_descriptor *spi, void *const hw) +{ + int32_t rc; + ASSERT(spi && hw); + rc = _spi_s_sync_init(&spi->dev, hw); + + if (rc < 0) { + return rc; + } + + spi->io.read = _spi_s_sync_io_read; + spi->io.write = _spi_s_sync_io_write; + + return ERR_NONE; +} + +void spi_s_sync_deinit(struct spi_s_sync_descriptor *spi) +{ + ASSERT(spi); + _spi_s_sync_deinit(&spi->dev); +} + +void spi_s_sync_enable(struct spi_s_sync_descriptor *spi) +{ + ASSERT(spi); + _spi_s_sync_enable(&spi->dev); +} + +void spi_s_sync_disable(struct spi_s_sync_descriptor *spi) +{ + ASSERT(spi); + _spi_s_sync_disable(&spi->dev); +} + +int32_t spi_s_sync_set_mode(struct spi_s_sync_descriptor *spi, const enum spi_transfer_mode mode) +{ + ASSERT(spi); + return _spi_s_sync_set_mode(&spi->dev, mode); +} + +int32_t spi_s_sync_set_char_size(struct spi_s_sync_descriptor *spi, const enum spi_char_size char_size) +{ + ASSERT(spi); + return _spi_s_sync_set_char_size(&spi->dev, char_size); +} + +int32_t spi_s_sync_set_data_order(struct spi_s_sync_descriptor *spi, const enum spi_data_order dord) +{ + ASSERT(spi); + return _spi_s_sync_set_data_order(&spi->dev, dord); +} + +void spi_s_sync_break_on_ss_detect(struct spi_s_sync_descriptor *spi, const bool enable) +{ + ASSERT(spi); + + spi->break_on_ss_det = enable; +} + +int32_t spi_s_sync_transfer(struct spi_s_sync_descriptor *spi, const struct spi_xfer *xfer) +{ + return _spi_s_sync_xfer(spi, xfer, SPI_XFER_RX_EN | SPI_XFER_TX_EN); +} + +int32_t spi_s_sync_get_io_descriptor(struct spi_s_sync_descriptor *spi, struct io_descriptor **io) +{ + ASSERT(spi && io); + *io = &spi->io; + return ERR_NONE; +} + +uint32_t spi_s_sync_get_version(void) +{ + return SPI_S_SYNC_DRIVER_VERSION; +} + +#ifdef __cplusplus +} +#endif diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/interrupts.h b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/interrupts.h index cb1bb14..793ae58 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/interrupts.h +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/interrupts.h @@ -19,11 +19,13 @@ void TC0_Handler( void ){ if (TC0->COUNT8.INTFLAG.bit.OVF && TC0->COUNT8.INTENSET.bit.OVF) { TC0->COUNT8.INTFLAG.bit.OVF = 0x01; + #ifdef _MASTER if ((ecat_state == wait2)|(ecat_state == wait)) { ecat_state= write_fifo; run_ECAT =true; } + #endif //MASTER Motor1.timerflags.motor_telemetry_flag = true; } if (TC0->COUNT8.INTFLAG.bit.MC0 && TC0->COUNT8.INTENSET.bit.MC0) diff --git a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/main.c b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/main.c index 1aaae90..1a6ef50 100644 --- a/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/main.c +++ b/2_Motor_Master_D51/Two_Motor_D51/Two_Motor_D51/main.c @@ -4,21 +4,23 @@ // Header Files // ---------------------------------------------------------------------- - -#include "EtherCAT_QSPI.h" - //#include "MSIF_master.h" - #include "configuration.h" #include "interrupts.h" #include "bldc.h" #include "bldc_types.h" -#include "EtherCAT_SlaveDef.h" + #include "statemachine.h" - - #include "angle_sensors.h" + +#ifdef _MASTER +#include "EtherCAT_SlaveDef.h" #include "ADS1299.h" +#endif // MASTER + +#ifdef _SLAVE +#include "MSIF_slave.h" +#endif // SLAVE @@ -83,13 +85,6 @@ void enable_NVIC_IRQ(void) //NVIC_SetPriority(TCC0_0_IRQn, 3); //NVIC_EnableIRQ(EIC_5_IRQn); - - - /* Reset Latch Interrupt */ - ext_irq_register(PIN_PB30, M1_RESET_BAR); - ext_irq_register(PIN_PB31, M2_RESET_BAR); - NVIC_EnableIRQ(EIC_14_IRQn); - NVIC_EnableIRQ(EIC_15_IRQn); } void APPLICATION_StateMachine(void) @@ -107,9 +102,18 @@ void APPLICATION_StateMachine(void) case SYSTEM_INIT: /* Toggle driver reset Latch */ gpio_set_pin_level(M1_RST, true); + delay_us(100); gpio_set_pin_level(M1_RST, false); + delay_us(100); gpio_set_pin_level(M2_RST, true); + delay_us(100); gpio_set_pin_level(M2_RST, false); + delay_us(100); + /*/* Reset Latch Interrupt */ + ext_irq_register(PIN_PB30, M1_RESET_BAR); + ext_irq_register(PIN_PB31, M2_RESET_BAR); + NVIC_EnableIRQ(EIC_14_IRQn); + NVIC_EnableIRQ(EIC_15_IRQn); /* Update State Variables */ applicationStatus.previousstate = applicationStatus.currentstate; applicationStatus.currentstate = SYSTEM_IDLE; @@ -154,10 +158,14 @@ int main(void) __disable_irq(); /* BLDC INIT */ - BldcInitStruct(&Motor1, &FH_22mm24BXTR); - BldcInitStruct(&Motor2, &FH_32mm12BXTR); - //Motor2.VdcBus_pu = 12.0; - //Motor2.VoneByDcBus_pu = 1.0/Motor2.VdcBus_pu; + #ifdef _MASTER + BldcInitStruct(&Motor1, &FH_22mm24BXTR); + BldcInitStruct(&Motor2, &FH_32mm12BXTR); + #else + BldcInitStruct(&Motor1, &FH_22mm24BXTR); + BldcInitStruct(&Motor2, &FH_22mm24BXTR); + #endif // + Motor1.readHall = &readHallSensorM1; Motor2.readHall = &readHallSensorM2; @@ -165,38 +173,47 @@ int main(void) read_zero_current_offset_value(&Motor1, &Motor2); /* Configure Hardware */ - config_qspi(); + #ifdef _MASTER + config_qspi(); + /* ECAT State Machine First run */ + ECAT_STATE_MACHINE(); + #else + slave_event_system_config(); + #endif // _MASTER + configure_tcc_pwm(); adc_sync_enable_channel(&ADC_1, 6); - - /* SPI Config */ + + /* Master Slave Interface init */ boardToBoardTransferInit(); /* DMA Configs */ init_dma(); - - /* ECAT State Machine First run */ - ECAT_STATE_MACHINE(); - //angle_sensor_init(); - initialize_ads(); + /* External IRQ Config */ custom_logic_enable(); - - delay_us(20); + /* ADS1299 Initialisation */ + #ifdef _MASTER + initialize_ads(); + delay_us(100); ADS1299_START(); - delay_us(20); + delay_us(100); + #endif // _MASTER + /* ADS Result Ready Interrupt, active low */ __enable_irq(); /* Enable Reception * Enable RX channels at startup, Linked to itself so never ends */ - _dma_enable_transaction(CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL, false); - _dma_enable_transaction(CONF_SERCOM_2_SPI_M_DMA_RX_CHANNEL, false); + _dma_enable_transaction(CONF_SERCOM_1_SPI_DMA_RX_CHANNEL, false); + #ifdef _MASTER + _dma_enable_transaction(CONF_SERCOM_2_SPI_DMA_RX_CHANNEL, false); + #endif //MASTER /* Clear Exint Flag */ - //EIC->INTFLAG.bit.EXTINT = (1<<2); + EIC->INTFLAG.bit.EXTINT = (1<<2); //ext_irq_register(GPIO_PIN(ADS_DATA_RDY), ADS1299_dataReadyISR); enable_NVIC_IRQ(); @@ -206,21 +223,17 @@ int main(void) if (Motor1.timerflags.adc_readings_ready_tic) {process_currents();} if (Motor1.timerflags.motor_telemetry_flag) { - - Motor1.timerflags.motor_telemetry_flag = false; - - //DMAC->Channel[CONF_SERCOM_1_SPI_M_DMA_RX_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; - if (!(DMAC->Channel[CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL].CHCTRLA.bit.ENABLE)) { + Motor1.timerflags.motor_telemetry_flag = false; + if (!(DMAC->Channel[CONF_SERCOM_1_SPI_DMA_TX_CHANNEL].CHCTRLA.bit.ENABLE)) { /* Enable */ - DMAC->Channel[CONF_SERCOM_1_SPI_M_DMA_TX_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; + DMAC->Channel[CONF_SERCOM_1_SPI_DMA_TX_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; } - - if(!(DMAC->Channel[CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL].CHCTRLA.bit.ENABLE)) { - /* Enable */ - DMAC->Channel[CONF_SERCOM_2_SPI_M_DMA_TX_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; - - } - + #ifdef _MASTER + if(!(DMAC->Channel[CONF_SERCOM_2_SPI_DMA_TX_CHANNEL].CHCTRLA.bit.ENABLE)) { + /* Enable */ + DMAC->Channel[CONF_SERCOM_2_SPI_DMA_TX_CHANNEL].CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE; + } + #endif //MASTER update_telemetry(); update_setpoints(); } @@ -231,10 +244,10 @@ int main(void) exec_commutation(&Motor1); exec_commutation(&Motor2); } - - - + + #ifdef _MASTER if(run_ECAT) {ECAT_STATE_MACHINE();} + #endif // _MASTER } } diff --git a/Screenshots/Event Manual Config/CH0.PNG b/Screenshots/Event Manual Config/CH0.PNG new file mode 100644 index 0000000000000000000000000000000000000000..dcc674bfcd8bc9f69e33a727cecc6938ab595658 GIT binary patch literal 11381 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

uC-}D^vP%MOB;~TkG6vIJl>;|#|)5*Q}X+RC8 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 STF6#m6b%)ia+RW0#D4)e@H4Og literal 0 HcmV?d00001 diff --git a/Screenshots/Event Manual Config/CH1.PNG b/Screenshots/Event Manual Config/CH1.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1b4a9ddd2d4eed39ecc77128bc6eed67badb97d3 GIT binary patch literal 12528 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 literal 0 HcmV?d00001 diff --git a/Screenshots/Event Manual Config/CH11.PNG b/Screenshots/Event Manual Config/CH11.PNG new file mode 100644 index 0000000000000000000000000000000000000000..563326f8a099ee66284762bd595dd0c03550577c GIT binary patch literal 12333 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 literal 0 HcmV?d00001 diff --git a/Screenshots/Event Manual Config/CH2.PNG b/Screenshots/Event Manual Config/CH2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..22229fda6e2e92157a1c8207a0ce84a529ed695d GIT binary patch literal 12384 zcmbVzXIN8Rw=E^~E(ju_BSpF(gf2)^siLCNyFh@@d+#ks2kBi@njjq{Q~?2{Na&$P zq!WSA@5c9izw>?P+~?fqxj#sGcJ|tPuQlcvW6rsV*3nXGhjONw?e{3A(?()$IO> z66E%NVlJuqz#-s8>cO4bJD4_~Dr3)fp9Nu#<){AMPo6znJ*x8Cv04@34fglYlvqe@~jyl(c|vQN#<769CC*({9gYy?@CTd{<|x;eV*6UIE0P3&_`VbrgM*5 zBbR*eM@4vO8KLPy^zygqW13khXO1(kB_r5QUHP~9xr!)C5=uqt5WO-SdF(DP_@bJO zkPr!1re89|KGD`Uya_{0Ra>y0ogJ6#Ci5_vFBaIOcgSRU>~%|@-a;S}HJ2j}U|~~K zwbk$6)AouXrdpkZWu9c1g^p{p7q{+Kvv(DshjeIvJR&THAQN9V-rZz6U-{(8Rg068Ez?J$X7 zq_IBXtI;&BlAE4dyn0L8N%iF+_40w)TMsqgbR6j>iWv_KY&UfH+s)VE5C-{)vFquC zhAEn2BA7%q)Gz+3u)aK>nAq>z^DM6{6bnjNRDVhe*G^#kv&1Bk zHQ6-oI+9A-ti{ZT?D%QLl{=)`dOAjTNOH@lqqxvCOg&J!=^lm8&OO(6T`V}EKYs@GRv4HLF5a)UJeT&` zi!a&z^)6M!s@JX2dG@(i9QSb(gZF zLG{f1g;5v*-%kSN*O~)I&96& z)+G#K4QTKZm4(dVE0tH%jfHH8 z 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 MFUAI6pm-2eap literal 0 HcmV?d00001 diff --git a/Twincat/MotorData/.vs/MotorData/v15/.suo b/Twincat/MotorData/.vs/MotorData/v15/.suo index ef574d913c0ea213ce69f4458663427ed1c83222..4438805ba680c4c068cba61c5f96defc473febd5 100644 GIT binary patch delta 1258 zcma))Uue@;6vywm`Qz``VvRLzLi#WNnigx9idL&8+G=%*jV4;Bq;qRP8I}tENvztc zX^m)6n&fx%r8+dfb`N{dt@$w@_SC5l4ulmEL>R*dhfiX~6!xOoxm#K)i1>rgIp==w zmvhhMcjJ$EJfTlDVUt(3niwl$jB(<9KA)$=fasqHRd6|Y_kJ!s_7uvs7{3f4A?PhF zOK6*%`Qk#>Q(jo8jg&#5IIJ1a0NtiBR~?k!B+l z-YchaZ`;HjU0TeDuuUd;);fC=N1?@{LKa;N^J??F`gEaQkPcZKJ83c7WcF+)X%$2b zVaH)}4FvE<$)y)QoRaFT8)&1IXd^Zfn}~J-O=Z@q4k|<^;SSELLsXZhLu00af_R2< zoY4M}B_qa5?3%sgxlT24JWyoPOy(ClIZWF=F9nPgEg@+d6k85QZ%!W6Ho3!Zo6;La=y2_Y!a-+tV z4K2n8exEk!?_P}dL(kRV7g=8dgocy;*6djyU}n5SxwZn6UrBiXx?hP;(vOvcFVyv18S292J+&Ags=|rk3ezuSsoit@;J!b^Q>Od;HrAq? zuSajE)gT@-!_Ap>rk%|ZwwK>~^@H!>n)ZeD7ciAMq9(X<=})|xcB{jXZM84L#~szU zzU^K%=<}lQ=z~v9qg4)W0PKqXKgjn{mozuP!>Aaby0@Xndw9p{<)^=kg}3(x_8#2W z)YsY5vg^O07*6kB`;n<)A5MjB0~UPMCt=OV82*}egB`z2ZvzLu90`CEo0ART!bmaz zZv2U2Ext=O>pZLun^OUNlp4T9YAZD2vrBb2IpWd&N;|na%0IWOWh0wn(CCSY}9uey140UASqCGB9J@_WG3&ZLPoXM1GH`NII3#}2*ZvX%Q delta 928 zcmZ9KUr3Wt7{J}Ciw)LK|iFDxiz0dQ$&o|D_ciaP#dx?+a zq;VEn2FA1`h4%*n0nt?v&d0ThTox!g|LxEs@^2 z&5MkNynnRmsr5)`5Kp!EztDB^rNnW}iZJc&B~?e%6DNq1L<4aZ&zLNFvDfqDnh6{> z)u)QaH8P_1QLQ3w5dDOk@bC`p;)l3L?euqyic5`98A|Sk>at%Xn;a=87-2C;-s-2y&8>En4-}8C8507TKKmrNLLcai1Kay zYSQ7o)sU_w4v*F@$a*g8B{`1EF&tZ>42r?HqEg#wTCh*~6RYMP^9CdGS)>zjR z9Mgj_B~YkRBR7AC#$af^d>|G}8*Iv4!nSSP#4 zF0*XfX!s|oLQ`sP@Q|T8w~00I7pt=cuk%ZzGY4_xUbn(!Kgj9a zGxG`W_%h^Kkc%ZOx@*GKQ4OZ7-N$FX3`oWO>rP0+{`I|(jt@v%@Hag(u)>?GvN9X? zd!1m%3SSj2dHe9&S|w!R#~C{=uGy5&zI2Y@D#Mzw7^Tkk5M+lWZ*T>E1poqa4#%5$ z9Uglk4*B2V>1nGWeVIX)Wts5=)v}5dj!burnV`f7V&K>sI3^<0Y(hJB3J&P(TV4B; Wakv0D)x8JZ!wEP!o1^sP4Z}Y%DPRo%