From 5fbe97fa5fa83d2b7326dbf3a6c0b6ad83ac119d Mon Sep 17 00:00:00 2001 From: NawfalMotii79 Date: Mon, 9 Mar 2026 00:17:39 +0000 Subject: [PATCH] Add files via upload --- .../ADAR1000_Manager.cpp | 757 + .../9_1_1_C_Cpp_Libraries/ADAR1000_Manager.h | 222 + .../9_1_1_C_Cpp_Libraries/ADS7830.H | 86 + .../9_1_1_C_Cpp_Libraries/ADS7830.c | 211 + .../9_1_1_C_Cpp_Libraries/BMP180.cpp | 462 + .../9_1_1_C_Cpp_Libraries/BMP180.h | 156 + .../9_1_1_C_Cpp_Libraries/DA5578.c | 397 + .../9_1_1_C_Cpp_Libraries/DAC5578.H | 91 + .../9_1_1_C_Cpp_Libraries/GY_85_HAL.c | 121 + .../9_1_1_C_Cpp_Libraries/GY_85_HAL.h | 25 + .../9_1_1_C_Cpp_Libraries/RadarSettings.cpp | 113 + .../9_1_1_C_Cpp_Libraries/RadarSettings.h | 53 + .../9_1_1_C_Cpp_Libraries/TinyGPS++.cpp | 509 + .../9_1_1_C_Cpp_Libraries/TinyGPS++.h | 289 + .../9_1_1_C_Cpp_Libraries/TinyGPSPlus.h | 26 + .../9_1_1_C_Cpp_Libraries/USBHandler.cpp | 93 + .../9_1_1_C_Cpp_Libraries/USBHandler.h | 46 + .../9_1_1_C_Cpp_Libraries/ad9523.c | 731 + .../9_1_1_C_Cpp_Libraries/ad9523.h | 509 + .../9_1_1_C_Cpp_Libraries/adar1000.c | 693 + .../9_1_1_C_Cpp_Libraries/adar1000.h | 294 + .../9_1_1_C_Cpp_Libraries/adf4382.c | 2120 ++ .../9_1_1_C_Cpp_Libraries/adf4382.h | 809 + .../9_1_1_C_Cpp_Libraries/adf4382a_manager.c | 510 + .../9_1_1_C_Cpp_Libraries/adf4382a_manager.h | 85 + .../9_1_1_C_Cpp_Libraries/errno.h | 100 + .../9_1_1_C_Cpp_Libraries/gps_handler.cpp | 119 + .../9_1_1_C_Cpp_Libraries/gps_handler.h | 33 + .../platform_noos_stm32.H | 25 + .../platform_noos_stm32.c | 64 + .../9_1_1_C_Cpp_Libraries/stm32_delay.c | 17 + .../9_1_1_C_Cpp_Libraries/stm32_delay.h | 10 + .../9_1_1_C_Cpp_Libraries/stm32_dma.c | 287 + .../9_1_1_C_Cpp_Libraries/stm32_dma.h | 101 + .../9_1_1_C_Cpp_Libraries/stm32_gpio.c | 394 + .../9_1_1_C_Cpp_Libraries/stm32_gpio.h | 69 + .../9_1_1_C_Cpp_Libraries/stm32_gpio_irq.c | 463 + .../9_1_1_C_Cpp_Libraries/stm32_gpio_irq.h | 64 + .../9_1_1_C_Cpp_Libraries/stm32_hal.h | 9 + .../9_1_1_C_Cpp_Libraries/stm32_i2c.c | 227 + .../9_1_1_C_Cpp_Libraries/stm32_i2c.h | 64 + .../9_1_1_C_Cpp_Libraries/stm32_irq.c | 701 + .../9_1_1_C_Cpp_Libraries/stm32_irq.h | 44 + .../9_1_1_C_Cpp_Libraries/stm32_pwm.c | 1114 ++ .../9_1_1_C_Cpp_Libraries/stm32_pwm.h | 151 + .../9_1_1_C_Cpp_Libraries/stm32_spi.c | 53 + .../9_1_1_C_Cpp_Libraries/stm32_spi.h | 9 + .../9_1_1_C_Cpp_Libraries/stm32_timer.c | 352 + .../9_1_1_C_Cpp_Libraries/stm32_timer.h | 63 + .../9_1_1_C_Cpp_Libraries/stm32_uart.c | 302 + .../9_1_1_C_Cpp_Libraries/stm32_uart.h | 73 + .../stm32f7xx_hal_conf.h | 484 + .../9_1_1_C_Cpp_Libraries/stm32f7xx_hal_msp.c | 567 + .../9_1_1_C_Cpp_Libraries/stm32f7xx_it.c | 217 + .../9_1_1_C_Cpp_Libraries/stm32f7xx_it.h | 67 + .../9_1_1_C_Cpp_Libraries/syscalls.c | 176 + .../9_1_1_C_Cpp_Libraries/sysmem.c | 79 + .../9_1_1_C_Cpp_Libraries/system_stm32f7xx.c | 259 + .../9_1_2_C_Cpp_Algorithms/STM32_ALGO.docx | 0 .../9_1_3_C_Cpp_Code/main.cpp | 2411 +++ .../9_1_3_C_Cpp_Code/main.h | 175 + 9_Firmware/9_2_FPGA/ad9484_interface_400m.v | 98 + 9_Firmware/9_2_FPGA/cdc_modules.v | 237 + 9_Firmware/9_2_FPGA/chirp_lut_init.v | 244 + .../9_2_FPGA/chirp_memory_loader_param.v | 130 + .../9_2_FPGA/cic_decimator_4x_enhanced.v | 300 + 9_Firmware/9_2_FPGA/dac_interface_single.v | 26 + 9_Firmware/9_2_FPGA/ddc_400m.v | 425 + 9_Firmware/9_2_FPGA/ddc_input_interface.v | 55 + 9_Firmware/9_2_FPGA/doppler_processor.v | 305 + 9_Firmware/9_2_FPGA/edge_detector.v | 26 + 9_Firmware/9_2_FPGA/fft_1024_forward.v | 124 + 9_Firmware/9_2_FPGA/fft_1024_inverse.v | 97 + 9_Firmware/9_2_FPGA/fir_lowpass.v | 124 + .../9_2_FPGA/frequency_matched_filter.v | 137 + 9_Firmware/9_2_FPGA/latency_buffer_2159.v | 107 + 9_Firmware/9_2_FPGA/long_chirp_seg0_i.mem | 1024 + 9_Firmware/9_2_FPGA/long_chirp_seg0_q.mem | 1024 + 9_Firmware/9_2_FPGA/long_chirp_seg1_i.mem | 1024 + 9_Firmware/9_2_FPGA/long_chirp_seg1_q.mem | 1024 + 9_Firmware/9_2_FPGA/long_chirp_seg2_i.mem | 1024 + 9_Firmware/9_2_FPGA/long_chirp_seg2_q.mem | 1024 + 9_Firmware/9_2_FPGA/lvds_to_cmos_400m.v | 45 + .../9_2_FPGA/matched_filter_multi_segment.v | 410 + 9_Firmware/9_2_FPGA/nco_400m_enhanced.v | 117 + 9_Firmware/9_2_FPGA/plfm_chirp_controller.v | 801 + 9_Firmware/9_2_FPGA/radar_receiver_final.v | 353 + 9_Firmware/9_2_FPGA/radar_transmitter.v | 157 + 9_Firmware/9_2_FPGA/short_chirp_i.mem | 50 + 9_Firmware/9_2_FPGA/short_chirp_q.mem | 50 + 9_Firmware/9_3_GUI/GUI_V1.py | 41 + 9_Firmware/9_3_GUI/GUI_V2.py | 1059 + 9_Firmware/9_3_GUI/GUI_V3.py | 1146 ++ 9_Firmware/9_3_GUI/GUI_V4.py | 1427 ++ 9_Firmware/9_3_GUI/GUI_V4_2_CSV.py | 678 + 9_Firmware/9_3_GUI/GUI_V5.py | 1542 ++ 9_Firmware/9_3_GUI/GUI_V5_Demo.py | 1356 ++ 9_Firmware/9_3_GUI/GUI_versions.txt | 6 + 9_Firmware/9_3_GUI/test_radar_data.csv | 16385 ++++++++++++++++ 99 files changed, 52953 insertions(+) create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADAR1000_Manager.cpp create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADAR1000_Manager.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADS7830.H create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADS7830.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/BMP180.cpp create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/BMP180.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/DA5578.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/DAC5578.H create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/GY_85_HAL.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/GY_85_HAL.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.cpp create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPS++.cpp create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPS++.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPSPlus.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/USBHandler.cpp create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/USBHandler.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ad9523.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ad9523.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adar1000.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adar1000.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/errno.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/gps_handler.cpp create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/gps_handler.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/platform_noos_stm32.H create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/platform_noos_stm32.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_delay.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_delay.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_dma.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_dma.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio_irq.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio_irq.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_hal.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_i2c.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_i2c.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_irq.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_irq.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_pwm.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_pwm.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_spi.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_spi.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_timer.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_timer.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_uart.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_uart.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_hal_conf.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_hal_msp.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_it.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_it.h create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/syscalls.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/sysmem.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/system_stm32f7xx.c create mode 100644 9_Firmware/9_1_Microcontroller/9_1_2_C_Cpp_Algorithms/STM32_ALGO.docx create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp create mode 100644 9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.h create mode 100644 9_Firmware/9_2_FPGA/ad9484_interface_400m.v create mode 100644 9_Firmware/9_2_FPGA/cdc_modules.v create mode 100644 9_Firmware/9_2_FPGA/chirp_lut_init.v create mode 100644 9_Firmware/9_2_FPGA/chirp_memory_loader_param.v create mode 100644 9_Firmware/9_2_FPGA/cic_decimator_4x_enhanced.v create mode 100644 9_Firmware/9_2_FPGA/dac_interface_single.v create mode 100644 9_Firmware/9_2_FPGA/ddc_400m.v create mode 100644 9_Firmware/9_2_FPGA/ddc_input_interface.v create mode 100644 9_Firmware/9_2_FPGA/doppler_processor.v create mode 100644 9_Firmware/9_2_FPGA/edge_detector.v create mode 100644 9_Firmware/9_2_FPGA/fft_1024_forward.v create mode 100644 9_Firmware/9_2_FPGA/fft_1024_inverse.v create mode 100644 9_Firmware/9_2_FPGA/fir_lowpass.v create mode 100644 9_Firmware/9_2_FPGA/frequency_matched_filter.v create mode 100644 9_Firmware/9_2_FPGA/latency_buffer_2159.v create mode 100644 9_Firmware/9_2_FPGA/long_chirp_seg0_i.mem create mode 100644 9_Firmware/9_2_FPGA/long_chirp_seg0_q.mem create mode 100644 9_Firmware/9_2_FPGA/long_chirp_seg1_i.mem create mode 100644 9_Firmware/9_2_FPGA/long_chirp_seg1_q.mem create mode 100644 9_Firmware/9_2_FPGA/long_chirp_seg2_i.mem create mode 100644 9_Firmware/9_2_FPGA/long_chirp_seg2_q.mem create mode 100644 9_Firmware/9_2_FPGA/lvds_to_cmos_400m.v create mode 100644 9_Firmware/9_2_FPGA/matched_filter_multi_segment.v create mode 100644 9_Firmware/9_2_FPGA/nco_400m_enhanced.v create mode 100644 9_Firmware/9_2_FPGA/plfm_chirp_controller.v create mode 100644 9_Firmware/9_2_FPGA/radar_receiver_final.v create mode 100644 9_Firmware/9_2_FPGA/radar_transmitter.v create mode 100644 9_Firmware/9_2_FPGA/short_chirp_i.mem create mode 100644 9_Firmware/9_2_FPGA/short_chirp_q.mem create mode 100644 9_Firmware/9_3_GUI/GUI_V1.py create mode 100644 9_Firmware/9_3_GUI/GUI_V2.py create mode 100644 9_Firmware/9_3_GUI/GUI_V3.py create mode 100644 9_Firmware/9_3_GUI/GUI_V4.py create mode 100644 9_Firmware/9_3_GUI/GUI_V4_2_CSV.py create mode 100644 9_Firmware/9_3_GUI/GUI_V5.py create mode 100644 9_Firmware/9_3_GUI/GUI_V5_Demo.py create mode 100644 9_Firmware/9_3_GUI/GUI_versions.txt create mode 100644 9_Firmware/9_3_GUI/test_radar_data.csv diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADAR1000_Manager.cpp b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADAR1000_Manager.cpp new file mode 100644 index 0000000..cc969b7 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADAR1000_Manager.cpp @@ -0,0 +1,757 @@ +// ADAR1000_Manager.cpp +#include "main.h" +#include "stm32f7xx_hal.h" +#include "ADAR1000_Manager.h" +#include +#include + +extern SPI_HandleTypeDef hspi1; +extern UART_HandleTypeDef huart3; + +// Chip Select GPIO definitions +static const struct { + GPIO_TypeDef* port; + uint16_t pin; +} CHIP_SELECTS[4] = { + {GPIOA, GPIO_PIN_0}, // ADAR1000 #1 + {GPIOA, GPIO_PIN_1}, // ADAR1000 #2 + {GPIOA, GPIO_PIN_2}, // ADAR1000 #3 + {GPIOA, GPIO_PIN_3} // ADAR1000 #4 +}; + +// Vector Modulator lookup tables +const uint8_t ADAR1000Manager::VM_I[128] = { + // ... (same as in your original file) +}; + +const uint8_t ADAR1000Manager::VM_Q[128] = { + // ... (same as in your original file) +}; + +const uint8_t ADAR1000Manager::VM_GAIN[128] = { + // ... (same as in your original file) +}; + +ADAR1000Manager::ADAR1000Manager() { + for (int i = 0; i < 4; ++i) { + devices_.push_back(std::make_unique(i)); + } +} + +ADAR1000Manager::~ADAR1000Manager() { + // Automatic cleanup by unique_ptr +} + +// System Management +bool ADAR1000Manager::powerUpSystem() { + const uint8_t msg[] = "Starting System Power-Up Sequence...\r\n"; + HAL_UART_Transmit(&huart3, msg, sizeof(msg) - 1, 1000); + + // Power-up sequence steps... + HAL_GPIO_WritePin(EN_P_3V3_VDD_SW_GPIO_Port, EN_P_3V3_VDD_SW_Pin, GPIO_PIN_SET); + HAL_Delay(2); + + HAL_GPIO_WritePin(EN_P_3V3_SW_GPIO_Port, EN_P_3V3_SW_Pin, GPIO_PIN_SET); + HAL_Delay(2); + + // Initialize devices + if (!initializeAllDevices()) { + const uint8_t err[] = "ERROR: ADAR1000 initialization failed!\r\n"; + HAL_UART_Transmit(&huart3, err, sizeof(err) - 1, 1000); + return false; + } + + // Start in RX mode + switchToRXMode(); + + const uint8_t success[] = "System Power-Up Sequence Completed Successfully.\r\n"; + HAL_UART_Transmit(&huart3, success, sizeof(success) - 1, 1000); + return true; +} + +bool ADAR1000Manager::powerDownSystem() { + switchToRXMode(); + HAL_Delay(10); + + disablePASupplies(); + disableLNASupplies(); + HAL_GPIO_WritePin(EN_P_3V3_SW_GPIO_Port, EN_P_3V3_SW_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(EN_P_3V3_VDD_SW_GPIO_Port, EN_P_3V3_VDD_SW_Pin, GPIO_PIN_RESET); + + return true; +} + +// Mode Switching +void ADAR1000Manager::switchToTXMode() { + setLNABias(false); + delayUs(10); + enablePASupplies(); + delayUs(100); + setPABias(true); + delayUs(50); + setADTR1107Control(true); + + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_RX_ENABLES, 0x00, BROADCAST_OFF); + adarWrite(dev, REG_TX_ENABLES, 0x0F, BROADCAST_OFF); + adarSetTxBias(dev, BROADCAST_OFF); + devices_[dev]->current_mode = BeamDirection::TX; + } + current_mode_ = BeamDirection::TX; +} + +void ADAR1000Manager::switchToRXMode() { + setPABias(false); + delayUs(50); + disablePASupplies(); + delayUs(10); + setADTR1107Control(false); + enableLNASupplies(); + delayUs(50); + setLNABias(true); + delayUs(50); + + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_TX_ENABLES, 0x00, BROADCAST_OFF); + adarWrite(dev, REG_RX_ENABLES, 0x0F, BROADCAST_OFF); + devices_[dev]->current_mode = BeamDirection::RX; + } + current_mode_ = BeamDirection::RX; +} + +void ADAR1000Manager::fastTXMode() { + setADTR1107Control(true); + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_RX_ENABLES, 0x00, BROADCAST_OFF); + adarWrite(dev, REG_TX_ENABLES, 0x0F, BROADCAST_OFF); + devices_[dev]->current_mode = BeamDirection::TX; + } + current_mode_ = BeamDirection::TX; +} + +void ADAR1000Manager::fastRXMode() { + setADTR1107Control(false); + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_TX_ENABLES, 0x00, BROADCAST_OFF); + adarWrite(dev, REG_RX_ENABLES, 0x0F, BROADCAST_OFF); + devices_[dev]->current_mode = BeamDirection::RX; + } + current_mode_ = BeamDirection::RX; +} + +void ADAR1000Manager::pulseTXMode() { + setADTR1107Control(true); + last_switch_time_us_ = HAL_GetTick() * 1000; +} + +void ADAR1000Manager::pulseRXMode() { + setADTR1107Control(false); + last_switch_time_us_ = HAL_GetTick() * 1000; +} + +// Beam Steering +bool ADAR1000Manager::setBeamAngle(float angle_degrees, BeamDirection direction) { + uint8_t phase_settings[4]; + calculatePhaseSettings(angle_degrees, phase_settings); + + if (direction == BeamDirection::TX) { + setAllDevicesTXMode(); + } else { + setAllDevicesRXMode(); + } + + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + for (uint8_t ch = 0; ch < 4; ++ch) { + if (direction == BeamDirection::TX) { + adarSetTxPhase(dev, ch + 1, phase_settings[ch], BROADCAST_OFF); + adarSetTxVgaGain(dev, ch + 1, 0x7F, BROADCAST_OFF); + } else { + adarSetRxPhase(dev, ch + 1, phase_settings[ch], BROADCAST_OFF); + adarSetRxVgaGain(dev, ch + 1, 30, BROADCAST_OFF); + } + } + } + return true; +} + +bool ADAR1000Manager::setCustomBeamPattern(const uint8_t phase_settings[4], const uint8_t gain_settings[4], BeamDirection direction) { + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + for (uint8_t ch = 0; ch < 4; ++ch) { + if (direction == BeamDirection::TX) { + adarSetTxPhase(dev, ch + 1, phase_settings[ch], BROADCAST_OFF); + adarSetTxVgaGain(dev, ch + 1, gain_settings[ch], BROADCAST_OFF); + } else { + adarSetRxPhase(dev, ch + 1, phase_settings[ch], BROADCAST_OFF); + adarSetRxVgaGain(dev, ch + 1, gain_settings[ch], BROADCAST_OFF); + } + } + } + return true; +} + +// Beam Sweeping +void ADAR1000Manager::startBeamSweeping() { + beam_sweeping_active_ = true; + current_beam_index_ = 0; + last_beam_update_time_ = HAL_GetTick(); +} + +void ADAR1000Manager::stopBeamSweeping() { + beam_sweeping_active_ = false; +} + +void ADAR1000Manager::updateBeamPosition() { + if (!beam_sweeping_active_) return; + + uint32_t current_time = HAL_GetTick(); + const std::vector& sequence = + (current_mode_ == BeamDirection::TX) ? tx_beam_sequence_ : rx_beam_sequence_; + + if (sequence.empty()) return; + + if (current_time - last_beam_update_time_ >= beam_dwell_time_ms_) { + const BeamConfig& beam = sequence[current_beam_index_]; + setCustomBeamPattern(beam.phase_settings, beam.gain_settings, current_mode_); + + current_beam_index_ = (current_beam_index_ + 1) % sequence.size(); + last_beam_update_time_ = current_time; + } +} + +void ADAR1000Manager::setBeamSequence(const std::vector& sequence, BeamDirection direction) { + if (direction == BeamDirection::TX) { + tx_beam_sequence_ = sequence; + } else { + rx_beam_sequence_ = sequence; + } +} + +void ADAR1000Manager::clearBeamSequence(BeamDirection direction) { + if (direction == BeamDirection::TX) { + tx_beam_sequence_.clear(); + } else { + rx_beam_sequence_.clear(); + } +} + +// Monitoring and Diagnostics +float ADAR1000Manager::readTemperature(uint8_t deviceIndex) { + if (deviceIndex >= devices_.size() || !devices_[deviceIndex]->initialized) { + return -273.15f; + } + + uint8_t temp_raw = adarAdcRead(deviceIndex, BROADCAST_OFF); + return (temp_raw * 0.5f) - 50.0f; +} + +bool ADAR1000Manager::verifyDeviceCommunication(uint8_t deviceIndex) { + if (deviceIndex >= devices_.size()) return false; + + uint8_t test_value = 0xA5; + adarWrite(deviceIndex, REG_SCRATCHPAD, test_value, BROADCAST_OFF); + HAL_Delay(1); + uint8_t readback = adarRead(deviceIndex, REG_SCRATCHPAD); + return (readback == test_value); +} + +uint8_t ADAR1000Manager::readRegister(uint8_t deviceIndex, uint32_t address) { + return adarRead(deviceIndex, address); +} + +void ADAR1000Manager::writeRegister(uint8_t deviceIndex, uint32_t address, uint8_t value) { + adarWrite(deviceIndex, address, value, BROADCAST_OFF); +} + +// Configuration +void ADAR1000Manager::setSwitchSettlingTime(uint32_t us) { + switch_settling_time_us_ = us; +} + +void ADAR1000Manager::setFastSwitchMode(bool enable) { + fast_switch_mode_ = enable; + if (enable) { + switch_settling_time_us_ = 10; + enablePASupplies(); + enableLNASupplies(); + setPABias(true); + setLNABias(true); + } else { + switch_settling_time_us_ = 50; + } +} + +void ADAR1000Manager::setBeamDwellTime(uint32_t ms) { + beam_dwell_time_ms_ = ms; +} + +// Private helper methods (implementation continues...) +// ... include all the private method implementations from your original file +// ============================================================================ +// PRIVATE HELPER METHODS - Add these to the end of ADAR1000_Manager.cpp +// ============================================================================ + +bool ADAR1000Manager::initializeAllDevices() { + + + // Initialize each ADAR1000 + for (uint8_t i = 0; i < devices_.size(); ++i) { + if (!initializeSingleDevice(i)) { + return false; + } + } + + setAllDevicesTXMode(); + return true; +} + +bool ADAR1000Manager::initializeSingleDevice(uint8_t deviceIndex) { + if (deviceIndex >= devices_.size()) return false; + + adarSoftReset(deviceIndex); + HAL_Delay(10); + + adarWriteConfigA(deviceIndex, INTERFACE_CONFIG_A_SDO_ACTIVE, BROADCAST_OFF); + adarSetRamBypass(deviceIndex, BROADCAST_OFF); + + // Initialize ADC + adarWrite(deviceIndex, REG_ADC_CONTROL, ADAR1000_ADC_2MHZ_CLK | ADAR1000_ADC_EN, BROADCAST_OFF); + + devices_[deviceIndex]->initialized = true; + return true; +} + +bool ADAR1000Manager::initializeADTR1107Sequence() { + + //Powering up ADTR1107 TX mode + const uint8_t msg[] = "Starting ADTR1107 Power Sequence...\r\n"; + HAL_UART_Transmit(&huart3, msg, sizeof(msg) - 1, 1000); + + // Step 1: Connect all GND pins to ground (assumed in hardware) + + // Step 2: Set VDD_SW to 3.3V + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_15, GPIO_PIN_SET); // EN_P_3V3_VDD_SW + HAL_Delay(1); + + // Step 3: Set VSS_SW to -3.3V + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14, GPIO_PIN_SET); // EN_P_3V3_SW + HAL_Delay(1); + + // Step 4: Set CTRL_SW to RX mode initially via GPIO + setADTR1107Control(false); // RX mode + HAL_Delay(1); + + // Step 5: Set VGG_LNA to 0 + uint8_t lna_bias_voltage = 0x00; // Example value, adjust based on your LNA requirements + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_LNA_BIAS_ON, lna_bias_voltage, BROADCAST_OFF); + adarWrite(dev, REG_LNA_BIAS_OFF, 0x00, BROADCAST_OFF); + } + + // Step 6: Set VDD_LNA to 0V for TX mode + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, GPIO_PIN_RESET); // EN_P_3V3_LNA + HAL_Delay(2); + + // Step 7: Set VGG_PA to safe negative voltage (PA off for TX mode) + /*A 0x00 value in the + on or off bias registers, correspond to a 0 V output. A 0xFF in the + on or off bias registers correspond to a −4.8 V output.*/ + uint8_t safe_pa_bias = 0x5D; // Safe negative voltage (-1.75V) to keep PA off + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_PA_CH1_BIAS_ON, safe_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH2_BIAS_ON, safe_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH3_BIAS_ON, safe_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH4_BIAS_ON, safe_pa_bias, BROADCAST_OFF); + } + HAL_Delay(10); + + // Step 8: Set VDD_PA to 0V (PA powered up for TX mode) + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_SET); // EN_P_5V0_PA + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_1, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_SET); + HAL_Delay(50); + + // Step 9: Adjust VGG_PA voltage between −1.75 V and −0.25 V to achieve the desired IDQ_PA=220mA + //Set VGG_PA to safe negative voltage (PA off for TX mode) + /*A 0x00 value in the + on or off bias registers, correspond to a 0 V output. A 0xFF in the + on or off bias registers correspond to a −4.8 V output.*/ + uint8_t Idq_pa_bias = 0x0D; // Safe negative voltage (-0.2447V) to keep PA off + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_PA_CH1_BIAS_ON, Idq_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH2_BIAS_ON, Idq_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH3_BIAS_ON, Idq_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH4_BIAS_ON, Idq_pa_bias, BROADCAST_OFF); + } + HAL_Delay(10); + + + const uint8_t success[] = "ADTR1107 power sequence completed.\r\n"; + HAL_UART_Transmit(&huart3, success, sizeof(success) - 1, 1000); + + return true; +} + +bool ADAR1000Manager::setAllDevicesTXMode() { + // Set ADTR1107 to TX mode first + setADTR1107Mode(BeamDirection::TX); + + // Then configure ADAR1000 for TX + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + // Disable RX first + adarWrite(dev, REG_RX_ENABLES, 0x00, BROADCAST_OFF); + + // Enable TX channels and set bias + adarWrite(dev, REG_TX_ENABLES, 0x0F, BROADCAST_OFF); // Enable all 4 channels + adarSetTxBias(dev, BROADCAST_OFF); + + devices_[dev]->current_mode = BeamDirection::TX; + } + current_mode_ = BeamDirection::TX; + return true; +} + +bool ADAR1000Manager::setAllDevicesRXMode() { + // Set ADTR1107 to RX mode first + setADTR1107Mode(BeamDirection::RX); + + // Then configure ADAR1000 for RX + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + // Disable TX first + adarWrite(dev, REG_TX_ENABLES, 0x00, BROADCAST_OFF); + + // Enable RX channels + adarWrite(dev, REG_RX_ENABLES, 0x0F, BROADCAST_OFF); // Enable all 4 channels + + devices_[dev]->current_mode = BeamDirection::RX; + } + current_mode_ = BeamDirection::RX; + return true; +} + +void ADAR1000Manager::setADTR1107Mode(BeamDirection direction) { + if (direction == BeamDirection::TX) { + setADTR1107Control(true); // TX mode + + // Step 1: Disable LNA power first + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, GPIO_PIN_RESET); // Disable LNA power + HAL_Delay(5); + + // Step 2: Set LNA bias to safe off value + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_LNA_BIAS_ON, 0x00, BROADCAST_OFF); // Turn off LNA bias + } + HAL_Delay(5); + + // Step 3: Enable PA power + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_SET); // EN_P_5V0_PA + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_1, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_SET); + HAL_Delay(10); + + // Step 4: Set PA bias to operational value + uint8_t operational_pa_bias = 0x7F; // Maximum bias for full power + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_PA_CH1_BIAS_ON, operational_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH2_BIAS_ON, operational_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH3_BIAS_ON, operational_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH4_BIAS_ON, operational_pa_bias, BROADCAST_OFF); + } + HAL_Delay(5); + + // Step 5: Set TR switch to TX mode + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarSetBit(dev, REG_SW_CONTROL, 2, BROADCAST_OFF); // TR_SOURCE = 1 (TX) + adarSetBit(dev, REG_MISC_ENABLES, 5, BROADCAST_OFF); // BIAS_EN + } + + } else { + // RECEIVE MODE: Enable LNA, Disable PA + setADTR1107Control(false); // RX mode + + // Step 1: Disable PA power first + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_RESET); // EN_P_5V0_PA + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_1, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_RESET); + HAL_Delay(5); + + // Step 2: Set PA bias to safe negative voltage + uint8_t safe_pa_bias = 0x20; + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_PA_CH1_BIAS_ON, safe_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH2_BIAS_ON, safe_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH3_BIAS_ON, safe_pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH4_BIAS_ON, safe_pa_bias, BROADCAST_OFF); + } + HAL_Delay(5); + + // Step 3: Enable LNA power + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, GPIO_PIN_SET); // EN_P_3V3_LNA + HAL_Delay(10); + + // Step 4: Set LNA bias to operational value + uint8_t operational_lna_bias = 0x30; // Adjust based on your LNA requirements + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_LNA_BIAS_ON, operational_lna_bias, BROADCAST_OFF); + } + HAL_Delay(5); + + // Step 5: Set TR switch to RX mode + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarResetBit(dev, REG_SW_CONTROL, 2, BROADCAST_OFF); // TR_SOURCE = 0 (RX) + adarSetBit(dev, REG_MISC_ENABLES, 4, BROADCAST_OFF); // LNA_BIAS_OUT_EN + } + } +} + +void ADAR1000Manager::setADTR1107Control(bool tx_mode) { + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + setTRSwitchPosition(dev, tx_mode); + } + delayUs(switch_settling_time_us_); +} + +void ADAR1000Manager::setTRSwitchPosition(uint8_t deviceIndex, bool tx_mode) { + if (tx_mode) { + // TX mode: Set TR_SOURCE = 1 + adarSetBit(deviceIndex, REG_SW_CONTROL, 2, BROADCAST_OFF); + } else { + // RX mode: Set TR_SOURCE = 0 + adarResetBit(deviceIndex, REG_SW_CONTROL, 2, BROADCAST_OFF); + } +} + +// Add the new public method +bool ADAR1000Manager::setCustomBeamPattern16(const uint8_t phase_pattern[16], BeamDirection direction) { + for (uint8_t dev = 0; dev < 4; ++dev) { + for (uint8_t ch = 0; ch < 4; ++ch) { + uint8_t phase = phase_pattern[dev * 4 + ch]; + if (direction == BeamDirection::TX) { + adarSetTxPhase(dev, ch + 1, phase, BROADCAST_OFF); + } else { + adarSetRxPhase(dev, ch + 1, phase, BROADCAST_OFF); + } + } + } + return true; +} + +void ADAR1000Manager::enablePASupplies() { + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_SET); // EN_P_5V0_PA + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_1, GPIO_PIN_SET); + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_SET); +} + +void ADAR1000Manager::disablePASupplies() { + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_0, GPIO_PIN_RESET); // EN_P_5V0_PA + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_1, GPIO_PIN_RESET); + HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_RESET); +} + +void ADAR1000Manager::enableLNASupplies() { + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, GPIO_PIN_SET); // EN_P_3V3_LNA +} + +void ADAR1000Manager::disableLNASupplies() { + HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, GPIO_PIN_RESET); // EN_P_3V3_LNA +} + +void ADAR1000Manager::setPABias(bool enable) { + uint8_t pa_bias = enable ? 0x7F : 0x20; // Operational vs safe bias + + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_PA_CH1_BIAS_ON, pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH2_BIAS_ON, pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH3_BIAS_ON, pa_bias, BROADCAST_OFF); + adarWrite(dev, REG_PA_CH4_BIAS_ON, pa_bias, BROADCAST_OFF); + } +} + +void ADAR1000Manager::setLNABias(bool enable) { + uint8_t lna_bias = enable ? 0x30 : 0x00; // Operational vs off + + for (uint8_t dev = 0; dev < devices_.size(); ++dev) { + adarWrite(dev, REG_LNA_BIAS_ON, lna_bias, BROADCAST_OFF); + } +} + +void ADAR1000Manager::delayUs(uint32_t microseconds) { + // Simple implementation - for F7 @ 216MHz, each loop ~7 cycles ≈ 0.032us + volatile uint32_t cycles = microseconds * 10; // Adjust this multiplier for your clock + while (cycles--) { + __NOP(); + } +} + +void ADAR1000Manager::calculatePhaseSettings(float angle_degrees, uint8_t phase_settings[4]) { + const float freq = 10.5e9; + const float c = 3e8; + const float wavelength = c / freq; + const float element_spacing = wavelength / 2; + + float angle_rad = angle_degrees * M_PI / 180.0; + float phase_shift = (2 * M_PI * element_spacing * sin(angle_rad)) / wavelength; + + for (int i = 0; i < 4; ++i) { + float element_phase = i * phase_shift; + while (element_phase < 0) element_phase += 2 * M_PI; + while (element_phase >= 2 * M_PI) element_phase -= 2 * M_PI; + phase_settings[i] = static_cast((element_phase / (2 * M_PI)) * 128); + } +} + +bool ADAR1000Manager::performSystemCalibration() { + for (uint8_t i = 0; i < devices_.size(); ++i) { + if (!verifyDeviceCommunication(i)) { + return false; + } + } + return true; +} + +// ============================================================================ +// LOW-LEVEL SPI COMMUNICATION METHODS +// ============================================================================ + +uint32_t ADAR1000Manager::spiTransfer(uint8_t* txData, uint8_t* rxData, uint32_t size) { + HAL_StatusTypeDef status; + + if (rxData) { + status = HAL_SPI_TransmitReceive(&hspi1, txData, rxData, size, 1000); + } else { + status = HAL_SPI_Transmit(&hspi1, txData, size, 1000); + } + + return (status == HAL_OK) ? size : 0; +} + +void ADAR1000Manager::setChipSelect(uint8_t deviceIndex, bool state) { + if (deviceIndex >= devices_.size()) return; + HAL_GPIO_WritePin(CHIP_SELECTS[deviceIndex].port, + CHIP_SELECTS[deviceIndex].pin, + state ? GPIO_PIN_RESET : GPIO_PIN_SET); +} + +void ADAR1000Manager::adarWrite(uint8_t deviceIndex, uint32_t mem_addr, uint8_t data, uint8_t broadcast) { + uint8_t instruction[3]; + + if (broadcast) { + instruction[0] = 0x08; + } else { + instruction[0] = ((devices_[deviceIndex]->dev_addr & 0x03) << 5); + } + + instruction[0] |= (0x1F00 & mem_addr) >> 8; + instruction[1] = (0xFF & mem_addr); + instruction[2] = data; + + setChipSelect(deviceIndex, true); + spiTransfer(instruction, nullptr, sizeof(instruction)); + setChipSelect(deviceIndex, false); +} + +uint8_t ADAR1000Manager::adarRead(uint8_t deviceIndex, uint32_t mem_addr) { + uint8_t instruction[3] = {0}; + uint8_t rx_buffer[3] = {0}; + + // Set SDO active + adarWrite(deviceIndex, REG_INTERFACE_CONFIG_A, INTERFACE_CONFIG_A_SDO_ACTIVE, 0); + + instruction[0] = 0x80 | ((devices_[deviceIndex]->dev_addr & 0x03) << 5); + instruction[0] |= ((0xff00 & mem_addr) >> 8); + instruction[1] = (0xff & mem_addr); + instruction[2] = 0x00; + + setChipSelect(deviceIndex, true); + spiTransfer(instruction, rx_buffer, sizeof(instruction)); + setChipSelect(deviceIndex, false); + + // Set SDO Inactive + adarWrite(deviceIndex, REG_INTERFACE_CONFIG_A, 0, 0); + + return rx_buffer[2]; +} + +void ADAR1000Manager::adarSetBit(uint8_t deviceIndex, uint32_t mem_addr, uint8_t bit, uint8_t broadcast) { + uint8_t temp = adarRead(deviceIndex, mem_addr); + uint8_t data = temp | (1 << bit); + adarWrite(deviceIndex, mem_addr, data, broadcast); +} + +void ADAR1000Manager::adarResetBit(uint8_t deviceIndex, uint32_t mem_addr, uint8_t bit, uint8_t broadcast) { + uint8_t temp = adarRead(deviceIndex, mem_addr); + uint8_t data = temp & ~(1 << bit); + adarWrite(deviceIndex, mem_addr, data, broadcast); +} + +void ADAR1000Manager::adarSoftReset(uint8_t deviceIndex) { + uint8_t instruction[3]; + instruction[0] = ((devices_[deviceIndex]->dev_addr & 0x03) << 5); + instruction[1] = 0x00; + instruction[2] = 0x81; + + setChipSelect(deviceIndex, true); + spiTransfer(instruction, nullptr, sizeof(instruction)); + setChipSelect(deviceIndex, false); +} + +void ADAR1000Manager::adarWriteConfigA(uint8_t deviceIndex, uint8_t flags, uint8_t broadcast) { + adarWrite(deviceIndex, REG_INTERFACE_CONFIG_A, flags, broadcast); +} + +void ADAR1000Manager::adarSetRamBypass(uint8_t deviceIndex, uint8_t broadcast) { + uint8_t data = (MEM_CTRL_BIAS_RAM_BYPASS | MEM_CTRL_BEAM_RAM_BYPASS); + adarWrite(deviceIndex, REG_MEM_CTL, data, broadcast); +} + +void ADAR1000Manager::adarSetRxPhase(uint8_t deviceIndex, uint8_t channel, uint8_t phase, uint8_t broadcast) { + uint8_t i_val = VM_I[phase % 128]; + uint8_t q_val = VM_Q[phase % 128]; + + uint32_t mem_addr_i = REG_CH1_RX_PHS_I + (channel & 0x03) * 2; + uint32_t mem_addr_q = REG_CH1_RX_PHS_Q + (channel & 0x03) * 2; + + adarWrite(deviceIndex, mem_addr_i, i_val, broadcast); + adarWrite(deviceIndex, mem_addr_q, q_val, broadcast); + adarWrite(deviceIndex, REG_LOAD_WORKING, 0x1, broadcast); +} + +void ADAR1000Manager::adarSetTxPhase(uint8_t deviceIndex, uint8_t channel, uint8_t phase, uint8_t broadcast) { + uint8_t i_val = VM_I[phase % 128]; + uint8_t q_val = VM_Q[phase % 128]; + + uint32_t mem_addr_i = REG_CH1_TX_PHS_I + (channel & 0x03) * 2; + uint32_t mem_addr_q = REG_CH1_TX_PHS_Q + (channel & 0x03) * 2; + + adarWrite(deviceIndex, mem_addr_i, i_val, broadcast); + adarWrite(deviceIndex, mem_addr_q, q_val, broadcast); + adarWrite(deviceIndex, REG_LOAD_WORKING, 0x1, broadcast); +} + +void ADAR1000Manager::adarSetRxVgaGain(uint8_t deviceIndex, uint8_t channel, uint8_t gain, uint8_t broadcast) { + uint32_t mem_addr = REG_CH1_RX_GAIN + (channel & 0x03); + adarWrite(deviceIndex, mem_addr, gain, broadcast); + adarWrite(deviceIndex, REG_LOAD_WORKING, 0x1, broadcast); +} + +void ADAR1000Manager::adarSetTxVgaGain(uint8_t deviceIndex, uint8_t channel, uint8_t gain, uint8_t broadcast) { + uint32_t mem_addr = REG_CH1_TX_GAIN + (channel & 0x03); + adarWrite(deviceIndex, mem_addr, gain, broadcast); + adarWrite(deviceIndex, REG_LOAD_WORKING, LD_WRK_REGS_LDTX_OVERRIDE, broadcast); +} + +void ADAR1000Manager::adarSetTxBias(uint8_t deviceIndex, uint8_t broadcast) { + adarWrite(deviceIndex, REG_BIAS_CURRENT_TX, 0x2D, broadcast); + adarWrite(deviceIndex, REG_BIAS_CURRENT_TX_DRV, 0x06, broadcast); + adarWrite(deviceIndex, REG_LOAD_WORKING, 0x2, broadcast); +} + +uint8_t ADAR1000Manager::adarAdcRead(uint8_t deviceIndex, uint8_t broadcast) { + adarWrite(deviceIndex, REG_ADC_CONTROL, ADAR1000_ADC_ST_CONV, broadcast); + + // Wait for conversion + while (!(adarRead(deviceIndex, REG_ADC_CONTROL) & 0x01)) { + // Busy wait + } + + return adarRead(deviceIndex, REG_ADC_OUT); +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADAR1000_Manager.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADAR1000_Manager.h new file mode 100644 index 0000000..165c5c5 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADAR1000_Manager.h @@ -0,0 +1,222 @@ +// ADAR1000_Manager.h +#ifndef ADAR1000_MANAGER_H +#define ADAR1000_MANAGER_H + +#include "stm32f7xx_hal.h" +#include "main.h" + +#include +#include + +class ADAR1000Manager { +public: + enum class BeamDirection { + TX = 0, + RX = 1 + }; + + struct BeamConfig { + float angle_degrees; + uint8_t phase_settings[4]; + uint8_t gain_settings[4]; + uint32_t dwell_time_ms; + + BeamConfig() : angle_degrees(0), dwell_time_ms(100) { + for(int i = 0; i < 4; i++) { + phase_settings[i] = 0; + gain_settings[i] = 0x7F; + } + } + + BeamConfig(float angle, uint32_t dwell = 100) : angle_degrees(angle), dwell_time_ms(dwell) { + for(int i = 0; i < 4; i++) { + phase_settings[i] = 0; + gain_settings[i] = 0x7F; + } + } + }; + + ADAR1000Manager(); + ~ADAR1000Manager(); + + // System Management + bool powerUpSystem(); + bool powerDownSystem(); + bool initializeAllDevices(); + bool performSystemCalibration(); + + // Mode Switching + void switchToTXMode(); + void switchToRXMode(); + void fastTXMode(); + void fastRXMode(); + void pulseTXMode(); + void pulseRXMode(); + + // Beam Steering + bool setBeamAngle(float angle_degrees, BeamDirection direction); + bool setCustomBeamPattern(const uint8_t phase_settings[16], const uint8_t gain_settings[4], BeamDirection direction); + bool setCustomBeamPattern16(const uint8_t phase_pattern[16], BeamDirection direction); + + // Beam Sweeping + void startBeamSweeping(); + void stopBeamSweeping(); + void updateBeamPosition(); + void setBeamSequence(const std::vector& sequence, BeamDirection direction); + void clearBeamSequence(BeamDirection direction); + + // Device Control + bool setAllDevicesTXMode(); + bool setAllDevicesRXMode(); + void setADTR1107Mode(BeamDirection direction); + void setADTR1107Control(bool tx_mode); + + // Monitoring and Diagnostics + float readTemperature(uint8_t deviceIndex); + bool verifyDeviceCommunication(uint8_t deviceIndex); + uint8_t readRegister(uint8_t deviceIndex, uint32_t address); + void writeRegister(uint8_t deviceIndex, uint32_t address, uint8_t value); + + // Configuration + void setSwitchSettlingTime(uint32_t us); + void setFastSwitchMode(bool enable); + void setBeamDwellTime(uint32_t ms); + + // Getters + bool isBeamSweepingActive() const { return beam_sweeping_active_; } + uint8_t getCurrentBeamIndex() const { return current_beam_index_; } + BeamDirection getCurrentMode() const { return current_mode_; } + uint32_t getLastSwitchTime() const { return last_switch_time_us_; } + + struct ADAR1000Device { + uint8_t dev_addr; + bool initialized; + BeamDirection current_mode; + float temperature; + + ADAR1000Device(uint8_t addr) + : dev_addr(addr), initialized(false), current_mode(BeamDirection::RX), temperature(25.0f) { + } + }; + + // Configuration + bool fast_switch_mode_ = false; + uint32_t switch_settling_time_us_ = 50; + uint32_t beam_dwell_time_ms_ = 100; + uint32_t last_switch_time_us_ = 0; + + // Device Management + std::vector> devices_; + BeamDirection current_mode_ = BeamDirection::RX; + + // Beam Sweeping + std::vector tx_beam_sequence_; + std::vector rx_beam_sequence_; + uint8_t current_beam_index_ = 0; + bool beam_sweeping_active_ = false; + uint32_t last_beam_update_time_ = 0; + + // Lookup tables + static const uint8_t VM_I[128]; + static const uint8_t VM_Q[128]; + static const uint8_t VM_GAIN[128]; + + // Private Methods + bool initializeSingleDevice(uint8_t deviceIndex); + bool initializeADTR1107Sequence(); + void calculatePhaseSettings(float angle_degrees, uint8_t phase_settings[4]); + void delayUs(uint32_t microseconds); + + // Power Management + void enablePASupplies(); + void disablePASupplies(); + void enableLNASupplies(); + void disableLNASupplies(); + void setPABias(bool enable); + void setLNABias(bool enable); + + // SPI Communication + void setChipSelect(uint8_t deviceIndex, bool state); + uint32_t spiTransfer(uint8_t* txData, uint8_t* rxData, uint32_t size); + void adarWrite(uint8_t deviceIndex, uint32_t mem_addr, uint8_t data, uint8_t broadcast); + uint8_t adarRead(uint8_t deviceIndex, uint32_t mem_addr); + void adarSetBit(uint8_t deviceIndex, uint32_t mem_addr, uint8_t bit, uint8_t broadcast); + void adarResetBit(uint8_t deviceIndex, uint32_t mem_addr, uint8_t bit, uint8_t broadcast); + void adarSoftReset(uint8_t deviceIndex); + void adarWriteConfigA(uint8_t deviceIndex, uint8_t flags, uint8_t broadcast); + void adarSetRamBypass(uint8_t deviceIndex, uint8_t broadcast); + + // Channel Configuration + void adarSetRxPhase(uint8_t deviceIndex, uint8_t channel, uint8_t phase, uint8_t broadcast); + void adarSetTxPhase(uint8_t deviceIndex, uint8_t channel, uint8_t phase, uint8_t broadcast); + void adarSetRxVgaGain(uint8_t deviceIndex, uint8_t channel, uint8_t gain, uint8_t broadcast); + void adarSetTxVgaGain(uint8_t deviceIndex, uint8_t channel, uint8_t gain, uint8_t broadcast); + void adarSetTxBias(uint8_t deviceIndex, uint8_t broadcast); + uint8_t adarAdcRead(uint8_t deviceIndex, uint8_t broadcast); + void setTRSwitchPosition(uint8_t deviceIndex, bool tx_mode); + +private: + +}; + +// Register Definitions +#define BROADCAST_OFF 0 +#define BROADCAST_ON 1 + +#define REG_INTERFACE_CONFIG_A 0x000 +#define REG_SCRATCHPAD 0x00A +#define REG_CH1_RX_GAIN 0x010 +#define REG_CH2_RX_GAIN 0x011 +#define REG_CH3_RX_GAIN 0x012 +#define REG_CH4_RX_GAIN 0x013 +#define REG_CH1_RX_PHS_I 0x014 +#define REG_CH1_RX_PHS_Q 0x015 +#define REG_CH2_RX_PHS_I 0x016 +#define REG_CH2_RX_PHS_Q 0x017 +#define REG_CH3_RX_PHS_I 0x018 +#define REG_CH3_RX_PHS_Q 0x019 +#define REG_CH4_RX_PHS_I 0x01A +#define REG_CH4_RX_PHS_Q 0x01B +#define REG_CH1_TX_GAIN 0x01C +#define REG_CH2_TX_GAIN 0x01D +#define REG_CH3_TX_GAIN 0x01E +#define REG_CH4_TX_GAIN 0x01F +#define REG_CH1_TX_PHS_I 0x020 +#define REG_CH1_TX_PHS_Q 0x021 +#define REG_CH2_TX_PHS_I 0x022 +#define REG_CH2_TX_PHS_Q 0x023 +#define REG_CH3_TX_PHS_I 0x024 +#define REG_CH3_TX_PHS_Q 0x025 +#define REG_CH4_TX_PHS_I 0x026 +#define REG_CH4_TX_PHS_Q 0x027 +#define REG_LOAD_WORKING 0x028 +#define REG_PA_CH1_BIAS_ON 0x029 +#define REG_PA_CH2_BIAS_ON 0x02A +#define REG_PA_CH3_BIAS_ON 0x02B +#define REG_PA_CH4_BIAS_ON 0x02C +#define REG_LNA_BIAS_ON 0x02D +#define REG_RX_ENABLES 0x02E +#define REG_TX_ENABLES 0x02F +#define REG_MISC_ENABLES 0x030 +#define REG_SW_CONTROL 0x031 +#define REG_ADC_CONTROL 0x032 +#define REG_ADC_OUT 0x033 +#define REG_BIAS_CURRENT_TX 0x036 +#define REG_BIAS_CURRENT_TX_DRV 0x037 +#define REG_MEM_CTL 0x038 +#define REG_PA_CH1_BIAS_OFF 0x046 +#define REG_PA_CH2_BIAS_OFF 0x047 +#define REG_PA_CH3_BIAS_OFF 0x048 +#define REG_PA_CH4_BIAS_OFF 0x049 +#define REG_LNA_BIAS_OFF 0x04A + +// Register Constants +#define INTERFACE_CONFIG_A_SDO_ACTIVE ((1 << 4) | (1 << 3)) +#define ADAR1000_ADC_2MHZ_CLK 0x00 +#define ADAR1000_ADC_EN 0x60 +#define ADAR1000_ADC_ST_CONV 0x70 +#define MEM_CTRL_BIAS_RAM_BYPASS (1 << 5) +#define MEM_CTRL_BEAM_RAM_BYPASS (1 << 6) +#define LD_WRK_REGS_LDTX_OVERRIDE (1 << 1) + +#endif // ADAR1000_MANAGER_H diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADS7830.H b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADS7830.H new file mode 100644 index 0000000..5183c21 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADS7830.H @@ -0,0 +1,86 @@ +#ifndef __ADS7830_H +#define __ADS7830_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stm32f7xx_hal.h" +#include +#include + +/* I2C Address Definitions */ +#define ADS7830_DEFAULT_ADDRESS (0x48) // 1001 000 (ADDR = GND) +#define ADS7830_VDD_ADDRESS (0x49) // 1001 001 (ADDR = VDD) +#define ADS7830_SDA_ADDRESS (0x4A) // 1001 010 (ADDR = SDA) +#define ADS7830_SCL_ADDRESS (0x4B) // 1001 011 (ADDR = SCL) + +/* Conversion Delay (in ms) */ +#define ADS7830_CONVERSIONDELAY (1) + +/* Command Byte Register Masks */ +#define ADS7830_REG_COMMAND_SD_MASK (0x80) // Single-Ended/Differential Inputs +#define ADS7830_REG_COMMAND_SD_DIFF (0x00) // Bit = 0, Differential Inputs +#define ADS7830_REG_COMMAND_SD_SINGLE (0x80) // Bit = 1, Single-Ended Inputs + +#define ADS7830_REG_COMMAND_CH_MASK (0x70) // Input multiplexer Configuration +#define ADS7830_REG_COMMAND_CH_DIFF_0_1 (0x00) // Differential P = CH0, N = CH1 +#define ADS7830_REG_COMMAND_CH_DIFF_2_3 (0x10) // Differential P = CH2, N = CH3 +#define ADS7830_REG_COMMAND_CH_DIFF_4_5 (0x20) // Differential P = CH4, N = CH5 +#define ADS7830_REG_COMMAND_CH_DIFF_6_7 (0x30) // Differential P = CH6, N = CH7 +#define ADS7830_REG_COMMAND_CH_DIFF_1_0 (0x40) // Differential P = CH1, N = CH0 +#define ADS7830_REG_COMMAND_CH_DIFF_3_2 (0x50) // Differential P = CH3, N = CH2 +#define ADS7830_REG_COMMAND_CH_DIFF_5_4 (0x60) // Differential P = CH5, N = CH4 +#define ADS7830_REG_COMMAND_CH_DIFF_7_6 (0x70) // Differential P = CH7, N = CH6 +#define ADS7830_REG_COMMAND_CH_SINGLE_0 (0x00) // Single-ended P = CH0, N = COM +#define ADS7830_REG_COMMAND_CH_SINGLE_1 (0x10) // Single-ended P = CH1, N = COM +#define ADS7830_REG_COMMAND_CH_SINGLE_2 (0x20) // Single-ended P = CH2, N = COM +#define ADS7830_REG_COMMAND_CH_SINGLE_3 (0x30) // Single-ended P = CH3, N = COM +#define ADS7830_REG_COMMAND_CH_SINGLE_4 (0x40) // Single-ended P = CH4, N = COM +#define ADS7830_REG_COMMAND_CH_SINGLE_5 (0x50) // Single-ended P = CH5, N = COM +#define ADS7830_REG_COMMAND_CH_SINGLE_6 (0x60) // Single-ended P = CH6, N = COM +#define ADS7830_REG_COMMAND_CH_SINGLE_7 (0x70) // Single-ended P = CH7, N = COM + +#define ADS7830_REG_COMMAND_PD_MASK (0x0C) // Power-Down Selection +#define ADS7830_REG_COMMAND_PD_PDADCONV (0x00) // Power Down Between A/D Converter Conversions +#define ADS7830_REG_COMMAND_PD_IROFF_ADON (0x04) // Internal Reference OFF and A/D Converter ON +#define ADS7830_REG_COMMAND_PD_IRON_ADOFF (0x08) // Internal Reference ON and A/D Converter OFF +#define ADS7830_REG_COMMAND_PD_IRON_ADON (0x0C) // Internal Reference ON and A/D Converter ON + +/* Mode Enumerations */ +typedef enum { + ADS7830_SDMODE_DIFF = ADS7830_REG_COMMAND_SD_DIFF, + ADS7830_SDMODE_SINGLE = ADS7830_REG_COMMAND_SD_SINGLE +} ADS7830_SDMode_t; + +typedef enum { + ADS7830_PDADCONV = ADS7830_REG_COMMAND_PD_PDADCONV, + ADS7830_PDIROFF_ADON = ADS7830_REG_COMMAND_PD_IROFF_ADON, + ADS7830_PDIRON_ADOFF = ADS7830_REG_COMMAND_PD_IRON_ADOFF, + ADS7830_PDIRON_ADON = ADS7830_REG_COMMAND_PD_IRON_ADON +} ADS7830_PDMode_t; + +/* ADC Handle Structure */ +typedef struct { + I2C_HandleTypeDef *hi2c; + uint8_t i2c_addr; + ADS7830_SDMode_t sdmode; + ADS7830_PDMode_t pdmode; + uint8_t conversion_delay; + uint8_t last_conversion_result; +} ADS7830_HandleTypeDef; + +/* Function Prototypes */ +bool ADS7830_Init(ADS7830_HandleTypeDef *hadc, I2C_HandleTypeDef *hi2c, uint8_t i2c_addr, + ADS7830_SDMode_t sdmode, ADS7830_PDMode_t pdmode); +bool ADS7830_SetSDMode(ADS7830_HandleTypeDef *hadc, ADS7830_SDMode_t sdmode); +bool ADS7830_SetPDMode(ADS7830_HandleTypeDef *hadc, ADS7830_PDMode_t pdmode); +uint8_t ADS7830_Measure_SingleEnded(ADS7830_HandleTypeDef *hadc, uint8_t channel); +int8_t ADS7830_Measure_Differential(ADS7830_HandleTypeDef *hadc, uint8_t channel); +uint8_t ADS7830_GetLastConversionResult(ADS7830_HandleTypeDef *hadc); + +#ifdef __cplusplus +} +#endif + +#endif /* __ADS7830_H */ \ No newline at end of file diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADS7830.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADS7830.c new file mode 100644 index 0000000..9b1891e --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ADS7830.c @@ -0,0 +1,211 @@ +#include "ADS7830.h" +#include + +/** + * @brief Initialize the ADS7830 ADC + * @param hadc: pointer to an ADS7830_HandleTypeDef structure + * @param hi2c: pointer to an I2C_HandleTypeDef structure + * @param i2c_addr: I2C address of the ADC + * @param sdmode: Single-ended or differential mode + * @param pdmode: Power-down mode + * @retval bool: true if successful, false otherwise + */ +bool ADS7830_Init(ADS7830_HandleTypeDef *hadc, I2C_HandleTypeDef *hi2c, uint8_t i2c_addr, + ADS7830_SDMode_t sdmode, ADS7830_PDMode_t pdmode) { + + if (hadc == NULL || hi2c == NULL) { + return false; + } + + hadc->hi2c = hi2c; + hadc->i2c_addr = i2c_addr << 1; // HAL requires 7-bit address shifted left + hadc->sdmode = sdmode; + hadc->pdmode = pdmode; + hadc->conversion_delay = ADS7830_CONVERSIONDELAY; + hadc->last_conversion_result = 0; + + /* Test communication by reading from a channel */ + return (ADS7830_Measure_SingleEnded(hadc, 0) != 0xFF); // 0xFF indicates communication error +} + +/** + * @brief Set Single-Ended/Differential mode + * @param hadc: pointer to an ADS7830_HandleTypeDef structure + * @param sdmode: Single-ended or differential mode + * @retval bool: true if successful, false otherwise + */ +bool ADS7830_SetSDMode(ADS7830_HandleTypeDef *hadc, ADS7830_SDMode_t sdmode) { + if (hadc == NULL) { + return false; + } + + hadc->sdmode = sdmode; + return true; +} + +/** + * @brief Set Power-Down mode + * @param hadc: pointer to an ADS7830_HandleTypeDef structure + * @param pdmode: Power-down mode + * @retval bool: true if successful, false otherwise + */ +bool ADS7830_SetPDMode(ADS7830_HandleTypeDef *hadc, ADS7830_PDMode_t pdmode) { + if (hadc == NULL) { + return false; + } + + hadc->pdmode = pdmode; + return true; +} + +/** + * @brief Measure single-ended voltage on specified channel + * @param hadc: pointer to an ADS7830_HandleTypeDef structure + * @param channel: ADC channel (0-7) + * @retval uint8_t: 8-bit conversion result (0-255), 0xFF on error + */ +uint8_t ADS7830_Measure_SingleEnded(ADS7830_HandleTypeDef *hadc, uint8_t channel) { + if (hadc == NULL || channel > 7) { + return 0xFF; + } + + uint8_t config = 0; + + // Set Single-Ended/Differential Inputs + config |= hadc->sdmode; + + // Set Power-Down Selection + config |= hadc->pdmode; + + // Set single-ended input channel + switch (channel) { + case (0): + config |= ADS7830_REG_COMMAND_CH_SINGLE_0; + break; + case (1): + config |= ADS7830_REG_COMMAND_CH_SINGLE_1; + break; + case (2): + config |= ADS7830_REG_COMMAND_CH_SINGLE_2; + break; + case (3): + config |= ADS7830_REG_COMMAND_CH_SINGLE_3; + break; + case (4): + config |= ADS7830_REG_COMMAND_CH_SINGLE_4; + break; + case (5): + config |= ADS7830_REG_COMMAND_CH_SINGLE_5; + break; + case (6): + config |= ADS7830_REG_COMMAND_CH_SINGLE_6; + break; + case (7): + config |= ADS7830_REG_COMMAND_CH_SINGLE_7; + break; + default: + return 0xFF; + } + + // Write config register to the ADC + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hadc->hi2c, hadc->i2c_addr, &config, 1, HAL_MAX_DELAY); + if (status != HAL_OK) { + return 0xFF; + } + + // Wait for the conversion to complete + HAL_Delay(hadc->conversion_delay); + + // Read the conversion results + uint8_t result = 0; + status = HAL_I2C_Master_Receive(hadc->hi2c, hadc->i2c_addr, &result, 1, HAL_MAX_DELAY); + if (status != HAL_OK) { + return 0xFF; + } + + hadc->last_conversion_result = result; + return result; +} + +/** + * @brief Measure differential voltage between specified channel pairs + * @param hadc: pointer to an ADS7830_HandleTypeDef structure + * @param channel: Channel pair (01, 10, 23, 32, 45, 54, 67, 76) + * @retval int8_t: 8-bit signed conversion result (-128 to 127), 0x80 on error + */ +int8_t ADS7830_Measure_Differential(ADS7830_HandleTypeDef *hadc, uint8_t channel) { + if (hadc == NULL) { + return (int8_t)0x80; + } + + uint8_t config = 0; + + // Set Single-Ended/Differential Inputs + config |= hadc->sdmode; + + // Set Power-Down Selection + config |= hadc->pdmode; + + // Set Differential input channel + switch (channel) { + case (01): + config |= ADS7830_REG_COMMAND_CH_DIFF_0_1; // CH0 = P, CH1 = N + break; + case (10): + config |= ADS7830_REG_COMMAND_CH_DIFF_1_0; // CH1 = P, CH0 = N + break; + case (23): + config |= ADS7830_REG_COMMAND_CH_DIFF_2_3; // CH2 = P, CH3 = N + break; + case (32): + config |= ADS7830_REG_COMMAND_CH_DIFF_3_2; // CH3 = P, CH2 = N + break; + case (45): + config |= ADS7830_REG_COMMAND_CH_DIFF_4_5; // CH4 = P, CH5 = N + break; + case (54): + config |= ADS7830_REG_COMMAND_CH_DIFF_5_4; // CH5 = P, CH4 = N + break; + case (67): + config |= ADS7830_REG_COMMAND_CH_DIFF_6_7; // CH6 = P, CH7 = N + break; + case (76): + config |= ADS7830_REG_COMMAND_CH_DIFF_7_6; // CH7 = P, CH6 = N + break; + default: + return (int8_t)0x80; + } + + // Write config register to the ADC + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hadc->hi2c, hadc->i2c_addr, &config, 1, HAL_MAX_DELAY); + if (status != HAL_OK) { + return (int8_t)0x80; + } + + // Wait for the conversion to complete + HAL_Delay(hadc->conversion_delay); + + // Read the conversion results + uint8_t raw_adc = 0; + status = HAL_I2C_Master_Receive(hadc->hi2c, hadc->i2c_addr, &raw_adc, 1, HAL_MAX_DELAY); + if (status != HAL_OK) { + return (int8_t)0x80; + } + + // Convert to signed 8-bit value + int8_t result = (int8_t)raw_adc; + hadc->last_conversion_result = raw_adc; + return result; +} + +/** + * @brief Get the last conversion result + * @param hadc: pointer to an ADS7830_HandleTypeDef structure + * @retval uint8_t: Last conversion result + */ +uint8_t ADS7830_GetLastConversionResult(ADS7830_HandleTypeDef *hadc) { + if (hadc == NULL) { + return 0; + } + return hadc->last_conversion_result; +} \ No newline at end of file diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/BMP180.cpp b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/BMP180.cpp new file mode 100644 index 0000000..7603ad0 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/BMP180.cpp @@ -0,0 +1,462 @@ +/***************************************************************************************************/ +/* + This is an Arduino basic library for Bosch BMP180 & BMP085 barometric pressure & + temperature sensor + + Power supply voltage: 1.8v - 3.6v + Range: 30,000Pa..110,000Pa at -40°C..+85°C + Typ. resolution: 1Pa / 0.1°C + Typ. accuracy: ±100Pa* / ±1.0°C* at 0°C..+65°C + Typ. relative accuracy: ±12Pa / xx°C + Duty cycle: 10% active & 90% inactive, to prevent self heating + + *sensor is sensitive to direct light, which can affect + the accuracy of the measurement + + written by : enjoyneering79 + sourse code: https://github.com/enjoyneering/ + + + This chip uses I2C bus to communicate, specials pins are required to interface + Board: SDA SCL Level + Uno, Mini, Pro, ATmega168, ATmega328..... A4 A5 5v + Mega2560................................. 20 21 5v + Due, SAM3X8E............................. 20 21 3.3v + Leonardo, Micro, ATmega32U4.............. 2 3 5v + Digistump, Trinket, ATtiny85............. 0/physical pin no.5 2/physical pin no.7 5v + Blue Pill, STM32F103xxxx boards.......... PB7 PB6 3.3v/5v + ESP8266 ESP-01........................... GPIO0/D5 GPIO2/D3 3.3v/5v + NodeMCU 1.0, WeMos D1 Mini............... GPIO4/D2 GPIO5/D1 3.3v/5v + ESP32.................................... GPIO21/D21 GPIO22/D22 3.3v + + NOTE: + - EOC pin is not used, shows the end of conversion + - XCLR pin is not used, reset pin + + Frameworks & Libraries: + ATtiny Core - https://github.com/SpenceKonde/ATTinyCore + ESP32 Core - https://github.com/espressif/arduino-esp32 + ESP8266 Core - https://github.com/esp8266/Arduino + STM32 Core - https://github.com/rogerclarkmelbourne/Arduino_STM32 + + GNU GPL license, all text above must be included in any redistribution, + see link for details - https://www.gnu.org/licenses/licenses.html +*/ +/***************************************************************************************************/ + +#include "BMP180.h" + + +/**************************************************************************/ +/* + Constructor + + NOTE: + - BMP180_ULTRALOWPOWER, pressure oversampled 1 time & consumption 3μA + - BMP180_STANDARD, pressure oversampled 2 times & consumption 5μA + - BMP180_HIGHRES, pressure oversampled 4 times & consumption 7μA + - BMP180_ULTRAHIGHRES, pressure oversampled 8 times & consumption 12μA +*/ +/**************************************************************************/ +BMP180::BMP180(BMP180_RESOLUTION res_mode) +{ + _resolution = res_mode; +} + + +/**************************************************************************/ +/* + getPressure() + + Calculates compensated pressure, in Pa + + NOTE: + - resolutin 1Pa with accuracy ±150Pa at range 30,000Pa..110,000Pa +*/ +/**************************************************************************/ +int32_t BMP180::getPressure(void) +{ + int32_t UT = 0; + int32_t UP = 0; + int32_t B3 = 0; + int32_t B5 = 0; + int32_t B6 = 0; + int32_t X1 = 0; + int32_t X2 = 0; + int32_t X3 = 0; + int32_t pressure = 0; + uint32_t B4 = 0; + uint32_t B7 = 0; + + UT = readRawTemperature(); //read uncompensated temperature, 16-bit + if (UT == BMP180_ERROR) return BMP180_ERROR; //error handler, collision on i2c bus + + UP = readRawPressure(); //read uncompensated pressure, 19-bit + if (UP == BMP180_ERROR) return BMP180_ERROR; //error handler, collision on i2c bus + + B5 = computeB5(UT); + + /* pressure calculation */ + B6 = B5 - 4000; + X1 = ((int32_t)_calCoeff.bmpB2 * ((B6 * B6) >> 12)) >> 11; + X2 = ((int32_t)_calCoeff.bmpAC2 * B6) >> 11; + X3 = X1 + X2; + B3 = ((((int32_t)_calCoeff.bmpAC1 * 4 + X3) << _resolution) + 2) / 4; + + X1 = ((int32_t)_calCoeff.bmpAC3 * B6) >> 13; + X2 = ((int32_t)_calCoeff.bmpB1 * ((B6 * B6) >> 12)) >> 16; + X3 = ((X1 + X2) + 2) >> 2; + B4 = ((uint32_t)_calCoeff.bmpAC4 * (X3 + 32768L)) >> 15; + B7 = (UP - B3) * (50000UL >> _resolution); + + if (B4 == 0) return BMP180_ERROR; //safety check, avoiding division by zero + + if (B7 < 0x80000000) pressure = (B7 * 2) / B4; + else pressure = (B7 / B4) * 2; + + X1 = pow((pressure >> 8), 2); + X1 = (X1 * 3038L) >> 16; + X2 = (-7357L * pressure) >> 16; + + return pressure = pressure + ((X1 + X2 + 3791L) >> 4); +} + +/**************************************************************************/ +/* + getTemperature() + + Calculates compensated temperature, in °C + + NOTE: + - resolution 0.1°C with accuracy ±1.0°C at range 0°C..+65°C +*/ +/**************************************************************************/ +float BMP180::getTemperature(void) +{ + int16_t rawTemperature = readRawTemperature(); + + if (rawTemperature == BMP180_ERROR) return BMP180_ERROR; //error handler, collision on i2c bus + return (float)((computeB5(rawTemperature) + 8) >> 4) / 10; +} + +/**************************************************************************/ +/* + getSeaLevelPressure() + + Converts current pressure to sea level pressure at specific true + altitude, in Pa + + NOTE: + - true altitude is the actual elevation above sea level, to find out + your current true altitude do search with google earth or gps + - see level pressure is commonly used in weather reports & forecasts + to compensate current true altitude + - for example, we know that a sunny day happens if the current sea + level pressure is 250Pa above the average sea level pressure of + 101325 Pa, so by converting the current pressure to sea level & + comparing it with an average sea level pressure we can instantly + predict the weather conditions +*/ +/**************************************************************************/ +int32_t BMP180::getSeaLevelPressure(int16_t trueAltitude) +{ + int32_t pressure = getPressure(); + + if (pressure == BMP180_ERROR) return BMP180_ERROR; + return (pressure / pow(1.0 - (float)trueAltitude / 44330, 5.255)); +} + +/**************************************************************************/ +/* + softReset() + + Soft reset + + NOTE: + - performs the same sequence as power on reset +*/ +/**************************************************************************/ +void BMP180::softReset(void) +{ + write8(BMP180_SOFT_RESET_REG, BMP180_SOFT_RESET_CTRL); +} + +/**************************************************************************/ +/* + readFirmwareVersion() + + Reads ML & AL Version + + NOTE: + - ML version is LSB, 4-bit..0-bit + - AL version is MSB, 7-bit..5-bit +*/ +/**************************************************************************/ +uint8_t BMP180::readFirmwareVersion(void) +{ + return read8(BMP180_GET_VERSION_REG); +} + +/**************************************************************************/ +/* + readDeviceID() + + Reads chip ID +*/ +/**************************************************************************/ +uint8_t BMP180::readDeviceID(void) +{ + if (read8(BMP180_GET_ID_REG) == BMP180_CHIP_ID) return 180; + return false; +} + +/**************************************************************************/ +/* + readCalibrationCoefficients() + + Reads factory calibration coefficients from E2PROM + + NOTE: + - every sensor module has individual calibration coefficients + - before first temperature & pressure calculation master have to read + calibration coefficients from 176-bit E2PROM +*/ +/**************************************************************************/ +bool BMP180::readCalibrationCoefficients() +{ + int32_t value = 0; + + for (uint8_t reg = BMP180_CAL_AC1_REG; reg <= BMP180_CAL_MD_REG; reg++) + { + value = read16(reg); + + if (value == BMP180_ERROR) return false; //error handler, collision on i2c bus + + switch (reg) + { + case BMP180_CAL_AC1_REG: //used for pressure computation + _calCoeff.bmpAC1 = value; + break; + + case BMP180_CAL_AC2_REG: //used for pressure computation + _calCoeff.bmpAC2 = value; + break; + + case BMP180_CAL_AC3_REG: //used for pressure computation + _calCoeff.bmpAC3 = value; + break; + + case BMP180_CAL_AC4_REG: //used for pressure computation + _calCoeff.bmpAC4 = value; + break; + + case BMP180_CAL_AC5_REG: //used for temperature computation + _calCoeff.bmpAC5 = value; + break; + + case BMP180_CAL_AC6_REG: //used for temperature computation + _calCoeff.bmpAC6 = value; + break; + + case BMP180_CAL_B1_REG: //used for pressure computation + _calCoeff.bmpB1 = value; + break; + + case BMP180_CAL_B2_REG: //used for pressure computation + _calCoeff.bmpB2 = value; + break; + + case BMP180_CAL_MB_REG: //??? + _calCoeff.bmpMB = value; + break; + + case BMP180_CAL_MC_REG: //used for temperature computation + _calCoeff.bmpMC = value; + break; + + case BMP180_CAL_MD_REG: //used for temperature computation + _calCoeff.bmpMD = value; + break; + } + } + + return true; +} + +/**************************************************************************/ +/* + readRawTemperature() + + Reads raw/uncompensated temperature value, 16-bit +*/ +/**************************************************************************/ +uint16_t BMP180::readRawTemperature(void) +{ + /* send temperature measurement command */ + if (write8(BMP180_START_MEASURMENT_REG, BMP180_GET_TEMPERATURE_CTRL) != true) return BMP180_ERROR; //error handler, collision on i2c bus + + /* set measurement delay */ + HAL_Delay(5); + + /* read result */ + return read16(BMP180_READ_ADC_MSB_REG); //reads msb + lsb +} + +/**************************************************************************/ +/* + readRawPressure() + + Reads raw/uncompensated pressure value, 19-bits +*/ +/**************************************************************************/ +uint32_t BMP180::readRawPressure(void) +{ + uint8_t regControl = 0; + uint32_t rawPressure = 0; + + /* convert resolution to register control */ + switch (_resolution) + { + case BMP180_ULTRALOWPOWER: //oss0 + regControl = BMP180_GET_PRESSURE_OSS0_CTRL; + break; + + case BMP180_STANDARD: //oss1 + regControl = BMP180_GET_PRESSURE_OSS1_CTRL; + break; + + case BMP180_HIGHRES: //oss2 + regControl = BMP180_GET_PRESSURE_OSS2_CTRL; + break; + + case BMP180_ULTRAHIGHRES: //oss3 + regControl = BMP180_GET_PRESSURE_OSS3_CTRL; + break; + } + + /* send pressure measurement command */ + if (write8(BMP180_START_MEASURMENT_REG, regControl) != true) return BMP180_ERROR; //error handler, collision on i2c bus + + /* set measurement delay */ + switch (_resolution) + { + case BMP180_ULTRALOWPOWER: + HAL_Delay(5); + break; + + case BMP180_STANDARD: + HAL_Delay(8); + break; + + case BMP180_HIGHRES: + HAL_Delay(14); + break; + + case BMP180_ULTRAHIGHRES: + HAL_Delay(26); + break; + } + + /* read result msb + lsb */ + rawPressure = read16(BMP180_READ_ADC_MSB_REG); //16-bits + if (rawPressure == BMP180_ERROR) return BMP180_ERROR; //error handler, collision on i2c bus + + /* read result xlsb */ + rawPressure <<= 8; + rawPressure |= read8(BMP180_READ_ADC_XLSB_REG); //19-bits + + rawPressure >>= (8 - _resolution); + + return rawPressure; +} + +/**************************************************************************/ +/* + computeB5() + + Computes B5 value + + NOTE: + - to compensate raw/uncompensated temperature + - also used for compensated pressure calculation +*/ +/**************************************************************************/ +int32_t BMP180::computeB5(int32_t UT) +{ + int32_t X1 = ((UT - (int32_t)_calCoeff.bmpAC6) * (int32_t)_calCoeff.bmpAC5) >> 15; + int32_t X2 = ((int32_t)_calCoeff.bmpMC << 11) / (X1 + (int32_t)_calCoeff.bmpMD); + + return X1 + X2; +} + +/**************************************************************************/ +/* + read8() + + Reads 8-bit value over I2C +*/ +/**************************************************************************/ +uint8_t BMP180::read8(uint8_t reg) +{ + uint8_t data = 0; + HAL_StatusTypeDef status; + + // Write register address + status = HAL_I2C_Master_Transmit(&hi2c3, BMP180_ADDRESS, ®, 1, I2C_TIMEOUT); + if (status != HAL_OK) return BMP180_ERROR; + + // Read data from register + status = HAL_I2C_Master_Receive(&hi2c3, BMP180_ADDRESS, &data, 1, I2C_TIMEOUT); + if (status != HAL_OK) return BMP180_ERROR; + + return data; +} + +/**************************************************************************/ +/* + read16() + + Reads 16-bits value over I2C +*/ +/**************************************************************************/ + +uint16_t BMP180::read16(uint8_t reg) +{ + uint8_t data[2] = {0, 0}; + uint16_t value = 0; + HAL_StatusTypeDef status; + + // Write register address + status = HAL_I2C_Master_Transmit(&hi2c3, BMP180_ADDRESS, ®, 1, I2C_TIMEOUT); + if (status != HAL_OK) return BMP180_ERROR; + + // Read 2 bytes from register + status = HAL_I2C_Master_Receive(&hi2c3, BMP180_ADDRESS, data, 2, I2C_TIMEOUT); + if (status != HAL_OK) return BMP180_ERROR; + + // Combine bytes (MSB first) + value = (data[0] << 8) | data[1]; + + return value; +} + + +/**************************************************************************/ +/* + write8() + + Writes 8-bits value over I2C +*/ +/**************************************************************************/ + +bool BMP180::write8(uint8_t reg, uint8_t control) +{ + uint8_t data[2] = {reg, control}; + HAL_StatusTypeDef status; + + // Write register address and data + status = HAL_I2C_Master_Transmit(&hi2c3, BMP180_ADDRESS, data, 2, I2C_TIMEOUT); + + return (status == HAL_OK); +} + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/BMP180.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/BMP180.h new file mode 100644 index 0000000..88754bc --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/BMP180.h @@ -0,0 +1,156 @@ +/***************************************************************************************************/ +/* + This is an Arduino basic library for Bosch BMP180 & BMP085 barometric pressure & + temperature sensor + + Power supply voltage: 1.8v - 3.6v + Range: 30,000Pa..110,000Pa at -40°C..+85°C + Typ. resolution: 1Pa / 0.1°C + Typ. accuracy: ±100Pa* / ±1.0°C* at 0°C..+65°C + Typ. relative accuracy: ±12Pa / xx°C + Duty cycle: 10% active & 90% inactive, to prevent self heating + + *sensor is sensitive to direct light, which can affect + the accuracy of the measurement + + written by : enjoyneering79 + sourse code: https://github.com/enjoyneering/ + + + This chip uses I2C bus to communicate, specials pins are required to interface + Board: SDA SCL Level + Uno, Mini, Pro, ATmega168, ATmega328..... A4 A5 5v + Mega2560................................. 20 21 5v + Due, SAM3X8E............................. 20 21 3.3v + Leonardo, Micro, ATmega32U4.............. 2 3 5v + Digistump, Trinket, ATtiny85............. 0/physical pin no.5 2/physical pin no.7 5v + Blue Pill, STM32F103xxxx boards.......... PB7 PB6 3.3v/5v + ESP8266 ESP-01........................... GPIO0/D5 GPIO2/D3 3.3v/5v + NodeMCU 1.0, WeMos D1 Mini............... GPIO4/D2 GPIO5/D1 3.3v/5v + ESP32.................................... GPIO21/D21 GPIO22/D22 3.3v + + NOTE: + - EOC pin is not used, shows the end of conversion + - XCLR pin is not used, reset pin + + Frameworks & Libraries: + ATtiny Core - https://github.com/SpenceKonde/ATTinyCore + ESP32 Core - https://github.com/espressif/arduino-esp32 + ESP8266 Core - https://github.com/esp8266/Arduino + STM32 Core - https://github.com/rogerclarkmelbourne/Arduino_STM32 + + GNU GPL license, all text above must be included in any redistribution, + see link for details - https://www.gnu.org/licenses/licenses.html +*/ +/***************************************************************************************************/ + +#ifndef BMP180_h +#define BMP180_h + +#include "stm32f7xx_hal.h" +#include + +extern I2C_HandleTypeDef hi2c3; + +/* resolutions */ +typedef enum : uint8_t +{ + BMP180_ULTRALOWPOWER = 0x00, //low power mode, oss0 + BMP180_STANDARD = 0x01, //standard mode, oss1 + BMP180_HIGHRES = 0x02, //high resolution mode, oss2 + BMP180_ULTRAHIGHRES = 0x03 //ultra high resolution mode, oss3 +} +BMP180_RESOLUTION; + + +/* calibration registers */ +typedef enum : uint8_t +{ + BMP180_CAL_AC1_REG = 0xAA, //ac1 pressure computation + BMP180_CAL_AC2_REG = 0xAC, //ac2 pressure computation + BMP180_CAL_AC3_REG = 0xAE, //ac3 pressure computation + BMP180_CAL_AC4_REG = 0xB0, //ac4 pressure computation + BMP180_CAL_AC5_REG = 0xB2, //ac5 temperature computation + BMP180_CAL_AC6_REG = 0xB4, //ac6 temperature computation + BMP180_CAL_B1_REG = 0xB6, //b1 pressure computation + BMP180_CAL_B2_REG = 0xB8, //b2 pressure computation + BMP180_CAL_MB_REG = 0xBA, //mb + BMP180_CAL_MC_REG = 0xBC, //mc temperature computation + BMP180_CAL_MD_REG = 0xBE //md temperature computation +} +BMP180_CAL_REG; + +#define BMP180_GET_ID_REG 0xD0 //device id register +#define BMP180_GET_VERSION_REG 0xD1 //device version register + +#define BMP180_SOFT_RESET_REG 0xE0 //soft reset register +#define BMP180_SOFT_RESET_CTRL 0xB6 //soft reset control + +#define BMP180_START_MEASURMENT_REG 0xF4 //start measurment register +#define BMP180_READ_ADC_MSB_REG 0xF6 //read adc msb register +#define BMP180_READ_ADC_LSB_REG 0xF7 //read adc lsb register +#define BMP180_READ_ADC_XLSB_REG 0xF8 //read adc xlsb register + +/* BMP180_START_MEASURMENT_REG controls */ +#define BMP180_GET_TEMPERATURE_CTRL 0x2E //get temperature control +#define BMP180_GET_PRESSURE_OSS0_CTRL 0x34 //get pressure oversampling 1 time/oss0 control +#define BMP180_GET_PRESSURE_OSS1_CTRL 0x74 //get pressure oversampling 2 time/oss1 control +#define BMP180_GET_PRESSURE_OSS2_CTRL 0xB4 //get pressure oversampling 4 time/oss2 control +#define BMP180_GET_PRESSURE_OSS3_CTRL 0xF4 //get pressure oversampling 8 time/oss3 control + +/* misc */ +#define BMP180_CHIP_ID 0x55 //id number + +#define BMP180_ERROR 255 //returns 255, if communication error is occurred + +#define BMP180_ADDRESS (0x77 << 1) // HAL requires 7-bit address shifted left by 1 bit + +#define I2C_TIMEOUT 100 + +/* to store calibration coefficients */ +typedef struct +{ + int16_t bmpAC1 = 0; + int16_t bmpAC2 = 0; + int16_t bmpAC3 = 0; + uint16_t bmpAC4 = 0; + uint16_t bmpAC5 = 0; + uint16_t bmpAC6 = 0; + + int16_t bmpB1 = 0; + int16_t bmpB2 = 0; + + int16_t bmpMB = 0; + int16_t bmpMC = 0; + int16_t bmpMD = 0; +} +BMP180_CAL_COEFF; + + +class BMP180 +{ + public: + BMP180(BMP180_RESOLUTION = BMP180_ULTRAHIGHRES); //BMP180_ULTRAHIGHRES, by default + int32_t getPressure(void); //in Pa + float getTemperature(void); //in °C + int32_t getSeaLevelPressure(int16_t trueAltitude = 115); //in Pa, by default true altitude id 115 meters + void softReset(void); + uint8_t readFirmwareVersion(void); + uint8_t readDeviceID(void); + + + private: + BMP180_CAL_COEFF _calCoeff; + + uint8_t _resolution; + + bool readCalibrationCoefficients(void); + uint16_t readRawTemperature(void); + uint32_t readRawPressure(void); + int32_t computeB5(int32_t UT); + uint8_t read8(uint8_t reg); + uint16_t read16(uint8_t reg); + bool write8(uint8_t reg, uint8_t control); +}; + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/DA5578.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/DA5578.c new file mode 100644 index 0000000..e6696bb --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/DA5578.c @@ -0,0 +1,397 @@ +#include "DAC5578.h" +#include + +/** + * @brief Initialize the DAC5578 + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param hi2c: pointer to an I2C_HandleTypeDef structure + * @param i2c_addr: I2C address of the DAC + * @param resolution: DAC resolution (only 8 is valid for DAC5578) + * @param ldac_port: GPIO port for LDAC pin + * @param ldac_pin: GPIO pin for LDAC pin + * @param clr_port: GPIO port for CLR pin + * @param clr_pin: GPIO pin for CLR pin + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_Init(DAC5578_HandleTypeDef *hdac, I2C_HandleTypeDef *hi2c, uint8_t i2c_addr, + uint8_t resolution, GPIO_TypeDef *ldac_port, uint16_t ldac_pin, + GPIO_TypeDef *clr_port, uint16_t clr_pin) { + + if (hdac == NULL || hi2c == NULL) { + return false; + } + + /* DAC5578 is 8-bit only */ + hdac->resolution_bits = 8; + hdac->clear_code = DAC5578_CLR_CODE_ZERO; // Default clear to zero + + hdac->hi2c = hi2c; + hdac->i2c_addr = i2c_addr << 1; // HAL requires 7-bit address shifted left + hdac->ldac_port = ldac_port; + hdac->ldac_pin = ldac_pin; + hdac->clr_port = clr_port; + hdac->clr_pin = clr_pin; + + /* Set LDAC high (inactive) and CLR high (normal operation) */ + if (ldac_port != NULL) { + HAL_GPIO_WritePin(ldac_port, ldac_pin, GPIO_PIN_SET); + } + + if (clr_port != NULL) { + HAL_GPIO_WritePin(clr_port, clr_pin, GPIO_PIN_SET); + } + + /* Reset the DAC and enable internal reference by default */ + bool success = DAC5578_Reset(hdac); + if (success) { + success = DAC5578_SetInternalReference(hdac, true); + } + + /* Set the clear code in the device */ + if (success) { + success = DAC5578_SetClearCode(hdac, hdac->clear_code); + } + + return success; +} + +/** + * @brief Reset the DAC5578 + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_Reset(DAC5578_HandleTypeDef *hdac) { + uint8_t buffer[3]; + buffer[0] = DAC5578_CMD_RESET; + buffer[1] = 0x00; + buffer[2] = 0x00; + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + return (status == HAL_OK); +} + +/** + * @brief Write a value to a specific channel's input register + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param channel: DAC channel (0-7) + * @param value: 8-bit value to write + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_WriteChannelValue(DAC5578_HandleTypeDef *hdac, uint8_t channel, uint16_t value) { + if (channel > 7) { + return false; + } + + /* DAC5578 is 8-bit, so mask value */ + value &= 0xFF; + + return DAC5578_CommandWrite(hdac, DAC5578_CMD_WRITE | (channel & 0x7), value); +} + +/** + * @brief Update a specific channel's DAC register from input register + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param channel: DAC channel (0-7) or DAC5578_CHANNEL_BROADCAST + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_UpdateChannel(DAC5578_HandleTypeDef *hdac, uint8_t channel) { + if (channel > 7 && channel != DAC5578_CHANNEL_BROADCAST) { + return false; + } + + /* Update command with channel selection */ + uint8_t command = DAC5578_CMD_UPDATE | (channel & 0x7); + if (channel == DAC5578_CHANNEL_BROADCAST) { + command = DAC5578_CMD_UPDATE | 0x8; // Broadcast flag + } + + uint8_t buffer[3]; + buffer[0] = command; + buffer[1] = 0x00; + buffer[2] = 0x00; + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + return (status == HAL_OK); +} + +/** + * @brief Write and update a specific channel in one operation + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param channel: DAC channel (0-7) + * @param value: 8-bit value to write and update + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_WriteAndUpdateChannelValue(DAC5578_HandleTypeDef *hdac, uint8_t channel, uint16_t value) { + if (channel > 7) { + return false; + } + + /* DAC5578 is 8-bit, so mask value */ + value &= 0xFF; + + return DAC5578_CommandWrite(hdac, DAC5578_CMD_WRITE_UPDATE | (channel & 0x7), value); +} + +/** + * @brief Write the same value to all channels' input registers + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param value: 8-bit value to write to all channels + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_WriteAllChannels(DAC5578_HandleTypeDef *hdac, uint16_t value) { + /* DAC5578 is 8-bit, so mask value */ + value &= 0xFF; + + return DAC5578_CommandWrite(hdac, DAC5578_CMD_WRITE_ALL, value); +} + +/** + * @brief Read the input register value of a specific channel + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param channel: DAC channel (0-7) + * @param value: pointer to store the read value + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_ReadInputChannelValue(DAC5578_HandleTypeDef *hdac, uint8_t channel, uint16_t *value) { + if (channel > 7) { + return false; + } + + /* Note: DAC5578 has limited read capability - this reads back the input register */ + return DAC5578_CommandRead(hdac, DAC5578_CMD_WRITE | (channel & 0x7), value); +} + +/** + * @brief Read the DAC register value (current output) of a specific channel + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param channel: DAC channel (0-7) + * @param value: pointer to store the read value + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_ReadDACChannelValue(DAC5578_HandleTypeDef *hdac, uint8_t channel, uint16_t *value) { + if (channel > 7) { + return false; + } + + /* Note: DAC5578 has limited read capability - this reads back the DAC register */ + return DAC5578_CommandRead(hdac, DAC5578_CMD_UPDATE | (channel & 0x7), value); +} + +/** + * @brief Set power down mode for a specific channel + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param channel: DAC channel (0-7) + * @param mode: power down mode + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_SetPowerDownMode(DAC5578_HandleTypeDef *hdac, uint8_t channel, DAC5578_PowerDownMode_t mode) { + if (channel > 7 || mode > 3) { + return false; + } + + uint8_t buffer[3]; + buffer[0] = DAC5578_CMD_POWERDOWN | (channel & 0x7); + buffer[1] = 0x00; + buffer[2] = mode & 0x03; + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + return (status == HAL_OK); +} + +/** + * @brief Set power down mode for all channels + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param mode: power down mode + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_SetPowerDownAll(DAC5578_HandleTypeDef *hdac, DAC5578_PowerDownMode_t mode) { + if (mode > 3) { + return false; + } + + uint8_t buffer[3]; + buffer[0] = DAC5578_CMD_POWERDOWN_ALL; + buffer[1] = 0x00; + buffer[2] = mode & 0x03; + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + return (status == HAL_OK); +} + +/** + * @brief Enable or disable the internal reference + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param enable: true to enable, false to disable + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_SetInternalReference(DAC5578_HandleTypeDef *hdac, bool enable) { + uint8_t command = enable ? DAC5578_CMD_INT_REF_ENABLE : DAC5578_CMD_INT_REF_DISABLE; + uint8_t buffer[3]; + buffer[0] = command; + buffer[1] = 0x00; + buffer[2] = 0x00; + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + return (status == HAL_OK); +} + +/** + * @brief Setup LDAC mask for hardware LDAC control + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param ldac_mask: 8-bit mask where each bit corresponds to a channel + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_SetupLDAC(DAC5578_HandleTypeDef *hdac, uint8_t ldac_mask) { + uint8_t buffer[3]; + buffer[0] = DAC5578_CMD_LDAC_SETUP; + buffer[1] = 0x00; + buffer[2] = ldac_mask & 0xFF; // Each bit corresponds to a channel (0-7) + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + return (status == HAL_OK); +} + +/** + * @brief Trigger software LDAC update + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_SoftwareLDAC(DAC5578_HandleTypeDef *hdac) { + uint8_t buffer[3]; + buffer[0] = DAC5578_CMD_SOFTWARE_LDAC; + buffer[1] = 0x00; + buffer[2] = 0x00; + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + return (status == HAL_OK); +} + +/* CLR Pin Functions */ + +/** + * @brief Set the clear code that determines what happens when CLR pin is activated + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param clear_code: desired clear code behavior + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_SetClearCode(DAC5578_HandleTypeDef *hdac, DAC5578_ClearCode_t clear_code) { + if (clear_code > DAC5578_CLR_CODE_NOP) { + return false; + } + + /* The clear code is set using the RESET command with specific data bits */ + uint8_t buffer[3]; + buffer[0] = DAC5578_CMD_RESET; + buffer[1] = 0x00; + buffer[2] = (clear_code & 0x03); // Clear code in bits 1:0 + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + + if (status == HAL_OK) { + hdac->clear_code = clear_code; + return true; + } + + return false; +} + +/** + * @brief Get the current clear code setting + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @retval DAC5578_ClearCode_t: current clear code setting + */ +DAC5578_ClearCode_t DAC5578_GetClearCode(DAC5578_HandleTypeDef *hdac) { + return hdac->clear_code; +} + +/** + * @brief Activate the CLR pin (set low) to clear DAC outputs + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @retval None + */ +void DAC5578_ActivateClearPin(DAC5578_HandleTypeDef *hdac) { + if (hdac->clr_port != NULL) { + HAL_GPIO_WritePin(hdac->clr_port, hdac->clr_pin, GPIO_PIN_RESET); + } +} + +/** + * @brief Deactivate the CLR pin (set high) for normal operation + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @retval None + */ +void DAC5578_DeactivateClearPin(DAC5578_HandleTypeDef *hdac) { + if (hdac->clr_port != NULL) { + HAL_GPIO_WritePin(hdac->clr_port, hdac->clr_pin, GPIO_PIN_SET); + } +} + +/** + * @brief Pulse the CLR pin to clear all DAC outputs according to clear code + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @retval None + */ +void DAC5578_ClearOutputs(DAC5578_HandleTypeDef *hdac) { + if (hdac->clr_port != NULL) { + /* Generate a pulse on CLR pin (active low) */ + HAL_GPIO_WritePin(hdac->clr_port, hdac->clr_pin, GPIO_PIN_RESET); + HAL_Delay(1); // Hold for at least 50ns (1ms is plenty) + HAL_GPIO_WritePin(hdac->clr_port, hdac->clr_pin, GPIO_PIN_SET); + } +} + +/** + * @brief Software clear - uses I2C command to clear outputs without CLR pin + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_SoftwareClear(DAC5578_HandleTypeDef *hdac) { + /* Use the reset command with the current clear code to perform software clear */ + return DAC5578_SetClearCode(hdac, hdac->clear_code); +} + +/* Private functions */ + +/** + * @brief Write a command and value to the DAC + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param command: command byte + * @param value: 8-bit value to write + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_CommandWrite(DAC5578_HandleTypeDef *hdac, uint8_t command, uint16_t value) { + uint8_t buffer[3]; + buffer[0] = command; + buffer[1] = (value >> 8) & 0xFF; // MSB (should be 0 for 8-bit DAC) + buffer[2] = value & 0xFF; // LSB (actual 8-bit data) + + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + return (status == HAL_OK); +} + +/** + * @brief Read a value from the DAC after sending a command + * @param hdac: pointer to a DAC5578_HandleTypeDef structure + * @param command: command byte + * @param value: pointer to store the read value + * @retval bool: true if successful, false otherwise + */ +bool DAC5578_CommandRead(DAC5578_HandleTypeDef *hdac, uint8_t command, uint16_t *value) { + uint8_t buffer[3]; + + /* First write the command to set up readback */ + HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hdac->hi2c, hdac->i2c_addr, &command, 1, HAL_MAX_DELAY); + if (status != HAL_OK) { + return false; + } + + /* Then read 3 bytes back */ + status = HAL_I2C_Master_Receive(hdac->hi2c, hdac->i2c_addr, buffer, 3, HAL_MAX_DELAY); + if (status != HAL_OK) { + return false; + } + + /* Extract the 8-bit value from the response */ + *value = buffer[2] & 0xFF; + return true; +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/DAC5578.H b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/DAC5578.H new file mode 100644 index 0000000..d4c7e99 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/DAC5578.H @@ -0,0 +1,91 @@ +#ifndef __DAC5578_H +#define __DAC5578_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "stm32f7xx_hal.h" +#include + + + +extern I2C_HandleTypeDef hi2c1; + +/* Command definitions - DAC5578 specific */ +#define DAC5578_CMD_WRITE (0x0 << 4) // Write to input register +#define DAC5578_CMD_UPDATE (0x1 << 4) // Update DAC register +#define DAC5578_CMD_WRITE_UPDATE (0x2 << 4) // Write and update +#define DAC5578_CMD_WRITE_ALL (0x3 << 4) // Write to all channels +#define DAC5578_CMD_POWERDOWN (0x4 << 4) // Power down +#define DAC5578_CMD_POWERDOWN_ALL (0x5 << 4) // Power down all channels +#define DAC5578_CMD_INT_REF_ENABLE (0x6 << 4) // Enable internal reference +#define DAC5578_CMD_INT_REF_DISABLE (0x7 << 4) // Disable internal reference +#define DAC5578_CMD_RESET (0x8 << 4) // Software reset +#define DAC5578_CMD_LDAC_SETUP (0x9 << 4) // LDAC setup register +#define DAC5578_CMD_SOFTWARE_LDAC (0xA << 4) // Software LDAC trigger + +/* Broadcast channel for simultaneous updates */ +#define DAC5578_CHANNEL_BROADCAST 0x8 + +/* Power down modes */ +typedef enum { + DAC5578_PWD_NORMAL = 0, // Normal operation + DAC5578_PWD_1K = 1, // 1kΩ to GND + DAC5578_PWD_100K = 2, // 100kΩ to GND + DAC5578_PWD_HIZ = 3 // High impedance +} DAC5578_PowerDownMode_t; + +/* Clear code options - determines what happens when CLR pin is activated */ +typedef enum { + DAC5578_CLR_CODE_ZERO = 0, // Clear to zero scale (0x00) + DAC5578_CLR_CODE_MID = 1, // Clear to midscale (0x80) + DAC5578_CLR_CODE_FULL = 2, // Clear to full scale (0xFF) + DAC5578_CLR_CODE_NOP = 3 // No operation (retain current value) +} DAC5578_ClearCode_t; + +/* DAC handle structure */ +typedef struct { + I2C_HandleTypeDef *hi2c; + uint8_t i2c_addr; + uint8_t resolution_bits; + GPIO_TypeDef *ldac_port; + uint16_t ldac_pin; + GPIO_TypeDef *clr_port; + uint16_t clr_pin; + DAC5578_ClearCode_t clear_code; // Current clear code setting +} DAC5578_HandleTypeDef; + +/* Function prototypes */ +bool DAC5578_Init(DAC5578_HandleTypeDef *hdac, I2C_HandleTypeDef *hi2c, uint8_t i2c_addr, + uint8_t resolution, GPIO_TypeDef *ldac_port, uint16_t ldac_pin, + GPIO_TypeDef *clr_port, uint16_t clr_pin); +bool DAC5578_Reset(DAC5578_HandleTypeDef *hdac); +bool DAC5578_WriteChannelValue(DAC5578_HandleTypeDef *hdac, uint8_t channel, uint16_t value); +bool DAC5578_UpdateChannel(DAC5578_HandleTypeDef *hdac, uint8_t channel); +bool DAC5578_WriteAndUpdateChannelValue(DAC5578_HandleTypeDef *hdac, uint8_t channel, uint16_t value); +bool DAC5578_WriteAllChannels(DAC5578_HandleTypeDef *hdac, uint16_t value); +bool DAC5578_ReadInputChannelValue(DAC5578_HandleTypeDef *hdac, uint8_t channel, uint16_t *value); +bool DAC5578_ReadDACChannelValue(DAC5578_HandleTypeDef *hdac, uint8_t channel, uint16_t *value); +bool DAC5578_SetPowerDownMode(DAC5578_HandleTypeDef *hdac, uint8_t channel, DAC5578_PowerDownMode_t mode); +bool DAC5578_SetPowerDownAll(DAC5578_HandleTypeDef *hdac, DAC5578_PowerDownMode_t mode); +bool DAC5578_SetInternalReference(DAC5578_HandleTypeDef *hdac, bool enable); +bool DAC5578_SetupLDAC(DAC5578_HandleTypeDef *hdac, uint8_t ldac_mask); +bool DAC5578_SoftwareLDAC(DAC5578_HandleTypeDef *hdac); + +/* CLR Pin Functions */ +bool DAC5578_SetClearCode(DAC5578_HandleTypeDef *hdac, DAC5578_ClearCode_t clear_code); +DAC5578_ClearCode_t DAC5578_GetClearCode(DAC5578_HandleTypeDef *hdac); +void DAC5578_ActivateClearPin(DAC5578_HandleTypeDef *hdac); +void DAC5578_DeactivateClearPin(DAC5578_HandleTypeDef *hdac); +void DAC5578_ClearOutputs(DAC5578_HandleTypeDef *hdac); // Pulse CLR pin to clear outputs + +/* Private functions */ +bool DAC5578_CommandWrite(DAC5578_HandleTypeDef *hdac, uint8_t command, uint16_t value); +bool DAC5578_CommandRead(DAC5578_HandleTypeDef *hdac, uint8_t command, uint16_t *value); + +#ifdef __cplusplus +} +#endif + +#endif /* __DAC5578_H */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/GY_85_HAL.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/GY_85_HAL.c new file mode 100644 index 0000000..2c735fd --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/GY_85_HAL.c @@ -0,0 +1,121 @@ +#include "GY_85_HAL.h" + +static int16_t g_offx = 0, g_offy = 0, g_offz = 0; + +// ---------------- Internal Functions ---------------- // +static void GY85_SetAccelerometer(void); +static void GY85_ReadAccelerometer(GY85_t *imu); +static void GY85_SetCompass(void); +static void GY85_ReadCompass(GY85_t *imu); +static void GY85_SetGyro(void); +static void GY85_GyroCalibrate(void); +static void GY85_ReadGyro(GY85_t *imu); + +// ---------------- Initialization ---------------- // +void GY85_Init(void) +{ + GY85_SetAccelerometer(); + GY85_SetCompass(); + GY85_SetGyro(); +} + +// ---------------- Update All Sensors ---------------- // +void GY85_Update(GY85_t *imu) +{ + GY85_ReadAccelerometer(imu); + GY85_ReadCompass(imu); + GY85_ReadGyro(imu); +} + +// ---------------- Accelerometer ---------------- // +static void GY85_SetAccelerometer(void) +{ + uint8_t data[2]; + data[0] = 0x31; data[1] = 0x01; + HAL_I2C_Master_Transmit(&hi2c3, ADXL345_ADDR, data, 2, HAL_MAX_DELAY); + + data[0] = 0x2D; data[1] = 0x08; + HAL_I2C_Master_Transmit(&hi2c3, ADXL345_ADDR, data, 2, HAL_MAX_DELAY); +} + +static void GY85_ReadAccelerometer(GY85_t *imu) +{ + uint8_t reg = 0x32; + uint8_t buf[6]; + HAL_I2C_Master_Transmit(&hi2c3, ADXL345_ADDR, ®, 1, HAL_MAX_DELAY); + HAL_I2C_Master_Receive(&hi2c3, ADXL345_ADDR, buf, 6, HAL_MAX_DELAY); + + imu->ax = (int16_t)((buf[1] << 8) | buf[0]); + imu->ay = (int16_t)((buf[3] << 8) | buf[2]); + imu->az = (int16_t)((buf[5] << 8) | buf[4]); +} + +// ---------------- Compass ---------------- // +static void GY85_SetCompass(void) +{ + uint8_t data[2] = {0x02, 0x00}; + HAL_I2C_Master_Transmit(&hi2c3, HMC5883_ADDR, data, 2, HAL_MAX_DELAY); +} + +static void GY85_ReadCompass(GY85_t *imu) +{ + uint8_t reg = 0x03; + uint8_t buf[6]; + HAL_I2C_Master_Transmit(&hi2c3, HMC5883_ADDR, ®, 1, HAL_MAX_DELAY); + HAL_I2C_Master_Receive(&hi2c3, HMC5883_ADDR, buf, 6, HAL_MAX_DELAY); + + imu->mx = (int16_t)((buf[0] << 8) | buf[1]); + imu->mz = (int16_t)((buf[2] << 8) | buf[3]); + imu->my = (int16_t)((buf[4] << 8) | buf[5]); +} + +// ---------------- Gyroscope ---------------- // +static void GY85_SetGyro(void) +{ + uint8_t data[2]; + data[0] = 0x3E; data[1] = 0x00; + HAL_I2C_Master_Transmit(&hi2c3, ITG3200_ADDR, data, 2, HAL_MAX_DELAY); + + data[0] = 0x15; data[1] = 0x07; + HAL_I2C_Master_Transmit(&hi2c3, ITG3200_ADDR, data, 2, HAL_MAX_DELAY); + + data[0] = 0x16; data[1] = 0x1E; + HAL_I2C_Master_Transmit(&hi2c3, ITG3200_ADDR, data, 2, HAL_MAX_DELAY); + + data[0] = 0x17; data[1] = 0x00; + HAL_I2C_Master_Transmit(&hi2c3, ITG3200_ADDR, data, 2, HAL_MAX_DELAY); + + HAL_Delay(10); + GY85_GyroCalibrate(); +} + +static void GY85_GyroCalibrate(void) +{ + int32_t tmpx = 0, tmpy = 0, tmpz = 0; + GY85_t imu; + + for(uint8_t i = 0; i < 10; i++) + { + HAL_Delay(10); + GY85_ReadGyro(&imu); + tmpx += imu.gx; + tmpy += imu.gy; + tmpz += imu.gz; + } + + g_offx = tmpx / 10; + g_offy = tmpy / 10; + g_offz = tmpz / 10; +} + +static void GY85_ReadGyro(GY85_t *imu) +{ + uint8_t reg = 0x1B; + uint8_t buf[8]; + HAL_I2C_Master_Transmit(&hi2c3, ITG3200_ADDR, ®, 1, HAL_MAX_DELAY); + HAL_I2C_Master_Receive(&hi2c3, ITG3200_ADDR, buf, 8, HAL_MAX_DELAY); + + imu->gx = ((int16_t)((buf[2] << 8) | buf[3])) - g_offx; + imu->gy = ((int16_t)((buf[4] << 8) | buf[5])) - g_offy; + imu->gz = ((int16_t)((buf[6] << 8) | buf[7])) - g_offz; +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/GY_85_HAL.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/GY_85_HAL.h new file mode 100644 index 0000000..9af4e50 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/GY_85_HAL.h @@ -0,0 +1,25 @@ +#ifndef __GY_85_HAL_H__ +#define __GY_85_HAL_H__ + +#include "stm32f7xx_hal.h" // change depending on MCU family +#include + +#define ADXL345_ADDR (0x53 << 1) +#define HMC5883_ADDR (0x1E << 1) +#define ITG3200_ADDR (0x68 << 1) + +extern I2C_HandleTypeDef hi2c3; + +// Struct to hold all sensor data +typedef struct { + int16_t ax, ay, az; // accelerometer + float gx, gy, gz; // gyroscope + int16_t mx, my, mz; // magnetometer +} GY85_t; + +// Public API +void GY85_Init(void); +void GY85_Update(GY85_t *imu); // reads all sensors and stores in struct + +#endif + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.cpp b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.cpp new file mode 100644 index 0000000..df34c25 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.cpp @@ -0,0 +1,113 @@ +#include "RadarSettings.h" +#include + +RadarSettings::RadarSettings() { + resetToDefaults(); +} + +void RadarSettings::resetToDefaults() { + system_frequency = 10.0e9; // 10 GHz + chirp_duration_1 = 30.0e-6; // 30 s + chirp_duration_2 = 0.5e-6; // 0.5 s + chirps_per_position = 32; + freq_min = 10.0e6; // 10 MHz + freq_max = 30.0e6; // 30 MHz + prf1 = 1000.0; // 1 kHz + prf2 = 2000.0; // 2 kHz + max_distance = 50000.0; // 50 km + map_size = 50000.0; // 50 km + + settings_valid = true; +} + +bool RadarSettings::parseFromUSB(const uint8_t* data, uint32_t length) { + // Minimum packet size: "SET" + 8 doubles + 1 uint32_t + "END" = 3 + 8*8 + 4 + 3 = 74 bytes + if (data == nullptr || length < 74) { + settings_valid = false; + return false; + } + + // Check for start marker "SET" + if (memcmp(data, "SET", 3) != 0) { + settings_valid = false; + return false; + } + + // Check for end marker "END" + if (memcmp(data + length - 3, "END", 3) != 0) { + settings_valid = false; + return false; + } + + uint32_t offset = 3; // Skip "SET" + + // Extract all parameters in order + system_frequency = extractDouble(data + offset); + offset += 8; + + chirp_duration_1 = extractDouble(data + offset); + offset += 8; + + chirp_duration_2 = extractDouble(data + offset); + offset += 8; + + chirps_per_position = extractUint32(data + offset); + offset += 4; + + freq_min = extractDouble(data + offset); + offset += 8; + + freq_max = extractDouble(data + offset); + offset += 8; + + prf1 = extractDouble(data + offset); + offset += 8; + + prf2 = extractDouble(data + offset); + offset += 8; + + max_distance = extractDouble(data + offset); + offset += 8; + + map_size = extractDouble(data + offset); + + // Validate the received settings + settings_valid = validateSettings(); + + return settings_valid; +} + +bool RadarSettings::validateSettings() { + // Check for reasonable value ranges + if (system_frequency < 1e9 || system_frequency > 100e9) return false; + if (chirp_duration_1 < 1e-6 || chirp_duration_1 > 1000e-6) return false; + if (chirp_duration_2 < 0.1e-6 || chirp_duration_2 > 10e-6) return false; + if (chirps_per_position < 1 || chirps_per_position > 256) return false; + if (freq_min < 1e6 || freq_min > 100e6) return false; + if (freq_max <= freq_min || freq_max > 100e6) return false; + if (prf1 < 100 || prf1 > 10000) return false; + if (prf2 < 100 || prf2 > 10000) return false; + if (max_distance < 100 || max_distance > 100000) return false; + if (map_size < 1000 || map_size > 200000) return false; + + return true; +} + +double RadarSettings::extractDouble(const uint8_t* data) { + uint64_t bits = 0; + for (int i = 0; i < 8; i++) { + bits = (bits << 8) | data[i]; + } + + double value; + memcpy(&value, &bits, sizeof(double)); + return value; +} + +uint32_t RadarSettings::extractUint32(const uint8_t* data) { + uint32_t value = 0; + for (int i = 0; i < 4; i++) { + value = (value << 8) | data[i]; + } + return value; +} \ No newline at end of file diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.h new file mode 100644 index 0000000..a2ae79d --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.h @@ -0,0 +1,53 @@ +#ifndef RADARSETTINGS_H +#define RADARSETTINGS_H + +#include + +class RadarSettings { +public: + // Default constructor with initial values + RadarSettings(); + + // Parse settings from USB CDC data + bool parseFromUSB(const uint8_t* data, uint32_t length); + + // Getters for all settings + double getSystemFrequency() const { return system_frequency; } + double getChirpDuration1() const { return chirp_duration_1; } + double getChirpDuration2() const { return chirp_duration_2; } + uint32_t getChirpsPerPosition() const { return chirps_per_position; } + double getFreqMin() const { return freq_min; } + double getFreqMax() const { return freq_max; } + double getPRF1() const { return prf1; } + double getPRF2() const { return prf2; } + double getMaxDistance() const { return max_distance; } + double getMapSize() const { return map_size; } + + // Check if settings are valid + bool isValid() const { return settings_valid; } + + // Reset to default values + void resetToDefaults(); + +private: + // Radar system parameters + double system_frequency; // Hz + double chirp_duration_1; // seconds (long chirp) + double chirp_duration_2; // seconds (short chirp) + uint32_t chirps_per_position; + double freq_min; // Hz + double freq_max; // Hz + double prf1; // Hz + double prf2; // Hz + double max_distance; // meters + double map_size; // meters + + bool settings_valid; + + // Helper methods + bool validateSettings(); + double extractDouble(const uint8_t* data); + uint32_t extractUint32(const uint8_t* data); +}; + +#endif // RADARSETTINGS_H \ No newline at end of file diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPS++.cpp b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPS++.cpp new file mode 100644 index 0000000..3a930e3 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPS++.cpp @@ -0,0 +1,509 @@ +/* +TinyGPS++ - a small GPS library for Arduino providing universal NMEA parsing +Based on work by and "distanceBetween" and "courseTo" courtesy of Maarten Lamers. +Suggestion to add satellites, courseTo(), and cardinal() by Matt Monson. +Location precision improvements suggested by Wayne Holder. +Copyright (C) 2008-2024 Mikal Hart +All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "TinyGPS++.h" + +#include +#include +#include +#include + +#define _RMCterm "RMC" +#define _GGAterm "GGA" + + +TinyGPSPlus::TinyGPSPlus() + : parity(0) + , isChecksumTerm(false) + , curSentenceType(GPS_SENTENCE_OTHER) + , curTermNumber(0) + , curTermOffset(0) + , sentenceHasFix(false) + , customElts(0) + , customCandidates(0) + , encodedCharCount(0) + , sentencesWithFixCount(0) + , failedChecksumCount(0) + , passedChecksumCount(0) +{ + term[0] = '\0'; +} + +// +// public methods +// + +bool TinyGPSPlus::encode(char c) +{ + ++encodedCharCount; + + switch(c) + { + case ',': // term terminators + parity ^= (uint8_t)c; + case '\r': + case '\n': + case '*': + { + bool isValidSentence = false; + if (curTermOffset < sizeof(term)) + { + term[curTermOffset] = 0; + isValidSentence = endOfTermHandler(); + } + ++curTermNumber; + curTermOffset = 0; + isChecksumTerm = c == '*'; + return isValidSentence; + } + break; + + case '$': // sentence begin + curTermNumber = curTermOffset = 0; + parity = 0; + curSentenceType = GPS_SENTENCE_OTHER; + isChecksumTerm = false; + sentenceHasFix = false; + return false; + + default: // ordinary characters + if (curTermOffset < sizeof(term) - 1) + term[curTermOffset++] = c; + if (!isChecksumTerm) + parity ^= c; + return false; + } + + return false; +} + +// +// internal utilities +// +int TinyGPSPlus::fromHex(char a) +{ + if (a >= 'A' && a <= 'F') + return a - 'A' + 10; + else if (a >= 'a' && a <= 'f') + return a - 'a' + 10; + else + return a - '0'; +} + +// static +// Parse a (potentially negative) number with up to 2 decimal digits -xxxx.yy +int32_t TinyGPSPlus::parseDecimal(const char *term) +{ + bool negative = *term == '-'; + if (negative) ++term; + int32_t ret = 100 * (int32_t)atol(term); + while (isdigit(*term)) ++term; + if (*term == '.' && isdigit(term[1])) + { + ret += 10 * (term[1] - '0'); + if (isdigit(term[2])) + ret += term[2] - '0'; + } + return negative ? -ret : ret; +} + +// static +// Parse degrees in that funny NMEA format DDMM.MMMM +void TinyGPSPlus::parseDegrees(const char *term, RawDegrees °) +{ + uint32_t leftOfDecimal = (uint32_t)atol(term); + uint16_t minutes = (uint16_t)(leftOfDecimal % 100); + uint32_t multiplier = 10000000UL; + uint32_t tenMillionthsOfMinutes = minutes * multiplier; + + deg.deg = (int16_t)(leftOfDecimal / 100); + + while (isdigit(*term)) + ++term; + + if (*term == '.') + while (isdigit(*++term)) + { + multiplier /= 10; + tenMillionthsOfMinutes += (*term - '0') * multiplier; + } + + deg.billionths = (5 * tenMillionthsOfMinutes + 1) / 3; + deg.negative = false; +} + +#define COMBINE(sentence_type, term_number) (((unsigned)(sentence_type) << 5) | term_number) + +// Processes a just-completed term +// Returns true if new sentence has just passed checksum test and is validated +bool TinyGPSPlus::endOfTermHandler() +{ + // If it's the checksum term, and the checksum checks out, commit + if (isChecksumTerm) + { + uint8_t checksum = 16 * fromHex(term[0]) + fromHex(term[1]); + if (checksum == parity) + { + passedChecksumCount++; + if (sentenceHasFix) + ++sentencesWithFixCount; + + switch(curSentenceType) + { + case GPS_SENTENCE_RMC: + date.commit(); + time.commit(); + if (sentenceHasFix) + { + location.commit(); + speed.commit(); + course.commit(); + } + break; + case GPS_SENTENCE_GGA: + time.commit(); + if (sentenceHasFix) + { + location.commit(); + altitude.commit(); + } + satellites.commit(); + hdop.commit(); + break; + } + + // Commit all custom listeners of this sentence type + for (TinyGPSCustom *p = customCandidates; p != NULL && strcmp(p->sentenceName, customCandidates->sentenceName) == 0; p = p->next) + p->commit(); + return true; + } + + else + { + ++failedChecksumCount; + } + + return false; + } + + // the first term determines the sentence type + if (curTermNumber == 0) + { + if (term[0] == 'G' && strchr("PNABL", term[1]) != NULL && !strcmp(term + 2, _RMCterm)) + curSentenceType = GPS_SENTENCE_RMC; + else if (term[0] == 'G' && strchr("PNABL", term[1]) != NULL && !strcmp(term + 2, _GGAterm)) + curSentenceType = GPS_SENTENCE_GGA; + else + curSentenceType = GPS_SENTENCE_OTHER; + + // Any custom candidates of this sentence type? + for (customCandidates = customElts; customCandidates != NULL && strcmp(customCandidates->sentenceName, term) < 0; customCandidates = customCandidates->next); + if (customCandidates != NULL && strcmp(customCandidates->sentenceName, term) > 0) + customCandidates = NULL; + + return false; + } + + if (curSentenceType != GPS_SENTENCE_OTHER && term[0]) + switch(COMBINE(curSentenceType, curTermNumber)) + { + case COMBINE(GPS_SENTENCE_RMC, 1): // Time in both sentences + case COMBINE(GPS_SENTENCE_GGA, 1): + time.setTime(term); + break; + case COMBINE(GPS_SENTENCE_RMC, 2): // RMC validity + sentenceHasFix = term[0] == 'A'; + break; + case COMBINE(GPS_SENTENCE_RMC, 3): // Latitude + case COMBINE(GPS_SENTENCE_GGA, 2): + location.setLatitude(term); + break; + case COMBINE(GPS_SENTENCE_RMC, 4): // N/S + case COMBINE(GPS_SENTENCE_GGA, 3): + location.rawNewLatData.negative = term[0] == 'S'; + break; + case COMBINE(GPS_SENTENCE_RMC, 5): // Longitude + case COMBINE(GPS_SENTENCE_GGA, 4): + location.setLongitude(term); + break; + case COMBINE(GPS_SENTENCE_RMC, 6): // E/W + case COMBINE(GPS_SENTENCE_GGA, 5): + location.rawNewLngData.negative = term[0] == 'W'; + break; + case COMBINE(GPS_SENTENCE_RMC, 7): // Speed (RMC) + speed.set(term); + break; + case COMBINE(GPS_SENTENCE_RMC, 8): // Course (RMC) + course.set(term); + break; + case COMBINE(GPS_SENTENCE_RMC, 9): // Date (RMC) + date.setDate(term); + break; + case COMBINE(GPS_SENTENCE_GGA, 6): // Fix data (GGA) + sentenceHasFix = term[0] > '0'; + location.newFixQuality = (TinyGPSLocation::Quality)term[0]; + break; + case COMBINE(GPS_SENTENCE_GGA, 7): // Satellites used (GGA) + satellites.set(term); + break; + case COMBINE(GPS_SENTENCE_GGA, 8): // HDOP + hdop.set(term); + break; + case COMBINE(GPS_SENTENCE_GGA, 9): // Altitude (GGA) + altitude.set(term); + break; + case COMBINE(GPS_SENTENCE_RMC, 12): + location.newFixMode = (TinyGPSLocation::Mode)term[0]; + break; + } + + // Set custom values as needed + for (TinyGPSCustom *p = customCandidates; p != NULL && strcmp(p->sentenceName, customCandidates->sentenceName) == 0 && p->termNumber <= curTermNumber; p = p->next) + if (p->termNumber == curTermNumber) + p->set(term); + + return false; +} + +/* static */ +double TinyGPSPlus::distanceBetween(double lat1, double long1, double lat2, double long2) +{ + // returns distance in meters between two positions, both specified + // as signed decimal-degrees latitude and longitude. Uses great-circle + // distance computation for hypothetical sphere of radius 6371009 meters. + // Because Earth is no exact sphere, rounding errors may be up to 0.5%. + // Courtesy of Maarten Lamers + double delta = (long1-long2)* (PI / 180); + double sdlong = sin(delta); + double cdlong = cos(delta); + lat1 = (lat1)* (PI / 180); + lat2 = (lat2)* (PI / 180); + double slat1 = sin(lat1); + double clat1 = cos(lat1); + double slat2 = sin(lat2); + double clat2 = cos(lat2); + delta = (clat1 * slat2) - (slat1 * clat2 * cdlong); + delta = delta*delta; + delta += (clat2 * sdlong)*(clat2 * sdlong); + delta = sqrt(delta); + double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong); + delta = atan2(delta, denom); + return delta * _GPS_EARTH_MEAN_RADIUS; +} + +double TinyGPSPlus::courseTo(double lat1, double long1, double lat2, double long2) +{ + // returns course in degrees (North=0, West=270) from position 1 to position 2, + // both specified as signed decimal-degrees latitude and longitude. + // Because Earth is no exact sphere, calculated course may be off by a tiny fraction. + // Courtesy of Maarten Lamers + double dlon = (PI/180)*(long2-long1); + lat1 = (PI/180)*(lat1); + lat2 = (PI/180)*(lat2); + double a1 = sin(dlon) * cos(lat2); + double a2 = sin(lat1) * cos(lat2) * cos(dlon); + a2 = cos(lat1) * sin(lat2) - a2; + a2 = atan2(a1, a2); + if (a2 < 0.0) + { + a2 += TWO_PI; + } + return 180/PI*(a2); +} + +const char *TinyGPSPlus::cardinal(double course) +{ + static const char* directions[] = {"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"}; + int direction = (int)((course + 11.25f) / 22.5f); + return directions[direction % 16]; +} + +void TinyGPSLocation::commit() +{ + rawLatData = rawNewLatData; + rawLngData = rawNewLngData; + fixQuality = newFixQuality; + fixMode = newFixMode; + lastCommitTime = HAL_GetTick(); + valid = updated = true; +} + +void TinyGPSLocation::setLatitude(const char *term) +{ + TinyGPSPlus::parseDegrees(term, rawNewLatData); +} + +void TinyGPSLocation::setLongitude(const char *term) +{ + TinyGPSPlus::parseDegrees(term, rawNewLngData); +} + +double TinyGPSLocation::lat() +{ + updated = false; + double ret = rawLatData.deg + rawLatData.billionths / 1000000000.0; + return rawLatData.negative ? -ret : ret; +} + +double TinyGPSLocation::lng() +{ + updated = false; + double ret = rawLngData.deg + rawLngData.billionths / 1000000000.0; + return rawLngData.negative ? -ret : ret; +} + +void TinyGPSDate::commit() +{ + date = newDate; + lastCommitTime = HAL_GetTick(); + valid = updated = true; +} + +void TinyGPSTime::commit() +{ + time = newTime; + lastCommitTime = HAL_GetTick(); + valid = updated = true; +} + +void TinyGPSTime::setTime(const char *term) +{ + newTime = (uint32_t)TinyGPSPlus::parseDecimal(term); +} + +void TinyGPSDate::setDate(const char *term) +{ + newDate = atol(term); +} + +uint16_t TinyGPSDate::year() +{ + updated = false; + uint16_t year = date % 100; + return year + 2000; +} + +uint8_t TinyGPSDate::month() +{ + updated = false; + return (date / 100) % 100; +} + +uint8_t TinyGPSDate::day() +{ + updated = false; + return date / 10000; +} + +uint8_t TinyGPSTime::hour() +{ + updated = false; + return time / 1000000; +} + +uint8_t TinyGPSTime::minute() +{ + updated = false; + return (time / 10000) % 100; +} + +uint8_t TinyGPSTime::second() +{ + updated = false; + return (time / 100) % 100; +} + +uint8_t TinyGPSTime::centisecond() +{ + updated = false; + return time % 100; +} + +void TinyGPSDecimal::commit() +{ + val = newval; + lastCommitTime = HAL_GetTick(); + valid = updated = true; +} + +void TinyGPSDecimal::set(const char *term) +{ + newval = TinyGPSPlus::parseDecimal(term); +} + +void TinyGPSInteger::commit() +{ + val = newval; + lastCommitTime = HAL_GetTick(); + valid = updated = true; +} + +void TinyGPSInteger::set(const char *term) +{ + newval = atol(term); +} + +TinyGPSCustom::TinyGPSCustom(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber) +{ + begin(gps, _sentenceName, _termNumber); +} + +void TinyGPSCustom::begin(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber) +{ + lastCommitTime = 0; + updated = valid = false; + sentenceName = _sentenceName; + termNumber = _termNumber; + memset(stagingBuffer, '\0', sizeof(stagingBuffer)); + memset(buffer, '\0', sizeof(buffer)); + + // Insert this item into the GPS tree + gps.insertCustom(this, _sentenceName, _termNumber); +} + +void TinyGPSCustom::commit() +{ + strcpy(this->buffer, this->stagingBuffer); + lastCommitTime = HAL_GetTick(); + valid = updated = true; +} + +void TinyGPSCustom::set(const char *term) +{ + strncpy(this->stagingBuffer, term, sizeof(this->stagingBuffer) - 1); +} + +void TinyGPSPlus::insertCustom(TinyGPSCustom *pElt, const char *sentenceName, int termNumber) +{ + TinyGPSCustom **ppelt; + + for (ppelt = &this->customElts; *ppelt != NULL; ppelt = &(*ppelt)->next) + { + int cmp = strcmp(sentenceName, (*ppelt)->sentenceName); + if (cmp < 0 || (cmp == 0 && termNumber < (*ppelt)->termNumber)) + break; + } + + pElt->next = *ppelt; + *ppelt = pElt; +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPS++.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPS++.h new file mode 100644 index 0000000..28fd30b --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPS++.h @@ -0,0 +1,289 @@ +/* +TinyGPS++ - a small GPS library for Arduino providing universal NMEA parsing +Based on work by and "distanceBetween" and "courseTo" courtesy of Maarten Lamers. +Suggestion to add satellites, courseTo(), and cardinal() by Matt Monson. +Location precision improvements suggested by Wayne Holder. +Copyright (C) 2008-2024 Mikal Hart +All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + + +#ifndef __TinyGPSPlus_h +#define __TinyGPSPlus_h + +#include +#include +#include "stm32f7xx_hal.h" + + +#define _GPS_VERSION "1.1.0" // software version of this library +#define _GPS_MPH_PER_KNOT 1.15077945 +#define _GPS_MPS_PER_KNOT 0.51444444 +#define _GPS_KMPH_PER_KNOT 1.852 +#define _GPS_MILES_PER_METER 0.00062137112 +#define _GPS_KM_PER_METER 0.001 +#define _GPS_FEET_PER_METER 3.2808399 +#define _GPS_MAX_FIELD_SIZE 15 +#define _GPS_EARTH_MEAN_RADIUS 6371009 // old: 6372795 + +#define PI 3.14159265359 +#define TWO_PI 6.28318530718 + +struct RawDegrees +{ + uint16_t deg; + uint32_t billionths; + bool negative; +public: + RawDegrees() : deg(0), billionths(0), negative(false) + {} +}; + +struct TinyGPSLocation +{ + friend class TinyGPSPlus; +public: + enum Quality { Invalid = '0', GPS = '1', DGPS = '2', PPS = '3', RTK = '4', FloatRTK = '5', Estimated = '6', Manual = '7', Simulated = '8' }; + enum Mode { N = 'N', A = 'A', D = 'D', E = 'E'}; + + bool isValid() const { return valid; } + bool isUpdated() const { return updated; } + uint32_t age() const { return valid ? HAL_GetTick() - lastCommitTime : (uint32_t)ULONG_MAX; } + const RawDegrees &rawLat() { updated = false; return rawLatData; } + const RawDegrees &rawLng() { updated = false; return rawLngData; } + double lat(); + double lng(); + Quality FixQuality() { updated = false; return fixQuality; } + Mode FixMode() { updated = false; return fixMode; } + + TinyGPSLocation() : valid(false), updated(false), fixQuality(Invalid), fixMode(N) + {} + +private: + bool valid, updated; + RawDegrees rawLatData, rawLngData, rawNewLatData, rawNewLngData; + Quality fixQuality, newFixQuality; + Mode fixMode, newFixMode; + uint32_t lastCommitTime; + void commit(); + void setLatitude(const char *term); + void setLongitude(const char *term); +}; + +struct TinyGPSDate +{ + friend class TinyGPSPlus; +public: + bool isValid() const { return valid; } + bool isUpdated() const { return updated; } + uint32_t age() const { return valid ? HAL_GetTick() - lastCommitTime : (uint32_t)ULONG_MAX; } + + uint32_t value() { updated = false; return date; } + uint16_t year(); + uint8_t month(); + uint8_t day(); + + TinyGPSDate() : valid(false), updated(false), date(0) + {} + +private: + bool valid, updated; + uint32_t date, newDate; + uint32_t lastCommitTime; + void commit(); + void setDate(const char *term); +}; + +struct TinyGPSTime +{ + friend class TinyGPSPlus; +public: + bool isValid() const { return valid; } + bool isUpdated() const { return updated; } + uint32_t age() const { return valid ? HAL_GetTick() - lastCommitTime : (uint32_t)ULONG_MAX; } + + uint32_t value() { updated = false; return time; } + uint8_t hour(); + uint8_t minute(); + uint8_t second(); + uint8_t centisecond(); + + TinyGPSTime() : valid(false), updated(false), time(0) + {} + +private: + bool valid, updated; + uint32_t time, newTime; + uint32_t lastCommitTime; + void commit(); + void setTime(const char *term); +}; + +struct TinyGPSDecimal +{ + friend class TinyGPSPlus; +public: + bool isValid() const { return valid; } + bool isUpdated() const { return updated; } + uint32_t age() const { return valid ? HAL_GetTick() - lastCommitTime : (uint32_t)ULONG_MAX; } + int32_t value() { updated = false; return val; } + + TinyGPSDecimal() : valid(false), updated(false), val(0) + {} + +private: + bool valid, updated; + uint32_t lastCommitTime; + int32_t val, newval; + void commit(); + void set(const char *term); +}; + +struct TinyGPSInteger +{ + friend class TinyGPSPlus; +public: + bool isValid() const { return valid; } + bool isUpdated() const { return updated; } + uint32_t age() const { return valid ? HAL_GetTick() - lastCommitTime : (uint32_t)ULONG_MAX; } + uint32_t value() { updated = false; return val; } + + TinyGPSInteger() : valid(false), updated(false), val(0) + {} + +private: + bool valid, updated; + uint32_t lastCommitTime; + uint32_t val, newval; + void commit(); + void set(const char *term); +}; + +struct TinyGPSSpeed : TinyGPSDecimal +{ + double knots() { return value() / 100.0; } + double mph() { return _GPS_MPH_PER_KNOT * value() / 100.0; } + double mps() { return _GPS_MPS_PER_KNOT * value() / 100.0; } + double kmph() { return _GPS_KMPH_PER_KNOT * value() / 100.0; } +}; + +struct TinyGPSCourse : public TinyGPSDecimal +{ + double deg() { return value() / 100.0; } +}; + +struct TinyGPSAltitude : TinyGPSDecimal +{ + double meters() { return value() / 100.0; } + double miles() { return _GPS_MILES_PER_METER * value() / 100.0; } + double kilometers() { return _GPS_KM_PER_METER * value() / 100.0; } + double feet() { return _GPS_FEET_PER_METER * value() / 100.0; } +}; + +struct TinyGPSHDOP : TinyGPSDecimal +{ + double hdop() { return value() / 100.0; } +}; + +class TinyGPSPlus; +class TinyGPSCustom +{ +public: + TinyGPSCustom() {}; + TinyGPSCustom(TinyGPSPlus &gps, const char *sentenceName, int termNumber); + void begin(TinyGPSPlus &gps, const char *_sentenceName, int _termNumber); + + bool isUpdated() const { return updated; } + bool isValid() const { return valid; } + uint32_t age() const { return valid ? HAL_GetTick() - lastCommitTime : (uint32_t)ULONG_MAX; } + const char *value() { updated = false; return buffer; } + +private: + void commit(); + void set(const char *term); + + char stagingBuffer[_GPS_MAX_FIELD_SIZE + 1]; + char buffer[_GPS_MAX_FIELD_SIZE + 1]; + unsigned long lastCommitTime; + bool valid, updated; + const char *sentenceName; + int termNumber; + friend class TinyGPSPlus; + TinyGPSCustom *next; +}; + +class TinyGPSPlus +{ +public: + TinyGPSPlus(); + bool encode(char c); // process one character received from GPS + TinyGPSPlus &operator << (char c) {encode(c); return *this;} + + TinyGPSLocation location; + TinyGPSDate date; + TinyGPSTime time; + TinyGPSSpeed speed; + TinyGPSCourse course; + TinyGPSAltitude altitude; + TinyGPSInteger satellites; + TinyGPSHDOP hdop; + + static const char *libraryVersion() { return _GPS_VERSION; } + + static double distanceBetween(double lat1, double long1, double lat2, double long2); + static double courseTo(double lat1, double long1, double lat2, double long2); + static const char *cardinal(double course); + + static int32_t parseDecimal(const char *term); + static void parseDegrees(const char *term, RawDegrees °); + + uint32_t charsProcessed() const { return encodedCharCount; } + uint32_t sentencesWithFix() const { return sentencesWithFixCount; } + uint32_t failedChecksum() const { return failedChecksumCount; } + uint32_t passedChecksum() const { return passedChecksumCount; } + +private: + enum {GPS_SENTENCE_GGA, GPS_SENTENCE_RMC, GPS_SENTENCE_OTHER}; + + // parsing state variables + uint8_t parity; + bool isChecksumTerm; + char term[_GPS_MAX_FIELD_SIZE]; + uint8_t curSentenceType; + uint8_t curTermNumber; + uint8_t curTermOffset; + bool sentenceHasFix; + + // custom element support + friend class TinyGPSCustom; + TinyGPSCustom *customElts; + TinyGPSCustom *customCandidates; + void insertCustom(TinyGPSCustom *pElt, const char *sentenceName, int index); + + // statistics + uint32_t encodedCharCount; + uint32_t sentencesWithFixCount; + uint32_t failedChecksumCount; + uint32_t passedChecksumCount; + + // internal utilities + int fromHex(char a); + bool endOfTermHandler(); +}; + +#endif // def(__TinyGPSPlus_h) diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPSPlus.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPSPlus.h new file mode 100644 index 0000000..23d9fef --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/TinyGPSPlus.h @@ -0,0 +1,26 @@ +/* +TinyGPSPlus - a small GPS library for Arduino providing universal NMEA parsing +Based on work by and "distanceBetween" and "courseTo" courtesy of Maarten Lamers. +Suggestion to add satellites, courseTo(), and cardinal() by Matt Monson. +Location precision improvements suggested by Wayne Holder. +Copyright (C) 2008-2024 Mikal Hart +All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef __TinyGPSPlus_h +#include "TinyGPS++.h" +#endif \ No newline at end of file diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/USBHandler.cpp b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/USBHandler.cpp new file mode 100644 index 0000000..2e56eb5 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/USBHandler.cpp @@ -0,0 +1,93 @@ +#include "USBHandler.h" +#include + +USBHandler::USBHandler() { + reset(); +} + +void USBHandler::reset() { + current_state = USBState::WAITING_FOR_START; + start_flag_received = false; + buffer_index = 0; + current_settings.resetToDefaults(); +} + +void USBHandler::processUSBData(const uint8_t* data, uint32_t length) { + if (data == nullptr || length == 0) { + return; + } + + switch (current_state) { + case USBState::WAITING_FOR_START: + processStartFlag(data, length); + break; + + case USBState::RECEIVING_SETTINGS: + processSettingsData(data, length); + break; + + case USBState::READY_FOR_DATA: + // Ready to receive radar data commands + // Add additional command processing here if needed + break; + } +} + +void USBHandler::processStartFlag(const uint8_t* data, uint32_t length) { + // Start flag: bytes [23, 46, 158, 237] + const uint8_t START_FLAG[] = {23, 46, 158, 237}; + + // Check if start flag is in the received data + for (uint32_t i = 0; i <= length - 4; i++) { + if (memcmp(data + i, START_FLAG, 4) == 0) { + start_flag_received = true; + current_state = USBState::RECEIVING_SETTINGS; + buffer_index = 0; // Reset buffer for settings data + + // You can send an acknowledgment back here if needed + // sendUSBAcknowledgment(); + + // If there's more data after the start flag, process it + if (length > i + 4) { + processSettingsData(data + i + 4, length - i - 4); + } + return; + } + } +} + +void USBHandler::processSettingsData(const uint8_t* data, uint32_t length) { + // Add data to buffer + uint32_t bytes_to_copy = (length < (MAX_BUFFER_SIZE - buffer_index)) ? + length : (MAX_BUFFER_SIZE - buffer_index); + + memcpy(usb_buffer + buffer_index, data, bytes_to_copy); + buffer_index += bytes_to_copy; + + // Check if we have a complete settings packet (contains "SET" and "END") + if (buffer_index >= 74) { // Minimum size for valid settings packet + // Look for "SET" at beginning and "END" somewhere in the packet + bool has_set = (memcmp(usb_buffer, "SET", 3) == 0); + bool has_end = false; + + for (uint32_t i = 3; i <= buffer_index - 3; i++) { + if (memcmp(usb_buffer + i, "END", 3) == 0) { + has_end = true; + + // Parse the complete packet up to "END" + if (has_set && current_settings.parseFromUSB(usb_buffer, i + 3)) { + current_state = USBState::READY_FOR_DATA; + + // You can send settings acknowledgment back here + // sendSettingsAcknowledgment(); + } + break; + } + } + + // If we didn't find a valid packet but buffer is full, reset + if (buffer_index >= MAX_BUFFER_SIZE && !has_end) { + buffer_index = 0; // Reset buffer to avoid overflow + } + } +} \ No newline at end of file diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/USBHandler.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/USBHandler.h new file mode 100644 index 0000000..725fef2 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/USBHandler.h @@ -0,0 +1,46 @@ +#ifndef USBHANDLER_H +#define USBHANDLER_H + +#include "RadarSettings.h" +#include + +class USBHandler { +public: + enum class USBState { + WAITING_FOR_START, + RECEIVING_SETTINGS, + READY_FOR_DATA + }; + + USBHandler(); + + // Process incoming USB data + void processUSBData(const uint8_t* data, uint32_t length); + + // Check if start flag was received + bool isStartFlagReceived() const { return start_flag_received; } + + // Get current settings + const RadarSettings& getSettings() const { return current_settings; } + + // Get current state + USBState getState() const { return current_state; } + + // Reset USB handler + void reset(); + +private: + RadarSettings current_settings; + USBState current_state; + bool start_flag_received; + + // Buffer for accumulating USB data + static constexpr uint32_t MAX_BUFFER_SIZE = 256; + uint8_t usb_buffer[MAX_BUFFER_SIZE]; + uint32_t buffer_index; + + void processStartFlag(const uint8_t* data, uint32_t length); + void processSettingsData(const uint8_t* data, uint32_t length); +}; + +#endif // USBHANDLER_H \ No newline at end of file diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ad9523.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ad9523.c new file mode 100644 index 0000000..a88e3dc --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ad9523.c @@ -0,0 +1,731 @@ +/***************************************************************************//** + * @file AD9523.c + * @brief Implementation of AD9523 Driver. + * @author ACozma(andrei.cozma@analog.com) + ******************************************************************************** + * Copyright 2012-2016(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ + +#include +#include +#include "ad9523.h" +#include "no_os_alloc.h" + +/* Helpers to avoid excess line breaks */ +#define AD_IFE(_pde, _a, _b) ((dev->pdata->_pde) ? _a : _b) +#define AD_IF(_pde, _a) AD_IFE(_pde, _a, 0) + +/***************************************************************************//** + * @brief Reads the value of the selected register. + * + * @param dev - The device structure. + * @param reg_addr - The address of the register to read. + * @param reg_data - Pointer to the read value. + + * @return Returns 0 in case of success or negative error code. + *******************************************************************************/ +int32_t ad9523_spi_read(struct ad9523_dev *dev, + uint32_t reg_addr, + uint32_t *reg_data) +{ + uint8_t buf[3]; + + int32_t ret = 0; + uint8_t index; + + *reg_data = 0; + for (index = 0; index < AD9523_TRANSF_LEN(reg_addr); index++) { + buf[0] = 0x80 | (reg_addr >> 8); + buf[1] = reg_addr & 0xFF; + buf[2] = 0x00; + ret |= no_os_spi_write_and_read(dev->spi_desc, + buf, + 3); + reg_addr--; + *reg_data <<= 8; + *reg_data |= buf[2]; + } + + return ret; +} + +/***************************************************************************//** + * @brief Writes a value to the selected register. + * + * @param dev - The device structure. + * @param reg_addr - The address of the register to write to. + * @param reg_data - The value to write to the register. + * + * @return Returns 0 in case of success or negative error code. + *******************************************************************************/ +int32_t ad9523_spi_write(struct ad9523_dev *dev, + uint32_t reg_addr, + uint32_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret = 0; + uint8_t index; + + for (index = 0; index < AD9523_TRANSF_LEN(reg_addr); index++) { + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = (reg_data >> ((AD9523_TRANSF_LEN(reg_addr) - index - 1) * 8)) & 0xFF; + ret |= no_os_spi_write_and_read(dev->spi_desc, + buf, + 3); + reg_addr--; + } + + return ret; +} + +/***************************************************************************//** + * @brief Updates the AD9523 configuration + * + * @param dev - The device structure. + * + * @return Returns 0 in case of success or negative error code. + *******************************************************************************/ +int32_t ad9523_io_update(struct ad9523_dev *dev) +{ + return ad9523_spi_write(dev, + AD9523_IO_UPDATE, + AD9523_IO_UPDATE_EN); +} + +/***************************************************************************//** + * @brief Sets the clock provider for selected channel. + * + * @param dev - The device structure. + * @param ch - Selected channel. + * @param out - Selected clock provider. + * + * @return Returns 0 in case of success or negative error code. + *******************************************************************************/ +int32_t ad9523_vco_out_map(struct ad9523_dev *dev, + uint32_t ch, + uint32_t out) +{ + int32_t ret; + uint32_t mask; + uint32_t reg_data; + + switch (ch) { + case 0 ... 3: + ret = ad9523_spi_read(dev, + AD9523_PLL1_OUTPUT_CHANNEL_CTRL, + ®_data); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 << ch; + if (out) { + reg_data |= mask; + out = AD9523_VCXO; + } else { + reg_data &= ~mask; + } + ret = ad9523_spi_write(dev, + AD9523_PLL1_OUTPUT_CHANNEL_CTRL, + reg_data); + break; + case 4 ... 6: + ret = ad9523_spi_read(dev, + AD9523_PLL1_OUTPUT_CTRL, + ®_data); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 << (ch - 4); + if (out) + reg_data |= mask; + else + reg_data &= ~mask; + ret = ad9523_spi_write(dev, + AD9523_PLL1_OUTPUT_CTRL, + reg_data); + break; + case 7 ... 9: + ret = ad9523_spi_read(dev, + AD9523_PLL1_OUTPUT_CHANNEL_CTRL, + ®_data); + if (ret < 0) + break; + mask = AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 << (ch - 7); + if (out) + reg_data |= mask; + else + reg_data &= ~mask; + ret = ad9523_spi_write(dev, + AD9523_PLL1_OUTPUT_CHANNEL_CTRL, + reg_data); + break; + default: + return 0; + } + + dev->ad9523_st.vco_out_map[ch] = out; + + return ret; +} + +/***************************************************************************//** + * @brief Updates the AD9523 configuration. + * + * @return Returns 0 in case of success or negative error code. + *******************************************************************************/ + +// vco calibration on default setup may not work (as it is a buffered write) +// calibration requires all registers to be written (not in hold registers) first. + +int32_t ad9523_calibrate(struct ad9523_dev *dev) +{ + uint32_t reg_data; + uint32_t timeout; + + ad9523_spi_write(dev, + AD9523_PLL2_VCO_CTRL, + AD9523_PLL2_VCO_CALIBRATE); + ad9523_io_update(dev); + + timeout = 0; + while (timeout < 100) { + no_os_mdelay(1); + timeout = timeout + 1; + ad9523_spi_read(dev, + AD9523_READBACK_1, + ®_data); + if ((reg_data & 0x1) == 0x0) + break; + } + ad9523_spi_read(dev, + AD9523_READBACK_1, + ®_data); + if ((reg_data & 0x1) != 0x0) { + printf("AD9523: VCO calibration failed (%#06lx)!\n", reg_data); + return (-1); + } + + return (0); +} + +/***************************************************************************//** + * @brief Updates the AD9523 configuration. + * + * @param dev - The device structure. + * + * @return Returns 0 in case of success or negative error code. + *******************************************************************************/ + +// status +// calibration requires all registers to be written (not in hold registers) first. + +int32_t ad9523_status(struct ad9523_dev *dev) +{ + int32_t ret; + uint32_t reg_data; + uint32_t status; + uint32_t timeout; + + status = 0; + + // vcxo + pll2 must always be okay- (is it not?) + + status = status | AD9523_READBACK_0_STAT_VCXO; + status = status | AD9523_READBACK_0_STAT_PLL2_LD; + + if (dev->pdata->pll1_bypass_en == 0) { + status = status | AD9523_READBACK_0_STAT_PLL2_REF_CLK; + status = status | AD9523_READBACK_0_STAT_PLL2_FB_CLK; + status = status | AD9523_READBACK_0_STAT_REF_TEST; + status = status | AD9523_READBACK_0_STAT_REFB; + status = status | AD9523_READBACK_0_STAT_REFA; + status = status | AD9523_READBACK_0_STAT_PLL1_LD; + } + + timeout = 0; + while (timeout < 100) { + no_os_mdelay(1); + timeout = timeout + 1; + ad9523_spi_read(dev, + AD9523_READBACK_0, + ®_data); + if ((reg_data & status) == status) + break; + } + + ret = 0; + if ((reg_data & AD9523_READBACK_0_STAT_VCXO) != AD9523_READBACK_0_STAT_VCXO) { + printf("AD9523: VCXO status errors (%#06lx)!\n", reg_data); + ret = -1; + } + + if ((reg_data & AD9523_READBACK_0_STAT_PLL2_LD) != + AD9523_READBACK_0_STAT_PLL2_LD) { + printf("AD9523: PLL2 NOT locked (%#06lx)!\n", reg_data); + ret = -1; + } + + return (ret); +} + +/***************************************************************************//** + * @brief Updates the AD9523 configuration. + * + * @param dev - The device structure. + * + * @return Returns 0 in case of success or negative error code. + *******************************************************************************/ +int32_t ad9523_sync(struct ad9523_dev *dev) +{ + int32_t ret, tmp; + uint32_t reg_data; + + ret = ad9523_spi_read(dev, + AD9523_STATUS_SIGNALS, + ®_data); + if (ret < 0) + return ret; + + tmp = reg_data; + tmp |= AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL; + + ret = ad9523_spi_write(dev, + AD9523_STATUS_SIGNALS, + tmp); + if (ret < 0) + return ret; + + ad9523_io_update(dev); + tmp &= ~AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL; + + ret = ad9523_spi_write(dev, + AD9523_STATUS_SIGNALS, + tmp); + if (ret < 0) + return ret; + + return ad9523_io_update(dev); + +} + +/***************************************************************************//** + * @brief Initialize the AD9523 data structure with the default register values. + * + * @param init_param - The device initial parameters. + * + * @return Always return 0. + *******************************************************************************/ +int32_t ad9523_init(struct ad9523_init_param *init_param) +{ + + int32_t i = 0; + + init_param->pdata->vcxo_freq = 0; + init_param->pdata->spi3wire = 0; + + /* Differential/ Single-Ended Input Configuration */ + init_param->pdata->refa_diff_rcv_en = 0; + init_param->pdata->refb_diff_rcv_en = 0; + init_param->pdata->zd_in_diff_en = 0; + init_param->pdata->osc_in_diff_en = 0; + + /* + * Valid if differential input disabled + * if not true defaults to pos input + */ + init_param->pdata->refa_cmos_neg_inp_en = 0; + init_param->pdata->refb_cmos_neg_inp_en = 0; + init_param->pdata->zd_in_cmos_neg_inp_en = 0; + init_param->pdata->osc_in_cmos_neg_inp_en = 0; + + /* PLL1 Setting */ + init_param->pdata->refa_r_div = 1; + init_param->pdata->refb_r_div = 1; + init_param->pdata->pll1_feedback_div = 1; + init_param->pdata->pll1_charge_pump_current_nA = 0; + init_param->pdata->zero_delay_mode_internal_en = 0; + init_param->pdata->osc_in_feedback_en = 0; + init_param->pdata->pll1_bypass_en = 1; + init_param->pdata->pll1_loop_filter_rzero = 1; + + /* Reference */ + init_param->pdata->ref_mode = 0; + + /* PLL2 Setting */ + init_param->pdata->pll2_charge_pump_current_nA = 0; + init_param->pdata->pll2_ndiv_a_cnt = 0; + init_param->pdata->pll2_ndiv_b_cnt = 4; + init_param->pdata->pll2_freq_doubler_en = 0; + init_param->pdata->pll2_r2_div = 0; + init_param->pdata->pll2_vco_diff_m1 = 0; /* 3..5 */ + init_param->pdata->pll2_vco_diff_m2 = 0; /* 3..5 */ + + /* Loop Filter PLL2 */ + init_param->pdata->rpole2 = 0; + init_param->pdata->rzero = 0; + init_param->pdata->cpole1 = 0; + init_param->pdata->rzero_bypass_en = 0; + + /* Output Channel Configuration */ + for (i = 0; i < init_param->pdata->num_channels; i++) { + (&init_param->pdata->channels[i])->channel_num = 0; + (&init_param->pdata->channels[i])->divider_output_invert_en = 0; + (&init_param->pdata->channels[i])->sync_ignore_en = 0; + (&init_param->pdata->channels[i])->low_power_mode_en = 0; + (&init_param->pdata->channels[i])->use_alt_clock_src = 0; + (&init_param->pdata->channels[i])->output_dis = 0; + (&init_param->pdata->channels[i])->driver_mode = LVPECL_8mA; + (&init_param->pdata->channels[i])->divider_phase = 0; + (&init_param->pdata->channels[i])->channel_divider = 0; + } + return 0; +} + + +/***************************************************************************//** + * @brief Setup the AD9523 device. + * + * @param device - The device structure. + * @param init_param - The structure holding the device initial parameters. + * + * @return Returns 0 in case of success or negative error code. + *******************************************************************************/ +int32_t ad9523_setup(struct ad9523_dev **device, + const struct ad9523_init_param *init_param) + +{ + struct ad9523_channel_spec *chan; + uint32_t active_mask = 0; + int32_t ret, i; + uint32_t reg_data; + uint32_t version_id; + struct ad9523_dev *dev; + + dev = (struct ad9523_dev *)no_os_malloc(sizeof(*dev)); + if (!dev) + return -1; + + /* SPI */ + ret = no_os_spi_init(&dev->spi_desc, &init_param->spi_init); + if (ret < 0) + return ret; + + dev->pdata = init_param->pdata; + + ret = ad9523_spi_write(dev, + AD9523_SERIAL_PORT_CONFIG, + AD9523_SER_CONF_SOFT_RESET | + (dev->pdata->spi3wire ? 0 : + AD9523_SER_CONF_SDO_ACTIVE)); + if (ret < 0) + return ret; + no_os_mdelay(1); + + ret = ad9523_spi_write(dev, + AD9523_READBACK_CTRL, + AD9523_READBACK_CTRL_READ_BUFFERED); + if (ret < 0) + return ret; + + ret = ad9523_io_update(dev); + if (ret < 0) + return ret; + + ret = ad9523_spi_read(dev, + AD9523_EEPROM_CUSTOMER_VERSION_ID, + &version_id); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_EEPROM_CUSTOMER_VERSION_ID, + 0xAD95); + if (ret < 0) + return ret; + + ret = ad9523_spi_read(dev, + AD9523_EEPROM_CUSTOMER_VERSION_ID, + ®_data); + if (ret < 0) + return ret; + + if (reg_data != 0xAD95) { + printf("AD9523: SPI write-verify failed (%#06lX)!\n\r", + reg_data); + return -1; + } + + ret = ad9523_spi_write(dev, + AD9523_EEPROM_CUSTOMER_VERSION_ID, + version_id); + if (ret < 0) + return ret; + + /* + * PLL1 Setup + */ + ret = ad9523_spi_write(dev, + AD9523_PLL1_REF_A_DIVIDER, + dev->pdata->refa_r_div); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL1_REF_B_DIVIDER, + dev->pdata->refb_r_div); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL1_FEEDBACK_DIVIDER, + dev->pdata->pll1_feedback_div); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL1_CHARGE_PUMP_CTRL, + AD_IFE(pll1_bypass_en, AD9523_PLL1_CHARGE_PUMP_TRISTATE, + AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(dev->pdata-> + pll1_charge_pump_current_nA) | + AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL | + AD9523_PLL1_BACKLASH_PW_MIN)); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL1_INPUT_RECEIVERS_CTRL, + AD_IFE(pll1_bypass_en, AD9523_PLL1_REFA_REFB_PWR_CTRL_EN | + AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) | + AD_IF(osc_in_cmos_neg_inp_en, AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN), + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_RCV_EN) | + AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_RCV_EN) | + AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) | + AD_IF(osc_in_cmos_neg_inp_en, + AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN) | + AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_DIFF_RCV_EN) | + AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_DIFF_RCV_EN))); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL1_REF_CTRL, + AD_IFE(pll1_bypass_en, AD9523_PLL1_BYPASS_FEEDBACK_DIV_EN | + AD9523_PLL1_ZERO_DELAY_MODE_INT, + AD_IF(zd_in_diff_en, AD9523_PLL1_ZD_IN_DIFF_EN) | + AD_IF(zd_in_cmos_neg_inp_en, + AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN) | + AD_IF(zero_delay_mode_internal_en, + AD9523_PLL1_ZERO_DELAY_MODE_INT) | + AD_IF(osc_in_feedback_en, AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN) | + AD_IF(refa_cmos_neg_inp_en, AD9523_PLL1_REFA_CMOS_NEG_INP_EN) | + AD_IF(refb_cmos_neg_inp_en, AD9523_PLL1_REFB_CMOS_NEG_INP_EN))); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL1_MISC_CTRL, + AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN | + AD9523_PLL1_REF_MODE(dev->pdata->ref_mode)); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL1_LOOP_FILTER_CTRL, + AD9523_PLL1_LOOP_FILTER_RZERO(dev->pdata-> + pll1_loop_filter_rzero)); + if (ret < 0) + return ret; + + /* + * PLL2 Setup + */ + + ret = ad9523_spi_write(dev, + AD9523_PLL2_CHARGE_PUMP, + AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(dev->pdata-> + pll2_charge_pump_current_nA)); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL2_FEEDBACK_DIVIDER_AB, + AD9523_PLL2_FB_NDIV_A_CNT(dev->pdata->pll2_ndiv_a_cnt) | + AD9523_PLL2_FB_NDIV_B_CNT(dev->pdata->pll2_ndiv_b_cnt)); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL2_CTRL, + AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL | + AD9523_PLL2_BACKLASH_CTRL_EN | + AD_IF(pll2_freq_doubler_en, + AD9523_PLL2_FREQ_DOUBLER_EN)); + if (ret < 0) + return ret; + + dev->ad9523_st.vco_freq = (dev->pdata->vcxo_freq * + (dev->pdata->pll2_freq_doubler_en ? 2 : 1) + / dev->pdata->pll2_r2_div) * AD9523_PLL2_FB_NDIV(dev->pdata-> + pll2_ndiv_a_cnt, + dev->pdata-> + pll2_ndiv_b_cnt); + + ret = ad9523_spi_write(dev, + AD9523_PLL2_VCO_CTRL, + AD9523_PLL2_VCO_CALIBRATE); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL2_VCO_DIVIDER, + AD9523_PLL2_VCO_DIV_M1(dev->pdata-> + pll2_vco_diff_m1) | + AD9523_PLL2_VCO_DIV_M2(dev->pdata-> + pll2_vco_diff_m2) | + AD_IFE(pll2_vco_diff_m1, + 0, + AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN) | + AD_IFE(pll2_vco_diff_m2, + 0, + AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN)); + if (ret < 0) + return ret; + + if (dev->pdata->pll2_vco_diff_m1) + dev->ad9523_st.vco_out_freq[AD9523_VCO1] = + dev->ad9523_st.vco_freq / dev->pdata->pll2_vco_diff_m1; + + if (dev->pdata->pll2_vco_diff_m2) + dev->ad9523_st.vco_out_freq[AD9523_VCO2] = + dev->ad9523_st.vco_freq / dev->pdata->pll2_vco_diff_m2; + + dev->ad9523_st.vco_out_freq[AD9523_VCXO] = dev->pdata->vcxo_freq; + + ret = ad9523_spi_write(dev, + AD9523_PLL2_R2_DIVIDER, + AD9523_PLL2_R2_DIVIDER_VAL(dev->pdata->pll2_r2_div)); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_PLL2_LOOP_FILTER_CTRL, + AD9523_PLL2_LOOP_FILTER_CPOLE1(dev->pdata->cpole1) | + AD9523_PLL2_LOOP_FILTER_RZERO(dev->pdata->rzero) | + AD9523_PLL2_LOOP_FILTER_RPOLE2(dev->pdata->rpole2) | + AD_IF(rzero_bypass_en, + AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN)); + if (ret < 0) + return ret; + + for (i = 0; i < dev->pdata->num_channels; i++) { + chan = &dev->pdata->channels[i]; + if (chan->channel_num < AD9523_NUM_CHAN) { + active_mask |= (1 << chan->channel_num); + ret = ad9523_spi_write(dev, + AD9523_CHANNEL_CLOCK_DIST(chan->channel_num), + AD9523_CLK_DIST_DRIVER_MODE(chan->driver_mode) | + AD9523_CLK_DIST_DIV(chan->channel_divider) | + AD9523_CLK_DIST_DIV_PHASE(chan->divider_phase) | + (chan->sync_ignore_en ? + AD9523_CLK_DIST_IGNORE_SYNC_EN : 0) | + (chan->divider_output_invert_en ? + AD9523_CLK_DIST_INV_DIV_OUTPUT_EN : 0) | + (chan->low_power_mode_en ? + AD9523_CLK_DIST_LOW_PWR_MODE_EN : 0) | + (chan->output_dis ? + AD9523_CLK_DIST_PWR_DOWN_EN : 0)); + if (ret < 0) + return ret; + + ret = ad9523_vco_out_map(dev, + chan->channel_num, + chan->use_alt_clock_src); + if (ret < 0) + return ret; + } + } + + for (i = 0; i < AD9523_NUM_CHAN; i++) { + if (!(active_mask & (1 << i))) { + ad9523_spi_write(dev, + AD9523_CHANNEL_CLOCK_DIST(i), + AD9523_CLK_DIST_DRIVER_MODE(TRISTATE) | + AD9523_CLK_DIST_PWR_DOWN_EN); + } + } + + ret = ad9523_spi_write(dev, + AD9523_POWER_DOWN_CTRL, + 0); + if (ret < 0) + return ret; + + ret = ad9523_spi_write(dev, + AD9523_STATUS_SIGNALS, + AD9523_STATUS_MONITOR_01_PLL12_LOCKED); + if (ret < 0) + return ret; + + ret = ad9523_io_update(dev); + if (ret < 0) + return ret; + + ret = ad9523_sync(dev); + if (ret < 0) + return ret; + + ad9523_spi_write(dev, + AD9523_READBACK_CTRL, + 0x0); + ad9523_io_update(dev); + ad9523_calibrate(dev); + ad9523_sync(dev); + + *device = dev; + + return (ad9523_status(dev)); +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9523_setup(). + * + * @param dev - The device structure. + * + * @return 0 in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9523_remove(struct ad9523_dev *dev) +{ + int32_t ret; + + ret = no_os_spi_remove(dev->spi_desc); + + no_os_free(dev); + + return ret; +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ad9523.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ad9523.h new file mode 100644 index 0000000..7dfee96 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/ad9523.h @@ -0,0 +1,509 @@ +/***************************************************************************//** + * @file AD9523.h + * @brief Header file of AD9523 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2012-2016(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *******************************************************************************/ +#ifndef _AD9523_H_ +#define _AD9523_H_ + +#include +#include "no_os_delay.h" +#include "no_os_spi.h" + +/* Registers */ + +#define AD9523_READ (1 << 15) +#define AD9523_WRITE (0 << 15) +#define AD9523_CNT(x) (((x) - 1) << 13) +#define AD9523_ADDR(x) ((x) & 0xFFF) + +#define AD9523_R1B (1 << 16) +#define AD9523_R2B (2 << 16) +#define AD9523_R3B (3 << 16) +#define AD9523_TRANSF_LEN(x) ((x) >> 16) + +#define AD9523_SERIAL_PORT_CONFIG (AD9523_R1B | 0x0) +#define AD9523_VERSION_REGISTER (AD9523_R1B | 0x2) +#define AD9523_PART_REGISTER (AD9523_R1B | 0x3) +#define AD9523_READBACK_CTRL (AD9523_R1B | 0x4) + +#define AD9523_EEPROM_CUSTOMER_VERSION_ID (AD9523_R2B | 0x6) + +#define AD9523_PLL1_REF_A_DIVIDER (AD9523_R2B | 0x11) +#define AD9523_PLL1_REF_B_DIVIDER (AD9523_R2B | 0x13) +#define AD9523_PLL1_REF_TEST_DIVIDER (AD9523_R1B | 0x14) +#define AD9523_PLL1_FEEDBACK_DIVIDER (AD9523_R2B | 0x17) +#define AD9523_PLL1_CHARGE_PUMP_CTRL (AD9523_R2B | 0x19) +#define AD9523_PLL1_INPUT_RECEIVERS_CTRL (AD9523_R1B | 0x1A) +#define AD9523_PLL1_REF_CTRL (AD9523_R1B | 0x1B) +#define AD9523_PLL1_MISC_CTRL (AD9523_R1B | 0x1C) +#define AD9523_PLL1_LOOP_FILTER_CTRL (AD9523_R1B | 0x1D) + +#define AD9523_PLL2_CHARGE_PUMP (AD9523_R1B | 0xF0) +#define AD9523_PLL2_FEEDBACK_DIVIDER_AB (AD9523_R1B | 0xF1) +#define AD9523_PLL2_CTRL (AD9523_R1B | 0xF2) +#define AD9523_PLL2_VCO_CTRL (AD9523_R1B | 0xF3) +#define AD9523_PLL2_VCO_DIVIDER (AD9523_R1B | 0xF4) +#define AD9523_PLL2_LOOP_FILTER_CTRL (AD9523_R2B | 0xF6) +#define AD9523_PLL2_R2_DIVIDER (AD9523_R1B | 0xF7) + +#define AD9523_CHANNEL_CLOCK_DIST(ch) (AD9523_R3B | (0x192 + 3 * ch)) + +#define AD9523_PLL1_OUTPUT_CTRL (AD9523_R1B | 0x1BA) +#define AD9523_PLL1_OUTPUT_CHANNEL_CTRL (AD9523_R1B | 0x1BB) + +#define AD9523_READBACK_0 (AD9523_R1B | 0x22C) +#define AD9523_READBACK_1 (AD9523_R1B | 0x22D) + +#define AD9523_STATUS_SIGNALS (AD9523_R3B | 0x232) +#define AD9523_POWER_DOWN_CTRL (AD9523_R1B | 0x233) +#define AD9523_IO_UPDATE (AD9523_R1B | 0x234) + +#define AD9523_EEPROM_DATA_XFER_STATUS (AD9523_R1B | 0xB00) +#define AD9523_EEPROM_ERROR_READBACK (AD9523_R1B | 0xB01) +#define AD9523_EEPROM_CTRL1 (AD9523_R1B | 0xB02) +#define AD9523_EEPROM_CTRL2 (AD9523_R1B | 0xB03) + +/* AD9523_SERIAL_PORT_CONFIG */ + +#define AD9523_SER_CONF_SDO_ACTIVE ((1 << 7) | (1 << 0)) +#define AD9523_SER_CONF_SOFT_RESET ((1 << 5) | (1 << 2)) + +/* AD9523_READBACK_CTRL */ +#define AD9523_READBACK_CTRL_READ_BUFFERED (1 << 0) + +/* AD9523_PLL1_CHARGE_PUMP_CTRL */ +#define AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(x) (((x) / 500) & 0x7F) +#define AD9523_PLL1_CHARGE_PUMP_TRISTATE (1 << 7) +#define AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL (3 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_DOWN (2 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_UP (1 << 8) +#define AD9523_PLL1_CHARGE_PUMP_MODE_TRISTATE (0 << 8) +#define AD9523_PLL1_BACKLASH_PW_MIN (0 << 10) +#define AD9523_PLL1_BACKLASH_PW_LOW (1 << 10) +#define AD9523_PLL1_BACKLASH_PW_HIGH (2 << 10) +#define AD9523_PLL1_BACKLASH_PW_MAX (3 << 10) + +/* AD9523_PLL1_INPUT_RECEIVERS_CTRL */ +#define AD9523_PLL1_REF_TEST_RCV_EN (1 << 7) +#define AD9523_PLL1_REFB_DIFF_RCV_EN (1 << 6) +#define AD9523_PLL1_REFA_DIFF_RCV_EN (1 << 5) +#define AD9523_PLL1_REFB_RCV_EN (1 << 4) +#define AD9523_PLL1_REFA_RCV_EN (1 << 3) +#define AD9523_PLL1_REFA_REFB_PWR_CTRL_EN (1 << 2) +#define AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN (1 << 1) +#define AD9523_PLL1_OSC_IN_DIFF_EN (1 << 0) + +/* AD9523_PLL1_REF_CTRL */ +#define AD9523_PLL1_BYPASS_REF_TEST_DIV_EN (1 << 7) +#define AD9523_PLL1_BYPASS_FEEDBACK_DIV_EN (1 << 6) +#define AD9523_PLL1_ZERO_DELAY_MODE_INT (1 << 5) +#define AD9523_PLL1_ZERO_DELAY_MODE_EXT (0 << 5) +#define AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN (1 << 4) +#define AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN (1 << 3) +#define AD9523_PLL1_ZD_IN_DIFF_EN (1 << 2) +#define AD9523_PLL1_REFB_CMOS_NEG_INP_EN (1 << 1) +#define AD9523_PLL1_REFA_CMOS_NEG_INP_EN (1 << 0) + +/* AD9523_PLL1_MISC_CTRL */ +#define AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN (1 << 7) +#define AD9523_PLL1_OSC_CTRL_FAIL_VCC_BY2_EN (1 << 6) +#define AD9523_PLL1_REF_MODE(x) ((x) << 2) +#define AD9523_PLL1_BYPASS_REFB_DIV (1 << 1) +#define AD9523_PLL1_BYPASS_REFA_DIV (1 << 0) + +/* AD9523_PLL1_LOOP_FILTER_CTRL */ +#define AD9523_PLL1_LOOP_FILTER_RZERO(x) ((x) & 0xF) + +/* AD9523_PLL2_CHARGE_PUMP */ +#define AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(x) ((x) / 3500) + +/* AD9523_PLL2_FEEDBACK_DIVIDER_AB */ +#define AD9523_PLL2_FB_NDIV_A_CNT(x) (((x) & 0x3) << 6) +#define AD9523_PLL2_FB_NDIV_B_CNT(x) (((x) & 0x3F) << 0) +#define AD9523_PLL2_FB_NDIV(a, b) (4 * (b) + (a)) + +/* AD9523_PLL2_CTRL */ +#define AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL (3 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_DOWN (2 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_UP (1 << 0) +#define AD9523_PLL2_CHARGE_PUMP_MODE_TRISTATE (0 << 0) +#define AD9523_PLL2_BACKLASH_PW_MIN (0 << 2) +#define AD9523_PLL2_BACKLASH_PW_LOW (1 << 2) +#define AD9523_PLL2_BACKLASH_PW_HIGH (2 << 2) +#define AD9523_PLL2_BACKLASH_PW_MAX (3 << 1) +#define AD9523_PLL2_BACKLASH_CTRL_EN (1 << 4) +#define AD9523_PLL2_FREQ_DOUBLER_EN (1 << 5) +#define AD9523_PLL2_LOCK_DETECT_PWR_DOWN_EN (1 << 7) + +/* AD9523_PLL2_VCO_CTRL */ +#define AD9523_PLL2_VCO_CALIBRATE (1 << 1) +#define AD9523_PLL2_FORCE_VCO_MIDSCALE (1 << 2) +#define AD9523_PLL2_FORCE_REFERENCE_VALID (1 << 3) +#define AD9523_PLL2_FORCE_RELEASE_SYNC (1 << 4) + +/* AD9523_PLL2_VCO_DIVIDER */ +#define AD9523_PLL2_VCO_DIV_M1(x) ((((x) - 3) & 0x3) << 0) +#define AD9523_PLL2_VCO_DIV_M2(x) ((((x) - 3) & 0x3) << 4) +#define AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN (1 << 2) +#define AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN (1 << 6) + +/* AD9523_PLL2_LOOP_FILTER_CTRL */ +#define AD9523_PLL2_LOOP_FILTER_CPOLE1(x) (((x) & 0x7) << 0) +#define AD9523_PLL2_LOOP_FILTER_RZERO(x) (((x) & 0x7) << 3) +#define AD9523_PLL2_LOOP_FILTER_RPOLE2(x) (((x) & 0x7) << 6) +#define AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN (1 << 8) + +/* AD9523_PLL2_R2_DIVIDER */ +#define AD9523_PLL2_R2_DIVIDER_VAL(x) (((x) & 0x1F) << 0) + +/* AD9523_CHANNEL_CLOCK_DIST */ +#define AD9523_CLK_DIST_DIV_PHASE(x) (((x) & 0x3F) << 18) +#define AD9523_CLK_DIST_DIV_PHASE_REV(x) ((ret >> 18) & 0x3F) +#define AD9523_CLK_DIST_DIV(x) ((((x) - 1) & 0x3FF) << 8) +#define AD9523_CLK_DIST_DIV_REV(x) (((ret >> 8) & 0x3FF) + 1) +#define AD9523_CLK_DIST_INV_DIV_OUTPUT_EN (1 << 7) +#define AD9523_CLK_DIST_IGNORE_SYNC_EN (1 << 6) +#define AD9523_CLK_DIST_PWR_DOWN_EN (1 << 5) +#define AD9523_CLK_DIST_LOW_PWR_MODE_EN (1 << 4) +#define AD9523_CLK_DIST_DRIVER_MODE(x) (((x) & 0xF) << 0) + +/* AD9523_PLL1_OUTPUT_CTRL */ +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH6_M2 (1 << 7) +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH5_M2 (1 << 6) +#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 (1 << 5) +#define AD9523_PLL1_OUTP_CTRL_CMOS_DRV_WEAK (1 << 4) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_1 (0 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_2 (1 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_4 (2 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_8 (4 << 0) +#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_16 (8 << 0) + +/* AD9523_PLL1_OUTPUT_CHANNEL_CTRL */ +#define AD9523_PLL1_OUTP_CH_CTRL_OUTPUT_PWR_DOWN_EN (1 << 7) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH9_M2 (1 << 6) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH8_M2 (1 << 5) +#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 (1 << 4) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH3 (1 << 3) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH2 (1 << 2) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH1 (1 << 1) +#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 (1 << 0) + +/* AD9523_READBACK_0 */ +#define AD9523_READBACK_0_STAT_PLL2_REF_CLK (1 << 7) +#define AD9523_READBACK_0_STAT_PLL2_FB_CLK (1 << 6) +#define AD9523_READBACK_0_STAT_VCXO (1 << 5) +#define AD9523_READBACK_0_STAT_REF_TEST (1 << 4) +#define AD9523_READBACK_0_STAT_REFB (1 << 3) +#define AD9523_READBACK_0_STAT_REFA (1 << 2) +#define AD9523_READBACK_0_STAT_PLL2_LD (1 << 1) +#define AD9523_READBACK_0_STAT_PLL1_LD (1 << 0) + +/* AD9523_READBACK_1 */ +#define AD9523_READBACK_1_HOLDOVER_ACTIVE (1 << 3) +#define AD9523_READBACK_1_AUTOMODE_SEL_REFB (1 << 2) +#define AD9523_READBACK_1_VCO_CALIB_IN_PROGRESS (1 << 0) + +/* AD9523_STATUS_SIGNALS */ +#define AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL (1 << 16) +#define AD9523_STATUS_MONITOR_01_PLL12_LOCKED (0x302) +/* AD9523_POWER_DOWN_CTRL */ +#define AD9523_POWER_DOWN_CTRL_PLL1_PWR_DOWN (1 << 2) +#define AD9523_POWER_DOWN_CTRL_PLL2_PWR_DOWN (1 << 1) +#define AD9523_POWER_DOWN_CTRL_DIST_PWR_DOWN (1 << 0) + +/* AD9523_IO_UPDATE */ +#define AD9523_IO_UPDATE_EN (1 << 0) + +/* AD9523_EEPROM_DATA_XFER_STATUS */ +#define AD9523_EEPROM_DATA_XFER_IN_PROGRESS (1 << 0) + +/* AD9523_EEPROM_ERROR_READBACK */ +#define AD9523_EEPROM_ERROR_READBACK_FAIL (1 << 0) + +/* AD9523_EEPROM_CTRL1 */ +#define AD9523_EEPROM_CTRL1_SOFT_EEPROM (1 << 1) +#define AD9523_EEPROM_CTRL1_EEPROM_WRITE_PROT_DIS (1 << 0) + +/* AD9523_EEPROM_CTRL2 */ +#define AD9523_EEPROM_CTRL2_REG2EEPROM (1 << 0) + +#define AD9523_NUM_CHAN 14 +#define AD9523_NUM_CHAN_ALT_CLK_SRC 10 + +enum outp_drv_mode { + TRISTATE, + LVPECL_8mA, + LVDS_4mA, + LVDS_7mA, + HSTL0_16mA, + HSTL1_8mA, + CMOS_CONF1, + CMOS_CONF2, + CMOS_CONF3, + CMOS_CONF4, + CMOS_CONF5, + CMOS_CONF6, + CMOS_CONF7, + CMOS_CONF8, + CMOS_CONF9 +}; + +enum ref_sel_mode { + NONEREVERTIVE_STAY_ON_REFB, + REVERT_TO_REFA, + SELECT_REFA, + SELECT_REFB, + EXT_REF_SEL +}; + +/** + * @struct ad9523_channel_spec + * @brief Output channel configuration + */ +struct ad9523_channel_spec { + /** Output channel number. */ + uint8_t channel_num; + /** Invert the polarity of the output clock. */ + uint8_t divider_output_invert_en; + /** Ignore chip-level SYNC signal. */ + uint8_t sync_ignore_en; + /** Reduce power used in the differential output modes. */ + uint8_t low_power_mode_en; + /** Channel divider uses alternative clk source: CH0..CH3 VCXO, CH4..CH9 VCO2 */ + uint8_t use_alt_clock_src; + /** Disables, powers down the entire channel. */ + uint8_t output_dis; + /** Output driver mode (logic level family). */ + uint8_t driver_mode; + /** Divider initial phase after a SYNC. Range 0..63 + * LSB = 1/2 of a period of the divider input clock. + */ + uint8_t divider_phase; + /** 10-bit channel divider. */ + uint16_t channel_divider; + /** Optional descriptive channel name. */ + int8_t extended_name[16]; +}; + +enum pll1_rzero_resistor { + RZERO_883_OHM, + RZERO_677_OHM, + RZERO_341_OHM, + RZERO_135_OHM, + RZERO_10_OHM, + RZERO_USE_EXT_RES = 8, +}; + +enum rpole2_resistor { + RPOLE2_900_OHM, + RPOLE2_450_OHM, + RPOLE2_300_OHM, + RPOLE2_225_OHM, +}; + +enum rzero_resistor { + RZERO_3250_OHM, + RZERO_2750_OHM, + RZERO_2250_OHM, + RZERO_2100_OHM, + RZERO_3000_OHM, + RZERO_2500_OHM, + RZERO_2000_OHM, + RZERO_1850_OHM, +}; + +enum cpole1_capacitor { + CPOLE1_0_PF, + CPOLE1_8_PF, + CPOLE1_16_PF, + CPOLE1_24_PF, + _CPOLE1_24_PF, /* place holder */ + CPOLE1_32_PF, + CPOLE1_40_PF, + CPOLE1_48_PF, +}; + +/** + * @struct ad9523_platform_data + * @brief platform specific information + */ +struct ad9523_platform_data { + /** External VCXO frequency in Hz */ + uint32_t vcxo_freq; + /** Enable SPI-3wire mode */ + uint8_t spi3wire; + + /** REFA differential/single-ended input selection. */ + uint8_t refa_diff_rcv_en; + /** REFB differential/single-ended input selection. */ + uint8_t refb_diff_rcv_en; + /** Zero Delay differential/single-ended input selection. */ + uint8_t zd_in_diff_en; + /** OSC differential/ single-ended input selection. */ + uint8_t osc_in_diff_en; + + /* + * Valid if differential input disabled + * if not true defaults to pos input + */ + /** REFA single-ended neg./pos. input enable. */ + uint8_t refa_cmos_neg_inp_en; + /* REFB single-ended neg./pos. input enable. */ + uint8_t refb_cmos_neg_inp_en; + /** Zero Delay single-ended neg./pos. input enable. */ + uint8_t zd_in_cmos_neg_inp_en; + /** OSC single-ended neg./pos. input enable. */ + uint8_t osc_in_cmos_neg_inp_en; + + /* PLL1 Setting */ + /** PLL1 10-bit: REFA R divider. */ + uint16_t refa_r_div; + /** PLL1 10-bit: REFB R divider. */ + uint16_t refb_r_div; + /** PLL1 10-bit Feedback N divider. */ + uint16_t pll1_feedback_div; + /** Magnitude of PLL1 charge pump current (nA). */ + uint16_t pll1_charge_pump_current_nA; + /** Internal, external Zero Delay mode selection. */ + uint8_t zero_delay_mode_internal_en; + /** PLL1 feedback path, local feedback from the + * OSC_IN receiver or zero delay mode + */ + uint8_t osc_in_feedback_en; + + /** Bypass PLL1 - Single loop mode */ + uint8_t pll1_bypass_en; + /** PLL1 Loop Filter Zero Resistor selection. */ + uint8_t pll1_loop_filter_rzero; + + /** Reference mode selection. */ + uint8_t ref_mode; + + /* PLL2 Setting */ + /** Magnitude of PLL2 charge pump current (nA). */ + uint32_t pll2_charge_pump_current_nA; + /** PLL2 Feedback N-divider, A Counter, range 0..4. */ + uint8_t pll2_ndiv_a_cnt; + /** PLL2 Feedback N-divider, B Counter, range 0..63. */ + uint8_t pll2_ndiv_b_cnt; + /** PLL2 frequency doubler enable. */ + uint8_t pll2_freq_doubler_en; + /** PLL2 R2 divider, range 0..31. */ + uint8_t pll2_r2_div; + /** VCO1 divider, range 3..5. */ + uint8_t pll2_vco_diff_m1; + /** VCO2 divider, range 3..5. */ + uint8_t pll2_vco_diff_m2; + + /* Loop Filter PLL2 */ + /** PLL2 loop filter Rpole resistor value. */ + uint8_t rpole2; + /** PLL2 loop filter Rzero resistor value. */ + uint8_t rzero; + /** PLL2 loop filter Cpole capacitor value. */ + uint8_t cpole1; + /** PLL2 loop filter Rzero bypass enable. */ + uint8_t rzero_bypass_en; + + /* Output Channel Configuration */ + /** Array size of struct ad9523_channel_spec. */ + int32_t num_channels; + /** Pointer to channel array. */ + struct ad9523_channel_spec *channels; + + /** Optional alternative iio device name. */ + int8_t name[16]; +}; + +struct ad9523_state { + struct ad9523_platform_data *pdata; + uint32_t vcxo_freq; + uint32_t vco_freq; + uint32_t vco_out_freq[3]; + uint8_t vco_out_map[14]; +}; + +enum ad9523_out_frequencies { + AD9523_VCO1, + AD9523_VCO2, + AD9523_VCXO, + AD9523_NUM_CLK_SRC, +}; + +struct ad9523_dev { + /* SPI */ + struct no_os_spi_desc *spi_desc; + /* Device Settings */ + struct ad9523_state ad9523_st; + struct ad9523_platform_data *pdata; +}; + +struct ad9523_init_param { + /* SPI */ + struct no_os_spi_init_param spi_init; + /* Device Settings */ + struct ad9523_platform_data *pdata; +}; + +/* Reads the value of the selected register. */ +int32_t ad9523_spi_read(struct ad9523_dev *dev, + uint32_t reg_addr, + uint32_t *reg_data); + +/* Writes a value to the selected register. */ +int32_t ad9523_spi_write(struct ad9523_dev *dev, + uint32_t reg_addr, + uint32_t reg_data); + +/* Updates the AD9523 configuration */ +int32_t ad9523_io_update(struct ad9523_dev *dev); + +/* Sets the clock provider for selected channel. */ +int32_t ad9523_vco_out_map(struct ad9523_dev *dev, + uint32_t ch, + uint32_t out); + +/* Updates the AD9523 configuration. */ +int32_t ad9523_sync(struct ad9523_dev *dev); + +/* Initialize the AD9523 data structure*/ +int32_t ad9523_init(struct ad9523_init_param *init_param); + +/* Configure the AD9523. */ +int32_t ad9523_setup(struct ad9523_dev **device, + const struct ad9523_init_param *init_param); + +/* Free the resources allocated by ad9523_setup(). */ +int32_t ad9523_remove(struct ad9523_dev *dev); + +int32_t ad9523_status(struct ad9523_dev *dev); +#endif // __AD9523_H__ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adar1000.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adar1000.c new file mode 100644 index 0000000..eeac0a4 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adar1000.c @@ -0,0 +1,693 @@ +/** + * MIT License + * + * Copyright (c) 2020 Jimmy Pentz + * + * Reach me at: github.com/jgpentz, jpentz1(at)gmail.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sells + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +/* ADAR1000 4-Channel, X Band and Ku Band Beamformer */ +// ---------------------------------------------------------------------------- +// Includes +// ---------------------------------------------------------------------------- +#include "main.h" +#include "stm32f7xx_hal.h" +#include "stm32f7xx_hal_spi.h" +#include "stm32f7xx_hal_gpio.h" +#include "adar1000.h" + + +// ---------------------------------------------------------------------------- +// Preprocessor Definitions and Constants +// ---------------------------------------------------------------------------- +// VM_GAIN is 15 dB of gain in 128 steps. ~0.12 dB per step. +// A 15 dB attenuator can be applied on top of these values. +const uint8_t VM_GAIN[128] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, +}; + +// VM_I and VM_Q are the settings for the vector modulator. 128 steps in 360 degrees. ~2.813 degrees per step. +const uint8_t VM_I[128] = { + 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3E, 0x3E, 0x3D, 0x3D, 0x3C, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, + 0x36, 0x35, 0x34, 0x33, 0x32, 0x30, 0x2F, 0x2E, 0x2C, 0x2B, 0x2A, 0x28, 0x27, 0x25, 0x24, 0x22, + 0x21, 0x01, 0x03, 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x11, 0x12, 0x13, 0x14, + 0x16, 0x17, 0x18, 0x19, 0x19, 0x1A, 0x1B, 0x1C, 0x1C, 0x1D, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, + 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1E, 0x1E, 0x1D, 0x1D, 0x1C, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, + 0x16, 0x15, 0x14, 0x13, 0x12, 0x10, 0x0F, 0x0E, 0x0C, 0x0B, 0x0A, 0x08, 0x07, 0x05, 0x04, 0x02, + 0x01, 0x21, 0x23, 0x24, 0x26, 0x27, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x2F, 0x31, 0x32, 0x33, 0x34, + 0x36, 0x37, 0x38, 0x39, 0x39, 0x3A, 0x3B, 0x3C, 0x3C, 0x3D, 0x3E, 0x3E, 0x3E, 0x3F, 0x3F, 0x3F, +}; + +const uint8_t VM_Q[128] = { + 0x20, 0x21, 0x23, 0x24, 0x26, 0x27, 0x28, 0x2A, 0x2B, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x38, 0x39, 0x3A, 0x3A, 0x3B, 0x3C, 0x3C, 0x3C, 0x3D, 0x3D, 0x3D, 0x3D, + 0x3D, 0x3D, 0x3D, 0x3D, 0x3D, 0x3C, 0x3C, 0x3C, 0x3B, 0x3A, 0x3A, 0x39, 0x38, 0x38, 0x37, 0x36, + 0x35, 0x34, 0x33, 0x31, 0x30, 0x2F, 0x2E, 0x2D, 0x2B, 0x2A, 0x28, 0x27, 0x26, 0x24, 0x23, 0x21, + 0x20, 0x01, 0x03, 0x04, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x14, + 0x15, 0x16, 0x17, 0x18, 0x18, 0x19, 0x1A, 0x1A, 0x1B, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D, + 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1C, 0x1C, 0x1C, 0x1B, 0x1A, 0x1A, 0x19, 0x18, 0x18, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0B, 0x0A, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, +}; + + +// ---------------------------------------------------------------------------- +// Function Definitions +// ---------------------------------------------------------------------------- +/** + * @brief Initialize the ADC on the ADAR by setting the ADC with a 2 MHz clk, + * and then enable it. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @warning This is setup to only read temperature sensor data, not the power detectors. + */ +void Adar_AdcInit(const AdarDevice * p_adar, uint8_t broadcast) +{ + uint8_t data; + + data = ADAR1000_ADC_2MHZ_CLK | ADAR1000_ADC_EN; + + Adar_Write(p_adar, REG_ADC_CONTROL, data, broadcast); +} + + +/** + * @brief Read a byte of data from the ADAR. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @return Returns a byte of data that has been converted from the temperature sensor. + * + * @warning This is setup to only read temperature sensor data, not the power detectors. + */ +uint8_t Adar_AdcRead(const AdarDevice * p_adar, uint8_t broadcast) +{ + uint8_t data; + + // Start the ADC conversion + Adar_Write(p_adar, REG_ADC_CONTROL, ADAR1000_ADC_ST_CONV, broadcast); + + // This is blocking for now... wait until data is converted, then read it + while (!(Adar_Read(p_adar, REG_ADC_CONTROL) & 0x01)) + { + } + + data = Adar_Read(p_adar, REG_ADC_OUT); + + return(data); +} + + +/** + * @brief Requests the device info from a specific ADAR and stores it in the + * provided AdarDeviceInfo struct. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param info[out] Struct that contains the device info fields. + * + * @return Returns ADAR_ERROR_NOERROR if information was successfully received and stored in the struct. + */ +uint8_t Adar_GetDeviceInfo(const AdarDevice * p_adar, AdarDeviceInfo * info) +{ + *((uint8_t *)info) = Adar_Read(p_adar, 0x002); + info->chip_type = Adar_Read(p_adar, 0x003); + info->product_id = ((uint16_t)Adar_Read(p_adar, 0x004)) << 8; + info->product_id |= ((uint16_t)Adar_Read(p_adar, 0x005)) & 0x00ff; + info->scratchpad = Adar_Read(p_adar, 0x00A); + info->spi_rev = Adar_Read(p_adar, 0x00B); + info->vendor_id = ((uint16_t)Adar_Read(p_adar, 0x00C)) << 8; + info->vendor_id |= ((uint16_t)Adar_Read(p_adar, 0x00D)) & 0x00ff; + info->rev_id = Adar_Read(p_adar, 0x045); + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Read the data that is stored in a single ADAR register. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param mem_addr Memory address of the register you wish to read from. + * + * @return Returns the byte of data that is stored in the desired register. + * + * @warning This function will clear ADDR_ASCN bits. + * @warning The ADAR does not allow for block reads. + */ +uint8_t Adar_Read(const AdarDevice * p_adar, uint32_t mem_addr) +{ + uint8_t instruction[3]; + + // Set SDO active + Adar_Write(p_adar, REG_INTERFACE_CONFIG_A, INTERFACE_CONFIG_A_SDO_ACTIVE, 0); + + instruction[0] = 0x80 | ((p_adar->dev_addr & 0x03) << 5); + instruction[0] |= ((0xff00 & mem_addr) >> 8); + instruction[1] = (0xff & mem_addr); + instruction[2] = 0x00; + + p_adar->Transfer(instruction, p_adar->p_rx_buffer, ADAR1000_RD_SIZE); + + // Set SDO Inactive + Adar_Write(p_adar, REG_INTERFACE_CONFIG_A, 0, 0); + + return(p_adar->p_rx_buffer[2]); +} + + +/** + * @brief Block memory write to an ADAR device. + * + * @pre ADDR_ASCN bits in register zero must be set! + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param mem_addr Memory address of the register you wish to read from. + * @param p_data Pointer to block of data to transfer (must have two unused bytes preceding the data for instruction). + * @param size Size of data in bytes, including the two additional leading bytes. + * + * @warning First two bytes of data will be corrupted if you do not provide two unused leading bytes! + */ +void Adar_ReadBlock(const AdarDevice * p_adar, uint16_t mem_addr, uint8_t * p_data, uint32_t size) +{ + // Set SDO active + Adar_Write(p_adar, REG_INTERFACE_CONFIG_A, INTERFACE_CONFIG_A_SDO_ACTIVE | INTERFACE_CONFIG_A_ADDR_ASCN, 0); + + // Prepare command + p_data[0] = 0x80 | ((p_adar->dev_addr & 0x03) << 5); + p_data[0] |= ((mem_addr) >> 8) & 0x1F; + p_data[1] = (0xFF & mem_addr); + + // Start the transfer + p_adar->Transfer(p_data, p_data, size); + + Adar_Write(p_adar, REG_INTERFACE_CONFIG_A, 0, 0); + // Return nothing since we assume this is non-blocking and won't wait around +} + + +/** + * @brief Sets the Rx/Tx bias currents for the LNA, VM, and VGA to be in either + * low power setting or nominal setting. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param p_bias[in] An AdarBiasCurrents struct filled with bias settings + * as seen in the datasheet Table 6. SPI Settings for + * Different Power Modules + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @return Returns ADAR_ERR_NOERROR if the bias currents were set + */ +uint8_t Adar_SetBiasCurrents(const AdarDevice * p_adar, AdarBiasCurrents * p_bias, uint8_t broadcast) +{ + uint8_t bias = 0; + + // RX LNA/VGA/VM bias + bias = (p_bias->rx_lna & 0x0f); + Adar_Write(p_adar, REG_BIAS_CURRENT_RX_LNA, bias, broadcast); // RX LNA bias + bias = (p_bias->rx_vga & 0x07 << 3) | (p_bias->rx_vm & 0x07); + Adar_Write(p_adar, REG_BIAS_CURRENT_RX, bias, broadcast); // RX VM/VGA bias + + // TX VGA/VM/DRV bias + bias = (p_bias->tx_vga & 0x07 << 3) | (p_bias->tx_vm & 0x07); + Adar_Write(p_adar, REG_BIAS_CURRENT_TX, bias, broadcast); // TX VM/VGA bias + bias = (p_bias->tx_drv & 0x07); + Adar_Write(p_adar, REG_BIAS_CURRENT_TX_DRV, bias, broadcast); // TX DRV bias + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Set the bias ON and bias OFF voltages for the four PA's and one LNA. + * + * @pre This will set all 5 bias ON values and all 5 bias OFF values at once. + * To enable these bias values, please see the data sheet and ensure that the BIAS_CTRL, + * LNA_BIAS_OUT_EN, TR_SOURCE, TX_EN, RX_EN, TR (input to chip), and PA_ON (input to chip) + * bits have all been properly set. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param bias_on_voltage Array that contains the bias ON voltages. + * @param bias_off_voltage Array that contains the bias OFF voltages. + * + * @return Returns ADAR_ERR_NOERROR if the bias currents were set + */ +uint8_t Adar_SetBiasVoltages(const AdarDevice * p_adar, uint8_t bias_on_voltage[5], uint8_t bias_off_voltage[5]) +{ + Adar_SetBit(p_adar, 0x30, 6, BROADCAST_OFF); + Adar_SetBit(p_adar, 0x31, 2, BROADCAST_OFF); + Adar_SetBit(p_adar, 0x38, 5, BROADCAST_OFF); + Adar_Write(p_adar, REG_PA_CH1_BIAS_ON,bias_on_voltage[0], BROADCAST_OFF); + Adar_Write(p_adar, REG_PA_CH2_BIAS_ON,bias_on_voltage[1], BROADCAST_OFF); + Adar_Write(p_adar, REG_PA_CH3_BIAS_ON,bias_on_voltage[2], BROADCAST_OFF); + Adar_Write(p_adar, REG_PA_CH4_BIAS_ON,bias_on_voltage[3], BROADCAST_OFF); + + Adar_Write(p_adar, REG_PA_CH1_BIAS_OFF,bias_off_voltage[0], BROADCAST_OFF); + Adar_Write(p_adar, REG_PA_CH2_BIAS_OFF,bias_off_voltage[1], BROADCAST_OFF); + Adar_Write(p_adar, REG_PA_CH3_BIAS_OFF,bias_off_voltage[2], BROADCAST_OFF); + Adar_Write(p_adar, REG_PA_CH4_BIAS_OFF,bias_off_voltage[3], BROADCAST_OFF); + + Adar_SetBit(p_adar, 0x30, 4, BROADCAST_OFF); + Adar_SetBit(p_adar, 0x30, 6, BROADCAST_OFF); + Adar_SetBit(p_adar, 0x31, 2, BROADCAST_OFF); + Adar_SetBit(p_adar, 0x38, 5, BROADCAST_OFF); + Adar_Write(p_adar, REG_LNA_BIAS_ON,bias_on_voltage[4], BROADCAST_OFF); + Adar_Write(p_adar, REG_LNA_BIAS_OFF,bias_off_voltage[4], BROADCAST_OFF); + + Adar_ResetBit(p_adar, 0x30, 7, BROADCAST_OFF); + Adar_SetBit(p_adar, 0x31, 2, BROADCAST_OFF); + Adar_SetBit(p_adar, 0x31, 4, BROADCAST_OFF); + Adar_SetBit(p_adar, 0x31, 7, BROADCAST_OFF); + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Setup the ADAR to use settings that are transferred over SPI. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @return Returns ADAR_ERR_NOERROR if the bias currents were set + */ +uint8_t Adar_SetRamBypass(const AdarDevice * p_adar, uint8_t broadcast) +{ + uint8_t data; + + data = (MEM_CTRL_BIAS_RAM_BYPASS | MEM_CTRL_BEAM_RAM_BYPASS); + + Adar_Write(p_adar, REG_MEM_CTL, data, broadcast); + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Set the VGA gain value of a Receive channel in dB. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param channel Channel in which to set the gain (1-4). + * @param vga_gain_db Gain to be applied to the channel, ranging from 0 - 30 dB. + * (Intended operation >16 dB). + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @return Returns ADAR_ERROR_NOERROR if the gain was successfully set. + * ADAR_ERROR_FAILED if an invalid channel was selected. + * + * @warning 0 dB or 15 dB step attenuator may also be turned on, which is why intended operation is >16 dB. + */ +uint8_t Adar_SetRxVgaGain(const AdarDevice * p_adar, uint8_t channel, uint8_t vga_gain_db, uint8_t broadcast) +{ + uint8_t vga_gain_bits = (uint8_t)(255*vga_gain_db/16); + uint32_t mem_addr = 0; + + if((channel == 0) || (channel > 4)) + { + return(ADAR_ERROR_FAILED); + } + + mem_addr = REG_CH1_RX_GAIN + (channel & 0x03); + + // Set gain + Adar_Write(p_adar, mem_addr, vga_gain_bits, broadcast); + + // Load the new setting + Adar_Write(p_adar, REG_LOAD_WORKING, 0x1, broadcast); + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Set the phase of a given receive channel using the I/Q vector modulator. + * + * @pre According to the given @param phase, this sets the polarity (bit 5) and gain (bits 4-0) + * of the @param channel, and then loads them into the working register. + * A vector modulator I/Q look-up table has been provided at the beginning of this library. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param channel Channel in which to set the gain (1-4). + * @param phase Byte that is used to set the polarity (bit 5) and gain (bits 4-0). + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @return Returns ADAR_ERROR_NOERROR if the phase was successfully set. + * ADAR_ERROR_FAILED if an invalid channel was selected. + * + * @note To obtain your phase: + * phase = degrees * 128; + * phase /= 360; + */ +uint8_t Adar_SetRxPhase(const AdarDevice * p_adar, uint8_t channel, uint8_t phase, uint8_t broadcast) +{ + uint8_t i_val = 0; + uint8_t q_val = 0; + uint32_t mem_addr_i, mem_addr_q; + + if((channel == 0) || (channel > 4)) + { + return(ADAR_ERROR_FAILED); + } + + //phase = phase % 128; + i_val = VM_I[phase]; + q_val = VM_Q[phase]; + + mem_addr_i = REG_CH1_RX_PHS_I + (channel & 0x03) * 2; + mem_addr_q = REG_CH1_RX_PHS_Q + (channel & 0x03) * 2; + + Adar_Write(p_adar, mem_addr_i, i_val, broadcast); + Adar_Write(p_adar, mem_addr_q, q_val, broadcast); + Adar_Write(p_adar, REG_LOAD_WORKING, 0x1, broadcast); + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Set the VGA gain value of a Tx channel in dB. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @return Returns ADAR_ERROR_NOERROR if the bias was successfully set. + * ADAR_ERROR_FAILED if an invalid channel was selected. + * + * @warning 0 dB or 15 dB step attenuator may also be turned on, which is why intended operation is >16 dB. + */ +uint8_t Adar_SetTxBias(const AdarDevice * p_adar, uint8_t broadcast) +{ + uint8_t vga_bias_bits; + uint8_t drv_bias_bits; + uint32_t mem_vga_bias; + uint32_t mem_drv_bias; + + mem_vga_bias = REG_BIAS_CURRENT_TX; + mem_drv_bias = REG_BIAS_CURRENT_TX_DRV; + + // Set bias to nom + vga_bias_bits = 0x2D; + drv_bias_bits = 0x06; + + // Set bias + Adar_Write(p_adar, mem_vga_bias, vga_bias_bits, broadcast); + // Set bias + Adar_Write(p_adar, mem_drv_bias, drv_bias_bits, broadcast); + + // Load the new setting + Adar_Write(p_adar, REG_LOAD_WORKING, 0x2, broadcast); + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Set the VGA gain value of a Tx channel. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param channel Tx channel in which to set the gain, ranging from 1 - 4. + * @param gain Gain to be applied to the channel, ranging from 0 - 127, + * plus the MSb 15dB attenuator (Intended operation >16 dB). + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @return Returns ADAR_ERROR_NOERROR if the gain was successfully set. + * ADAR_ERROR_FAILED if an invalid channel was selected. + * + * @warning 0 dB or 15 dB step attenuator may also be turned on, which is why intended operation is >16 dB. + */ +uint8_t Adar_SetTxVgaGain(const AdarDevice * p_adar, uint8_t channel, uint8_t gain, uint8_t broadcast) +{ + uint32_t mem_addr; + + if((channel == 0) || (channel > 4)) + { + return(ADAR_ERROR_FAILED); + } + + mem_addr = REG_CH1_TX_GAIN + (channel & 0x03); + + // Set gain + Adar_Write(p_adar, mem_addr, gain, broadcast); + + // Load the new setting + Adar_Write(p_adar, REG_LOAD_WORKING, LD_WRK_REGS_LDTX_OVERRIDE, broadcast); + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Set the phase of a given transmit channel using the I/Q vector modulator. + * + * @pre According to the given @param phase, this sets the polarity (bit 5) and gain (bits 4-0) + * of the @param channel, and then loads them into the working register. + * A vector modulator I/Q look-up table has been provided at the beginning of this library. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param channel Channel in which to set the gain (1-4). + * @param phase Byte that is used to set the polarity (bit 5) and gain (bits 4-0). + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + * + * @return Returns ADAR_ERROR_NOERROR if the phase was successfully set. + * ADAR_ERROR_FAILED if an invalid channel was selected. + * + * @note To obtain your phase: + * phase = degrees * 128; + * phase /= 360; + */ +uint8_t Adar_SetTxPhase(const AdarDevice * p_adar, uint8_t channel, uint8_t phase, uint8_t broadcast) +{ + uint8_t i_val = 0; + uint8_t q_val = 0; + uint32_t mem_addr_i, mem_addr_q; + + if((channel == 0) || (channel > 4)) + { + return(ADAR_ERROR_FAILED); + } + + //phase = phase % 128; + i_val = VM_I[phase]; + q_val = VM_Q[phase]; + + mem_addr_i = REG_CH1_TX_PHS_I + (channel & 0x03) * 2; + mem_addr_q = REG_CH1_TX_PHS_Q + (channel & 0x03) * 2; + + Adar_Write(p_adar, mem_addr_i, i_val, broadcast); + Adar_Write(p_adar, mem_addr_q, q_val, broadcast); + Adar_Write(p_adar, REG_LOAD_WORKING, 0x1, broadcast); + + return(ADAR_ERROR_NOERROR); +} + + +/** + * @brief Reset the whole ADAR device. + * + * @param p_adar[in] ADAR pointer Which specifies the device and what function + * to use for SPI transfer. + */ +void Adar_SoftReset(const AdarDevice * p_adar) +{ + uint8_t instruction[3]; + + instruction[0] = ((p_adar->dev_addr & 0x03) << 5); + instruction[1] = 0x00; + instruction[2] = 0x81; + + p_adar->Transfer(instruction, NULL, sizeof(instruction)); +} + + +/** + * @brief Reset ALL ADAR devices in the SPI chain. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + */ +void Adar_SoftResetAll(const AdarDevice * p_adar) +{ + uint8_t instruction[3]; + + instruction[0] = 0x08; + instruction[1] = 0x00; + instruction[2] = 0x81; + + p_adar->Transfer(instruction, NULL, sizeof(instruction)); +} + + +/** + * @brief Write a byte of @param data to the register located at @param mem_addr. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param mem_addr Memory address of the register you wish to read from. + * @param data Byte of data to be stored in the register. + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + if this set to BROADCAST_ON. + * + * @warning If writing the same data to multiple registers, use ADAR_WriteBlock. + */ +void Adar_Write(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t data, uint8_t broadcast) +{ + uint8_t instruction[3]; + + if (broadcast) + { + instruction[0] = 0x08; + } + else + { + instruction[0] = ((p_adar->dev_addr & 0x03) << 5); + } + + instruction[0] |= (0x1F00 & mem_addr) >> 8; + instruction[1] = (0xFF & mem_addr); + instruction[2] = data; + + p_adar->Transfer(instruction, NULL, sizeof(instruction)); +} + + +/** + * @brief Block memory write to an ADAR device. + * + * @pre ADDR_ASCN BITS IN REGISTER ZERO MUST BE SET! + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param mem_addr Memory address of the register you wish to read from. + * @param p_data[in] Pointer to block of data to transfer (must have two unused bytes + preceding the data for instruction). + * @param size Size of data in bytes, including the two additional leading bytes. + * + * @warning First two bytes of data will be corrupted if you do not provide two unused leading bytes! + */ +void Adar_WriteBlock(const AdarDevice * p_adar, uint16_t mem_addr, uint8_t * p_data, uint32_t size) +{ + // Prepare command + p_data[0] = ((p_adar->dev_addr & 0x03) << 5); + p_data[0] |= ((mem_addr) >> 8) & 0x1F; + p_data[1] = (0xFF & mem_addr); + + // Start the transfer + p_adar->Transfer(p_data, NULL, size); + + // Return nothing since we assume this is non-blocking and won't wait around +} + + +/** + * @brief Set contents of the INTERFACE_CONFIG_A register. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param flags #INTERFACE_CONFIG_A_SOFTRESET, #INTERFACE_CONFIG_A_LSB_FIRST, + * #INTERFACE_CONFIG_A_ADDR_ASCN, #INTERFACE_CONFIG_A_SDO_ACTIVE + * @param broadcast Send the message as a broadcast to all ADARs in the SPI chain + * if this set to BROADCAST_ON. + */ +void Adar_WriteConfigA(const AdarDevice * p_adar, uint8_t flags, uint8_t broadcast) +{ + Adar_Write(p_adar, 0x00, flags, broadcast); +} + + +/** + * @brief Write a byte of @param data to the register located at @param mem_addr and + * then read from the device and verify that the register was correctly set. + * + * @param p_adar[in] Adar pointer Which specifies the device and what function + * to use for SPI transfer. + * @param mem_addr Memory address of the register you wish to read from. + * @param data Byte of data to be stored in the register. + * + * @return Returns the number of attempts that it took to successfully write to a register, + * starting from zero. + * @warning This function currently only supports writes to a single regiter in a single ADAR. + */ +uint8_t Adar_WriteVerify(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t data) +{ + uint8_t rx_data; + + for (uint8_t ii = 0; ii < 3; ii++) + { + Adar_Write(p_adar, mem_addr, data, 0); + + // Can't read back from an ADAR with HW address 0 + if (!((p_adar->dev_addr) % 4)) + { + return(ADAR_ERROR_INVALIDADDR); + } + rx_data = Adar_Read(p_adar, mem_addr); + if (rx_data == data) + { + return(ii); + } + } + + return(ADAR_ERROR_FAILED); +} + +void Adar_SetBit(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t bit, uint8_t broadcast) + { + uint8_t temp = Adar_Read(p_adar, mem_addr); + uint8_t data = temp|(1< +#include +#include + +#ifdef __cplusplus +extern "C" { // Prevent C++ name mangling +#endif + + + + +// ---------------------------------------------------------------------------- +// Datatypes +// ---------------------------------------------------------------------------- +extern SPI_HandleTypeDef hspi1; +extern const uint8_t VM_GAIN[128]; +extern const uint8_t VM_I[128]; +extern const uint8_t VM_Q[128]; + +/// A function pointer prototype for a SPI transfer, the 3 parameters would be +/// p_txData, p_rxData, and size (number of bytes to transfer), respectively. +typedef uint32_t (*Adar_SpiTransfer)( uint8_t *, uint8_t *, uint32_t); + +typedef struct + { + uint8_t dev_addr; ///< 2-bit device hardware address, 0x00, 0x01, 0x10, 0x11 + Adar_SpiTransfer Transfer; ///< Function pointer to the function used for SPI transfers + uint8_t * p_rx_buffer; ///< Data buffer to store received bytes into + }const AdarDevice; + + +/// Use this to store bias current values into, as seen in the datasheet +/// Table 6. SPI Settings for Different Power Modules +typedef struct +{ + uint8_t rx_lna; ///< nominal: 8, low power: 5 + uint8_t rx_vm; ///< nominal: 5, low power: 2 + uint8_t rx_vga; ///< nominal: 10, low power: 3 + uint8_t tx_vm; ///< nominal: 5, low power: 2 + uint8_t tx_vga; ///< nominal: 5, low power: 5 + uint8_t tx_drv; ///< nominal: 6, low power: 3 +} AdarBiasCurrents; + +/// Useful for queries regarding the device info +typedef struct +{ + uint8_t norm_operating_mode : 2; + uint8_t cust_operating_mode : 2; + uint8_t dev_status : 4; + uint8_t chip_type; + uint16_t product_id; + uint8_t scratchpad; + uint8_t spi_rev; + uint16_t vendor_id; + uint8_t rev_id; +} AdarDeviceInfo; + +/// Return types for functions in this library +typedef enum { + ADAR_ERROR_NOERROR = 0, + ADAR_ERROR_FAILED = 1, + ADAR_ERROR_INVALIDADDR = 2, +} AdarErrorCodes; + + +// ---------------------------------------------------------------------------- +// Function Prototypes +// ---------------------------------------------------------------------------- +void Adar_AdcInit(const AdarDevice * p_adar, uint8_t broadcast_bit); + +uint8_t Adar_AdcRead(const AdarDevice * p_adar, uint8_t broadcast_bit); + +uint8_t Adar_GetDeviceInfo(const AdarDevice * p_adar, AdarDeviceInfo * info); + +uint8_t Adar_Read(const AdarDevice * p_adar, uint32_t mem_addr); + +void Adar_ReadBlock(const AdarDevice * p_adar, uint16_t mem_addr, uint8_t * p_data, uint32_t size); + +uint8_t Adar_SetBiasCurrents(const AdarDevice * p_adar, AdarBiasCurrents * p_bias, uint8_t broadcast_bit); + +uint8_t Adar_SetBiasVoltages(const AdarDevice * p_adar, uint8_t bias_on_voltage[5], uint8_t bias_off_voltage[5]); + +uint8_t Adar_SetRamBypass(const AdarDevice * p_adar, uint8_t broadcast_bit); + +uint8_t Adar_SetRxVgaGain(const AdarDevice * p_adar, uint8_t channel, uint8_t vga_gain_db, uint8_t broadcast_bit); + +uint8_t Adar_SetRxPhase(const AdarDevice * p_adar, uint8_t channel, uint8_t phase, uint8_t broadcast_bit); + +uint8_t Adar_SetTxBias(const AdarDevice * p_adar, uint8_t broadcast_bit); + +uint8_t Adar_SetTxVgaGain(const AdarDevice * p_adar, uint8_t channel, uint8_t vga_gain_db, uint8_t broadcast_bit); + +uint8_t Adar_SetTxPhase(const AdarDevice * p_adar, uint8_t channel, uint8_t phase, uint8_t broadcast_bit); + +void Adar_SoftReset(const AdarDevice * p_adar); + +void Adar_SoftResetAll(const AdarDevice * p_adar); + +void Adar_Write(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t data, uint8_t broadcast_bit); + +void Adar_WriteBlock(const AdarDevice * p_adar, uint16_t mem_addr, uint8_t * p_data, uint32_t size); + +void Adar_WriteConfigA(const AdarDevice * p_adar, uint8_t flags, uint8_t broadcast); + +uint8_t Adar_WriteVerify(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t data); + +void Adar_SetBit(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t bit, uint8_t broadcast); + +void Adar_ResetBit(const AdarDevice * p_adar, uint32_t mem_addr, uint8_t bit, uint8_t broadcast); + + +// ---------------------------------------------------------------------------- +// Preprocessor Definitions and Constants +// ---------------------------------------------------------------------------- +// Using BROADCAST_ON will send a command to all ADARs that share a bus +#define BROADCAST_OFF 0 +#define BROADCAST_ON 1 + +// The minimum size of a read from the ADARs consists of 3 bytes +#define ADAR1000_RD_SIZE 3 + +// Address at which the TX RAM starts +#define ADAR_TX_RAM_START_ADDR 0x1800 + +// ADC Defines +#define ADAR1000_ADC_2MHZ_CLK 0x00 +#define ADAR1000_ADC_EN 0x60 +#define ADAR1000_ADC_ST_CONV 0x70 + +/* REGISTER DEFINITIONS */ +#define REG_INTERFACE_CONFIG_A 0x000 +#define REG_INTERFACE_CONFIG_B 0x001 +#define REG_DEV_CONFIG 0x002 +#define REG_SCRATCHPAD 0x00A +#define REG_TRANSFER 0x00F +#define REG_CH1_RX_GAIN 0x010 +#define REG_CH2_RX_GAIN 0x011 +#define REG_CH3_RX_GAIN 0x012 +#define REG_CH4_RX_GAIN 0x013 +#define REG_CH1_RX_PHS_I 0x014 +#define REG_CH1_RX_PHS_Q 0x015 +#define REG_CH2_RX_PHS_I 0x016 +#define REG_CH2_RX_PHS_Q 0x017 +#define REG_CH3_RX_PHS_I 0x018 +#define REG_CH3_RX_PHS_Q 0x019 +#define REG_CH4_RX_PHS_I 0x01A +#define REG_CH4_RX_PHS_Q 0x01B +#define REG_CH1_TX_GAIN 0x01C +#define REG_CH2_TX_GAIN 0x01D +#define REG_CH3_TX_GAIN 0x01E +#define REG_CH4_TX_GAIN 0x01F +#define REG_CH1_TX_PHS_I 0x020 +#define REG_CH1_TX_PHS_Q 0x021 +#define REG_CH2_TX_PHS_I 0x022 +#define REG_CH2_TX_PHS_Q 0x023 +#define REG_CH3_TX_PHS_I 0x024 +#define REG_CH3_TX_PHS_Q 0x025 +#define REG_CH4_TX_PHS_I 0x026 +#define REG_CH4_TX_PHS_Q 0x027 +#define REG_LOAD_WORKING 0x028 +#define REG_PA_CH1_BIAS_ON 0x029 +#define REG_PA_CH2_BIAS_ON 0x02A +#define REG_PA_CH3_BIAS_ON 0x02B +#define REG_PA_CH4_BIAS_ON 0x02C +#define REG_LNA_BIAS_ON 0x02D +#define REG_RX_ENABLES 0x02E +#define REG_TX_ENABLES 0x02F +#define REG_MISC_ENABLES 0x030 +#define REG_SW_CONTROL 0x031 +#define REG_ADC_CONTROL 0x032 +#define REG_ADC_CONTROL_TEMP_EN 0xf0 +#define REG_ADC_OUT 0x033 +#define REG_BIAS_CURRENT_RX_LNA 0x034 +#define REG_BIAS_CURRENT_RX 0x035 +#define REG_BIAS_CURRENT_TX 0x036 +#define REG_BIAS_CURRENT_TX_DRV 0x037 +#define REG_MEM_CTL 0x038 +#define REG_RX_CHX_MEM 0x039 +#define REG_TX_CHX_MEM 0x03A +#define REG_RX_CH1_MEM 0x03D +#define REG_RX_CH2_MEM 0x03E +#define REG_RX_CH3_MEM 0x03F +#define REG_RX_CH4_MEM 0x040 +#define REG_TX_CH1_MEM 0x041 +#define REG_TX_CH2_MEM 0x042 +#define REG_TX_CH3_MEM 0x043 +#define REG_TX_CH4_MEM 0x044 +#define REG_PA_CH1_BIAS_OFF 0x046 +#define REG_PA_CH2_BIAS_OFF 0x047 +#define REG_PA_CH3_BIAS_OFF 0x048 +#define REG_PA_CH4_BIAS_OFF 0x049 +#define REG_LNA_BIAS_OFF 0x04A +#define REG_TX_BEAM_STEP_START 0x04D +#define REG_TX_BEAM_STEP_STOP 0x04E +#define REG_RX_BEAM_STEP_START 0x04F +#define REG_RX_BEAM_STEP_STOP 0x050 + +// REGISTER CONSTANTS +#define INTERFACE_CONFIG_A_SOFTRESET ((1 << 7) | (1 << 0)) +#define INTERFACE_CONFIG_A_LSB_FIRST ((1 << 6) | (1 << 1)) +#define INTERFACE_CONFIG_A_ADDR_ASCN ((1 << 5) | (1 << 2)) +#define INTERFACE_CONFIG_A_SDO_ACTIVE ((1 << 4) | (1 << 3)) + +#define LD_WRK_REGS_LDRX_OVERRIDE (1 << 0) +#define LD_WRK_REGS_LDTX_OVERRIDE (1 << 1) + +#define RX_ENABLES_TX_VGA_EN (1 << 0) +#define RX_ENABLES_TX_VM_EN (1 << 1) +#define RX_ENABLES_TX_DRV_EN (1 << 2) +#define RX_ENABLES_CH3_TX_EN (1 << 3) +#define RX_ENABLES_CH2_TX_EN (1 << 4) +#define RX_ENABLES_CH1_TX_EN (1 << 5) +#define RX_ENABLES_CH0_TX_EN (1 << 6) + +#define TX_ENABLES_TX_VGA_EN (1 << 0) +#define TX_ENABLES_TX_VM_EN (1 << 1) +#define TX_ENABLES_TX_DRV_EN (1 << 2) +#define TX_ENABLES_CH3_TX_EN (1 << 3) +#define TX_ENABLES_CH2_TX_EN (1 << 4) +#define TX_ENABLES_CH1_TX_EN (1 << 5) +#define TX_ENABLES_CH0_TX_EN (1 << 6) + +#define MISC_ENABLES_CH4_DET_EN (1 << 0) +#define MISC_ENABLES_CH3_DET_EN (1 << 1) +#define MISC_ENABLES_CH2_DET_EN (1 << 2) +#define MISC_ENABLES_CH1_DET_EN (1 << 3) +#define MISC_ENABLES_LNA_BIAS_OUT_EN (1 << 4) +#define MISC_ENABLES_BIAS_EN (1 << 5) +#define MISC_ENABLES_BIAS_CTRL (1 << 6) +#define MISC_ENABLES_SW_DRV_TR_MODE_SEL (1 << 7) + +#define SW_CTRL_POL (1 << 0) +#define SW_CTRL_TR_SPI (1 << 1) +#define SW_CTRL_TR_SOURCE (1 << 2) +#define SW_CTRL_SW_DRV_EN_POL (1 << 3) +#define SW_CTRL_SW_DRV_EN_TR (1 << 4) +#define SW_CTRL_RX_EN (1 << 5) +#define SW_CTRL_TX_EN (1 << 6) +#define SW_CTRL_SW_DRV_TR_STATE (1 << 7) + +#define MEM_CTRL_RX_CHX_RAM_BYPASS (1 << 0) +#define MEM_CTRL_TX_CHX_RAM_BYPASS (1 << 1) +#define MEM_CTRL_RX_BEAM_STEP_EN (1 << 2) +#define MEM_CTRL_TX_BEAM_STEP_EN (1 << 3) +#define MEM_CTRL_BIAS_RAM_BYPASS (1 << 5) +#define MEM_CTRL_BEAM_RAM_BYPASS (1 << 6) +#define MEM_CTRL_SCAN_MODE_EN (1 << 7) + +#ifdef __cplusplus +} // End extern "C" +#endif + +#endif /* LIB_ADAR1000_H_ */ + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382.c new file mode 100644 index 0000000..668ae78 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382.c @@ -0,0 +1,2120 @@ +/***************************************************************************//** + * @file adf4382.c + * @brief Implementation of adf4382 Driver. + * @author Ciprian Hegbeli (ciprian.hegbeli@analog.com) + * @author Jude Osemene (jude.osemene@analog.com) +******************************************************************************** + * Copyright 2024(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include "adf4382.h" +#include "no_os_alloc.h" +#include "no_os_delay.h" +#include "no_os_error.h" +#include "no_os_print_log.h" +#include "no_os_util.h" + +/* Charge pump current values expressed in uA */ +static const int adf4382_ci_ua[] = { + 700, + 900, + 1100, + 1300, + 1400, + 1800, + 2200, + 2500, + 2900, + 3600, + 4300, + 5000, + 5800, + 7200, + 8600, + 11100 +}; + +/** + * @brief Writes data to ADF4382 over SPI. + * @param dev - The device structure. + * @param reg_addr - The register address. + * @param data - Data value to write. + * @return - 0 in case of success or negative error code otherwise. + */ +int adf4382_spi_write(struct adf4382_dev *dev, uint16_t reg_addr, uint8_t data) +{ + uint8_t buff[ADF4382_BUFF_SIZE_BYTES]; + uint16_t cmd; + + if (!dev) + return -EINVAL; + + cmd = ADF4382_SPI_WRITE_CMD | reg_addr; + if (dev->spi_desc->bit_order) { + buff[0] = no_os_bit_swap_constant_8(cmd & 0xFF); + buff[1] = no_os_bit_swap_constant_8(cmd >> 8); + buff[2] = no_os_bit_swap_constant_8(data); + } else { + buff[0] = cmd >> 8; + buff[1] = cmd & 0xFF; + buff[2] = data; + } + + return no_os_spi_write_and_read(dev->spi_desc, buff, + ADF4382_BUFF_SIZE_BYTES); +} + +/** + * @brief Reads data from ADF4382 over SPI. + * @param dev - The device structure. + * @param reg_addr - The register address. + * @param data - Data read from the device. + * @return - 0 in case of success or negative error code otherwise. + */ +int adf4382_spi_read(struct adf4382_dev *dev, uint16_t reg_addr, uint8_t *data) +{ + int ret; + uint8_t buff[ADF4382_BUFF_SIZE_BYTES]; + uint16_t cmd; + + if (!dev) + return -EINVAL; + + cmd = ADF4382_SPI_READ_CMD | reg_addr; + if (dev->spi_desc->bit_order) { + buff[0] = no_os_bit_swap_constant_8(cmd & 0xFF); + buff[1] = no_os_bit_swap_constant_8(cmd >> 8); + buff[2] = no_os_bit_swap_constant_8(ADF4382_SPI_DUMMY_DATA); + } else { + buff[0] = cmd >> 8; + buff[1] = cmd & 0xFF; + buff[2] = ADF4382_SPI_DUMMY_DATA; + } + + ret = no_os_spi_write_and_read(dev->spi_desc, buff, + ADF4382_BUFF_SIZE_BYTES); + if (ret) + return ret; + + *data = buff[2]; + + return 0; +} + +/** + * @brief Updates the values of the ADF4382 register. + * @param dev - The device structure. + * @param reg_addr - The register address. + * @param mask - Bits to be updated. + * @param data - Update value for the mask. + * @return - 0 in case of success or negative error code otherwise. + */ +int adf4382_spi_update_bits(struct adf4382_dev *dev, uint16_t reg_addr, + uint8_t mask, uint8_t data) +{ + uint8_t tmp, orig; + int ret; + + ret = adf4382_spi_read(dev, reg_addr, &orig); + if (ret) + return ret; + + tmp = orig & ~mask; + tmp |= data & mask; + + if (tmp != orig) + return adf4382_spi_write(dev, reg_addr, tmp); + + return 0; +} + +/** + * @brief Will output on the terminal the values of all the ADF4382 registers. + * @param dev - The device structure. + * @return - 0 in case of success or negative error code. + */ +int adf4382_reg_dump(struct adf4382_dev *dev) +{ + uint8_t val; + uint16_t i; + int ret; + + for (i = 0; i < 0x68; i++) { + ret = adf4382_spi_read(dev, i, &val); + if (ret) + return ret; + + pr_info("0x%X 0x%X\n", i, val); + } + + for (i = 0x100; i < 0x112; i++) { + ret = adf4382_spi_read(dev, i, &val); + if (ret) + return ret; + + pr_info("0x%X 0x%X\n", i, val); + } + + for (i = 0x200; i < 0x274; i++) { + ret = adf4382_spi_read(dev, i, &val); + if (ret) + return ret; + + pr_info("0x%X 0x%X\n", i, val); + } + + return ret; +} + +/** + * @brief Set the desired reference frequency and reset everything over to maximum + * supported value of 5GHz to the max. value and everything under the minimum + * supported value of 10MHz to the min. value. This should also update the + * frequency and the VCO calibration values. + * @param dev - The device structure. + * @param val - The desired reference frequency in Hz. + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_ref_clk(struct adf4382_dev *dev, uint64_t val) +{ + int ret; + + if (!dev) + return -EINVAL; + + dev->ref_freq_hz = val; + + if (val > ADF4382_REF_CLK_MAX) + dev->ref_freq_hz = ADF4382_REF_CLK_MAX; + + if (val < ADF4382_REF_CLK_MIN) + dev->ref_freq_hz = ADF4382_REF_CLK_MIN; + + ret = adf4382_set_freq(dev); + if (ret) + return ret; + return adf4382_set_vco_cal_timeout(dev); +} + +/** + * @brief Gets the user proposed reference frequency + * @param dev - The device structure. + * @param val - The set value of the reference frequency in Hz. + * @return - Reference frequency in KHz. + */ +int adf4382_get_ref_clk(struct adf4382_dev *dev, uint64_t *val) +{ + if (!dev) + return -EINVAL; + + *val = dev->ref_freq_hz; + + return 0; +} + +/** + * @brief Set the reference doubler to enable or disable based on the passed + * parameter. If the parameter is different then 0 it will set the doubler to + * enable. This should also update the frequency and the VCO calibration values. + * @param dev - The device structure. + * @param en - The enable or disable value of the reference doubler. + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_en_ref_doubler(struct adf4382_dev *dev, bool en) +{ + int ret; + + if (!dev) + return -EINVAL; + + dev->ref_doubler_en = en; + + ret = adf4382_set_freq(dev); + if (ret) + return ret; + return adf4382_set_vco_cal_timeout(dev); +} + +/** + * @brief Gets the value the doubler if it is enabled or disable and stores it + * it the dev structure. + * @param dev - The device structure. + * @param en - The read value of the reference doubler. + * @return - 0 in case of success or negative error code. + */ +int adf4382_get_en_ref_doubler(struct adf4382_dev *dev, bool *en) +{ + uint8_t tmp; + int ret; + + ret = adf4382_spi_read(dev, 0x20, &tmp); + if (ret) + return ret; + + dev->ref_doubler_en = no_os_field_get(tmp, ADF4382_EN_RDBLR_MSK); + *en = dev->ref_doubler_en; + + return 0; +} + +/** + * @brief Set the reference divider value and reset everything over to maximum + * supported value of 63 to the max. value + * @param dev - The device structure. + * @param div - The reference divider value. + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_ref_div(struct adf4382_dev *dev, int32_t div) +{ + int ret; + + if (!dev) + return -EINVAL; + + dev->ref_div = div; + + if (div > ADF4382_REF_DIV_MAX) + dev->ref_div = ADF4382_REF_DIV_MAX; + + ret = adf4382_set_freq(dev); + if (ret) + return ret; + return adf4382_set_vco_cal_timeout(dev); +} + +/** + * @brief Gets the value the reference divider. + * @param dev - The device structure. + * @param div - The read reference divider value. + * @return - Result of the reading procedure, error code otherwise. + */ +int adf4382_get_ref_div(struct adf4382_dev *dev, int32_t *div) +{ + uint8_t tmp; + int ret; + + ret = adf4382_spi_read(dev, 0x20, &tmp); + if (ret) + return ret; + + dev->ref_div = no_os_field_get(ADF4382_R_DIV_MSK, tmp); + *div = dev->ref_div; + + return 0; +} + +/** + * @brief Set the charge pump value which will be written to the register. The + * value will be between 0 and 15 on 8 bits. For more information please + * consult the Datasheet. + * @param dev - The device structure. + * @param reg_val - The desired charge pump register value. + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_cp_i(struct adf4382_dev *dev, int32_t reg_val) +{ + if (!dev) + return -EINVAL; + + dev->cp_i = (uint8_t)reg_val; + + if (reg_val > ADF4382_CPI_VAL_MAX) + dev->cp_i = ADF4382_CPI_VAL_MAX; + + return adf4382_set_freq(dev); +} + +/** + * @brief Gets the charge pump value from the register. The value will be + * between 0 and 15 on 8 bits. For more information please consult the + * Datasheet. + * @param dev - The device structure. + * @param reg_val - The read charge pump register value. + * @return - 0 in case of success or negative error code. + */ +int adf4382_get_cp_i(struct adf4382_dev *dev, int32_t *reg_val) +{ + uint8_t tmp; + int ret; + + ret = adf4382_spi_read(dev, 0x1F, &tmp); + if (ret) + return ret; + + dev->cp_i = no_os_field_get(ADF4382_CP_I_MSK, tmp); + *reg_val = dev->cp_i; + + return 0; +} + +/** + * @brief Set the bleed word, which represents the value of the bleed current + * written to the register space. + * @param dev - The device structure. + * @param word - The bleed current register value. + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_bleed_word(struct adf4382_dev *dev, int32_t word) +{ + if (!dev) + return -EINVAL; + + dev->bleed_word = (uint16_t)word; + + if (word > ADF4382_BLEED_WORD_MAX) + dev->bleed_word = ADF4382_BLEED_WORD_MAX; + + return adf4382_set_freq(dev); +} + +/** + * @brief Gets the value of the set bleed word. + * @param dev - The device structure. + * @param word - The read bleed current register value. + * @return - Result of the reading procedure, error code otherwise. + */ +int adf4382_get_bleed_word(struct adf4382_dev *dev, int32_t *word) +{ + uint8_t upper; + uint8_t lower; + int ret; + + ret = adf4382_spi_read(dev, 0x1E, &upper); + if (ret) + return ret; + + upper &= (ADF4382_COARSE_BLEED_MSK | ADF4382_FINE_BLEED_MSB_MSK); + + ret = adf4382_spi_read(dev, 0x1D, &lower); + if (ret) + return ret; + + dev->bleed_word = (upper << 8) | lower; + *word = dev->bleed_word; + + return 0; +} + +/** + * @brief Set the output power register value of a channel and reset everything + * over to maximum supported value of 15 to the max. value. + * @param dev - The device structure. + * @param ch - The channel to set the power off. + * @param pwr - The output power register value. + * @return - Result of the writing procedure, error code otherwise. + */ +int adf4382_set_out_power(struct adf4382_dev *dev, uint8_t ch, int32_t pwr) +{ + uint8_t tmp; + + if (pwr > ADF4382_OUT_PWR_MAX) + pwr = ADF4382_OUT_PWR_MAX; + + if (!ch) { + tmp = no_os_field_prep(ADF4382_CLK1_OPWR_MSK, pwr); + return adf4382_spi_update_bits(dev, 0x29, ADF4382_CLK1_OPWR_MSK, + tmp); + } + + tmp = no_os_field_prep(ADF4382_CLK2_OPWR_MSK, pwr); + return adf4382_spi_update_bits(dev, 0x29, ADF4382_CLK2_OPWR_MSK, tmp); +} + +/** + * @brief Gets the output power register value. + * @param dev - The device structure. + * @param ch - The channel to get the power off. + * @param pwr - The output power register value. + * @return - Result of the reading procedure, error code otherwise. + */ +int adf4382_get_out_power(struct adf4382_dev *dev, uint8_t ch, int32_t *pwr) +{ + + uint8_t tmp; + int ret; + + ret = adf4382_spi_read(dev, 0x29, &tmp); + if (ret) + return ret; + + if (!ch) + *pwr = no_os_field_get(ADF4382_CLK1_OPWR_MSK, tmp); + else + *pwr = no_os_field_get(ADF4382_CLK2_OPWR_MSK, tmp); + + return 0; +} + +/** + * @brief Set the output channel to enable or disable based on the passed + * parameter. If the parameter is different then 0 it will set the doubler to + * enable. + * @param dev - The device structure. + * @param ch - The channel to set state. + * @param en - The enable or disable value of the output channel. + * @return - Result of the writing procedure, error code otherwise. + */ +int adf4382_set_en_chan(struct adf4382_dev *dev, uint8_t ch, bool en) +{ + uint8_t enable; + + if (!ch) { + enable = no_os_field_prep(ADF4382_PD_CLKOUT1_MSK, !en); + return adf4382_spi_update_bits(dev, 0x2B, + ADF4382_PD_CLKOUT1_MSK, + enable); + } + + enable = no_os_field_prep(ADF4382_PD_CLKOUT2_MSK, !en); + return adf4382_spi_update_bits(dev, 0x2B, ADF4382_PD_CLKOUT2_MSK, + enable); +} + +/** + * @brief Gets the value the output channel if it is enabled or disable. + * @param dev - The device structure. + * @param ch - The channel to get state. + * @param en - The status of the output channel. + * @return - 0 in case of success or negative error code. + */ +int adf4382_get_en_chan(struct adf4382_dev *dev, uint8_t ch, bool *en) +{ + uint8_t tmp; + bool enable; + int ret; + + ret = adf4382_spi_read(dev, 0x2B, &tmp); + if (ret) + return ret; + + if (!ch) + enable = no_os_field_get(tmp, ADF4382_PD_CLKOUT1_MSK); + else + enable = no_os_field_get(tmp, ADF4382_PD_CLKOUT2_MSK); + + *en = !enable; + + return 0; +} + +/** + * @brief Set the desired output frequency and reset everything over to maximum + * supported value of 22GHz (21GHz for ADF4382A) to the max. value and + * everything under the minimum supported value of 687.5MHz (2.875GHz for + * ADF4382A) to the min. value. + * @param dev - The device structure. + * @param val - The desired output frequency in Hz. + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_rfout(struct adf4382_dev *dev, uint64_t val) +{ + if (!dev) + return -EINVAL; + + dev->freq = val; + + if (val > dev->freq_max) + dev->freq = dev->freq_max; + + if (val < dev->freq_min) + dev->freq = dev->freq_min; + + return adf4382_set_freq(dev); +} + +/** + * @brief Computes the PFD frequency and returns the value in Hz. + * @param dev - The device structure. + * @return - PFD value in Hz. + */ +static uint64_t adf4382_pfd_compute(struct adf4382_dev *dev) +{ + uint64_t pfd_freq; + + pfd_freq = NO_OS_DIV_ROUND_CLOSEST(dev->ref_freq_hz, dev->ref_div); + if (dev->ref_doubler_en) + pfd_freq *= 2; + + return pfd_freq; +} + +/** + * @brief Gets the user proposed output frequency + * @param dev - The device structure. + * @param val - The set value of the output frequency in Hz. + * @return - 0 in case of success or negative error code. + */ +int adf4382_get_rfout(struct adf4382_dev *dev, uint64_t *val) +{ + uint32_t frac1 = 0; + uint32_t frac2 = 0; + uint32_t mod2 = 0; + uint64_t freq; + uint64_t pfd; + uint8_t tmp; + uint16_t n; + int ret; + + pfd = adf4382_pfd_compute(dev); + + ret = adf4382_spi_read(dev, 0x11, &tmp); + if (ret) + return ret; + n = tmp & ADF4382_N_INT_MSB_MSK; + n = n << 8; + + ret = adf4382_spi_read(dev, 0x10, &tmp); + if (ret) + return ret; + n |= tmp; + + ret = adf4382_spi_read(dev, 0x15, &tmp); + if (ret) + return ret; + frac1 = tmp & ADF4382_FRAC1WORD_MSB; + frac1 = frac1 << 8; + + ret = adf4382_spi_read(dev, 0x14, &tmp); + if (ret) + return ret; + frac1 |= tmp; + frac1 = frac1 << 8; + + ret = adf4382_spi_read(dev, 0x13, &tmp); + if (ret) + return ret; + frac1 |= tmp; + frac1 = frac1 << 8; + + ret = adf4382_spi_read(dev, 0x12, &tmp); + if (ret) + return ret; + frac1 |= tmp; + + ret = adf4382_spi_read(dev, 0x19, &tmp); + if (ret) + return ret; + frac2 = tmp; + frac2 = frac2 << 8; + + ret = adf4382_spi_read(dev, 0x18, &tmp); + if (ret) + return ret; + frac2 |= tmp; + frac2 = frac2 << 8; + + ret = adf4382_spi_read(dev, 0x17, &tmp); + if (ret) + return ret; + frac2 |= tmp; + + ret = adf4382_spi_read(dev, 0x1c, &tmp); + if (ret) + return ret; + mod2 = tmp; + mod2 = mod2 << 8; + + ret = adf4382_spi_read(dev, 0x1b, &tmp); + if (ret) + return ret; + mod2 |= tmp; + mod2 = mod2 << 8; + + ret = adf4382_spi_read(dev, 0x1a, &tmp); + if (ret) + return ret; + mod2 |= tmp; + + freq = frac2 * pfd; + freq = no_os_div_u64(freq, mod2); + freq = freq + (frac1 * pfd); + freq = no_os_div_u64(freq, ADF4382_MOD1WORD); + freq = freq + (n * pfd); + + *val = freq; + return 0; +} + +/** + * @brief Computes the second fractional part of the feedback divider if needed. + * @param dev - The device structure. + * @param res - Residue from the first fractional part. + * @param pfd_freq - Phase/frequency detector frequency. + * @param frac2_word - Second fractional part of the feedback divider, which + * will be returned. + * @param mod2_word - Modulo for the second fractional part of the feedback + * divider, which will be returned. + * @return - 0 in case of success, negative error code otherwise. + */ +static int adf4382_frac2_compute(struct adf4382_dev *dev, uint64_t res, + uint64_t pfd_freq, uint32_t *frac2_word, + uint32_t *mod2_word) +{ + uint32_t channel_spacing; + uint8_t en_phase_resync; + uint32_t chsp_freq; + uint32_t mod2_tmp; + uint32_t mod2_max; + uint32_t mod2_wd; + uint32_t gcd; + uint8_t tmp; + int ret; + + channel_spacing = 1; + mod2_wd = 1; + + ret = adf4382_spi_read(dev, 0x1E, &tmp); + if (ret) + return ret; + + en_phase_resync = no_os_field_get(tmp, ADF4382_EN_PHASE_RESYNC_MSK); + + if (en_phase_resync) + mod2_max = ADF4382_PHASE_RESYNC_MOD2WORD_MAX; + else + mod2_max = ADF4382_MOD2WORD_MAX; + + do { + + chsp_freq = channel_spacing * ADF4382_MOD1WORD; + gcd = no_os_greatest_common_divisor(chsp_freq, pfd_freq); + mod2_tmp = NO_OS_DIV_ROUND_UP(pfd_freq, gcd); + + if (mod2_tmp > mod2_max) { + channel_spacing *= 5; + } else { + mod2_wd = mod2_tmp; + break; + } + + } while (channel_spacing < ADF4382_CHANNEL_SPACING_MAX); + + if (!en_phase_resync) { + mod2_wd *= NO_OS_DIV_U64(mod2_max, mod2_wd); + } + + *frac2_word = NO_OS_DIV_ROUND_CLOSEST_ULL(res * mod2_wd, pfd_freq); + *mod2_word = mod2_wd; + + return 0; +} + +/** + * @brief Computes the feedback divider values for the PLL. + * @param dev - The device structure. + * @param freq - The output frequency. + * @param pfd_freq - Phase/frequency detector frequency. + * @param n_int - Integer part of the feedback divider, which will be + * returned. + * @param frac1_word - First fractional part of the feedback divider, which will + * be returned. + * @param frac2_word - Second fractional part of the feedback divider, which + * will be returned. + * @param mod2_word - Modulo for the second fractional part of the feedback + * divider, which will be returned. + * @return - 0 in case of success, negative error code otherwise. + */ +static int adf4382_pll_fract_n_compute(struct adf4382_dev *dev, uint64_t freq, + uint64_t pfd_freq, uint16_t *n_int, + uint32_t *frac1_word, uint32_t *frac2_word, + uint32_t *mod2_word) +{ + uint64_t rem; + uint64_t res; + + *n_int = no_os_div64_u64_rem(freq, pfd_freq, &rem); + + res = rem * ADF4382_MOD1WORD; + *frac1_word = (uint32_t)no_os_div64_u64_rem(res, pfd_freq, &rem); + + *frac2_word = 0; + *mod2_word = 0; + + if (rem > 0) + return adf4382_frac2_compute(dev, rem, pfd_freq, frac2_word, + mod2_word); + + return 0; +} + +/** + * @brief Fast calibration function. Computes Minimum VCO frequency (fmin), + * uses the minimum NDIV value to generate fastcal Lookup table (LUT), and + * finally enables LUT Calibration. + * @param dev - The device structure. + * @param en_fast_cal - Enables the fast calibration routine. + * @return - N_INT value corresponding to minimum VCO frequency for + * fast calibration LUT generation. + */ +int adf4382_set_en_fast_calibration(struct adf4382_dev *dev, bool en_fast_cal) +{ + uint64_t operating_pfd_freq; + uint64_t pfd_freq_lut = 0; + uint8_t ref_div_lut = 0; + uint8_t timeout = 0; + uint8_t lut_scale; + uint16_t lut_int; + uint8_t fsm_busy; + uint16_t n_int; + uint8_t tmp; + uint8_t val; + int ret; + + if (!dev) + return -EINVAL; + + if (!en_fast_cal) + return 0; + + // Stabilize PFD Frequency for Fast Calibration LUT Generation + operating_pfd_freq = adf4382_pfd_compute(dev); + + if (operating_pfd_freq > 125 * MHZ) { + ref_div_lut = dev->ref_div; + pfd_freq_lut = operating_pfd_freq; + // Increase reference divider until PFD frequency is below 125MHz + do { + dev->ref_div += 1; + if (dev->ref_div > ADF4382_REF_DIV_MAX) + break; + pfd_freq_lut = adf4382_pfd_compute(dev); + } while (pfd_freq_lut > 125 * MHZ); + ret = adf4382_set_ref_div(dev, dev->ref_div); + if (ret) + return ret; + } else { + pfd_freq_lut = operating_pfd_freq; + } + + // Set cal_gen values for fast calibration + ret = adf4382_spi_update_bits(dev, 0x44, ADF4382_VPTAT_CALGEN_MSK, + no_os_field_prep + (ADF4382_VPTAT_CALGEN_MSK, + ADF4382_FASTCAL_VPTAT_CALGEN)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x45, ADF4382_VCTAT_CALGEN_MSK, + no_os_field_prep + (ADF4382_VCTAT_CALGEN_MSK, + ADF4382_FASTCAL_VCTAT_CALGEN)); + if (ret) + return ret; + + // Enable LUT Generation + dev->en_lut_gen = en_fast_cal; + ret = adf4382_spi_update_bits(dev, 0x36, ADF4382_EN_LUT_GEN_MSK, + no_os_field_prep(ADF4382_EN_LUT_GEN_MSK, + dev->en_lut_gen)); + if (ret) + return ret; + + // Compute and set the minimum N_INT values + n_int = NO_OS_DIV_ROUND_UP(dev->vco_min, pfd_freq_lut); + val = n_int & ADF4382_N_INT_LSB_MSK; + ret = adf4382_spi_write(dev, 0x10, val); + if (ret) + return ret; + + // Monitor FSM busy status + ret = adf4382_spi_read(dev, 0x58, &val); + if (ret) + return ret; + fsm_busy = no_os_field_get(val, ADF4382_FSM_BUSY_MSK); + + while (fsm_busy == 1) { + if (timeout++ > ADF4382_FSM_BUSY_LOOP_CNT) + break; + no_os_mdelay(10); + ret = adf4382_spi_read(dev, 0x58, &val); + if (ret) + return ret; + fsm_busy = no_os_field_get(val, ADF4382_FSM_BUSY_MSK); + } + if (timeout > ADF4382_FSM_BUSY_LOOP_CNT) + return -ETIMEDOUT; + + // Compute the LUT scale based on PFD frequency + lut_scale = NO_OS_DIV_ROUND_CLOSEST(operating_pfd_freq, pfd_freq_lut); + lut_scale *= 8; + val = lut_scale & ADF4382_LUT_SCALE_MSK; + ret = adf4382_spi_write(dev, 0x4F, val); + if (ret) + return ret; + + dev->en_lut_gen = !en_fast_cal; + ret = adf4382_spi_update_bits(dev, 0x36, ADF4382_EN_LUT_GEN_MSK, + no_os_field_prep + (ADF4382_EN_LUT_GEN_MSK, + dev->en_lut_gen)); + if (ret) + return ret; + + // Lock to the maximum frequency + dev->freq = dev->freq_max; + ret = adf4382_set_freq(dev); + if (ret) + return ret; + + + // Read LUT int value directly from registers and write it to the LUT + ret = adf4382_spi_read(dev, 0x11, &tmp); + if (ret) + return ret; + lut_int = no_os_field_get(tmp, ADF4382_N_INT_MSB_MSK); + lut_int = lut_int << 8; + + ret = adf4382_spi_read(dev, 0x10, &tmp); + if (ret) + return ret; + lut_int |= tmp; + + val = (lut_int >> 6) & ADF4382_M_LUT_N_MSB_MSK; + ret = adf4382_spi_write(dev, 0x203, val); + if (ret) + return ret; + + val = lut_int & ADF4382_M_LUT_N_LSB_MSK; + ret = adf4382_spi_update_bits(dev, 0x202, ADF4382_M_LUT_N_LSB_MSK, + no_os_field_prep + (ADF4382_M_LUT_N_LSB_MSK, val)); + if (ret) + return ret; + + ret = adf4382_spi_read(dev, 0x5F, &tmp); + if (ret) + return ret; + + val = no_os_field_get(tmp, ADF4382_VCO_CORE_MSK); + ret = adf4382_spi_update_bits(dev, 0x202, ADF4382_M_LUT_CORE_MSK, + no_os_field_prep + (ADF4382_M_LUT_CORE_MSK, val)); + if (ret) + return ret; + + ret = adf4382_spi_read(dev, 0x5E, &tmp); + if (ret) + return ret; + + val = no_os_field_get(tmp, ADF4382_VCO_BAND_LSB_MSK); + ret = adf4382_spi_write(dev, 0x201, val); + if (ret) + return ret; + + ret = adf4382_spi_read(dev, 0x5F, &tmp); + if (ret) + return ret; + + val = no_os_field_get(tmp, ADF4382_M_LUT_BAND_MSB_MSK); + ret = adf4382_spi_update_bits(dev, 0x202, ADF4382_M_LUT_BAND_MSB_MSK, + no_os_field_prep + (ADF4382_M_LUT_BAND_MSB_MSK, val)); + if (ret) + return ret; + + val = no_os_field_prep(ADF4382_LUT_WR_ADDR_MSK, 31) | + no_os_field_prep(ADF4382_O_VCO_LUT_MSK, 1); + ret = adf4382_spi_write(dev, 0x200, val); + if (ret) + return ret; + + // Revert the R_DIV value to original value if changed. + if (ref_div_lut != 0) { + dev->ref_div = ref_div_lut; + ret = adf4382_set_ref_div(dev, dev->ref_div); + if (ret) + return ret; + } + dev->en_lut_cal = en_fast_cal; + adf4382_spi_update_bits(dev, 0x36, ADF4382_EN_LUT_CAL_MSK, + dev->en_lut_cal); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x15, ADF4382_INT_MODE_MSK, + no_os_field_prep(ADF4382_INT_MODE_MSK, 0)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x2A, ADF4382_PD_CALGEN_MSK, + no_os_field_prep(ADF4382_PD_CALGEN_MSK, 1)); + if (ret) + return ret; + + return adf4382_spi_update_bits(dev, 0x38, ADF4382_CAL_VTUNE_TO_LSB_MSK, + no_os_field_prep( + ADF4382_CAL_VTUNE_TO_LSB_MSK, 0)); +} + +/** + * @brief Gets Fast calibration LUT Calibration status. + * @param dev - The device structure. + * @param en - The set value of LUT Calibration. + * @return - 0 in case of success, negative error code otherwise. + */ +int adf4382_get_en_lut_calibration(struct adf4382_dev *dev, bool *en) +{ + uint8_t tmp; + int ret; + + ret = adf4382_spi_read(dev, 0x36, &tmp); + if (ret) + return ret; + + *en = no_os_field_get(tmp, ADF4382_EN_LUT_CAL_MSK); + return 0; +} + +/** + * @brief Sets Fast calibration LUT Calibration. Refer to en_fastcal function to + * first generate fastcal Lookup Table (LUT). + * @param dev - The device structure. + * @param en_lut_cal - Enable/Disable LUT Calibration. + * @return - 0 in case of success, negative error code otherwise. + */ +int adf4382_set_en_lut_calibration(struct adf4382_dev *dev, bool en_lut_cal) +{ + int ret; + uint8_t vptat_calgen, vctat_calgen, pd_calgen; + uint32_t cal_vtune_to; + + dev->en_lut_cal = en_lut_cal; + + if (dev->en_lut_cal == 0) { + vptat_calgen = ADF4382_VPTAT_CALGEN; + vctat_calgen = ADF4382_VCTAT_CALGEN; + pd_calgen = 0; + cal_vtune_to = dev->cal_vtune_to; + } else { + vptat_calgen = ADF4382_FASTCAL_VPTAT_CALGEN; + vctat_calgen = ADF4382_FASTCAL_VCTAT_CALGEN; + pd_calgen = 1; + cal_vtune_to = 0; + } + + ret = adf4382_spi_update_bits(dev, 0x44, ADF4382_VPTAT_CALGEN_MSK, + no_os_field_prep(ADF4382_VPTAT_CALGEN_MSK, + vptat_calgen)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x45, ADF4382_VCTAT_CALGEN_MSK, + no_os_field_prep(ADF4382_VCTAT_CALGEN_MSK, + vctat_calgen)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x2A, ADF4382_PD_CALGEN_MSK, + no_os_field_prep(ADF4382_PD_CALGEN_MSK, + pd_calgen)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x38, ADF4382_CAL_VTUNE_TO_LSB_MSK, + no_os_field_prep(ADF4382_CAL_VTUNE_TO_LSB_MSK, + cal_vtune_to)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x39, ADF4382_CAL_VTUNE_TO_MSB_MSK, + no_os_field_prep(ADF4382_CAL_VTUNE_TO_MSB_MSK, + cal_vtune_to >> 8)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x36, ADF4382_EN_LUT_CAL_MSK, + no_os_field_prep(ADF4382_EN_LUT_CAL_MSK, + dev->en_lut_cal)); + if (ret) + return ret; + + return adf4382_spi_update_bits(dev, 0x15, ADF4382_INT_MODE_MSK, + no_os_field_prep(ADF4382_INT_MODE_MSK, 0)); +} + +/** + * @brief Gets the user proposed output frequency from the device tree without + * reading from the device. This is to enable and accurate reading of device + * lock-time. + * @param dev - The device structure. + * @param val - Holds the software value of RFOUT Frequency set. + * @return - Output frequency in KHz. + */ +int adf4382_get_change_rfout(struct adf4382_dev *dev, uint64_t *val) +{ + *val = dev->freq; + return 0; +} + +/** + * @brief Set the desired output frequency and reset everything over to maximum + * supported value of 22GHz (21GHz for ADF4382A) to the max without starting + * autocalibration. value and everything under the minimum supported value of + * 687.5MHz (2.875GHz for ADF4382A) to the min. value. + * @param dev - The device structure. + * @param val - The desired output frequency in Hz. + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_change_rfout(struct adf4382_dev *dev, uint64_t val) +{ + if (!dev) + return -EINVAL; + + dev->freq = val; + + if (val > dev->freq_max) + dev->freq = dev->freq_max; + + if (val < dev->freq_min) + dev->freq = dev->freq_min; + + return adf4382_set_change_freq(dev); +} + +/** + * @brief Computes the optimized bleed word value for the PLL in fractional mode. + * @param dev - The device structure. + * @param pfd_freq - Phase detector frequency. + * @return - 0 in case of success or negative error code. + */ +static int adf4382_bleed_word_compute(struct adf4382_dev *dev, + uint64_t pfd_freq) +{ + uint32_t coars_bleed; + uint16_t bleed_delay = 0; + uint32_t fine_bleed; + uint16_t bleed_word_tmp; + uint64_t bleed_i; + uint64_t rem; + + if (!dev) + return -EINVAL; + + /* Computes the bleed delay based on rfout frequency in SDM MODE 0. + See Product DataSheet for more details. */ + if (dev->freq < 1800000000UL) + bleed_delay = 3600; + else if (dev->freq < 4000000000) + bleed_delay = 1000; + else if (dev->freq < 10000000000UL) + bleed_delay = 625; + else if (dev->freq >= 10000000000UL) + bleed_delay = 300; + + bleed_i = bleed_delay * pfd_freq * adf4382_ci_ua[dev->cp_i]; + bleed_i = NO_OS_DIV_ROUND_CLOSEST(bleed_i, PS_TO_S); + coars_bleed = no_os_div64_u64_rem(bleed_i, ADF4382_COARSE_BLEED_CONST, + &rem); + fine_bleed = rem * ADF4382_FINE_BLEED_CONST_1; + fine_bleed = NO_OS_DIV_ROUND_UP(fine_bleed, ADF4382_FINE_BLEED_CONST_2); + bleed_word_tmp = coars_bleed << 9 | fine_bleed; + bleed_word_tmp = no_os_clamp(bleed_word_tmp, 1, 8191); + dev->bleed_word = bleed_word_tmp; + return 0; +} + +/** + * @brief Set the output frequency. This will set the required registers to + * device but skip NDIV value, to be written separately. This Function will not + * start autocalibration until REG0010 is written. + * @param dev - The device structure. + * @return - 0 in case of success, negative error code otherwise. + */ +int adf4382_set_change_freq(struct adf4382_dev *dev) +{ + uint32_t frac2_word; + uint32_t frac1_word; + uint32_t mod2_word; + uint8_t clkout_div; + uint64_t pfd_freq; + uint8_t ldwin_pw = 0; + uint8_t en_bleed; + uint16_t n_int; + uint64_t tmp; + uint64_t vco = 0; + uint8_t val; + int ret; + + for (clkout_div = 0; clkout_div <= dev->clkout_div_reg_val_max; clkout_div++) { + tmp = (1 << clkout_div) * dev->freq; + if (tmp < dev->vco_min || tmp > dev->vco_max) + continue; + + vco = tmp; + break; + } + + if (!vco) { + pr_err("VCO is 0\n"); + return -EINVAL; + } + + //Calculates the PFD freq. the output will be in Hz + pfd_freq = adf4382_pfd_compute(dev); + + ret = adf4382_pll_fract_n_compute(dev, dev->freq, pfd_freq, &n_int, + &frac1_word, &frac2_word, &mod2_word); + if (ret) + return ret; + + if (frac1_word || frac2_word) { + en_bleed = 1; + if (pfd_freq <= 40 * MHZ) { + ldwin_pw = 7; + } else if (pfd_freq <= 50 * MHZ) { + ldwin_pw = 6; + } else if (pfd_freq <= 100 * MHZ) { + ldwin_pw = 5; + } else if (pfd_freq <= 200 * MHZ) { + ldwin_pw = 4; + } else if (pfd_freq <= 250 * MHZ) { + if (dev->freq >= 5000U * MHZ && + dev->freq < 6400U * MHZ) { + ldwin_pw = 3; + } else { + ldwin_pw = 2; + } + } + ret = adf4382_bleed_word_compute(dev, pfd_freq); + if (ret) + return ret; + } else { + en_bleed = 0; + + tmp = NO_OS_DIV_ROUND_UP(pfd_freq, MICROAMPER_PER_AMPER); + tmp *= adf4382_ci_ua[dev->cp_i]; + tmp = NO_OS_DIV_ROUND_UP(dev->bleed_word, tmp); + if (tmp <= 85) + ldwin_pw = 0; + else + ldwin_pw = 1; + } + + if (frac2_word) { + ret = adf4382_spi_update_bits(dev, 0x28, ADF4382_VAR_MOD_EN_MSK, + 0xff); + if (ret) + return ret; + } else { + ret = adf4382_spi_update_bits(dev, 0x28, ADF4382_VAR_MOD_EN_MSK, + 0x0); + if (ret) + return ret; + } + + val = dev->bleed_word & ADF4382_FINE_BLEED_LSB_MSK; + ret = adf4382_spi_write(dev, 0x1D, val); + if (ret) + return ret; + val = (dev->bleed_word >> 8) & ADF4382_BLEED_MSB_MSK; + ret = adf4382_spi_update_bits(dev, 0x1E, ADF4382_BLEED_MSB_MSK, + no_os_field_prep(ADF4382_BLEED_MSB_MSK, + val)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x1F, ADF4382_EN_BLEED_MSK, + no_os_field_prep(ADF4382_EN_BLEED_MSK, + en_bleed)); + if (ret) + return ret; + + val = mod2_word & ADF4382_MOD2WORD_LSB_MSK; + ret = adf4382_spi_write(dev, 0x1A, val); + if (ret) + return ret; + val = (mod2_word >> 8) & ADF4382_MOD2WORD_MID_MSK; + ret = adf4382_spi_write(dev, 0x1B, val); + if (ret) + return ret; + val = (mod2_word >> 16) & ADF4382_MOD2WORD_MSB_MSK; + ret = adf4382_spi_write(dev, 0x1C, val); + if (ret) + return ret; + + val = frac2_word & ADF4382_FRAC2WORD_LSB_MSK; + ret = adf4382_spi_write(dev, 0x17, val); + if (ret) + return ret; + val = (frac2_word >> 8) & ADF4382_FRAC2WORD_MID_MSK; + ret = adf4382_spi_write(dev, 0x18, val); + if (ret) + return ret; + val = (frac2_word >> 16) & ADF4382_FRAC2WORD_MSB_MSK; + ret = adf4382_spi_write(dev, 0x19, val); + if (ret) + return ret; + + val = frac1_word & ADF4382_FRAC1WORD_LSB_MSK; + ret = adf4382_spi_write(dev, 0x12, val); + if (ret) + return ret; + val = (frac1_word >> 8) & ADF4382_FRAC1WORD_MID_MSK; + ret = adf4382_spi_write(dev, 0x13, val); + if (ret) + return ret; + val = (frac1_word >> 16) & ADF4382_FRAC1WORD_MSB_MSK; + ret = adf4382_spi_write(dev, 0x14, val); + if (ret) + return ret; + + val = (frac1_word >> 24) & ADF4382_FRAC1WORD_MSB; + ret = adf4382_spi_update_bits(dev, 0x15, ADF4382_FRAC1WORD_MSB, val); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x2C, ADF4382_LDWIN_PW_MSK, + no_os_field_prep(ADF4382_LDWIN_PW_MSK, + ldwin_pw)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x11, ADF4382_CLKOUT_DIV_MSK, + no_os_field_prep(ADF4382_CLKOUT_DIV_MSK, + clkout_div)); + if (ret) + return ret; + + val = (n_int >> 8) & ADF4382_N_INT_MSB_MSK; + ret = adf4382_spi_update_bits(dev, 0x11, ADF4382_N_INT_MSB_MSK, val); + if (ret) + return ret; + // Need to store N_INT to trigger an auto-calibration in another function + dev->n_int = n_int; + + return 0; +} + +/** + * @brief Get the status of start calibration. Will always return zero to allow + * users set it multiple times to trigger autocalibration. + * @param dev - The device structure. + * @param start_cal - Overwrites start calibration attribute to 0. + * @return - 0 in case of success, negative error code otherwise. + */ +int adf4382_get_start_calibration(struct adf4382_dev *dev, bool *start_cal) +{ + *start_cal = 0; + return 0; +} + +/** + * @brief Set REG0010 value in device structure to the device to start autocal. + * @param dev - The device structure. + * @return - 0 in case of success, negative error code otherwise. + */ +int adf4382_set_start_calibration(struct adf4382_dev *dev) +{ + uint8_t n_value; + n_value = dev->n_int & ADF4382_N_INT_LSB_MSK; + return adf4382_spi_write(dev, 0x10, n_value); +} + +/** + * @brief Set the output frequency. + * @param dev - The device structure. + * @return - 0 in case of success, negative error code otherwise. + */ +int adf4382_set_freq(struct adf4382_dev *dev) +{ + uint32_t frac2_word; + uint32_t frac1_word; + uint32_t mod2_word; + uint8_t clkout_div; + uint8_t dclk_div1; + uint64_t pfd_freq; + uint8_t ldwin_pw = 0; + uint8_t int_mode; + uint8_t en_bleed; + uint8_t locked; + uint16_t n_int; + uint8_t div1; + uint64_t tmp; + uint64_t vco = 0; + uint8_t val; + int ret; + + val = no_os_field_prep(ADF4382_EN_RDBLR_MSK, dev->ref_doubler_en) | + no_os_field_prep(ADF4382_R_DIV_MSK, dev->ref_div); + ret = adf4382_spi_update_bits(dev, 0x20, + ADF4382_EN_RDBLR_MSK | ADF4382_R_DIV_MSK, + val); + if (ret) + return ret; + + for (clkout_div = 0; clkout_div <= dev->clkout_div_reg_val_max; clkout_div++) { + tmp = (1 << clkout_div) * dev->freq; + if (tmp < dev->vco_min || tmp > dev->vco_max) + continue; + + vco = tmp; + break; + } + + if (!vco) { + pr_err("VCO is 0\n"); + return -EINVAL; + } + + //Calculates the PFD freq. the output will be in Hz + pfd_freq = adf4382_pfd_compute(dev); + + ret = adf4382_spi_update_bits(dev, 0x1F, ADF4382_CP_I_MSK, + no_os_field_prep(ADF4382_CP_I_MSK, + dev->cp_i)); + if (ret) + return ret; + + ret = adf4382_pll_fract_n_compute(dev, dev->freq, pfd_freq, &n_int, + &frac1_word, &frac2_word, &mod2_word); + if (ret) + return ret; + + if (frac1_word || frac2_word) { + int_mode = 0; + en_bleed = 1; + + /*The lock detector pulse window is determined based on the + PFD frequency as described in the datasheet*/ + if (pfd_freq <= 40 * MHZ) { + ldwin_pw = 7; + } else if (pfd_freq <= 50 * MHZ) { + ldwin_pw = 6; + } else if (pfd_freq <= 100 * MHZ) { + ldwin_pw = 5; + } else if (pfd_freq <= 200 * MHZ) { + ldwin_pw = 4; + } else if (pfd_freq <= 250 * MHZ) { + if (dev->freq >= 5000U * MHZ && + dev->freq < 6400U * MHZ) { + ldwin_pw = 3; + } else { + ldwin_pw = 2; + } + } + + ret = adf4382_bleed_word_compute(dev, pfd_freq); + if (ret) + return ret; + + } else { + int_mode = 1; + en_bleed = 0; + + tmp = NO_OS_DIV_ROUND_UP(pfd_freq, MICROAMPER_PER_AMPER); + tmp *= adf4382_ci_ua[dev->cp_i]; + tmp = NO_OS_DIV_ROUND_UP(dev->bleed_word, tmp); + if (tmp <= 85) + ldwin_pw = 0; + else + ldwin_pw = 1; + } + + if (frac2_word) { + ret = adf4382_spi_update_bits(dev, 0x28, ADF4382_VAR_MOD_EN_MSK, + 0xff); + if (ret) + return ret; + } else { + ret = adf4382_spi_update_bits(dev, 0x28, ADF4382_VAR_MOD_EN_MSK, + 0x0); + if (ret) + return ret; + } + + ret = adf4382_spi_update_bits(dev, 0x15, ADF4382_INT_MODE_MSK, + no_os_field_prep(ADF4382_INT_MODE_MSK, + int_mode)); + if (ret) + return ret; + + val = dev->bleed_word & ADF4382_FINE_BLEED_LSB_MSK; + ret = adf4382_spi_write(dev, 0x1D, val); + if (ret) + return ret; + val = (dev->bleed_word >> 8) & ADF4382_BLEED_MSB_MSK; + ret = adf4382_spi_update_bits(dev, 0x1E, ADF4382_BLEED_MSB_MSK, + no_os_field_prep(ADF4382_BLEED_MSB_MSK, + val)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x1F, ADF4382_EN_BLEED_MSK, + no_os_field_prep(ADF4382_EN_BLEED_MSK, + en_bleed)); + if (ret) + return ret; + + val = mod2_word & ADF4382_MOD2WORD_LSB_MSK; + ret = adf4382_spi_write(dev, 0x1A, val); + if (ret) + return ret; + val = (mod2_word >> 8) & ADF4382_MOD2WORD_MID_MSK; + ret = adf4382_spi_write(dev, 0x1B, val); + if (ret) + return ret; + val = (mod2_word >> 16) & ADF4382_MOD2WORD_MSB_MSK; + ret = adf4382_spi_write(dev, 0x1C, val); + if (ret) + return ret; + + val = frac2_word & ADF4382_FRAC2WORD_LSB_MSK; + ret = adf4382_spi_write(dev, 0x17, val); + if (ret) + return ret; + val = (frac2_word >> 8) & ADF4382_FRAC2WORD_MID_MSK; + ret = adf4382_spi_write(dev, 0x18, val); + if (ret) + return ret; + val = (frac2_word >> 16) & ADF4382_FRAC2WORD_MSB_MSK; + ret = adf4382_spi_write(dev, 0x19, val); + if (ret) + return ret; + + val = frac1_word & ADF4382_FRAC1WORD_LSB_MSK; + ret = adf4382_spi_write(dev, 0x12, val); + if (ret) + return ret; + val = (frac1_word >> 8) & ADF4382_FRAC1WORD_MID_MSK; + ret = adf4382_spi_write(dev, 0x13, val); + if (ret) + return ret; + val = (frac1_word >> 16) & ADF4382_FRAC1WORD_MSB_MSK; + ret = adf4382_spi_write(dev, 0x14, val); + if (ret) + return ret; + + val = (frac1_word >> 24) & ADF4382_FRAC1WORD_MSB; + ret = adf4382_spi_update_bits(dev, 0x15, ADF4382_FRAC1WORD_MSB, val); + if (ret) + return ret; + + dclk_div1 = 2; + div1 = 8; + if (pfd_freq <= ADF4382_DCLK_DIV1_0_MAX) { + dclk_div1 = 0; + div1 = 1; + } else if (pfd_freq <= ADF4382_DCLK_DIV1_1_MAX) { + dclk_div1 = 1; + div1 = 2; + } + + ret = adf4382_spi_update_bits(dev, 0x24, ADF4382_DCLK_DIV1_MSK, + no_os_field_prep(ADF4382_DCLK_DIV1_MSK, + dclk_div1)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x31, ADF4382_DCLK_MODE_MSK, 0xff); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x31, ADF4382_CAL_CT_SEL_MSK, 0xff); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x31, ADF4382_EN_ADC_CLK_MSK, 0xff); + if (ret) + return ret; + + //VCO automatic level calibration time + ret = adf4382_spi_write(dev, 0x3A, ADF4382_VCO_CAL_ALC); + if (ret) + return ret; + + tmp = NO_OS_DIV_ROUND_UP(no_os_div_u64(pfd_freq, div1 * 400000) - 2, 4); + tmp = no_os_clamp(tmp, 0U, 255U); + ret = adf4382_spi_write(dev, 0x3E, tmp); + if (ret) + return ret; + + // Set LD COUNT + ret = adf4382_spi_update_bits(dev, 0x2C, ADF4382_LD_COUNT_OPWR_MSK, + dev->ld_count); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x2C, ADF4382_LDWIN_PW_MSK, + no_os_field_prep(ADF4382_LDWIN_PW_MSK, + ldwin_pw)); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x11, ADF4382_CLKOUT_DIV_MSK, + no_os_field_prep(ADF4382_CLKOUT_DIV_MSK, + clkout_div)); + if (ret) + return ret; + + val = (n_int >> 8) & ADF4382_N_INT_MSB_MSK; + ret = adf4382_spi_update_bits(dev, 0x11, ADF4382_N_INT_MSB_MSK, val); + if (ret) + return ret; + + // Need to set N_INT last to trigger an auto-calibration + val = n_int & ADF4382_N_INT_LSB_MSK; + ret = adf4382_spi_write(dev, 0x10, val); + if (ret) + return ret; + + no_os_udelay(ADF4382_LKD_DELAY_US); + ret = adf4382_spi_read(dev, 0x58, &val); + if (ret) + return ret; + + locked = no_os_field_get(val, ADF4382_LOCKED_MSK); + if (!locked) + return -EIO; + + return 0; +} + +/** + * @brief Set the phase adjustment in pico-seconds. The phase adjust will + * enable the Bleed current option as well as delay mode to 0. + * @param dev - The device structure. + * @param phase_ps - The phase adjustment in pico-seconds. + * @return - 0 in case of success, negative error code otherwise. + */ +int adf4382_set_phase_adjust(struct adf4382_dev *dev, uint32_t phase_ps) +{ + uint64_t phase_reg_value; + uint32_t rfout_deg_ns; + uint32_t phase_deg_ns; + uint64_t rfout_deg_s; + uint64_t phase_bleed; + uint16_t phase_deg; + uint64_t phase_ci; + uint64_t pfd_freq; + int ret; + + ret = adf4382_spi_update_bits(dev, 0x1E, ADF4382_EN_PHASE_RESYNC_MSK, 0xff); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x1F, ADF4382_EN_BLEED_MSK, 0xff); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x32, ADF4382_DEL_MODE_MSK, 0x0); + if (ret) + return ret; + + dev->phase_adj = phase_ps; + + //Determine the output freq. in degrees/s + rfout_deg_s = 360 * dev->freq; + //Convert it to degrees/ns + rfout_deg_ns = no_os_div_u64(rfout_deg_s, S_TO_NS); + //Determine the phase adjustment in degrees relative the output freq. + phase_deg_ns = rfout_deg_ns * phase_ps; + //Convert it to degrees/ps + phase_deg = no_os_div_u64(phase_deg_ns, NS_TO_PS); + + if (phase_deg > 360) { + pr_err("Phase Adjustment cannot exceed 360deg per Clock Period\n"); + return EINVAL; + } + + //Phase adjustment can only be done if bleed is active, and a bleed + //constant needs to be added + phase_bleed = phase_deg * ADF4382_PHASE_BLEED_CNST; + //The charge pump current will also need to be taken in to account + phase_ci = phase_bleed * adf4382_ci_ua[dev->cp_i]; + phase_ci = no_os_div_u64(phase_ci, MICROAMPER_PER_AMPER); + + //Computation of the register value for the phase adjust + pfd_freq = adf4382_pfd_compute(dev); + phase_reg_value = no_os_div_u64((phase_ci * pfd_freq), (360 * dev->freq)); + + if (phase_reg_value > 255) + phase_reg_value -= 255; + + ret = adf4382_spi_write(dev, 0x33, phase_reg_value); + if (ret) + return ret; + + return adf4382_spi_update_bits(dev, 0x34, ADF4382_PHASE_ADJ_MSK, 0xff); +} + +/** + * @brief Set the phase polarity. If pol = 0 then it will add the phase value + * otherwise it will subtract the phase value. + * @param dev - The device structure. + * @param polarity - The polarity to be set. + * @return - Result of the writing procedure, error code otherwise. + */ +int adf4382_set_phase_pol(struct adf4382_dev *dev, bool polarity) +{ + uint8_t pol; + + pol = no_os_field_prep(ADF4382_PHASE_ADJ_POL_MSK, polarity); + return adf4382_spi_update_bits(dev, 0x32, ADF4382_PHASE_ADJ_POL_MSK, pol); +} + +/** + uint8_t pol; + * @brief Gets the polarity of the phase adjust. + * @param dev - The device structure. + * @param polarity - The read polarity of the phase. + * @return - Result of the tesint procedure, negative error code + * otherwise. + */ +int adf4382_get_phase_pol(struct adf4382_dev *dev, bool *polarity) +{ + uint8_t tmp; + int ret; + + ret = adf4382_spi_read(dev, 0x32, &tmp); + if (ret) + return ret; + + *polarity = no_os_field_get(tmp, ADF4382_PHASE_ADJ_POL_MSK); + return 0; +} + +/** + * @brief Set the EZSYNC features' initial state. Awaits the SW_SYNC toggle. + * @param dev - The device structure. + * @param sync - The enable or disable sync. + * @return - Result of the writing procedure, error code otherwise. + */ +int adf4382_set_ezsync_setup(struct adf4382_dev *dev, bool sync) +{ + int ret; + + if (!dev) + return -EINVAL; + + if (sync == 1) { + ret = adf4382_spi_update_bits(dev, 0x2A, ADF4382_PD_SYNC_MSK, 0); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x53, + ADF4382_SYNC_SEL_MSK, 0xff); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x1E, + ADF4382_TIMED_SYNC_MSK, 0); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x1E, + (ADF4382_EN_REF_RST_MSK | + ADF4382_EN_PHASE_RESYNC_MSK), 0xff); + if (ret) + return ret; + + } else { + ret = adf4382_spi_update_bits(dev, 0x2A, ADF4382_PD_SYNC_MSK, + 0xff); + if (ret) + return ret; + } + return 0; +} + +/** + * @brief Set Timed SYNC features' initial state. Uses SYNC pin. + * @param dev - The device structure. + * @param sync - The enable or disable sync. + * @return - Result of the writing procedure, error code otherwise. + */ +int adf4382_set_timed_sync_setup(struct adf4382_dev *dev, bool sync) +{ + uint64_t pfd_freq; + uint8_t delay; + uint8_t val; + int ret; + + if (!dev) + return -EINVAL; + + if (sync == 1) { + // Timed Sync + ret = adf4382_spi_update_bits(dev, 0x2A, ADF4382_PD_SYNC_MSK, 0); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x53, + ADF4382_SYNC_SEL_MSK, 0); + if (ret) + return ret; + + ret = adf4382_spi_update_bits(dev, 0x1E, (ADF4382_EN_REF_RST_MSK + | ADF4382_TIMED_SYNC_MSK + | ADF4382_EN_PHASE_RESYNC_MSK), + 0xff); + if (ret) + return ret; + + pfd_freq = adf4382_pfd_compute(dev); + if (pfd_freq >= 225 * MHZ) { + delay = 3; + } else if (pfd_freq >= 200 * MHZ) { + delay = 4; + } else if (pfd_freq >= 148 * MHZ) { + delay = 1; + } else if (pfd_freq >= 130 * MHZ) { + delay = 3; + } else if (pfd_freq >= 85 * MHZ) { + delay = 4; + } else if (pfd_freq < 85 * MHZ) { + delay = 0; + } + ret = adf4382_spi_update_bits(dev, 0x31, ADF4382_SYNC_DEL_MSK, + no_os_field_prep + (ADF4382_SYNC_DEL_MSK, delay)); + if (ret) + return ret; + + val = no_os_field_prep(ADF4382_DRCLK_DEL_MSK, delay) | + no_os_field_prep(ADF4382_DNCLK_DEL_MSK, delay); + ret = adf4382_spi_update_bits(dev, 0x34, + ADF4382_DRCLK_DEL_MSK + | ADF4382_DNCLK_DEL_MSK, val); + + if (ret) + return ret; + } else { + ret = adf4382_spi_update_bits(dev, 0x2A, ADF4382_PD_SYNC_MSK, + 0xff); + if (ret) + return ret; + } + return 0; +} + + +/** + * @brief Gets the value of the SYNC powerdown bit. + * @param dev - The device structure. + * @param en - The read status of the sync enable. + * @return - 0 in case of success or negative error code. + */ +int adf4382_get_phase_sync_setup(struct adf4382_dev *dev, bool *en) +{ + uint8_t tmp; + int ret; + + ret = adf4382_spi_read(dev, 0x2A, &tmp); + if (ret) + return ret; + + *en = no_os_field_get(tmp, ADF4382_PD_SYNC_MSK); + return 0; +} + +/** + * @brief Set Software SYNC Request. Setting SW_SYNC resets the RF block. + * Clearing SW_SYNC makes ready for a new reference clock. + * @param dev - The device structure. + * @param sw_sync - Set send SW_SYNC request + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_sw_sync(struct adf4382_dev *dev, bool sw_sync) +{ + uint8_t tmp; + + if (!dev) + return -EINVAL; + + tmp = no_os_field_prep(ADF4382_SW_SYNC_MSK, sw_sync); + return adf4382_spi_update_bits(dev, 0x1F, ADF4382_SW_SYNC_MSK, tmp); +} + +/** + * @brief Gets the value of the SW_SYNC bit. + * @param dev - The device structure. + * @param sw_sync - The read value of the SW_SYNC. + * @return - 0 in case of success or negative error code. + */ +int adf4382_get_sw_sync(struct adf4382_dev *dev, bool *sw_sync) +{ + uint8_t tmp; + int ret; + + if (!dev) + return -EINVAL; + + ret = adf4382_spi_read(dev, 0x1F, &tmp); + if (ret) + return ret; + *sw_sync = no_os_field_get(tmp, ADF4382_SW_SYNC_MSK); + + return 0; +} + +/** + * @brief Computes and sets the VCO Calibration Timeout values. + * @param dev - The device structure. + * @return - 0 in case of success or negative error code. + */ +int adf4382_set_vco_cal_timeout(struct adf4382_dev *dev) +{ + uint32_t cal_count_to, cal_vtune_to, cal_vco_to; + uint32_t cal_count_to_time = 235; // Default value in 23.5us steps + uint8_t dclk_div1, dclk_div, val; + uint64_t pfd_freq; + int ret; + + if (!dev) + return -EINVAL; + + pfd_freq = adf4382_pfd_compute(dev); + + // Read DCLK_DIV1 once + ret = adf4382_spi_read(dev, 0x24, &val); + if (ret) + return ret; + dclk_div1 = no_os_field_get(val, ADF4382_DCLK_DIV1_MSK); + dclk_div = 1 << dclk_div1; + + // VCO Calibration Count Timeout + cal_count_to = NO_OS_DIV_ROUND_CLOSEST_ULL((cal_count_to_time * pfd_freq), + (10 * MHZ * dclk_div * 16)); + ret = adf4382_spi_write(dev, 0x37, + (cal_count_to & ADF4382_CAL_COUNT_TO_MSK)); + if (ret) + return ret; + + cal_vtune_to = NO_OS_DIV_ROUND_CLOSEST_ULL + (dev->max_lpf_cap_value_uf * 80000ULL * pfd_freq, + 420000000000ULL * dclk_div); + dev->cal_vtune_to = cal_vtune_to & ADF4382_CAL_VTUNE_TO_LSB_MSK; + ret = adf4382_spi_write(dev, 0x38, dev->cal_vtune_to); + if (ret) + return ret; + ret = adf4382_spi_update_bits(dev, 0x39, ADF4382_CAL_VTUNE_TO_MSB_MSK, + no_os_field_prep(ADF4382_CAL_VTUNE_TO_MSB_MSK, + dev->cal_vtune_to >> 8)); + if (ret) + return ret; + + // VCO Calibration VCO Timeout + cal_vco_to = NO_OS_DIV_ROUND_CLOSEST_ULL(pfd_freq, MHZ * dclk_div); + ret = adf4382_spi_write(dev, 0x3A, cal_vco_to); + if (ret) + return ret; + return adf4382_spi_update_bits(dev, 0x3B, ADF4382_CAL_VCO_TO_MSB_MSK, + no_os_field_prep(ADF4382_CAL_VCO_TO_MSB_MSK, + cal_vco_to >> 8)); +} + +/** + * @brief ADF4382 SPI Scratchpad check. + * @param dev - The device structure. + * @return - 0 in case of success or negative error code. + */ +static int adf4382_check_scratchpad(struct adf4382_dev *dev) +{ + uint8_t scratchpad; + int ret; + + ret = adf4382_spi_write(dev, 0x00A, ADF4382_SPI_SCRATCHPAD_TEST); + if (ret) + return ret; + + ret = adf4382_spi_read(dev, 0x00A, &scratchpad); + if (ret) + return ret; + + if (scratchpad != ADF4382_SPI_SCRATCHPAD_TEST) + return -EINVAL; + + return 0; +} + +/** + * @brief Update core bias table for ADF4383. + * @param dev - The device structure. + * @return - 0 in case of success or negative error code. + */ +static int adf4383_update_core_bias_table(struct adf4382_dev *dev) +{ + int ret; + + ret = adf4382_spi_write(dev, 0x109, 0x3); + if (ret) + return ret; + ret = adf4382_spi_write(dev, 0x10A, 0x7); + if (ret) + return ret; + ret = adf4382_spi_write(dev, 0x10F, 0x7); + if (ret) + return ret; + ret = adf4382_spi_write(dev, 0x110, 0x7); + if (ret) + return ret; + ret = adf4382_spi_write(dev, 0x111, 0x7); + if (ret) + return ret; + + return 0; +} + +/** + * @brief Initializes the ADF4382. + * @param dev - The device structure. + * @param init_param - The structure containing the device initial parameters. + * @return - 0 in case of success or negative error code. + */ +int adf4382_init(struct adf4382_dev **dev, + struct adf4382_init_param *init_param) +{ + struct adf4382_dev *device; + bool en = true; + uint8_t i; + int ret; + + device = (struct adf4382_dev *)no_os_calloc(1, sizeof(*device)); + if (!device) + return -ENOMEM; + + ret = no_os_spi_init(&device->spi_desc, init_param->spi_init); + if (ret) + goto error_dev; + + device->spi_3wire_en = init_param->spi_3wire_en; + device->cmos_3v3 = init_param->cmos_3v3; + device->ref_freq_hz = init_param->ref_freq_hz; + device->freq = init_param->freq; + device->ref_doubler_en = init_param->ref_doubler_en; + device->ref_div = init_param->ref_div; + device->cp_i = init_param->cp_i; + device->bleed_word = init_param->bleed_word; + device->ld_count = init_param->ld_count; + device->phase_adj = 0; + device->max_lpf_cap_value_uf = init_param->max_lpf_cap_value_uf; + + switch (init_param->id) { + case ID_ADF4382: + device->freq_max = ADF4382_RFOUT_MAX; + device->freq_min = ADF4382_RFOUT_MIN; + device->vco_max = ADF4382_VCO_FREQ_MAX; + device->vco_min = ADF4382_VCO_FREQ_MIN; + device->clkout_div_reg_val_max = ADF4382_CLKOUT_DIV_REG_VAL_MAX; + break; + case ID_ADF4382A: + device->freq_max = ADF4382A_RFOUT_MAX; + device->freq_min = ADF4382A_RFOUT_MIN; + device->vco_max = ADF4382A_VCO_FREQ_MAX; + device->vco_min = ADF4382A_VCO_FREQ_MIN; + device->clkout_div_reg_val_max = ADF4382A_CLKOUT_DIV_REG_VAL_MAX; + break; + case ID_ADF4383: + device->freq_max = ADF4383_RFOUT_MAX; + device->freq_min = ADF4383_RFOUT_MIN; + device->vco_max = ADF4383_VCO_FREQ_MAX; + device->vco_min = ADF4383_VCO_FREQ_MIN; + device->clkout_div_reg_val_max = ADF4382_CLKOUT_DIV_REG_VAL_MAX; + break; + default: + goto error_spi; + } + + ret = adf4382_spi_write(device, 0x00, ADF4382_RESET_CMD); + if (ret) + goto error_spi; + + no_os_udelay(ADF4382_POR_DELAY_US); + + if (device->spi_3wire_en) + en = false; + + /* SPI set to 4 wire */ + ret = adf4382_spi_write(device, 0x00, ADF4382_SPI_3W_CFG(en)); + if (ret) + goto error_spi; + + ret = adf4382_spi_write(device, 0x3D, + no_os_field_prep(ADF4382_CMOS_OV_MSK, + device->cmos_3v3)); + if (ret) + goto error_spi; + + ret = adf4382_check_scratchpad(device); + if (ret) + goto error_spi; + + for (i = 0; i < NO_OS_ARRAY_SIZE(adf4382_reg_defaults); i++) { + ret = adf4382_spi_write(device, + adf4382_reg_defaults[i].reg, + adf4382_reg_defaults[i].val); + if (ret) + goto error_spi; + } + + if (ID_ADF4383 == init_param->id) { + ret = adf4383_update_core_bias_table(device); + if (ret) + goto error_spi; + } + + ret = adf4382_set_freq(device); + if (ret) + goto error_spi; + + ret = adf4382_set_vco_cal_timeout(device); + if (ret) + goto error_spi; + + ret = adf4382_set_out_power(device, 0, 9); + if (ret) + goto error_spi; + ret = adf4382_set_out_power(device, 1, 9); + if (ret) + goto error_spi; + *dev = device; + + return ret; +error_spi: + no_os_spi_remove(device->spi_desc); +error_dev: + no_os_free(device); + return ret; +} + +/** + * @brief Free resources allocated for ADF4382 + * @param dev - The device structure. + * @return - 0 in case of success or negative error code. + */ +int adf4382_remove(struct adf4382_dev *dev) +{ + int ret; + + ret = no_os_spi_remove(dev->spi_desc); + if (ret) + no_os_free(dev); + + return 0; +} + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382.h new file mode 100644 index 0000000..1bcbddf --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382.h @@ -0,0 +1,809 @@ +/***************************************************************************//** + * @file adf4382.h + * @brief Implementation of adf4382 Driver. + * @author Ciprian Hegbeli (ciprian.hegbeli@analog.com) + * @author Jude Osemene (jude.osemene@analog.com) +******************************************************************************** + * Copyright 2024(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef _ADF4382_H_ +#define _ADF4382_H_ + +#include +#include +#include "no_os_units.h" +#include "no_os_util.h" +#include "no_os_spi.h" + +/* ADF4382 REG0000 Map */ +#define ADF4382_SOFT_RESET_R_MSK NO_OS_BIT(7) +#define ADF4382_LSB_FIRST_R_MSK NO_OS_BIT(6) +#define ADF4382_ADDRESS_ASC_R_MSK NO_OS_BIT(5) +#define ADF4382_SDO_ACTIVE_R_MSK NO_OS_BIT(4) +#define ADF4382_SDO_ACTIVE_MSK NO_OS_BIT(3) +#define ADF4382_ADDRESS_ASC_MSK NO_OS_BIT(2) +#define ADF4382_LSB_FIRST_MSK NO_OS_BIT(1) +#define ADF4382_SOFT_RESET_MSK NO_OS_BIT(0) +#define ADF4382_RESET_CMD 0x81 + +/* ADF4382 REG0000 NO_OS_BIT Definition */ +#define ADF4382_SDO_ACTIVE_SPI_3W 0x0 +#define ADF4382_SDO_ACTIVE_SPI_4W 0x1 + +#define ADF4382_ADDR_ASC_AUTO_DECR 0x0 +#define ADF4382_ADDR_ASC_AUTO_INCR 0x1 + +#define ADF4382_LSB_FIRST_MSB 0x0 +#define ADF4382_LSB_FIRST_LSB 0x1 + +#define ADF4382_SOFT_RESET_N_OP 0x0 +#define ADF4382_SOFT_RESET_EN 0x1 + +/* ADF4382 REG0001 Map */ +#define ADF4382_SINGLE_INSTR_MSK NO_OS_BIT(7) +#define ADF4382_MASTER_RB_CTRL_MSK NO_OS_BIT(5) + +/* ADF4382 REG0001 NO_OS_BIT Definition */ +#define ADF4382_SPI_STREAM_EN 0x0 +#define ADF4382_SPI_STREAM_DIS 0x1 + +#define ADF4382_RB_SLAVE_REG 0x0 +#define ADF4382_RB_MASTER_REG 0x1 + +/* ADF4382 REG0003 NO_OS_BIT Definition */ +#define ADF4382_CHIP_TYPE 0x06 + +/* ADF4382 REG0004 NO_OS_BIT Definition */ +#define ADF4382_PRODUCT_ID_LSB 0x0005 + +/* ADF4382 REG0005 NO_OS_BIT Definition */ +#define ADF4382_PRODUCT_ID_MSB 0x0005 + +/* ADF4382 REG000A Map */ +#define ADF4382_SCRATCHPAD_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG000C NO_OS_BIT Definition */ +#define ADF4382_VENDOR_ID_LSB 0x56 + +/* ADF4382 REG000D NO_OS_BIT Definition */ +#define ADF4382_VENDOR_ID_MSB 0x04 + +/* ADF4382 REG000F NO_OS_BIT Definition */ +#define ADF4382_M_S_TRANSF_NO_OS_BIT_MSK NO_OS_BIT(0) + +/* ADF4382 REG0010 Map*/ +#define ADF4382_N_INT_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0011 Map*/ +#define ADF4382_CLKOUT_DIV_MSK NO_OS_GENMASK(7, 5) +#define ADF4382_INV_CLK_OUT_MSK NO_OS_BIT(4) +#define ADF4382_N_INT_MSB_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG0012 Map */ +#define ADF4382_FRAC1WORD_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0013 Map */ +#define ADF4382_FRAC1WORD_MID_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0014 Map */ +#define ADF4382_FRAC1WORD_MSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0015 Map */ +#define ADF4382_M_VCO_BAND_LSB_MSK NO_OS_BIT(7) +#define ADF4382_M_VCO_CORE_MSK NO_OS_BIT(6) +#define ADF4382_BIAS_DEC_MODE_MSK NO_OS_GENMASK(5, 3) +#define ADF4382_INT_MODE_MSK NO_OS_BIT(2) +#define ADF4382_PFD_POL_MSK NO_OS_BIT(1) +#define ADF4382_FRAC1WORD_MSB NO_OS_BIT(0) + +/* ADF4382 REG0016 Map */ +#define ADF4382_M_VCO_BAND_MSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0017 Map */ +#define ADF4382_FRAC2WORD_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0018 Map */ +#define ADF4382_FRAC2WORD_MID_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0019 Map */ +#define ADF4382_FRAC2WORD_MSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG001A Map */ +#define ADF4382_MOD2WORD_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG001B Map */ +#define ADF4382_MOD2WORD_MID_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG001C Map */ +#define ADF4382_MOD2WORD_MSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG001D Map */ +#define ADF4382_FINE_BLEED_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG001E Map */ +#define ADF4382_EN_PHASE_RESYNC_MSK NO_OS_BIT(7) +#define ADF4382_EN_REF_RST_MSK NO_OS_BIT(6) +#define ADF4382_TIMED_SYNC_MSK NO_OS_BIT(5) +#define ADF4382_COARSE_BLEED_MSK NO_OS_GENMASK(4, 1) +#define ADF4382_FINE_BLEED_MSB_MSK NO_OS_BIT(0) + +/* ADF4382 REG001F Map */ +#define ADF4382_SW_SYNC_MSK NO_OS_BIT(7) +#define ADF4382_SPARE_1F_MSK NO_OS_BIT(6) +#define ADF4382_BLEED_POL_MSK NO_OS_BIT(5) +#define ADF4382_EN_BLEED_MSK NO_OS_BIT(4) +#define ADF4382_CP_I_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG0020 Map */ +#define ADF4382_EN_AUTOCAL_MSK NO_OS_BIT(7) +#define ADF4382_EN_RDBLR_MSK NO_OS_BIT(6) +#define ADF4382_R_DIV_MSK NO_OS_GENMASK(5, 0) + +/* ADF4382 REG0021 Map */ +#define ADF4382_PHASE_WORD_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0022 Map */ +#define ADF4382_PHASE_WORD_MID_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0023 Map */ +#define ADF4382_PHASE_WORD_MSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0024 Map */ +#define ADF4382_SPARE_24_MSK NO_OS_GENMASK(7, 5) +#define ADF4382_DCLK_DIV_SEL_MSK NO_OS_BIT(4) +#define ADF4382_DNCLK_DIV1_MSK NO_OS_GENMASK(3, 2) +#define ADF4382_DCLK_DIV1_MSK NO_OS_GENMASK(1, 0) + +/* ADF4382 REG0025 Map */ +#define ADF4382_RESYNC_WAIT_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0026 Map */ +#define ADF4382_RESYNC_WAIT_MSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0027 Map */ +#define ADF4382_CAL_BLEED_FINE_MIN_MSK NO_OS_GENMASK(7, 4) +#define ADF4382_BLEED_ADJ_SCALE_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG0028 Map */ +#define ADF4382_PH_RESYNC_RB_SEL_MSK NO_OS_BIT(7) +#define ADF4382_LSB_P1_MSK NO_OS_BIT(6) +#define ADF4382_VAR_MOD_EN_MSK NO_OS_BIT(5) +#define ADF4382_DITHER1_SCALE_MSK NO_OS_GENMASK(4, 2) +#define ADF4382_EN_DITHER2_MSK NO_OS_BIT(1) +#define ADF4382_EN_DITHER1_MSK NO_OS_BIT(0) + +/* ADF4382 REG0029 Map */ +#define ADF4382_CLK2_OPWR_MSK NO_OS_GENMASK(7, 4) +#define ADF4382_CLK1_OPWR_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG002A Map */ +#define ADF4382_FN_DBL_MSK NO_OS_BIT(7) +#define ADF4382_PD_NDIV_TL_MSK NO_OS_BIT(6) +#define ADF4382_CLKOUT_BST_MSK NO_OS_BIT(5) +#define ADF4382_PD_SYNC_MSK NO_OS_BIT(4) +#define ADF4382_PD_CLK_MSK NO_OS_BIT(3) +#define ADF4382_PD_RDET_MSK NO_OS_BIT(2) +#define ADF4382_PD_ADC_MSK NO_OS_BIT(1) +#define ADF4382_PD_CALGEN_MSK NO_OS_BIT(0) + +/* ADF4382 REG002B Map */ +#define ADF4382_PD_ALL_MSK NO_OS_BIT(7) +#define ADF4382_PD_RDIV_TL_MSK NO_OS_BIT(6) +#define ADF4382_PD_NDIV_MSK NO_OS_BIT(5) +#define ADF4382_PD_VCO_MSK NO_OS_BIT(4) +#define ADF4382_PD_LD_MSK NO_OS_BIT(3) +#define ADF4382_PD_PFDCP_MSK NO_OS_BIT(2) +#define ADF4382_PD_CLKOUT1_MSK NO_OS_BIT(1) +#define ADF4382_PD_CLKOUT2_MSK NO_OS_BIT(0) + +/* ADF4382 REG002C Map */ +#define ADF4382_LDWIN_PW_MSK NO_OS_GENMASK(7, 5) +#define ADF4382_LD_COUNT_OPWR_MSK NO_OS_GENMASK(4, 0) + +/* ADF4382 REG002D Map */ +#define ADF4382_EN_DNCLK_MSK NO_OS_BIT(7) +#define ADF4382_EN_DRCLK_MSK NO_OS_BIT(6) +#define ADF4382_EN_LOL_MSK NO_OS_BIT(5) +#define ADF4382_EN_LDWIN_MSK NO_OS_BIT(4) +#define ADF4382_PDET_POL_MSK NO_OS_BIT(3) +#define ADF4382_RST_LD_MSK NO_OS_BIT(2) +#define ADF4382_LD_O_CTRL_MSK NO_OS_GENMASK(1, 0) + +/* ADF4382 REG002E Map */ +#define ADF4382_MUXOUT_MSK NO_OS_GENMASK(7, 4) +#define ADF4382_ABPW_WD_MSK NO_OS_BIT(3) +#define ADF4382_EN_CPTEST_MSK NO_OS_BIT(2) +#define ADF4382_CP_DOWN_MSK NO_OS_BIT(1) +#define ADF4382_CP_UP_MSK NO_OS_BIT(0) + +/* ADF4382 REG002F Map*/ +#define ADF4382_BST_REF_MSK NO_OS_BIT(7) +#define ADF4382_FILT_REF_MSK NO_OS_BIT(6) +#define ADF4382_RDBLR_DC_MSK NO_OS_GENMASK(5, 0) + +/* ADF4382 REG0030 Map */ +#define ADF4382_MUTE_NCLK_MSK NO_OS_BIT(7) +#define ADF4382_MUTE_RCLK_MSK NO_OS_BIT(6) +#define ADF4382_REF_SEL_MSK NO_OS_BIT(5) +#define ADF4382_INV_RDBLR_MSK NO_OS_BIT(4) +#define ADF4382_RDBLR_DEL_SEL_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG0031 Map */ +#define ADF4382_SYNC_DEL_MSK NO_OS_GENMASK(7, 5) +#define ADF4382_RST_SYS_MSK NO_OS_BIT(4) +#define ADF4382_EN_ADC_CLK_MSK NO_OS_BIT(3) +#define ADF4382_EN_VCAL_MSK NO_OS_BIT(2) +#define ADF4382_CAL_CT_SEL_MSK NO_OS_BIT(1) +#define ADF4382_DCLK_MODE_MSK NO_OS_BIT(0) + +/* ADF4382 REG0032 Map */ +#define ADF4382_SPARE_32_MSK NO_OS_BIT(7) +#define ADF4382_BLEED_ADJ_CAL_MSK NO_OS_BIT(6) +#define ADF4382_DEL_MODE_MSK NO_OS_BIT(5) +#define ADF4382_EN_AUTO_ALIGN_MSK NO_OS_BIT(4) +#define ADF4382_PHASE_ADJ_POL_MSK NO_OS_BIT(3) +#define ADF4382_EFM3_MODE_MSK NO_OS_GENMASK(2, 0) + +/* ADF4382 REG0033 Map */ +#define ADF4382_PHASE_ADJUST_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0034 Map */ +#define ADF4382_PHASE_ADJ_MSK NO_OS_BIT(7) +#define ADF4382_DRCLK_DEL_MSK NO_OS_GENMASK(6, 4) +#define ADF4382_DNCLK_DEL_MSK NO_OS_GENMASK(3, 1) +#define ADF4382_RST_CNTR_MSK NO_OS_BIT(0) + +/* ADF4382 REG0035 Map */ +#define ADF4382_SPARE_35_MSK NO_OS_GENMASK(7, 6) +#define ADF4382_M_VCO_BIAS_MSK NO_OS_GENMASK(5, 0) + +/* ADF4382 REG0036 Map */ +#define ADF4382_CLKODIV_DB_MSK NO_OS_BIT(7) +#define ADF4382_DCLK_DIV_DB_MSK NO_OS_BIT(6) +#define ADF4382_SPARE_36_MSK NO_OS_GENMASK(5, 2) +#define ADF4382_EN_LUT_GEN_MSK NO_OS_BIT(1) +#define ADF4382_EN_LUT_CAL_MSK NO_OS_BIT(0) + +/* ADF4382 REG0037 Map */ +#define ADF4382_CAL_COUNT_TO_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0038 Map */ +#define ADF4382_CAL_VTUNE_TO_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0039 Map */ +#define ADF4382_O_VCO_DB_MSK NO_OS_BIT(7) +#define ADF4382_CAL_VTUNE_TO_MSB_MSK NO_OS_GENMASK(6, 0) + +/* ADF4382 REG003A Map */ +#define ADF4382_CAL_VCO_TO_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG003B Map */ +#define ADF4382_DEL_CTRL_DB_MSK NO_OS_BIT(7) +#define ADF4382_CAL_VCO_TO_MSB_MSK NO_OS_GENMASK(6, 0) + +/* ADF4382 REG003C Map */ +#define ADF4382_CNTR_DIV_WORD_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG003D Map */ +#define ADF4382_SPARE_3D_MSK NO_OS_BIT(7) +#define ADF4382_SYNC_SP_DB_MSK NO_OS_BIT(6) +#define ADF4382_CMOS_OV_MSK NO_OS_BIT(5) +#define ADF4382_READ_MODE_MSK NO_OS_BIT(4) +#define ADF4382_CNTR_DIV_WORD_MSB_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG003E Map */ +#define ADF4382_ADC_CLK_DIV_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG003F Map */ +#define ADF4382_EN_ADC_CNV_MSK NO_OS_BIT(7) +#define ADF4382_EN_ADC_VTEST_MSK NO_OS_BIT(6) +#define ADF4382_ADC_VTEST_SEL_MSK NO_OS_BIT(5) +#define ADF4382_ADC_MUX_SEL_MSK NO_OS_BIT(4) +#define ADF4382_ADC_F_CONV_MSK NO_OS_BIT(3) +#define ADF4382_ADC_C_CONV_MSK NO_OS_BIT(2) +#define ADF4382_EN_ADC_MSK NO_OS_BIT(1) +#define ADF4382_SPARE_3F_MSK NO_OS_BIT(0) + +/* ADF4382 REG0040 Map */ +#define ADF4382_EXT_DIV_DEC_SEL_MSK NO_OS_BIT(7) +#define ADF4382_ADC_CLK_TEST_SEL_MSK NO_OS_BIT(6) +#define ADF4382_MUTE_CLKOUT2_MSK NO_OS_GENMASK(5, 3) +#define ADF4382_MUTE_CLKOUT1_MSK NO_OS_GENMASK(2, 0) + +/* ADF4382 REG0041 Map */ +#define ADF4382_EXT_DIV_MSK NO_OS_GENMASK(7, 5) +#define ADF4382_EN_VCO_CAP_TEST_MSK NO_OS_BIT(4) +#define ADF4382_EN_CALGEN_CAP_TEST_MSK NO_OS_BIT(3) +#define ADF4382_EN_CP_CAP_TEST_MSK NO_OS_BIT(2) +#define ADF4382_CAP_TEST_STATE_MSK NO_OS_BIT(1) +#define ADF4382_TRANS_LOOP_SEL_MSK NO_OS_BIT(0) + +/* ADF4382 REG0042 Map */ +#define ADF4382_NDIV_PWRUP_TIMEOUT_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0043 Map */ +#define ADF4382_CAL_BLEED_FINE_MAX_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0044 Map */ +#define ADF4382_VCAL_ZERO_MSK NO_OS_BIT(7) +#define ADF4382_VPTAT_CALGEN_MSK NO_OS_GENMASK(6, 0) + +/* ADF4382 REG0045 Map */ +#define ADF4382_SPARE_45_MSK NO_OS_BIT(7) +#define ADF4382_VCTAT_CALGEN_MSK NO_OS_GENMASK(6, 0) + +/* ADF4382 REG0046 Map */ +#define ADF4382_NVMDIN_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0047 Map */ +#define ADF4382_SPARE_47_MSK NO_OS_BIT(7) +#define ADF4382_NVMADDR_MSK NO_OS_GENMASK(6, 3) +#define ADF4382_NVMNO_OS_BIT_SEL NO_OS_GENMASK(2, 0) + +/* ADF4382 REG0048 Map */ +#define ADF4382_TRIM_LATCH_MSK NO_OS_BIT(7) +#define ADF4382_NVMTEST_MSK NO_OS_BIT(6) +#define ADF4382_NVMPROG_MSK NO_OS_BIT(5) +#define ADF4382_NVMRD_MSK NO_OS_BIT(4) +#define ADF4382_NVMSTART_MSK NO_OS_BIT(3) +#define ADF4382_NVMON_MSK NO_OS_BIT(2) +#define ADF4382_MARGIN_MSK NO_OS_GENMASK(1, 0) + +/* ADF4382 REG0049 Map */ +#define ADF4382_NVMDOUT_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG004A Map */ +#define ADF4382_SCAN_MODE_CODE_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG004B Map */ +#define ADF4382_TEMP_OFFSET_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG004C Map */ +#define ADF4382_SPARE_4C_MSK NO_OS_GENMASK(7, 6) +#define ADF4382_TEMP_SLOPE_MSK NO_OS_GENMASK(5, 0) + +/* ADF4382 REG004D Map */ +#define ADF4382_VCO_FSM_TEST_MUX_MSK NO_OS_GENMASK(7, 5) +#define ADF4382_SPARE_4D_MSK NO_OS_GENMASK(4, 3) +#define ADF4382_O_VCO_BIAS_MSK NO_OS_BIT(2) +#define ADF4382_O_VCO_BAND_MSK NO_OS_BIT(1) +#define ADF4382_O_VCO_CORE_MSK NO_OS_BIT(0) + +/* ADF4382 REG004E Map */ +#define ADF4382_SPARE_4E_MSK NO_OS_GENMASK(7, 5) +#define ADF4382_EN_TWO_PASS_CAL_MSK NO_OS_BIT(4) +#define ADF4382_TWO_PASS_BAND_START_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG004F Map */ +#define ADF4382_LUT_SCALE_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0050 Map */ +#define ADF4382_SPARE0_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0051 Map */ +#define ADF4382_SPARE1_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0052 Map */ +#define ADF4382_SYNC_REF_SPARE_MSK NO_OS_GENMASK(7, 4) +#define ADF4382_SYNC_MON_DEL_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG0053 Map */ +#define ADF4382_SPARE_53_MSK NO_OS_BIT(7) +#define ADF4382_PD_SYNC_MON_MSK NO_OS_BIT(6) +#define ADF4382_SYNC_SEL_MSK NO_OS_BIT(5) +#define ADF4382_RST_SYNC_MON_MSK NO_OS_BIT(4) +#define ADF4382_SYNC_SH_DEL_MSK NO_OS_GENMASK(3, 0) + +/* ADF4382 REG0054 Map */ +#define ADF4382_ADC_ST_CNV_MSK NO_OS_BIT(0) + +/* ADF4382 REG0058 Map */ +#define ADF4382_FSM_BUSY_MSK NO_OS_BIT(1) +#define ADF4382_LOCKED_MSK NO_OS_BIT(0) + +/* ADF4382 REG005E Map */ +#define ADF4382_VCO_BAND_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG005F Map */ +#define ADF4382_VCO_CORE_MSK NO_OS_BIT(1) +#define ADF4382_VCO_BAND_MSB_MSK NO_OS_BIT(0) + +/* ADF4382 REG0200 Map */ +#define ADF4382_LUT_WR_ADDR_MSK NO_OS_GENMASK(5, 1) +#define ADF4382_O_VCO_LUT_MSK NO_OS_BIT(0) + +/* ADF4382 REG0201 Map */ +#define ADF4382_M_LUT_BAND_LSB_MSK NO_OS_GENMASK(7, 0) + +/* ADF4382 REG0202 Map */ +#define ADF4382_M_LUT_N_LSB_MSK NO_OS_GENMASK(7, 2) +#define ADF4382_M_LUT_CORE_MSK NO_OS_BIT(1) +#define ADF4382_M_LUT_BAND_MSB_MSK NO_OS_BIT(0) + +/* ADF4382 REG0203 Map */ +#define ADF4382_M_LUT_N_MSB_MSK NO_OS_GENMASK(5, 0) + +#define ADF4382_SPI_3W_CFG(x) (no_os_field_prep(ADF4382_SDO_ACTIVE_MSK, x) | \ + no_os_field_prep(ADF4382_SDO_ACTIVE_R_MSK, x)) + +#define ADF4382_BLEED_MSB_MSK (ADF4382_COARSE_BLEED_MSK | \ + ADF4382_FINE_BLEED_MSB_MSK) + +#define ADF4382_SPI_SCRATCHPAD_TEST 0x5A + +/* Specifications */ +#define ADF4382_SPI_WRITE_CMD 0x0 +#define ADF4382_SPI_READ_CMD 0x8000 +#define ADF4382_SPI_DUMMY_DATA 0x00 +#define ADF4382_BUFF_SIZE_BYTES 3 +#define ADF4382_VCO_FREQ_MIN 11000000000U // 11GHz +#define ADF4382_VCO_FREQ_MAX 22000000000U // 22GHz +#define ADF4383_VCO_FREQ_MIN 10000000000U // 10GHz +#define ADF4383_VCO_FREQ_MAX 20000000000U // 20GHz +#define ADF4382A_VCO_FREQ_MIN 11500000000U // 11.5GHz +#define ADF4382A_VCO_FREQ_MAX 21000000000U // 21GHz +#define ADF4382_MOD1WORD 0x2000000U // 2^25 +#define ADF4382_MOD2WORD_MAX 0xFFFFFFU // 2^24 - 1 +#define ADF4382_PHASE_RESYNC_MOD2WORD_MAX 0x1FFFFU // 2^17 - 1 +#define ADF4382_CHANNEL_SPACING_MAX 78125U +#define ADF4382_PFD_FREQ_MAX 625000000U // 625MHz +#define ADF4382_PFD_FREQ_FRAC_MAX 250000000U // 250MHz +#define ADF4382_PFD_FREQ_MIN 5400000U // 5.4MHz +#define ADF4382_DCLK_DIV1_0_MAX 160000000U // 160MHz +#define ADF4382_DCLK_DIV1_1_MAX 320000000U // 320MHz +#define ADF4382_CLKOUT_DIV_REG_VAL_MAX 4 +#define ADF4382A_CLKOUT_DIV_REG_VAL_MAX 2 + +#define ADF4383_RFOUT_MAX 20000000000U +#define ADF4383_RFOUT_MIN 625000000U +#define ADF4382_RFOUT_MAX 22000000000U +#define ADF4382_RFOUT_MIN 687500000U +#define ADF4382A_RFOUT_MAX 21000000000U +#define ADF4382A_RFOUT_MIN 2875000000U +#define ADF4382_REF_CLK_MAX 5000000000U +#define ADF4382_REF_CLK_MIN 10000000 +#define ADF4382_REF_DIV_MAX 63 +#define ADF4382_OUT_PWR_MAX 15 +#define ADF4382_CPI_VAL_MAX 15 +#define ADF4382_BLEED_WORD_MAX 8191 + +#define ADF4382_VPTAT_CALGEN 46 +#define ADF4382_VCTAT_CALGEN 82 +#define ADF4382_FASTCAL_VPTAT_CALGEN 7 +#define ADF4382_FASTCAL_VCTAT_CALGEN 21 +#define ADF4382_PHASE_BLEED_CNST 2044000 +#define ADF4382_VCO_CAL_CNT 183 +#define ADF4382_VCO_CAL_VTUNE 640 +#define ADF4382_VCO_CAL_ALC 123 +#define ADF4382_POR_DELAY_US 200 +#define ADF4382_LKD_DELAY_US 1000 +#define ADF4382_COARSE_BLEED_CONST 180U // 180 microseconds +#define ADF4382_FINE_BLEED_CONST_1 512U // 512 microseconds +#define ADF4382_FINE_BLEED_CONST_2 250U // 250 microseconds +#define ADF4382_CAL_VTUNE_TO 124U +#define ADF4382_FSM_BUSY_LOOP_CNT 100U + +#define MHZ MEGA +#define S_TO_NS NANO +#define PS_TO_S PICO +#define NS_TO_PS KHZ_PER_MHZ + +/** + * @brief Supported device ids. +*/ +enum adf4382_dev_id { + ID_ADF4382, + ID_ADF4382A, + ID_ADF4383, +}; + +/** + * @struct adf4382_init_param + * @brief ADF4382 Initialization Parameters structure. + */ +struct adf4382_init_param { + /** SPI Initialization parameters */ + struct no_os_spi_init_param *spi_init; + bool spi_3wire_en; + bool cmos_3v3; + uint64_t ref_freq_hz; + uint64_t freq; + bool ref_doubler_en; + uint8_t ref_div; + uint8_t cp_i; + uint16_t bleed_word; + uint8_t ld_count; + uint8_t en_lut_gen; + uint8_t en_lut_cal; + uint8_t max_lpf_cap_value_uf; + enum adf4382_dev_id id; +}; + +/** + * @struct adf4382_dev + * @brief ADF4382 Device Descriptor. + */ +struct adf4382_dev { + /** SPI Descriptor */ + struct no_os_spi_desc *spi_desc; + bool spi_3wire_en; + bool cmos_3v3; + uint64_t ref_freq_hz; + uint64_t freq; + bool ref_doubler_en; + uint8_t ref_div; + uint8_t cp_i; + uint16_t bleed_word; + uint8_t ld_count; + uint32_t phase_adj; + uint8_t en_lut_gen; + uint8_t en_lut_cal; + uint64_t vco_max; + uint64_t vco_min; + uint64_t freq_max; + uint64_t freq_min; + uint8_t clkout_div_reg_val_max; + uint8_t max_lpf_cap_value_uf; + uint32_t cal_vtune_to; + // N_INT variable to trigger auto calibration + uint16_t n_int; +}; + +/** + * @struct reg_sequence + * @brief ADF4382 register format structure for default values + */ +struct reg_sequence { + uint16_t reg; + uint8_t val; +}; + +/** + * @struct adf4382_reg_defaults + * @brief ADF4382 register initialization + */ +static const struct reg_sequence adf4382_reg_defaults[] = { + { 0x000, 0x18 }, + { 0x00a, 0xA5 }, + { 0x200, 0x00 }, + { 0x201, 0x00 }, + { 0x202, 0x00 }, + { 0x203, 0x00 }, + { 0x203, 0x00 }, + { 0x203, 0x00 }, + { 0x100, 0x25 }, + { 0x101, 0x3F }, + { 0x102, 0x3F }, + { 0x103, 0x3F }, + { 0x104, 0x3F }, + { 0x105, 0x3F }, + { 0x106, 0x3F }, + { 0x107, 0x3F }, + { 0x108, 0x3F }, + { 0x109, 0x25 }, + { 0x10A, 0x25 }, + { 0x10B, 0x3F }, + { 0x10C, 0x3F }, + { 0x10D, 0x3F }, + { 0x10E, 0x3F }, + { 0x10F, 0x3F }, + { 0x110, 0x3F }, + { 0x111, 0x3F }, + { 0x054, 0x00 }, + { 0x053, 0x45 }, + { 0x052, 0x00 }, + { 0x051, 0x00 }, + { 0x050, 0x00 }, + { 0x04f, 0x08 }, + { 0x04e, 0x06 }, + { 0x04d, 0x00 }, + { 0x04c, 0x2B }, + { 0x04b, 0x5D }, + { 0x04a, 0x00 }, + { 0x048, 0x00 }, + { 0x047, 0x00 }, + { 0x046, 0x00 }, + { 0x045, 0x52 }, + { 0x044, 0x2E }, + { 0x043, 0xB8 }, + { 0x042, 0x01 }, + { 0x041, 0x00 }, + { 0x040, 0x00 }, + { 0x03f, 0x82 }, + { 0x03e, 0x4E }, + { 0x03d, 0x00 }, + { 0x03c, 0x00 }, + { 0x03b, 0x00 }, + { 0x03a, 0xFA }, + { 0x039, 0x00 }, + { 0x038, 0x7C }, + { 0x037, 0xCA }, + { 0x036, 0xC0 }, + { 0x035, 0x00 }, + { 0x034, 0x36 }, + { 0x033, 0x00 }, + { 0x032, 0x40 }, + { 0x031, 0x63 }, + { 0x030, 0x0F }, + { 0x02f, 0x3F }, + { 0x02e, 0x00 }, + { 0x02d, 0xF1 }, + { 0x02c, 0x0E }, + { 0x02b, 0x01 }, + { 0x02a, 0x30 }, + { 0x029, 0x09 }, + { 0x028, 0x00 }, + { 0x027, 0xF0 }, + { 0x026, 0x00 }, + { 0x025, 0x01 }, + { 0x024, 0x01 }, + { 0x023, 0x00 }, + { 0x022, 0x00 }, + { 0x021, 0x00 }, + { 0x020, 0xC1 }, + { 0x01f, 0x0F }, + { 0x01e, 0x20 }, + { 0x01d, 0x00 }, + { 0x01c, 0x00 }, + { 0x01b, 0x00 }, + { 0x01a, 0x00 }, + { 0x019, 0x00 }, + { 0x018, 0x00 }, + { 0x017, 0x00 }, + { 0x016, 0x00 }, + { 0x015, 0x06 }, + { 0x014, 0x00 }, + { 0x013, 0x00 }, + { 0x012, 0x00 }, + { 0x011, 0x00 }, + { 0x010, 0x50 }, +}; + +/** ADF4382 SPI write */ +int adf4382_spi_write(struct adf4382_dev *dev, uint16_t reg_addr, uint8_t data); + +/** ADF4382 SPI Read */ +int adf4382_spi_read(struct adf4382_dev *dev, uint16_t reg_addr, uint8_t *data); + +/** ADF4382 updates a bit in the register space over SPI */ +int adf4382_spi_update_bits(struct adf4382_dev *dev, uint16_t reg_addr, + uint8_t mask, uint8_t data); + +/** ADF4382 Register dump */ +int adf4382_reg_dump(struct adf4382_dev *dev); + +/** ADF4382 Set reference frequency attribute */ +int adf4382_set_ref_clk(struct adf4382_dev *dev, uint64_t val); + +/** ADF4382 Get reference frequency attribute */ +int adf4382_get_ref_clk(struct adf4382_dev *dev, uint64_t *val); + +/** ADF4382 Set reference doubler attribute */ +int adf4382_set_en_ref_doubler(struct adf4382_dev *dev, bool en); + +/** ADF4382 Get reference doubler attribute */ +int adf4382_get_en_ref_doubler(struct adf4382_dev *dev, bool *en); + +/** ADF4382 Set reference divider attribute */ +int adf4382_set_ref_div(struct adf4382_dev *dev, int32_t div); + +/** ADF4382 Get reference divider attribute */ +int adf4382_get_ref_div(struct adf4382_dev *dev, int32_t *div); + +/** ADF4382 Set charge pump current attribute */ +int adf4382_set_cp_i(struct adf4382_dev *dev, int32_t reg_val); + +/** ADF4382 Get charge pump current attribute */ +int adf4382_get_cp_i(struct adf4382_dev *dev, int32_t *reg_val); + +/** ADF4382 Set bleed current attribute */ +int adf4382_set_bleed_word(struct adf4382_dev *dev, int32_t word); + +/** ADF4382 Get bleed current attribute */ +int adf4382_get_bleed_word(struct adf4382_dev *dev, int32_t *word); + +/** ADF4382 Set output frequency attribute */ +int adf4382_set_rfout(struct adf4382_dev *dev, uint64_t val); + +/** ADF4382 Get output frequency attribute */ +int adf4382_get_rfout(struct adf4382_dev *dev, uint64_t *val); + +/** ADF4382 Set output power attributes */ +int adf4382_set_out_power(struct adf4382_dev *dev, uint8_t ch, int32_t pwr); + +/** ADF4382 Get output power attributes */ +int adf4382_get_out_power(struct adf4382_dev *dev, uint8_t ch, int32_t *pwr); + +/** ADF4382 Set channel enable attributes */ +int adf4382_set_en_chan(struct adf4382_dev *dev, uint8_t ch, bool en); + +/** ADF4382 Get channel enable attributes */ +int adf4382_get_en_chan(struct adf4382_dev *dev, uint8_t ch, bool *en); + +/** ADF4382 Sets frequency */ +int adf4382_set_freq(struct adf4382_dev *dev); + +/** ADF4382 Set fast calibration attributes */ +int adf4382_set_en_fast_calibration(struct adf4382_dev *dev, bool en_fast_cal); + +/** ADF4382 Set fast calibration LUT calibration attributes */ +int adf4382_set_en_lut_calibration(struct adf4382_dev *dev, bool en_lut_cal); + +/** ADF4382 Get Fast Calibration LUT Calibration attributes */ +int adf4382_get_en_lut_calibration(struct adf4382_dev *dev, bool *en); + +/** ADF4382 Set Output Frequency without writing the Ndiv Register */ +int adf4382_set_change_freq(struct adf4382_dev *dev); + +/** ADF4382 Get Change Output Frequency attribute value */ +int adf4382_get_change_rfout(struct adf4382_dev *dev, uint64_t *val); + +/** ADF4382 Set Change Output Frequency attribute value */ +int adf4382_set_change_rfout(struct adf4382_dev *dev, uint64_t val); + +/** ADF4382 Set the NDIV register attribute value */ +int adf4382_set_start_calibration(struct adf4382_dev *dev); + +/** ADF4382 Get the NDIV register attribute value as 0 */ +int adf4382_get_start_calibration(struct adf4382_dev *dev, bool *start_cal); + +/** ADF4382 Sets Phase adjustment */ +int adf4382_set_phase_adjust(struct adf4382_dev *dev, uint32_t phase_ps); + +/** ADF4382 Sets Phase adjustment polarity*/ +int adf4382_set_phase_pol(struct adf4382_dev *dev, bool polarity); + +/** ADF4382 Gets Phase adjustment polarity*/ +int adf4382_get_phase_pol(struct adf4382_dev *dev, bool *polarity); + +/** ADF4382 Set EZSYNC feature attributes */ +int adf4382_set_ezsync_setup(struct adf4382_dev *dev, bool sync); + +/** ADF4382 Set Timed SYNC feature attributes */ +int adf4382_set_timed_sync_setup(struct adf4382_dev *dev, bool sync); + +/** ADF4382 Get EZSYNC and Timed SYNC feature attributes */ +int adf4382_get_phase_sync_setup(struct adf4382_dev *dev, bool *en); + +/** ADF4382 Set sw_sync attribute */ +int adf4382_set_sw_sync(struct adf4382_dev *dev, bool sw_sync); + +/** ADF4382 Get sw_sync attribute */ +int adf4382_get_sw_sync(struct adf4382_dev *dev, bool *sw_sync); + +/** ADF4382 Set VCO calibration settings attributes */ +int adf4382_set_vco_cal_timeout(struct adf4382_dev *dev); + +/** ADF4382 Initialization */ +int adf4382_init(struct adf4382_dev **device, + struct adf4382_init_param *init_param); + +/** ADF4382 Remove */ +int adf4382_remove(struct adf4382_dev *dev); + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.c new file mode 100644 index 0000000..319475b --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.c @@ -0,0 +1,510 @@ +#include "adf4382a_manager.h" +#include "no_os_delay.h" +#include +#include + +// External SPI handle +extern SPI_HandleTypeDef hspi4; + +// Static function prototypes +static void set_chip_enable(uint8_t ce_pin, bool state); +static void set_deladj_pin(uint8_t device, bool state); +static void set_delstr_pin(uint8_t device, bool state); +static uint16_t phase_ps_to_duty_cycle(uint16_t phase_ps); + +int ADF4382A_Manager_Init(ADF4382A_Manager *manager, SyncMethod method) +{ + struct adf4382_init_param tx_param, rx_param; + int ret; + + if (!manager) { + return ADF4382A_MANAGER_ERROR_INVALID; + } + + // Initialize manager structure + manager->tx_dev = NULL; + manager->rx_dev = NULL; + manager->initialized = false; + manager->sync_method = method; + manager->tx_phase_shift_ps = 0; + manager->rx_phase_shift_ps = 0; + + // Initialize SPI parameters in manager + memset(&manager->spi_tx_param, 0, sizeof(manager->spi_tx_param)); + memset(&manager->spi_rx_param, 0, sizeof(manager->spi_rx_param)); + + // Setup TX SPI parameters for SPI4 + manager->spi_tx_param.device_id = ADF4382A_SPI_DEVICE_ID; + manager->spi_tx_param.max_speed_hz = ADF4382A_SPI_SPEED_HZ; + manager->spi_tx_param.mode = NO_OS_SPI_MODE_0; + manager->spi_tx_param.chip_select = TX_CS_Pin; + manager->spi_tx_param.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST; + manager->spi_tx_param.platform_ops = NULL; + manager->spi_tx_param.extra = &hspi4; + + // Setup RX SPI parameters for SPI4 + manager->spi_rx_param.device_id = ADF4382A_SPI_DEVICE_ID; + manager->spi_rx_param.max_speed_hz = ADF4382A_SPI_SPEED_HZ; + manager->spi_rx_param.mode = NO_OS_SPI_MODE_0; + manager->spi_rx_param.chip_select = RX_CS_Pin; + manager->spi_rx_param.bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST; + manager->spi_rx_param.platform_ops = NULL; + manager->spi_rx_param.extra = &hspi4; + + // Configure TX parameters (10.5 GHz) + memset(&tx_param, 0, sizeof(tx_param)); + tx_param.spi_3wire_en = 0; + tx_param.cmos_3v3 = 1; + tx_param.ref_freq_hz = REF_FREQ_HZ; + tx_param.ref_div = 1; + tx_param.ref_doubler_en = false; + tx_param.freq = TX_FREQ_HZ; + tx_param.id = ID_ADF4382A; + tx_param.cp_i = 3; + tx_param.bleed_word = 1000; + tx_param.ld_count = 0x07; + tx_param.spi_init = &manager->spi_tx_param; + + // Configure RX parameters (10.38 GHz) + memset(&rx_param, 0, sizeof(rx_param)); + rx_param.spi_3wire_en = 0; + rx_param.cmos_3v3 = 1; + rx_param.ref_freq_hz = REF_FREQ_HZ; + rx_param.ref_div = 1; + rx_param.ref_doubler_en = false; + rx_param.freq = RX_FREQ_HZ; + rx_param.id = ID_ADF4382A; + rx_param.cp_i = 4; + rx_param.bleed_word = 1200; + rx_param.ld_count = 0x07; + rx_param.spi_init = &manager->spi_rx_param; + + // Enable chips + set_chip_enable(TX_CE_Pin, true); + set_chip_enable(RX_CE_Pin, true); + no_os_udelay(1000); + + // Initialize DELADJ and DELSTR pins + set_deladj_pin(0, false); // TX device + set_deladj_pin(1, false); // RX device + set_delstr_pin(0, false); // TX device + set_delstr_pin(1, false); // RX device + + // Initialize TX device first + printf("Initializing TX ADF4382A (10.5 GHz) on SPI4...\n"); + ret = adf4382_init(&manager->tx_dev, &tx_param); + if (ret) { + printf("TX ADF4382A initialization failed: %d\n", ret); + set_chip_enable(TX_CE_Pin, false); + set_chip_enable(RX_CE_Pin, false); + return ADF4382A_MANAGER_ERROR_SPI; + } + + // Small delay between initializations + no_os_udelay(5000); + + // Initialize RX device + printf("Initializing RX ADF4382A (10.38 GHz) on SPI4...\n"); + ret = adf4382_init(&manager->rx_dev, &rx_param); + if (ret) { + printf("RX ADF4382A initialization failed: %d\n", ret); + adf4382_remove(manager->tx_dev); + set_chip_enable(TX_CE_Pin, false); + set_chip_enable(RX_CE_Pin, false); + return ADF4382A_MANAGER_ERROR_SPI; + } + + // Set output power + adf4382_set_out_power(manager->tx_dev, 0, 12); + adf4382_set_out_power(manager->tx_dev, 1, 12); + adf4382_set_out_power(manager->rx_dev, 0, 12); + adf4382_set_out_power(manager->rx_dev, 1, 12); + + // Enable outputs + adf4382_set_en_chan(manager->tx_dev, 0, true); + adf4382_set_en_chan(manager->tx_dev, 1, false); + adf4382_set_en_chan(manager->rx_dev, 0, true); + adf4382_set_en_chan(manager->rx_dev, 1, false); + + // Setup synchronization based on selected method + if (method == SYNC_METHOD_TIMED) { + ret = ADF4382A_SetupTimedSync(manager); + if (ret) { + printf("Timed sync setup failed: %d\n", ret); + } + } else { + ret = ADF4382A_SetupEZSync(manager); + if (ret) { + printf("EZSync setup failed: %d\n", ret); + } + } + + manager->initialized = true; + printf("ADF4382A Manager initialized with %s synchronization on SPI4\n", + (method == SYNC_METHOD_TIMED) ? "TIMED" : "EZSYNC"); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_SetupTimedSync(ADF4382A_Manager *manager) +{ + int ret; + + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + printf("Setting up Timed Synchronization (60 MHz SYNCP/SYNCN)...\n"); + + // Setup TX for timed sync + ret = adf4382_set_timed_sync_setup(manager->tx_dev, true); + if (ret) { + printf("TX timed sync setup failed: %d\n", ret); + return ret; + } + + // Setup RX for timed sync + ret = adf4382_set_timed_sync_setup(manager->rx_dev, true); + if (ret) { + printf("RX timed sync setup failed: %d\n", ret); + return ret; + } + + manager->sync_method = SYNC_METHOD_TIMED; + printf("Timed synchronization configured for 60 MHz SYNCP/SYNCN\n"); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_SetupEZSync(ADF4382A_Manager *manager) +{ + int ret; + + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + printf("Setting up EZSync (SPI-based synchronization)...\n"); + + // Setup TX for EZSync + ret = adf4382_set_ezsync_setup(manager->tx_dev, true); + if (ret) { + printf("TX EZSync setup failed: %d\n", ret); + return ret; + } + + // Setup RX for EZSync + ret = adf4382_set_ezsync_setup(manager->rx_dev, true); + if (ret) { + printf("RX EZSync setup failed: %d\n", ret); + return ret; + } + + manager->sync_method = SYNC_METHOD_EZSYNC; + printf("EZSync configured\n"); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_TriggerTimedSync(ADF4382A_Manager *manager) +{ + if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_TIMED) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + printf("Timed sync ready - SYNC pin will trigger synchronization\n"); + printf("Ensure 60 MHz phase-aligned clocks are present on SYNCP/SYNCN pins\n"); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_TriggerEZSync(ADF4382A_Manager *manager) +{ + int ret; + + if (!manager || !manager->initialized || manager->sync_method != SYNC_METHOD_EZSYNC) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Trigger software sync on both devices + ret = adf4382_set_sw_sync(manager->tx_dev, true); + if (ret) { + printf("TX software sync failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + ret = adf4382_set_sw_sync(manager->rx_dev, true); + if (ret) { + printf("RX software sync failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + // Small delay for sync to take effect + no_os_udelay(10); + + // Clear software sync + ret = adf4382_set_sw_sync(manager->tx_dev, false); + if (ret) { + printf("TX sync clear failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + ret = adf4382_set_sw_sync(manager->rx_dev, false); + if (ret) { + printf("RX sync clear failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + printf("EZSync triggered via SPI\n"); + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_Manager_Deinit(ADF4382A_Manager *manager) +{ + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Disable outputs first + if (manager->tx_dev) { + adf4382_set_en_chan(manager->tx_dev, 0, false); + adf4382_set_en_chan(manager->tx_dev, 1, false); + } + + if (manager->rx_dev) { + adf4382_set_en_chan(manager->rx_dev, 0, false); + adf4382_set_en_chan(manager->rx_dev, 1, false); + } + + // Remove devices + if (manager->tx_dev) { + adf4382_remove(manager->tx_dev); + manager->tx_dev = NULL; + } + + if (manager->rx_dev) { + adf4382_remove(manager->rx_dev); + manager->rx_dev = NULL; + } + + // Disable chips and phase control pins + set_chip_enable(TX_CE_Pin, false); + set_chip_enable(RX_CE_Pin, false); + set_deladj_pin(0, false); + set_deladj_pin(1, false); + set_delstr_pin(0, false); + set_delstr_pin(1, false); + + manager->initialized = false; + + printf("ADF4382A Manager deinitialized\n"); + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_CheckLockStatus(ADF4382A_Manager *manager, bool *tx_locked, bool *rx_locked) +{ + uint8_t tx_status, rx_status; + int ret; + + if (!manager || !manager->initialized || !tx_locked || !rx_locked) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Read lock status from registers + ret = adf4382_spi_read(manager->tx_dev, 0x58, &tx_status); + if (ret) { + printf("TX lock status read failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + ret = adf4382_spi_read(manager->rx_dev, 0x58, &rx_status); + if (ret) { + printf("RX lock status read failed: %d\n", ret); + return ADF4382A_MANAGER_ERROR_SPI; + } + + *tx_locked = (tx_status & ADF4382_LOCKED_MSK) != 0; + *rx_locked = (rx_status & ADF4382_LOCKED_MSK) != 0; + + // Also check GPIO lock detect pins as backup + bool tx_gpio_locked = HAL_GPIO_ReadPin(TX_LKDET_GPIO_Port, TX_LKDET_Pin) == GPIO_PIN_SET; + bool rx_gpio_locked = HAL_GPIO_ReadPin(RX_LKDET_GPIO_Port, RX_LKDET_Pin) == GPIO_PIN_SET; + + // Use both register and GPIO status + *tx_locked = *tx_locked && tx_gpio_locked; + *rx_locked = *rx_locked && rx_gpio_locked; + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_SetOutputPower(ADF4382A_Manager *manager, uint8_t tx_power, uint8_t rx_power) +{ + int ret; + + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Clamp power values (0-15) + tx_power = (tx_power > 15) ? 15 : tx_power; + rx_power = (rx_power > 15) ? 15 : rx_power; + + // Set TX power for both channels + ret = adf4382_set_out_power(manager->tx_dev, 0, tx_power); + if (ret) return ret; + ret = adf4382_set_out_power(manager->tx_dev, 1, tx_power); + if (ret) return ret; + + // Set RX power for both channels + ret = adf4382_set_out_power(manager->rx_dev, 0, rx_power); + if (ret) return ret; + ret = adf4382_set_out_power(manager->rx_dev, 1, rx_power); + + printf("Output power set: TX=%d, RX=%d\n", tx_power, rx_power); + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_EnableOutputs(ADF4382A_Manager *manager, bool tx_enable, bool rx_enable) +{ + int ret; + + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Enable/disable TX outputs + ret = adf4382_set_en_chan(manager->tx_dev, 0, tx_enable); + if (ret) return ret; + ret = adf4382_set_en_chan(manager->tx_dev, 1, tx_enable); + if (ret) return ret; + + // Enable/disable RX outputs + ret = adf4382_set_en_chan(manager->rx_dev, 0, rx_enable); + if (ret) return ret; + ret = adf4382_set_en_chan(manager->rx_dev, 1, rx_enable); + + printf("Outputs: TX=%s, RX=%s\n", + tx_enable ? "ENABLED" : "DISABLED", + rx_enable ? "ENABLED" : "DISABLED"); + return ADF4382A_MANAGER_OK; +} + +// New phase delay functions + +int ADF4382A_SetPhaseShift(ADF4382A_Manager *manager, uint16_t tx_phase_ps, uint16_t rx_phase_ps) +{ + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Clamp phase shift values + tx_phase_ps = (tx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : tx_phase_ps; + rx_phase_ps = (rx_phase_ps > PHASE_SHIFT_MAX_PS) ? PHASE_SHIFT_MAX_PS : rx_phase_ps; + + // Convert phase shift to duty cycle and apply + if (tx_phase_ps != manager->tx_phase_shift_ps) { + uint16_t duty_cycle = phase_ps_to_duty_cycle(tx_phase_ps); + ADF4382A_SetFinePhaseShift(manager, 0, duty_cycle); // 0 = TX device + manager->tx_phase_shift_ps = tx_phase_ps; + } + + if (rx_phase_ps != manager->rx_phase_shift_ps) { + uint16_t duty_cycle = phase_ps_to_duty_cycle(rx_phase_ps); + ADF4382A_SetFinePhaseShift(manager, 1, duty_cycle); // 1 = RX device + manager->rx_phase_shift_ps = rx_phase_ps; + } + + printf("Phase shift set: TX=%d ps, RX=%d ps\n", tx_phase_ps, rx_phase_ps); + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_GetPhaseShift(ADF4382A_Manager *manager, uint16_t *tx_phase_ps, uint16_t *rx_phase_ps) +{ + if (!manager || !manager->initialized || !tx_phase_ps || !rx_phase_ps) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + *tx_phase_ps = manager->tx_phase_shift_ps; + *rx_phase_ps = manager->rx_phase_shift_ps; + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_SetFinePhaseShift(ADF4382A_Manager *manager, uint8_t device, uint16_t duty_cycle) +{ + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Clamp duty cycle + duty_cycle = (duty_cycle > DELADJ_MAX_DUTY_CYCLE) ? DELADJ_MAX_DUTY_CYCLE : duty_cycle; + + // For simplicity, we'll use a basic implementation + // In a real system, you would generate a PWM signal on DELADJ pin + // Here we just set the pin state based on a simplified approach + + if (duty_cycle == 0) { + set_deladj_pin(device, false); + } else if (duty_cycle >= DELADJ_MAX_DUTY_CYCLE) { + set_deladj_pin(device, true); + } else { + // For intermediate values, you would need PWM generation + // This is a simplified implementation + set_deladj_pin(device, true); + } + + printf("Device %d DELADJ duty cycle set to %d/%d\n", + device, duty_cycle, DELADJ_MAX_DUTY_CYCLE); + + return ADF4382A_MANAGER_OK; +} + +int ADF4382A_StrobePhaseShift(ADF4382A_Manager *manager, uint8_t device) +{ + if (!manager || !manager->initialized) { + return ADF4382A_MANAGER_ERROR_NOT_INIT; + } + + // Generate a pulse on DELSTR pin to latch the current DELADJ value + set_delstr_pin(device, true); + no_os_udelay(DELADJ_PULSE_WIDTH_US); + set_delstr_pin(device, false); + + printf("Device %d phase shift strobed\n", device); + + return ADF4382A_MANAGER_OK; +} + +// Static helper functions + +static void set_chip_enable(uint8_t ce_pin, bool state) +{ + GPIO_TypeDef* port = (ce_pin == TX_CE_Pin) ? TX_CE_GPIO_Port : RX_CE_GPIO_Port; + HAL_GPIO_WritePin(port, ce_pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); +} + +static void set_deladj_pin(uint8_t device, bool state) +{ + if (device == 0) { // TX device + HAL_GPIO_WritePin(TX_DELADJ_GPIO_Port, TX_DELADJ_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); + } else { // RX device + HAL_GPIO_WritePin(RX_DELADJ_GPIO_Port, RX_DELADJ_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); + } +} + +static void set_delstr_pin(uint8_t device, bool state) +{ + if (device == 0) { // TX device + HAL_GPIO_WritePin(TX_DELSTR_GPIO_Port, TX_DELSTR_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); + } else { // RX device + HAL_GPIO_WritePin(RX_DELSTR_GPIO_Port, RX_DELSTR_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); + } +} + +static uint16_t phase_ps_to_duty_cycle(uint16_t phase_ps) +{ + // Convert phase shift in picoseconds to DELADJ duty cycle + // This is a linear mapping - adjust based on your specific requirements + uint32_t duty = (uint32_t)phase_ps * DELADJ_MAX_DUTY_CYCLE / PHASE_SHIFT_MAX_PS; + return (uint16_t)duty; +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.h new file mode 100644 index 0000000..9cc4c13 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/adf4382a_manager.h @@ -0,0 +1,85 @@ +#ifndef ADF4382A_MANAGER_H +#define ADF4382A_MANAGER_H + +#include "main.h" +#include "adf4382.h" +#include "no_os_spi.h" + +// GPIO Definitions +#define TX_CE_Pin GPIO_PIN_0 +#define TX_CE_GPIO_Port GPIOG +#define TX_CS_Pin GPIO_PIN_1 +#define TX_CS_GPIO_Port GPIOG +#define TX_DELADJ_Pin GPIO_PIN_2 +#define TX_DELADJ_GPIO_Port GPIOG +#define TX_DELSTR_Pin GPIO_PIN_3 +#define TX_DELSTR_GPIO_Port GPIOG +#define TX_LKDET_Pin GPIO_PIN_4 +#define TX_LKDET_GPIO_Port GPIOG + +#define RX_CE_Pin GPIO_PIN_5 +#define RX_CE_GPIO_Port GPIOG +#define RX_CS_Pin GPIO_PIN_6 +#define RX_CS_GPIO_Port GPIOG +#define RX_DELADJ_Pin GPIO_PIN_7 +#define RX_DELADJ_GPIO_Port GPIOG +#define RX_DELSTR_Pin GPIO_PIN_8 +#define RX_DELSTR_GPIO_Port GPIOG +#define RX_LKDET_Pin GPIO_PIN_9 +#define RX_LKDET_GPIO_Port GPIOG + +// Frequency definitions +#define REF_FREQ_HZ 300000000ULL // 300 MHz +#define TX_FREQ_HZ 10500000000ULL // 10.5 GHz +#define RX_FREQ_HZ 10380000000ULL // 10.38 GHz +#define SYNC_CLOCK_FREQ 60000000ULL // 60 MHz sync clock + +// SPI Configuration +#define ADF4382A_SPI_DEVICE_ID 4 // Using SPI4 +#define ADF4382A_SPI_SPEED_HZ 10000000 // 10 MHz + +// Phase delay configuration +#define DELADJ_MAX_DUTY_CYCLE 1000 // Maximum duty cycle for DELADJ PWM (1000 = 100%) +#define DELADJ_PULSE_WIDTH_US 10 // Width of DELSTR pulse in microseconds +#define PHASE_SHIFT_MAX_PS 10000 // Maximum phase shift in picoseconds + +// Error code definitions +#define ADF4382A_MANAGER_OK 0 +#define ADF4382A_MANAGER_ERROR_INVALID -1 +#define ADF4382A_MANAGER_ERROR_NOT_INIT -2 +#define ADF4382A_MANAGER_ERROR_SPI -3 + +typedef enum { + SYNC_METHOD_EZSYNC = 0, // Software synchronization via SPI + SYNC_METHOD_TIMED = 1 // Hardware synchronization via SYNCP/SYNCN +} SyncMethod; + +typedef struct { + struct adf4382_dev *tx_dev; + struct adf4382_dev *rx_dev; + struct no_os_spi_init_param spi_tx_param; + struct no_os_spi_init_param spi_rx_param; + bool initialized; + SyncMethod sync_method; + uint16_t tx_phase_shift_ps; // Current TX phase shift in picoseconds + uint16_t rx_phase_shift_ps; // Current RX phase shift in picoseconds +} ADF4382A_Manager; + +// Public functions +int ADF4382A_Manager_Init(ADF4382A_Manager *manager, SyncMethod method); +int ADF4382A_Manager_Deinit(ADF4382A_Manager *manager); +int ADF4382A_SetupTimedSync(ADF4382A_Manager *manager); +int ADF4382A_SetupEZSync(ADF4382A_Manager *manager); +int ADF4382A_TriggerTimedSync(ADF4382A_Manager *manager); +int ADF4382A_TriggerEZSync(ADF4382A_Manager *manager); +int ADF4382A_CheckLockStatus(ADF4382A_Manager *manager, bool *tx_locked, bool *rx_locked); +int ADF4382A_SetOutputPower(ADF4382A_Manager *manager, uint8_t tx_power, uint8_t rx_power); +int ADF4382A_EnableOutputs(ADF4382A_Manager *manager, bool tx_enable, bool rx_enable); + +// New phase delay functions +int ADF4382A_SetPhaseShift(ADF4382A_Manager *manager, uint16_t tx_phase_ps, uint16_t rx_phase_ps); +int ADF4382A_GetPhaseShift(ADF4382A_Manager *manager, uint16_t *tx_phase_ps, uint16_t *rx_phase_ps); +int ADF4382A_SetFinePhaseShift(ADF4382A_Manager *manager, uint8_t device, uint16_t duty_cycle); +int ADF4382A_StrobePhaseShift(ADF4382A_Manager *manager, uint8_t device); + +#endif // ADF4382A_MANAGER_H diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/errno.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/errno.h new file mode 100644 index 0000000..d28d672 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/errno.h @@ -0,0 +1,100 @@ +/***************************************************************************//** + * @file errno.h + * @brief Error macro definition for ARM Compiler +******************************************************************************** + * Copyright (c) 2021-2022 Analog Devices, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef MBED_ERRNO_H_ +#define MBED_ERRNO_H_ + +// Platform drivers needs to be C-compatible to work with other drivers +#ifdef __cplusplus +extern "C" +{ +#endif // _cplusplus + +#if defined(__ARMCC_VERSION) +#if !defined(__ELASTERROR) +#define __ELASTERROR 2000 +#endif +#if !defined(ENOTSUP) +#define ENOTSUP 9926 +#endif +#if !defined(EBADMSG) +#define EBADMSG 9905 +#endif +#if !defined(ETIME) +#define ETIME 9935 +#endif +#if !defined(EACCES) +#define EACCES 9973 +#endif +#if !defined(ETIMEDOUT) +#define ETIMEDOUT 9938 +#endif +#if !defined(ENODEV) +#define ENODEV 9967 +#endif +#if !defined(EFAULT) +#define EFAULT 9948 +#endif +#if !defined(EIO) +#define EIO 9961 +#endif +#if !defined(ENOENT) +#define ENOENT 9968 +#endif +#if !defined(EBUSY) +#define EBUSY 9952 +#endif +#if !defined(EAGAIN) +#define EAGAIN 9976 +#endif +#if !defined(EINVAL) +#define EINVAL 9943 +#endif +#if !defined(ENOMEM) +#define ENOMEM 9971 +#endif +#if !defined(ENOSYS) +#define ENOSYS 88 +#endif +#if !defined(ENOTCONN) +#define ENOTCONN 128 +#endif + +// End of defined(__ARMCC_VERSION) +#endif + +#include_next + +#ifdef __cplusplus +} +#endif // _cplusplus + +#endif // MBED_ERRNO_H_ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/gps_handler.cpp b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/gps_handler.cpp new file mode 100644 index 0000000..2b15cc2 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/gps_handler.cpp @@ -0,0 +1,119 @@ +// gps_handler.cpp +#include "gps_handler.h" +#include + +// UART handle for communication with GUI +static UART_HandleTypeDef* gui_huart = NULL; + +// GPS data buffer +static GPS_Data_t current_gps = {0}; + +void GPS_Init(UART_HandleTypeDef* huart) +{ + gui_huart = huart; + memset(¤t_gps, 0, sizeof(GPS_Data_t)); +} + +uint8_t GPS_IsDataValid(GPS_Data_t* gps_data) +{ + // Check if GPS data is within valid ranges + if (gps_data->latitude < -90.0 || gps_data->latitude > 90.0) + return 0; + if (gps_data->longitude < -180.0 || gps_data->longitude > 180.0) + return 0; + if (gps_data->altitude < -1000.0 || gps_data->altitude > 10000.0) // -1km to 10km + return 0; + + return 1; +} + +void GPS_ProcessData(GPS_Data_t* gps_data) +{ + // Validate GPS data + if (!GPS_IsDataValid(gps_data)) { + return; + } + + // Update current GPS data + memcpy(¤t_gps, gps_data, sizeof(GPS_Data_t)); + current_gps.timestamp = HAL_GetTick(); + + // Send to GUI + GPS_SendToGUI(¤t_gps); +} + +void GPS_SendToGUI(GPS_Data_t* gps_data) +{ + if (gui_huart == NULL) return; + + // Create packet: "GPS:lat,lon,alt\r\n" + char buffer[64]; + + // Convert double and float to string with high precision + int len = snprintf(buffer, sizeof(buffer), "GPS:%.8f,%.8f,%.2f\r\n", + gps_data->latitude, + gps_data->longitude, + gps_data->altitude); + + if (len > 0 && len < (int)sizeof(buffer)) { + // Send via UART3 to GUI + HAL_UART_Transmit(gui_huart, (uint8_t*)buffer, len, 1000); + } +} + +// Alternative binary protocol version (more efficient) +void GPS_SendBinaryToGUI(GPS_Data_t* gps_data) +{ + if (gui_huart == NULL) return; + + // Binary packet structure: + // [Header 4 bytes][Latitude 8 bytes][Longitude 8 bytes][Altitude 4 bytes][Pitch 4 bytes][CRC 2 bytes] + + uint8_t packet[30]; // 4 + 8 + 8 + 4 + 4 + 2 = 30 bytes + uint16_t crc = 0; + + // Header: "GPSB" + packet[0] = 'G'; + packet[1] = 'P'; + packet[2] = 'S'; + packet[3] = 'B'; + + // Convert double latitude to bytes (big-endian) + uint64_t lat_bits; + memcpy(&lat_bits, &gps_data->latitude, sizeof(double)); + for(int i = 0; i < 8; i++) { + packet[4 + i] = (lat_bits >> (56 - i*8)) & 0xFF; + } + + // Convert double longitude to bytes (big-endian) + uint64_t lon_bits; + memcpy(&lon_bits, &gps_data->longitude, sizeof(double)); + for(int i = 0; i < 8; i++) { + packet[12 + i] = (lon_bits >> (56 - i*8)) & 0xFF; + } + + // Convert float altitude to bytes (big-endian) + uint32_t alt_bits; + memcpy(&alt_bits, &gps_data->altitude, sizeof(float)); + for(int i = 0; i < 4; i++) { + packet[20 + i] = (alt_bits >> (24 - i*8)) & 0xFF; + } + + // Convert float altitude to bytes (big-endian) + uint32_t pitch_bits; + memcpy(&pitch_bits, &gps_data->pitch, sizeof(float)); + for(int i = 0; i < 4; i++) { + packet[24 + i] = (pitch_bits >> (24 - i*8)) & 0xFF; + } + + // Calculate simple checksum (you can use CRC16 instead) + for(int i = 0; i < 28; i++) { + crc += packet[i]; + } + + packet[28] = (crc >> 8) & 0xFF; + packet[29] = crc & 0xFF; + + // Send binary packet + CDC_Transmit_FS(packet, sizeof(packet)); +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/gps_handler.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/gps_handler.h new file mode 100644 index 0000000..0425698 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/gps_handler.h @@ -0,0 +1,33 @@ +// gps_handler.h +#ifndef GPS_HANDLER_H +#define GPS_HANDLER_H + +#include "main.h" +#include "usb_device.h" +#include "usbd_cdc_if.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + double latitude; + double longitude; + float altitude; + float pitch; + uint32_t timestamp; +} GPS_Data_t; + +void GPS_Init(UART_HandleTypeDef* huart); +void GPS_ProcessData(GPS_Data_t* gps_data); +void GPS_SendToGUI(GPS_Data_t* gps_data); +void GPS_SendBinaryToGUI(GPS_Data_t* gps_data); +uint8_t GPS_IsDataValid(GPS_Data_t* gps_data); + +#ifdef __cplusplus +} +#endif + +#endif /* GPS_HANDLER_H */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/platform_noos_stm32.H b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/platform_noos_stm32.H new file mode 100644 index 0000000..14d1e21 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/platform_noos_stm32.H @@ -0,0 +1,25 @@ +/* platform_noos_stm32.h */ +#ifndef PLATFORM_NOOS_STM32_H +#define PLATFORM_NOOS_STM32_H + +#include "stm32f7xx_hal.h" +#include +#include +#include + +/* Export the HAL SPI handle that will be used by no-OS SPI wrapper */ +extern SPI_HandleTypeDef hspi4; + +/* Simple wrapper prototypes for no-OS */ +int32_t platform_spi_init(void **desc, uint32_t max_speed_hz, uint8_t mode); +int32_t platform_spi_write_and_read(void *desc, uint8_t *data, uint16_t len); +int32_t platform_spi_remove(void *desc); + +int32_t platform_gpio_init(void *gpio_desc, uint8_t port_pin, bool is_output); +int32_t platform_gpio_direction_output(void *gpio_desc, uint8_t port_pin, uint8_t value); +int32_t platform_gpio_set_value(void *gpio_desc, uint8_t port_pin, uint8_t value); +int32_t platform_gpio_remove(void *gpio_desc); + +void platform_delay_ms(uint32_t ms); + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/platform_noos_stm32.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/platform_noos_stm32.c new file mode 100644 index 0000000..869aa4d --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/platform_noos_stm32.c @@ -0,0 +1,64 @@ +/* platform_noos_stm32.c */ +#include "platform_noos_stm32.h" + +/* Use existing CubeMX handles */ +extern SPI_HandleTypeDef hspi4; + +/* SPI descriptor we pass to no-OS (just a pointer to HAL handle) */ +int32_t platform_spi_init(void **desc, uint32_t max_speed_hz, uint8_t mode) +{ + /* For STM32 HAL we already configured hspi4 in CubeMX, + so just return that pointer as the descriptor. */ + if (!desc) return -1; + *desc = (void*)&hspi4; + return 0; +} + +/* SPI write/read - single transaction (no-OS expects raw transfer) */ +int32_t platform_spi_write_and_read(void *desc, uint8_t *data, uint16_t len) +{ + SPI_HandleTypeDef *hdl = (SPI_HandleTypeDef*)desc; + if (!hdl) return -1; + /* ADI no-OS SPI wrappers often do full-duplex transfers */ + if (HAL_SPI_Transmit(hdl, data, len, HAL_MAX_DELAY) != HAL_OK) + return -1; + return 0; +} + +int32_t platform_spi_remove(void *desc) +{ + (void)desc; + return 0; +} + +/* Minimal GPIO wrapper: we will just use HAL GPIO directly */ +/* For simplicity we store nothing in gpio_desc, port_pin encodes both port and pin: + You'll map an enum (0..n) -> HAL GPIO Port/Pin in your code. */ + +int32_t platform_gpio_init(void *gpio_desc, uint8_t port_pin, bool is_output) +{ + (void)gpio_desc; (void)port_pin; (void)is_output; + /* Assume CubeMX already configured the GPIO pins: nothing to do */ + return 0; +} + +int32_t platform_gpio_direction_output(void *gpio_desc, uint8_t port_pin, uint8_t value) +{ + (void)gpio_desc; + /* Implement mapping here from port_pin index to actual port/pin */ + /* Example stub: user must implement mapping function: hal_set_gpio_by_index(port_pin, value) */ + extern void hal_set_gpio_by_index(uint8_t idx, uint8_t value); + hal_set_gpio_by_index(port_pin, value); + return 0; +} + +int32_t platform_gpio_set_value(void *gpio_desc, uint8_t port_pin, uint8_t value) +{ + extern void hal_set_gpio_by_index(uint8_t idx, uint8_t value); + hal_set_gpio_by_index(port_pin, value); + return 0; +} + +int32_t platform_gpio_remove(void *gpio_desc) { (void)gpio_desc; return 0; } + +void platform_delay_ms(uint32_t ms) { HAL_Delay(ms); } diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_delay.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_delay.c new file mode 100644 index 0000000..b6a5862 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_delay.c @@ -0,0 +1,17 @@ +#include "stm32f7xx_hal.h" +#include "no_os_delay.h" + +/* microsecond delay using DWT cycle counter */ +void no_os_udelay(uint32_t usec) +{ + uint32_t start = DWT->CYCCNT; + uint32_t cycles = (HAL_RCC_GetHCLKFreq() / 1000000U) * usec; + while ((DWT->CYCCNT - start) < cycles); +} + +/* millisecond delay wrapper */ +void no_os_mdelay(uint32_t msec) +{ + HAL_Delay(msec); +} + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_delay.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_delay.h new file mode 100644 index 0000000..c23b310 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_delay.h @@ -0,0 +1,10 @@ +#ifndef _STM32_DELAY_H_ +#define _STM32_DELAY_H_ + +#include "stm32f7xx_hal.h" + +/* prototypes for compatibility */ +void no_os_udelay(uint32_t usec); +void no_os_mdelay(uint32_t msec); + +#endif /* _STM32_DELAY_H_ */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_dma.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_dma.c new file mode 100644 index 0000000..6bf69ca --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_dma.c @@ -0,0 +1,287 @@ +/***************************************************************************//** + * @file stm32/stm32_dma.c + * @brief Implementation of stm32 DMA functionality. + * @author Janani Sunil (janani.sunil@analog.com) +******************************************************************************** + * Copyright 2024(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include "stm32_dma.h" +#include "no_os_error.h" +#include "no_os_alloc.h" +#include "stm32_irq.h" + +/** +* @brief There is only one DMA controller +*/ +static struct no_os_dma_desc *dma_descriptor; + +/** + * @brief Configure a DMA channel for a transfer. + * @param channel - The DMA channel descriptor. + * @param xfer - Descriptor for the transfer. + * @return 0 in case of success, negative error codes otherwise + */ +int stm32_dma_config_xfer(struct no_os_dma_ch *channel, + struct no_os_dma_xfer_desc *xfer) +{ + struct stm32_dma_channel* sdma_ch; + int ret; + + if (!channel || !xfer || !channel->extra) + return -EINVAL; + + sdma_ch = channel->extra; + + /* Note: Channel number is assigned via the Instance for MCU + * families other than STM32F2, STM32F4 and STM32F7 */ +#if defined (STM32F2) || defined (STM32F4) || defined (STM32F7) + sdma_ch->hdma->Init.Channel = sdma_ch->ch_num; +#else + sdma_ch->hdma->Instance = sdma_ch->ch_num; +#endif + sdma_ch->hdma->Init.MemInc = sdma_ch->mem_increment ? DMA_MINC_ENABLE : + DMA_MINC_DISABLE; + sdma_ch->hdma->Init.PeriphInc = sdma_ch->per_increment ? DMA_PINC_ENABLE : + DMA_PINC_DISABLE; + + switch (sdma_ch->mem_data_alignment) { + case DATA_ALIGN_BYTE: + sdma_ch->hdma->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + break; + case DATA_ALIGN_HALF_WORD: + sdma_ch->hdma->Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + break; + case DATA_ALIGN_WORD: + sdma_ch->hdma->Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + break; + default: + return -EINVAL; + } + + switch (sdma_ch->per_data_alignment) { + case DATA_ALIGN_BYTE: + sdma_ch->hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + break; + case DATA_ALIGN_HALF_WORD: + sdma_ch->hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; + break; + case DATA_ALIGN_WORD: + sdma_ch->hdma->Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + break; + default: + return -EINVAL; + } + + switch (sdma_ch->dma_mode) { + case DMA_NORMAL_MODE: + sdma_ch->hdma->Init.Mode = DMA_NORMAL; + break; + case DMA_CIRCULAR_MODE: + sdma_ch->hdma->Init.Mode = DMA_CIRCULAR; + break; + default: + return -EINVAL; + } + + switch (xfer->xfer_type) { + case MEM_TO_MEM: + sdma_ch->hdma->Init.Direction = DMA_MEMORY_TO_MEMORY; + break; + case MEM_TO_DEV: + sdma_ch->hdma->Init.Direction = DMA_MEMORY_TO_PERIPH; + break; + case DEV_TO_MEM: + sdma_ch->hdma->Init.Direction = DMA_PERIPH_TO_MEMORY; + break; + default: + return -EINVAL; + } + + sdma_ch->src = xfer->src; + sdma_ch->dst = xfer->dst; + sdma_ch->length = xfer->length; + + ret = HAL_DMA_Init(sdma_ch->hdma); + if (ret != HAL_OK) + return -EINVAL; + + return 0; +} + +/** + * @brief Initialize a DMA controller. + * @param desc - Descriptor to be initialized. + * @param param - Initialization parameter for the decriptor. + * @return 0 in case of success + * -ENOMEM if there is not enough free memory + */ +int stm32_dma_init(struct no_os_dma_desc** desc, + const struct no_os_dma_init_param* param) +{ + struct no_os_dma_desc* descriptor; + int ret; + uint8_t i; + struct no_os_irq_init_param irq_param = { + .irq_ctrl_id = 0, + .platform_ops = &stm32_irq_ops, + .extra = NULL + }; + + if (!desc) + return -EINVAL; + + if (dma_descriptor) { + /* + * There is only one DMA controller and it's already + * initialized. + */ + *desc = dma_descriptor; + return 0; + } + + descriptor = no_os_calloc(1, sizeof(*descriptor)); + if (!descriptor) + return -ENOMEM; + + descriptor->channels = no_os_calloc(param->num_ch, + sizeof(*descriptor->channels)); + if (!descriptor->channels) { + ret = -ENOMEM; + goto free_descriptor; + } + + descriptor->id = param->id; + descriptor->num_ch = param->num_ch; + descriptor->sg_handler = param->sg_handler; + + for (i = 0; i < param->num_ch; i++) { + descriptor->channels[i].free = true; + } + + no_os_irq_ctrl_init(&descriptor->irq_ctrl, &irq_param); + + *desc = descriptor; + + return 0; + +free_descriptor: + no_os_free(descriptor); + descriptor = NULL; + + return ret; +} + +/** + * @brief Start a DMA transfer for a specific channel . + * @param desc - Descriptor for the DMA controller. + * @param chan - The DMA Channel + * @return 0 in case of success, negative error codes otherwise + */ +int stm32_dma_xfer_start(struct no_os_dma_desc *desc, + struct no_os_dma_ch *chan) +{ + int ret; + struct stm32_dma_channel* sdma_chan; + + if (!desc || !chan || !chan->extra) + return -EINVAL; + + sdma_chan = chan->extra; + + if (chan->irq_num) { + ret = HAL_DMA_Start_IT(sdma_chan->hdma, (uint32_t)sdma_chan->src, + (uint32_t)sdma_chan->dst, sdma_chan->length); + } else { + ret = HAL_DMA_Start(sdma_chan->hdma, (uint32_t)sdma_chan->src, + (uint32_t)sdma_chan->dst, sdma_chan->length); + } + + if (ret != HAL_OK) + return -EINVAL; + + return 0; +} + +/** + * @brief Disable a DMA channel. + * @param desc - Descriptor for the DMA controller. + * @param chan - The DMA Channel + * @return 0 in case of success, negative error codes otherwise + */ +int stm32_dma_xfer_abort(struct no_os_dma_desc* desc, + struct no_os_dma_ch* chan) +{ + int ret; + struct stm32_dma_channel* sdma_chan; + + if (!desc || !chan || !chan->extra) + return -EINVAL; + + sdma_chan = chan->extra; + + if (chan->irq_num) + ret = HAL_DMA_Abort_IT(sdma_chan->hdma); + else + ret = HAL_DMA_Abort(sdma_chan->hdma); + + if (ret != HAL_OK) + return -EINVAL; + + return 0; +} + +/** + * @brief Free the resources allocated for a DMA descriptor. + * @param desc - Descriptor to be freed. + * @return 0 in case of success, negative error code otherwise + */ +int stm32_dma_remove(struct no_os_dma_desc* desc) +{ + no_os_irq_ctrl_remove(desc->irq_ctrl); + + no_os_free(desc->channels); + + no_os_free(desc); + + dma_descriptor = NULL; + + return 0; +} + +/** + * @brief stm32 platform specific DMA platform ops structure + */ +const struct no_os_dma_platform_ops stm32_dma_ops = { + .dma_init = stm32_dma_init, + .dma_config_xfer = stm32_dma_config_xfer, + .dma_xfer_start = stm32_dma_xfer_start, + .dma_xfer_abort = stm32_dma_xfer_abort, + .dma_remove = stm32_dma_remove +}; + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_dma.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_dma.h new file mode 100644 index 0000000..7ba742e --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_dma.h @@ -0,0 +1,101 @@ +/***************************************************************************//** + * @file stm32_dma.h + * @brief Platform independent function definitions and data types + * for the DMA API. + * @author Janani Sunil (janani.sunil@analog.com) +******************************************************************************** + * Copyright 2024(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef STM32_DMA_H_ +#define STM32_DMA_H_ + +#include "no_os_dma.h" +#include "stm32_hal.h" + +/** + * @enum stm32_dma_data_alignment + * @brief DMA Data alignment + */ +enum stm32_dma_data_alignment { + DATA_ALIGN_BYTE = 0, + DATA_ALIGN_HALF_WORD = 1, + DATA_ALIGN_WORD = 2 +}; + +/** + * @enum stm32_dma_mode + * @brief DMA Data Modes + */ +enum stm32_dma_mode { + DMA_NORMAL_MODE = 0, + DMA_CIRCULAR_MODE = 1 +}; + +/** + * @struct stm32_dma_channel + * @brief STM32 DMA Channels + */ +struct stm32_dma_channel { + /* DMA Handle */ + DMA_HandleTypeDef *hdma; + /* Channel Number */ + uint32_t ch_num; + /* Memory Increment */ + bool mem_increment; + /* Peripheral Increment */ + bool per_increment; + /* Memory Data Alignment */ + enum stm32_dma_data_alignment mem_data_alignment; + /* Peripheral Data Alignment */ + enum stm32_dma_data_alignment per_data_alignment; + /* DMA Mode */ + enum stm32_dma_mode dma_mode; + /* Source Address for the data */ + uint8_t* src; + /* Destination Address for the data */ + uint8_t* dst; + /* Transfer length in Bytes */ + uint32_t length; +}; + +struct stm32_dma_init_param { + /* DMA Channel descriptor */ + struct stm32_dma_channel *chn; +}; + +struct stm32_dma_desc { + /* DMA Channel Descriptor */ + struct stm32_dma_channel* chn; +}; + +extern const struct no_os_dma_platform_ops stm32_dma_ops; +extern const struct no_os_dma_platform_ops stm32_gpdma_ops; + +#endif + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio.c new file mode 100644 index 0000000..c0f71f2 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio.c @@ -0,0 +1,394 @@ +/***************************************************************************//** + * @file stm32/stm32_gpio.c + * @brief Implementation of stm32 gpio functionality. + * @author Darius Berghe (darius.berghe@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#include +#include +#include "no_os_util.h" +#include "no_os_gpio.h" +#include "no_os_alloc.h" +#include "stm32_gpio.h" + +/** + * @brief Prepare the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - The structure that contains the GPIO parameters. + * @return 0 in case of success, -1 otherwise. + */ +static int32_t _gpio_init(struct no_os_gpio_desc *desc, + const struct no_os_gpio_init_param *param) +{ + int32_t ret = 0; + struct stm32_gpio_desc *extra = desc->extra; + struct stm32_gpio_init_param *pextra = param->extra; + uint32_t mode = GPIO_MODE_INPUT; + uint32_t speed = GPIO_SPEED_FREQ_LOW; + + if (!param) + return -EINVAL; + + /* enable gpio port in RCC */ + if (param->port == 0) { + __HAL_RCC_GPIOA_CLK_ENABLE(); + extra->port = GPIOA; + } +#ifdef GPIOB + else if (param->port == 1) { + __HAL_RCC_GPIOB_CLK_ENABLE(); + extra->port = GPIOB; + } +#endif +#ifdef GPIOC + else if (param->port == 2) { + __HAL_RCC_GPIOC_CLK_ENABLE(); + extra->port = GPIOC; + } +#endif +#ifdef GPIOD + else if (param->port == 3) { + __HAL_RCC_GPIOD_CLK_ENABLE(); + extra->port = GPIOD; + } +#endif +#ifdef GPIOE + else if (param->port == 4) { + __HAL_RCC_GPIOE_CLK_ENABLE(); + extra->port = GPIOE; + } +#endif +#ifdef GPIOF + else if (param->port == 5) { + __HAL_RCC_GPIOF_CLK_ENABLE(); + extra->port = GPIOF; + } +#endif +#ifdef GPIOG + else if (param->port == 6) { + __HAL_RCC_GPIOG_CLK_ENABLE(); + extra->port = GPIOG; + } +#endif +#ifdef GPIOH + else if (param->port == 7) { + __HAL_RCC_GPIOH_CLK_ENABLE(); + extra->port = GPIOH; + } +#endif +#ifdef GPIOI + else if (param->port == 8) { + __HAL_RCC_GPIOI_CLK_ENABLE(); + extra->port = GPIOI; + } +#endif +#ifdef GPIOJ + else if (param->port == 9) { + __HAL_RCC_GPIOJ_CLK_ENABLE(); + extra->port = GPIOJ; + } +#endif +#ifdef GPIOK + else if (param->port == 10) { + __HAL_RCC_GPIOK_CLK_ENABLE(); + extra->port = GPIOK; + } +#endif + else + return -EINVAL; + + if (param->extra) { + mode = pextra->mode; + speed = pextra->speed; + } + + if (!IS_GPIO_MODE(mode)) + return -EINVAL; + + switch (mode) { + case GPIO_MODE_INPUT: + case GPIO_MODE_OUTPUT_PP: + case GPIO_MODE_OUTPUT_OD: + break; + case GPIO_MODE_AF_PP: + extra->gpio_config.Alternate = pextra->alternate; + break; + default: + return -EINVAL; + } + + /* copy the settings to gpio descriptor */ + desc->port = param->port; + desc->number = param->number; + desc->pull = param->pull; + + switch (param->pull) { + case NO_OS_PULL_NONE: + extra->gpio_config.Pull = GPIO_NOPULL; + break; + case NO_OS_PULL_UP: + case NO_OS_PULL_UP_WEAK: + extra->gpio_config.Pull = GPIO_PULLUP; + break; + case NO_OS_PULL_DOWN: + case NO_OS_PULL_DOWN_WEAK: + extra->gpio_config.Pull = GPIO_PULLDOWN; + break; + default: + return -EINVAL; + } + + /* configure gpio with user configuration */ + extra->gpio_config.Pin = NO_OS_BIT(param->number); + extra->gpio_config.Mode = mode; + extra->gpio_config.Speed = speed; + + HAL_GPIO_Init(extra->port, &extra->gpio_config); + + return ret; +} + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO initialization parameters + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_gpio_get(struct no_os_gpio_desc **desc, + const struct no_os_gpio_init_param *param) +{ + struct no_os_gpio_desc *descriptor; + struct stm32_gpio_desc *extra; + int32_t ret; + + if (!desc || !param) + return -EINVAL; + + descriptor = (struct no_os_gpio_desc *)no_os_malloc(sizeof(*descriptor)); + if (!descriptor) { + ret = -ENOMEM; + goto error; + } + extra = (struct stm32_gpio_desc*)no_os_malloc(sizeof(*extra)); + if (!extra) { + ret = -ENOMEM; + goto error; + } + + descriptor->extra = extra; + ret = _gpio_init(descriptor, param); + if (ret < 0) + goto error; + + *desc = descriptor; + + return 0; +error: + no_os_free(extra); + no_os_free(descriptor); + + return ret; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_gpio_get_optional(struct no_os_gpio_desc **desc, + const struct no_os_gpio_init_param *param) +{ + if (param == NULL) { + *desc = NULL; + return 0; + } + + return stm32_gpio_get(desc, param); +} + +/** + * @brief Free the resources allocated by no_os_gpio_get(). + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_gpio_remove(struct no_os_gpio_desc *desc) +{ + if (desc != NULL) + no_os_free(desc->extra); + + no_os_free(desc); + + return 0; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_gpio_direction_input(struct no_os_gpio_desc *desc) +{ + struct stm32_gpio_desc *extra; + + if (!desc) + return -EINVAL; + + if (!desc->extra) + return -EFAULT; + + extra = desc->extra; + + /* configure gpio with user configuration */ + extra->gpio_config.Mode = GPIO_MODE_INPUT; + HAL_GPIO_Init(extra->port, &extra->gpio_config); + + return 0; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: NO_OS_GPIO_HIGH + * NO_OS_GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_gpio_direction_output(struct no_os_gpio_desc *desc, + uint8_t value) +{ + struct stm32_gpio_desc *extra; + + if (!desc) + return -EINVAL; + + if (!desc->extra) + return -EFAULT; + + extra = desc->extra; + + /* configure gpio output level */ + HAL_GPIO_WritePin(extra->port, NO_OS_BIT(desc->number), (GPIO_PinState)value); + + /* configure gpio with user configuration */ + if (extra->gpio_config.Mode == GPIO_MODE_INPUT) + extra->gpio_config.Mode = GPIO_MODE_OUTPUT_PP; + HAL_GPIO_Init(extra->port, &extra->gpio_config); + + return 0; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: NO_OS_GPIO_OUT + * NO_OS_GPIO_IN + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_gpio_get_direction(struct no_os_gpio_desc *desc, + uint8_t *direction) +{ + if (!desc || !direction) + return -EINVAL; + + struct stm32_gpio_desc *extra = desc->extra; + if (!extra->gpio_config.Mode) + *direction = NO_OS_GPIO_IN; + else + *direction = NO_OS_GPIO_OUT; + return 0; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: NO_OS_GPIO_HIGH + * NO_OS_GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_gpio_set_value(struct no_os_gpio_desc *desc, + uint8_t value) +{ + struct stm32_gpio_desc *extra; + + if (!desc) + return -EINVAL; + + if (!desc->extra) + return -EFAULT; + + extra = desc->extra; + + /* configure gpio output level */ + HAL_GPIO_WritePin(extra->port, NO_OS_BIT(desc->number), (GPIO_PinState)value); + + return 0; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: NO_OS_GPIO_HIGH + * NO_OS_GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_gpio_get_value(struct no_os_gpio_desc *desc, + uint8_t *value) +{ + struct stm32_gpio_desc *extra; + + if (!desc || !value) + return -EINVAL; + + if (!desc->extra) + return -EFAULT; + + extra = desc->extra; + + *value = (uint8_t)HAL_GPIO_ReadPin(extra->port, NO_OS_BIT(desc->number)); + + return 0; +} + +/** + * @brief stm32 platform specific GPIO platform ops structure + */ +const struct no_os_gpio_platform_ops stm32_gpio_ops = { + .gpio_ops_get = &stm32_gpio_get, + .gpio_ops_get_optional = &stm32_gpio_get_optional, + .gpio_ops_remove = &stm32_gpio_remove, + .gpio_ops_direction_input = &stm32_gpio_direction_input, + .gpio_ops_direction_output = &stm32_gpio_direction_output, + .gpio_ops_get_direction = &stm32_gpio_get_direction, + .gpio_ops_set_value = &stm32_gpio_set_value, + .gpio_ops_get_value = &stm32_gpio_get_value, +}; diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio.h new file mode 100644 index 0000000..539ed62 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio.h @@ -0,0 +1,69 @@ +/***************************************************************************//** + * @file stm32/stm32_gpio.h + * @brief Header file for stm32 gpio specifics. + * @author Darius Berghe (darius.berghe@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef STM32_GPIO_H_ +#define STM32_GPIO_H_ + +#include +#include +#include "stm32_hal.h" + +/** + * @struct stm32_gpio_init_param + * @brief Structure holding the initialization parameters for stm32 platform + */ +struct stm32_gpio_init_param { + /** Output mode */ + uint32_t mode; + /** Speed grade */ + uint32_t speed; + /** Alternate functionality */ + uint32_t alternate; +}; + +/** + * @struct stm32_gpio_desc + * @brief stm32 platform specific gpio descriptor + */ +struct stm32_gpio_desc { + /** Port */ + GPIO_TypeDef *port; + /** GPIO configuration */ + GPIO_InitTypeDef gpio_config; +}; + +/** + * @brief stm32 platform specific gpio platform ops structure + */ +extern const struct no_os_gpio_platform_ops stm32_gpio_ops; + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio_irq.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio_irq.c new file mode 100644 index 0000000..c0cb6fc --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio_irq.c @@ -0,0 +1,463 @@ +/***************************************************************************//** + * @file stm32/stm32_gpio_irq.c + * @brief Source file for GPIO IRQ driver. + * @author Ramona Bolboaca (ramona.bolboaca@analog.com) +******************************************************************************** + * Copyright 2022(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include +#include +#include "no_os_list.h" +#include "no_os_irq.h" +#include "no_os_util.h" +#include "no_os_alloc.h" +#include "stm32_gpio_irq.h" + +#define STM32_IRQ_CTRL_NB 16 + +/** + * @brief Struct used to store a (peripheral, callback) pair + */ +struct irq_action { + uint32_t irq_id; + void (*callback)(void *context); + void *ctx; +}; + +static struct no_os_list_desc *actions; + +static int32_t irq_action_cmp(void *data1, void *data2) +{ + return ((struct irq_action *)data1)->irq_id - + ((struct irq_action *)data2)->irq_id; +} + +static bool initialized[STM32_IRQ_CTRL_NB] = {false}; + +/** + * @brief Generic Interrupt handler callback + * @param pin pin number on which the interrupt occurred (GPIO_PIN_pin) + */ +static inline void stm32_handle_generic_callback(uint16_t pin) +{ + int ret; + struct irq_action *action; + struct irq_action key; + + key.irq_id = no_os_find_first_set_bit(pin); + + ret = no_os_list_read_find(actions, (void **)&action, &key); + if (ret) + return; + + if (action->callback) + action->callback(action->ctx); +} + +/** + * @brief EXTI GPIO Interrupt handler callback + * @param pin pin number on which the interrupt occurred (GPIO_PIN_pin) + */ +void HAL_GPIO_EXTI_Callback(uint16_t pin) +{ + stm32_handle_generic_callback(pin); +} + +/** + * @brief EXTI GPIO Interrupt handler callback for rising edge detection + * @param pin pin number on which the interrupt occurred (GPIO_PIN_pin) + */ +void HAL_GPIO_EXTI_Rising_Callback(uint16_t pin) +{ + stm32_handle_generic_callback(pin); +} + +/** + * @brief EXTI GPIO Interrupt handler callback for falling edge detection + * @param pin pin number on which the interrupt occurred (GPIO_PIN_pin) + */ +void HAL_GPIO_EXTI_Falling_Callback(uint16_t pin) +{ + stm32_handle_generic_callback(pin); +} + +/** + * @brief Initialize the GPIO interrupt controller + * @param desc - Pointer where the configured instance is stored + * @param param - Configuration information for the instance + * @return 0 in case of success, errno error codes otherwise. + */ +static int stm32_gpio_irq_ctrl_init(struct no_os_irq_ctrl_desc **desc, + const struct no_os_irq_init_param *param) +{ + static struct no_os_irq_ctrl_desc *gpio_irq_desc_arr[STM32_IRQ_CTRL_NB]; + + int ret; + struct no_os_irq_ctrl_desc *gpio_irq_desc; + struct stm32_gpio_irq_desc *sdesc; + struct stm32_gpio_irq_init_param *gpio_irq_ip; + + if (!param || !param->extra) + return -EINVAL; + + gpio_irq_ip = param->extra; + + /* Check port number */ + if (!IS_EXTI_GPIO_PORT(gpio_irq_ip->port_nb)) + return -EINVAL; + + /* Check pin number */ + if (!IS_EXTI_GPIO_PIN(param->irq_ctrl_id)) + return -EINVAL; + + if (!initialized[param->irq_ctrl_id]) { + + gpio_irq_desc = no_os_calloc(1, sizeof(*gpio_irq_desc)); + if (!gpio_irq_desc) + return -ENOMEM; + + sdesc = (struct stm32_gpio_irq_desc*)no_os_calloc(1, sizeof(*sdesc)); + if (!sdesc) { + ret = -ENOMEM; + goto error; + } + /* Add port number */ + sdesc->port_nb = gpio_irq_ip->port_nb; + + gpio_irq_desc->extra = sdesc; + gpio_irq_desc->irq_ctrl_id = param->irq_ctrl_id; + + ret = no_os_list_init(&actions, NO_OS_LIST_PRIORITY_LIST, irq_action_cmp); + if (ret) + goto error; + + gpio_irq_desc_arr[param->irq_ctrl_id] = gpio_irq_desc; + initialized[param->irq_ctrl_id] = true; + } + + *desc = gpio_irq_desc_arr[param->irq_ctrl_id]; + + return 0; +error: + no_os_list_remove(actions); + no_os_free(gpio_irq_desc); + no_os_free(sdesc); + + return ret; +} + +/** + * @brief Free the resources allocated by irq_ctrl_init() + * @param desc - GPIO interrupt controller descriptor. + * @return 0 in case of success, errno error codes otherwise. + */ +static int stm32_gpio_irq_ctrl_remove(struct no_os_irq_ctrl_desc *desc) +{ + struct no_os_callback_desc *discard; + + if (!desc) + return -EINVAL; + + while (0 == no_os_list_get_first(actions, (void **)&discard)) + no_os_free(discard); + + no_os_list_remove(actions); + + initialized[desc->irq_ctrl_id] = false; + + no_os_free(desc->extra); + no_os_free(desc); + + return 0; +} + +/** + * @brief Set the trigger condition. + * @param desc - GPIO interrupt controller descriptor. + * @param irq_id - Not used, pin id is already present in desc. + * @param level - the trigger condition. + * @return 0 in case of success, errno error codes otherwise + */ +static int stm32_gpio_irq_trigger_level_set(struct no_os_irq_ctrl_desc + *desc, + uint32_t irq_id, + enum no_os_irq_trig_level level) +{ + int ret; + EXTI_ConfigTypeDef config; + struct stm32_gpio_irq_desc *sdesc; + + if (!desc || !desc->extra || !IS_EXTI_GPIO_PIN(desc->irq_ctrl_id)) + return -EINVAL; + + sdesc = desc->extra; + + ret = HAL_EXTI_GetConfigLine(&sdesc->hexti, &config); + if (ret != HAL_OK) + return -EFAULT; + + switch (level) { + case NO_OS_IRQ_EDGE_FALLING: + config.Trigger = EXTI_TRIGGER_FALLING; + break; + case NO_OS_IRQ_EDGE_RISING: + config.Trigger = EXTI_TRIGGER_RISING; + break; + case NO_OS_IRQ_EDGE_BOTH: + config.Trigger = EXTI_TRIGGER_RISING_FALLING; + break; + default: + return -EINVAL; + } + + config.GPIOSel = sdesc->port_nb; + ret = HAL_EXTI_SetConfigLine(&sdesc->hexti, &config); + if (ret != HAL_OK) + return -EFAULT; + + return 0; +} + +/** + * @brief Register a callback function to be triggered when an + * interrupt occurs. + * @param desc - GPIO interrupt controller descriptor. + * @param irq_id - Not used, pin id is already present in desc. + * @param cb - Descriptor of the callback. + * @return 0 if successful, negative error code otherwise. + */ +static int stm32_gpio_irq_register_callback(struct no_os_irq_ctrl_desc + *desc, + uint32_t irq_id, + struct no_os_callback_desc *cb) +{ + int ret; + struct irq_action *action; + struct irq_action action_key = {.irq_id = desc->irq_ctrl_id}; + struct stm32_gpio_irq_desc *sdesc; + + if (!desc || !desc->extra || !cb || !IS_EXTI_GPIO_PIN(desc->irq_ctrl_id)) + return -EINVAL; + + sdesc = desc->extra; + + ret = no_os_list_read_find(actions, (void **)&action, &action_key); + /* + * If no action was found, insert a new one, otherwise update it + */ + if (ret) { + action = no_os_calloc(1, sizeof(*action)); + if (!action) + return -ENOMEM; + + action->irq_id = desc->irq_ctrl_id; + action->ctx = cb->ctx; + action->callback = cb->callback; + + ret = no_os_list_add_last(actions, action); + if (ret) + goto free_action; + } else { + action->irq_id = desc->irq_ctrl_id; + action->ctx = cb->ctx; + action->callback = cb->callback; + } + + EXTI_ConfigTypeDef config; + config.Mode = EXTI_MODE_INTERRUPT; + config.GPIOSel = sdesc->port_nb; + config.Line = EXTI_GPIO | desc->irq_ctrl_id; + ret = HAL_EXTI_SetConfigLine(&sdesc->hexti, &config); + if (ret) { + ret = -EFAULT; + goto free_action; + } + + return 0; + +free_action: + no_os_free(action); + return ret; +} + +/** + * @brief Unregister a callback. + * @param desc - GPIO interrupt controller descriptor. + * @param irq_id - Not used, pin id is already present in desc. + * @param cb - Descriptor of the callback. + * @return 0 if successful, negative error code otherwise. + */ +static int stm32_gpio_irq_unregister_callback(struct no_os_irq_ctrl_desc + *desc, + uint32_t irq_id, struct no_os_callback_desc *cb) +{ + int ret; + struct irq_action *discard_action = NULL; + struct irq_action action_key = {.irq_id = desc->irq_ctrl_id}; + + if (!desc || !cb || !IS_EXTI_GPIO_PIN(desc->irq_ctrl_id)) + return -EINVAL; + + ret = no_os_list_read_find(actions, (void **)&discard_action, &action_key); + if (ret) + return -ENODEV; + + no_os_free(discard_action); + return 0; +} + +/** + * @brief Unused + * @param desc - GPIO interrupt controller descriptor. + * @return -ENOSYS + */ +static int stm32_gpio_irq_global_enable(struct no_os_irq_ctrl_desc *desc) +{ + return -ENOSYS; +} + +/** + * @brief Unused + * @param desc - GPIO interrupt controller descriptor. + * @return -ENOSYS + */ +static int stm32_gpio_irq_global_disable(struct no_os_irq_ctrl_desc *desc) +{ + return -ENOSYS; +} + +/** + * @brief Enable a specific gpio interrupt. + * @param desc - GPIO interrupt controller descriptor. + * @param irq_id - Not used, pin id is already present in desc. + * @return 0 in case of success, -EINVAL otherwise. + */ +static int stm32_gpio_irq_enable(struct no_os_irq_ctrl_desc *desc, + uint32_t irq_id) +{ + IRQn_Type nvic_irq_id; + int ret; + + if (!desc || !desc->extra || !IS_EXTI_GPIO_PIN(desc->irq_ctrl_id)) + return -EINVAL; + + ret = stm32_get_exti_irq_id_from_pin(desc->irq_ctrl_id, &nvic_irq_id); + if (ret) + return ret; + + HAL_NVIC_EnableIRQ(nvic_irq_id); + + return 0; +} + +/** + * @brief Disable a specific gpio interrupt. + * @param desc - GPIO interrupt controller descriptor. + * @param irq_id - Not used, pin id is already present in desc. + * @return 0 in case of success, -EINVAL otherwise. + */ +static int stm32_gpio_irq_disable(struct no_os_irq_ctrl_desc *desc, + uint32_t irq_id) +{ + IRQn_Type nvic_irq_id; + int ret; + + if (!desc || !desc->extra || !IS_EXTI_GPIO_PIN(desc->irq_ctrl_id)) + return -EINVAL; + + ret = stm32_get_exti_irq_id_from_pin(desc->irq_ctrl_id, &nvic_irq_id); + if (ret) + return ret; + + HAL_NVIC_DisableIRQ(nvic_irq_id); + + return 0; +} + +/* + * @brief Set the interrupt priority for the current GPIO pin. + * @param desc - GPIO interrupt controller descriptor. + * @param irq_id - Not used, pin id is already present in desc. + * @param priority_level - The interrupt priority level. + * @return 0 + */ +static int stm32_gpio_irq_set_priority(struct no_os_irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t priority_level) +{ + IRQn_Type nvic_irq_id; + int ret; + + if (!desc || !desc->extra || !IS_EXTI_GPIO_PIN(desc->irq_ctrl_id)) + return -EINVAL; + + ret = stm32_get_exti_irq_id_from_pin(desc->irq_ctrl_id, &nvic_irq_id); + if (ret) + return ret; + + NVIC_SetPriority(nvic_irq_id, priority_level); + + return 0; +} + +/* + * @brief Clear the pending interrupt for the current GPIO pin. + * @param desc - GPIO interrupt controller descriptor. + * @param irq_id - Not used, pin id is already present in desc. + * @return 0 + */ +static int stm32_irq_clear_pending(struct no_os_irq_ctrl_desc* desc, + uint32_t irq_id) +{ + if (!desc || !desc->extra || !IS_EXTI_GPIO_PIN(desc->irq_ctrl_id)) + return -EINVAL; + + if (__HAL_GPIO_EXTI_GET_IT(1 << (desc->irq_ctrl_id))) + __HAL_GPIO_EXTI_CLEAR_IT(1 << (desc->irq_ctrl_id)); + + return 0; +} + +/** + * @brief stm32 specific IRQ platform ops structure + */ +const struct no_os_irq_platform_ops stm32_gpio_irq_ops = { + .init = &stm32_gpio_irq_ctrl_init, + .trigger_level_set = &stm32_gpio_irq_trigger_level_set, + .register_callback = &stm32_gpio_irq_register_callback, + .unregister_callback = &stm32_gpio_irq_unregister_callback, + .global_enable = &stm32_gpio_irq_global_enable, + .global_disable = &stm32_gpio_irq_global_disable, + .enable = &stm32_gpio_irq_enable, + .disable = &stm32_gpio_irq_disable, + .set_priority = &stm32_gpio_irq_set_priority, + .remove = &stm32_gpio_irq_ctrl_remove, + .clear_pending = &stm32_irq_clear_pending +}; diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio_irq.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio_irq.h new file mode 100644 index 0000000..7c51317 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_gpio_irq.h @@ -0,0 +1,64 @@ +/***************************************************************************//** + * @file stm32/stm32_gpio_irq.h + * @brief Header file for stm32 gpio irq specifics. + * @author Ramona Bolboaca (ramona.bolboaca@analog.com) +******************************************************************************** + * Copyright 2022(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef STM32_GPIO_IRQ_H +#define STM32_GPIO_IRQ_H + +#include "no_os_irq.h" +#include "stm32_hal.h" + +/** + * @struct stm32_gpio_irq_init_param + * @brief Structure holding the initialization parameters for stm32 platform + * specific GPIO IRQ parameters. + */ +struct stm32_gpio_irq_init_param { + uint8_t port_nb; +}; + +/** + * @struct stm32_gpio_irq_desc + * @brief stm32 platform specific GPIO IRQ descriptor + */ +struct stm32_gpio_irq_desc { + /** EXTI line instance */ + EXTI_HandleTypeDef hexti; + /** Port number */ + uint8_t port_nb; +}; + +/** + * @brief stm32 platform specific irq platform ops structure + */ +extern const struct no_os_irq_platform_ops stm32_gpio_irq_ops; + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_hal.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_hal.h new file mode 100644 index 0000000..d115d4c --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_hal.h @@ -0,0 +1,9 @@ +#ifndef _STM32_HAL_H +#define _STM32_HAL_H + +#include "main.h" + +int stm32_init(void); +int stm32_get_exti_irq_id_from_pin(uint8_t pin_nb, IRQn_Type *irq_id); + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_i2c.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_i2c.c new file mode 100644 index 0000000..c35071f --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_i2c.c @@ -0,0 +1,227 @@ +/***************************************************************************//** + * @file stm32/stm32_i2c.c + * @brief Implementation of stm32 i2c driver. + * @author Darius Berghe (darius.berghe@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#include +#include +#include "no_os_util.h" +#include "no_os_alloc.h" +#include "no_os_i2c.h" +#include "stm32_i2c.h" + +/** + * @brief Initialize the I2C communication peripheral. + * @param desc - The I2C descriptor. + * @param param - The structure that contains the I2C parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_i2c_init(struct no_os_i2c_desc **desc, + const struct no_os_i2c_init_param *param) +{ + int32_t ret; + struct no_os_i2c_desc *descriptor; + struct stm32_i2c_desc *xdesc; + struct stm32_i2c_init_param *i2cinit; + I2C_TypeDef *base = NULL; + + if (!desc || !param) + return -EINVAL; + + descriptor = (struct no_os_i2c_desc *)no_os_calloc(1, + sizeof(struct no_os_i2c_desc)); + if (!descriptor) + return -ENOMEM; + + xdesc = (struct stm32_i2c_desc *)no_os_calloc(1, sizeof(struct stm32_i2c_desc)); + if (!xdesc) { + ret = -ENOMEM; + goto error_1; + } + + i2cinit = param->extra; + descriptor->extra = xdesc; + + switch (param->device_id) { +#if defined(I2C1) + case 1: + base = I2C1; + break; +#endif +#if defined(I2C2) + case 2: + base = I2C2; + break; +#endif +#if defined(I2C3) + case 3: + base = I2C3; + break; +#endif + default: + ret = -EINVAL; + goto error_2; + }; + + xdesc->hi2c.Instance = base; +#if defined (STM32F4) || defined (STM32F1) || defined (STM32F2) || defined (STM32L1) + xdesc->hi2c.Init.ClockSpeed = param->max_speed_hz; + xdesc->hi2c.Init.DutyCycle = I2C_DUTYCYCLE_2; +#else + xdesc->hi2c.Init.Timing = i2cinit->i2c_timing; +#endif + xdesc->hi2c.Init.OwnAddress1 = 0; + xdesc->hi2c.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + xdesc->hi2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + xdesc->hi2c.Init.OwnAddress2 = 0; + xdesc->hi2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + xdesc->hi2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + + ret = HAL_I2C_Init(&xdesc->hi2c); + if (ret != HAL_OK) { + ret = -EIO; + goto error_2; + } + + /* copy settings to device descriptor */ + descriptor->device_id = param->device_id; + descriptor->max_speed_hz = param->max_speed_hz; + descriptor->slave_address = param->slave_address; + *desc = descriptor; + + return 0; +error_2: + no_os_free(xdesc); +error_1: + no_os_free(descriptor); + return ret; +} + +/** + * @brief Free the resources allocated by no_os_i2c_init(). + * @param desc - The I2C descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_i2c_remove(struct no_os_i2c_desc *desc) +{ + struct stm32_i2c_desc *sdesc; + + if (!desc || !desc->extra) + return -EINVAL; + + sdesc = desc->extra; + HAL_I2C_DeInit(&sdesc->hi2c); + no_os_free(desc->extra); + no_os_free(desc); + return 0; +} + +/** + * @brief I2C write transaction as master. + * @param desc - The I2C descriptor. + * @param data - The buffer with the data to transmit. + * @param bytes_number - Number of bytes in the buffer. + * @param stop_bit - Specifis whether to end the transaction with a stop bit. + * @return 0 in case of success, -1 otherwise. + */ +int32_t stm32_i2c_write(struct no_os_i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + int ret; + struct stm32_i2c_desc *xdesc; + + if (!desc || !desc->extra || !data) + return -EINVAL; + + xdesc = desc->extra; + + if (!stop_bit) { + ret = HAL_I2C_Master_Seq_Transmit_IT(&xdesc->hi2c, desc->slave_address << 1, + data, + bytes_number, I2C_FIRST_FRAME); + } else { + ret = HAL_I2C_Master_Transmit(&xdesc->hi2c, desc->slave_address << 1, data, + bytes_number, HAL_MAX_DELAY); + } + + if (ret != HAL_OK) + return -EIO; + + return 0; +} + +/** + * @brief I2C read transaction as master. + * @param desc - The I2C descriptor. + * @param data - The buffer where received data is to be stored. + * @param bytes_number - Number of bytes to receive. + * @param stop_bit - Specifis whether to end the transaction with a stop bit. + * @return 0 in case of success, -1 otherwise. + */ + +int32_t stm32_i2c_read(struct no_os_i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + int ret; + struct stm32_i2c_desc *xdesc; + + if (!desc || !desc->extra || !data) + return -EINVAL; + + xdesc = desc->extra; + + if (!stop_bit) { + ret = HAL_I2C_Master_Seq_Receive_IT(&xdesc->hi2c, desc->slave_address << 1, + data, + bytes_number, I2C_LAST_FRAME); + } else { + ret = HAL_I2C_Master_Receive(&xdesc->hi2c, desc->slave_address << 1, data, + bytes_number, HAL_MAX_DELAY); + } + + if (ret != HAL_OK) + return -EIO; + + return 0; +} + +/** + * @brief stm32 platform specific I2C platform ops structure + */ +const struct no_os_i2c_platform_ops stm32_i2c_ops = { + .i2c_ops_init = &stm32_i2c_init, + .i2c_ops_write = &stm32_i2c_write, + .i2c_ops_read = &stm32_i2c_read, + .i2c_ops_remove = &stm32_i2c_remove +}; diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_i2c.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_i2c.h new file mode 100644 index 0000000..6941d9f --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_i2c.h @@ -0,0 +1,64 @@ +/***************************************************************************//** + * @file stm32/stm32_i2c.h + * @brief Header file for the stm32 i2c driver. + * @author Darius Berghe (darius.berghe@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef STM32_I2C_H_ +#define STM32_I2C_H_ + +#include +#include "no_os_i2c.h" +#include "stm32_hal.h" + +/** + * @struct stm32_i2c_desc + * @brief stm32 platform specific I2C descriptor + */ +struct stm32_i2c_desc { + /** I2C instance */ + I2C_HandleTypeDef hi2c; +}; + +/** + * @struct stm32_i2c_init_param + * @brief Structure holding the initialization parameters for stm32 platform + * specific I2C parameters. + */ +struct stm32_i2c_init_param { + /** I2C Timing */ + uint32_t i2c_timing; +}; + +/** + * @brief stm32 specific I2C platform ops structure + */ +extern const struct no_os_i2c_platform_ops stm32_i2c_ops; + +#endif // STM32_I2C_H_ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_irq.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_irq.c new file mode 100644 index 0000000..334e1cd --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_irq.c @@ -0,0 +1,701 @@ +/***************************************************************************//** + * @file stm32/stm32_irq.c + * @brief Implementation of external irq driver. + * @author Darius Berghe (darius.berghe@analog.com) +******************************************************************************** + * Copyright 2022(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include +#include +#include "main.h" +#include "no_os_list.h" +#include "no_os_irq.h" +#include "no_os_util.h" +#include "no_os_alloc.h" +#include "stm32_irq.h" +#include "stm32_hal.h" +#include "stm32f7xx_hal.h" +#include "stm32f7xx_hal_uart.h" +#include "stm32f7xx_hal_conf.h" +#include "stm32f7xx_hal_def.h" +#include "stm32f7xx_hal_tim.h" + +struct irq_action { + void *handle; + void (*callback)(void *context); + void *ctx; +}; + +struct event_list { + enum no_os_irq_event event; + uint32_t hal_event; + struct no_os_list_desc *actions; +}; + +static bool initialized = false; + +typedef enum +{ + HAL_UART_TX_HALFCOMPLETE_CB_ID = 0x00U, /*!< UART Tx Half Complete Callback ID */ + HAL_UART_TX_COMPLETE_CB_ID = 0x01U, /*!< UART Tx Complete Callback ID */ + HAL_UART_RX_HALFCOMPLETE_CB_ID = 0x02U, /*!< UART Rx Half Complete Callback ID */ + HAL_UART_RX_COMPLETE_CB_ID = 0x03U, /*!< UART Rx Complete Callback ID */ + HAL_UART_ERROR_CB_ID = 0x04U, /*!< UART Error Callback ID */ + HAL_UART_ABORT_COMPLETE_CB_ID = 0x05U, /*!< UART Abort Complete Callback ID */ + HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID = 0x06U, /*!< UART Abort Transmit Complete Callback ID */ + HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID = 0x07U, /*!< UART Abort Receive Complete Callback ID */ + HAL_UART_WAKEUP_CB_ID = 0x08U, /*!< UART Wakeup Callback ID */ + + HAL_UART_MSPINIT_CB_ID = 0x0BU, /*!< UART MspInit callback ID */ + HAL_UART_MSPDEINIT_CB_ID = 0x0CU /*!< UART MspDeInit callback ID */ + +} HAL_UART_CallbackIDTypeDef; + +typedef enum +{ + HAL_TIM_BASE_MSPINIT_CB_ID = 0x00U /*!< TIM Base MspInit Callback ID */ + , HAL_TIM_BASE_MSPDEINIT_CB_ID = 0x01U /*!< TIM Base MspDeInit Callback ID */ + , HAL_TIM_IC_MSPINIT_CB_ID = 0x02U /*!< TIM IC MspInit Callback ID */ + , HAL_TIM_IC_MSPDEINIT_CB_ID = 0x03U /*!< TIM IC MspDeInit Callback ID */ + , HAL_TIM_OC_MSPINIT_CB_ID = 0x04U /*!< TIM OC MspInit Callback ID */ + , HAL_TIM_OC_MSPDEINIT_CB_ID = 0x05U /*!< TIM OC MspDeInit Callback ID */ + , HAL_TIM_PWM_MSPINIT_CB_ID = 0x06U /*!< TIM PWM MspInit Callback ID */ + , HAL_TIM_PWM_MSPDEINIT_CB_ID = 0x07U /*!< TIM PWM MspDeInit Callback ID */ + , HAL_TIM_ONE_PULSE_MSPINIT_CB_ID = 0x08U /*!< TIM One Pulse MspInit Callback ID */ + , HAL_TIM_ONE_PULSE_MSPDEINIT_CB_ID = 0x09U /*!< TIM One Pulse MspDeInit Callback ID */ + , HAL_TIM_ENCODER_MSPINIT_CB_ID = 0x0AU /*!< TIM Encoder MspInit Callback ID */ + , HAL_TIM_ENCODER_MSPDEINIT_CB_ID = 0x0BU /*!< TIM Encoder MspDeInit Callback ID */ + , HAL_TIM_HALL_SENSOR_MSPINIT_CB_ID = 0x0CU /*!< TIM Hall Sensor MspDeInit Callback ID */ + , HAL_TIM_HALL_SENSOR_MSPDEINIT_CB_ID = 0x0DU /*!< TIM Hall Sensor MspDeInit Callback ID */ + , HAL_TIM_PERIOD_ELAPSED_CB_ID = 0x0EU /*!< TIM Period Elapsed Callback ID */ + , HAL_TIM_PERIOD_ELAPSED_HALF_CB_ID = 0x0FU /*!< TIM Period Elapsed half complete Callback ID */ + , HAL_TIM_TRIGGER_CB_ID = 0x10U /*!< TIM Trigger Callback ID */ + , HAL_TIM_TRIGGER_HALF_CB_ID = 0x11U /*!< TIM Trigger half complete Callback ID */ + , HAL_TIM_IC_CAPTURE_CB_ID = 0x12U /*!< TIM Input Capture Callback ID */ + , HAL_TIM_IC_CAPTURE_HALF_CB_ID = 0x13U /*!< TIM Input Capture half complete Callback ID */ + , HAL_TIM_OC_DELAY_ELAPSED_CB_ID = 0x14U /*!< TIM Output Compare Delay Elapsed Callback ID */ + , HAL_TIM_PWM_PULSE_FINISHED_CB_ID = 0x15U /*!< TIM PWM Pulse Finished Callback ID */ + , HAL_TIM_PWM_PULSE_FINISHED_HALF_CB_ID = 0x16U /*!< TIM PWM Pulse Finished half complete Callback ID */ + , HAL_TIM_ERROR_CB_ID = 0x17U /*!< TIM Error Callback ID */ + , HAL_TIM_COMMUTATION_CB_ID = 0x18U /*!< TIM Commutation Callback ID */ + , HAL_TIM_COMMUTATION_HALF_CB_ID = 0x19U /*!< TIM Commutation half complete Callback ID */ + , HAL_TIM_BREAK_CB_ID = 0x1AU /*!< TIM Break Callback ID */ + , HAL_TIM_BREAK2_CB_ID = 0x1BU /*!< TIM Break2 Callback ID */ +} HAL_TIM_CallbackIDTypeDef; + +static struct event_list _events[] = { + [NO_OS_EVT_GPIO] = {.event = NO_OS_EVT_GPIO, .hal_event = HAL_EXTI_COMMON_CB_ID}, + [NO_OS_EVT_UART_TX_COMPLETE] = {.event = NO_OS_EVT_UART_TX_COMPLETE, .hal_event = HAL_UART_TX_COMPLETE_CB_ID}, + [NO_OS_EVT_UART_RX_COMPLETE] = {.event = NO_OS_EVT_UART_RX_COMPLETE, .hal_event = HAL_UART_RX_COMPLETE_CB_ID}, + [NO_OS_EVT_UART_ERROR] = {.event = NO_OS_EVT_UART_ERROR, .hal_event = HAL_UART_ERROR_CB_ID}, +#ifdef HAL_TIM_MODULE_ENABLED + [NO_OS_EVT_TIM_ELAPSED] = {.event = NO_OS_EVT_TIM_ELAPSED, .hal_event = HAL_TIM_PERIOD_ELAPSED_CB_ID}, + [NO_OS_EVT_TIM_PWM_PULSE_FINISHED] = {.event = NO_OS_EVT_TIM_PWM_PULSE_FINISHED, .hal_event = HAL_TIM_PWM_PULSE_FINISHED_CB_ID}, +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + [NO_OS_EVT_LPTIM_PWM_PULSE_FINISHED] = {.event = NO_OS_EVT_LPTIM_PWM_PULSE_FINISHED, .hal_event = HAL_LPTIM_COMPARE_MATCH_CB_ID}, +#endif +#ifdef HAL_DMA_MODULE_ENABLED + [NO_OS_EVT_DMA_RX_COMPLETE] = {.event = NO_OS_EVT_DMA_RX_COMPLETE, .hal_event = HAL_DMA_XFER_CPLT_CB_ID}, + [NO_OS_EVT_DMA_RX_HALF_COMPLETE] = {.event = NO_OS_EVT_DMA_RX_HALF_COMPLETE, .hal_event = HAL_DMA_XFER_HALFCPLT_CB_ID}, + [NO_OS_EVT_DMA_TX_COMPLETE] = {.event = NO_OS_EVT_DMA_TX_COMPLETE, .hal_event = HAL_DMA_XFER_CPLT_CB_ID}, +#endif +}; + +static int32_t irq_action_cmp(void *data1, void *data2) +{ + return (int32_t)((struct irq_action *)data1)->handle - + (int32_t)((struct irq_action *)data2)->handle; +} + +#ifdef HAL_TIM_MODULE_ENABLED +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + struct event_list *ee = &_events[NO_OS_EVT_TIM_ELAPSED]; + struct irq_action *a; + struct irq_action key = {.handle = htim}; + int ret; + + /* Find & call callback */ + ret = no_os_list_read_find(ee->actions, (void **)&a, &key); + if (ret < 0) + return; + + if (a->callback) + a->callback(a->ctx); +} + +void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) +{ + struct event_list *ee = &_events[NO_OS_EVT_TIM_PWM_PULSE_FINISHED]; + struct irq_action *a; + struct irq_action key = {.handle = htim}; + int ret; + + /* Find & call callback */ + ret = no_os_list_read_find(ee->actions, (void **)&a, &key); + if (ret < 0) + return; + + if (a->callback) + a->callback(a->ctx); +} +#endif + +#ifdef HAL_LPTIM_MODULE_ENABLED +void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim) +{ + struct event_list *ee = &_events[NO_OS_EVT_LPTIM_PWM_PULSE_FINISHED]; + struct irq_action *a; + struct irq_action key = {.handle = hlptim}; + int ret; + + /* Find & call callback */ + ret = no_os_list_read_find(ee->actions, (void **)&a, &key); + if (ret < 0) + return; + + if (a->callback) + a->callback(a->ctx); +} +#endif + +static inline void _common_uart_callback(UART_HandleTypeDef *huart, + uint32_t no_os_event) +{ + struct event_list *ue = &_events[no_os_event]; + struct irq_action *a; + struct irq_action key = {.handle = huart}; + int ret; + ret = no_os_list_read_find(ue->actions, (void **)&a, &key); + if (ret < 0) + return; + + if (a->callback) + a->callback(a->ctx); +} + +#if defined (HAL_SAI_MODULE_ENABLED) +static inline void _common_sai_dma_callback(SAI_HandleTypeDef *hsai, + uint32_t no_os_event) +{ + struct event_list *ue = &_events[no_os_event]; + struct irq_action *a; + struct irq_action key = {.handle = hsai}; + int ret; + ret = no_os_list_read_find(ue->actions, (void **)&a, &key); + if (ret < 0) + return; + + if (a->callback) + a->callback(a->ctx); +} +#endif + +#if defined (HAL_DMA_MODULE_ENABLED) +static inline void _common_dma_callback(DMA_HandleTypeDef *hdma, + uint32_t no_os_event) +{ + struct event_list *ue = &_events[no_os_event]; + struct irq_action *a; + struct irq_action key = {.handle = hdma}; + int ret; + ret = no_os_list_read_find(ue->actions, (void **)&a, &key); + if (ret < 0) + return; + + if (a->callback) + a->callback(a->ctx); +} +#endif + +// equivalent of HAL_UART_TxCpltCallback +void _TxCpltCallback(UART_HandleTypeDef *huart) +{ + _common_uart_callback(huart, NO_OS_EVT_UART_TX_COMPLETE); +} + +// equivalent of HAL_UART_RxCpltCallback +void _RxCpltCallback(UART_HandleTypeDef *huart) +{ + _common_uart_callback(huart, NO_OS_EVT_UART_RX_COMPLETE); +} + +#if defined (HAL_SAI_MODULE_ENABLED) +void _SAIRxCpltCallback(SAI_HandleTypeDef *hsai) +{ + _common_sai_dma_callback(hsai, NO_OS_EVT_DMA_RX_COMPLETE); +} + +void _SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai) +{ + _common_sai_dma_callback(hsai, NO_OS_EVT_DMA_RX_HALF_COMPLETE); +} +#endif + +#if defined (HAL_DMA_MODULE_ENABLED) +void _DMA_RX_CpltCallback(DMA_HandleTypeDef* hdma) +{ + _common_dma_callback(hdma, NO_OS_EVT_DMA_RX_COMPLETE); +} + +void _DMA_TX_CpltCallback(DMA_HandleTypeDef* hdma) +{ + _common_dma_callback(hdma, NO_OS_EVT_DMA_TX_COMPLETE); +} + +void _DMA_HalfCpltCallback(DMA_HandleTypeDef *hdma) +{ + _common_dma_callback(hdma, NO_OS_EVT_DMA_RX_HALF_COMPLETE); +} +#endif + +// equivalent of HAL_UART_ErrorCallback +void _ErrorCallback(UART_HandleTypeDef *huart) +{ + _common_uart_callback(huart, NO_OS_EVT_UART_ERROR); +} + +/** + * @brief Initialized the controller for the STM32 external interrupts + * @param desc - Pointer where the configured instance is stored + * @param param - Configuration information for the instance + * @return 0 in case of success, errno error codes otherwise. + */ +int stm32_irq_ctrl_init(struct no_os_irq_ctrl_desc **desc, + const struct no_os_irq_init_param *param) +{ + static struct no_os_irq_ctrl_desc *descriptor; + if (!param) + return -EINVAL; + + if (!initialized) { + descriptor = no_os_calloc(1, sizeof(*descriptor)); + if (!descriptor) + return -ENOMEM; + } + + // unused, there is only 1 interrupt controller and that is NVIC + descriptor->irq_ctrl_id = param->irq_ctrl_id; + descriptor->extra = param->extra; + + *desc = descriptor; + + return 0; +} + +/** + * @brief Free the resources allocated by irq_ctrl_init() + * @param desc - Interrupt controller descriptor. + * @return 0 in case of success, errno error codes otherwise. + */ +int stm32_irq_ctrl_remove(struct no_os_irq_ctrl_desc *desc) +{ + initialized = false; + + if (desc) + no_os_free(desc); + + return 0; +} + +/** + * @brief Unused. + * @param desc -irq descriptor. + * @param irq_id - The interrupt vector entry id of the peripheral. + * @param level - the trigger condition. + * @return -ENOSYS + */ +int stm32_trigger_level_set(struct no_os_irq_ctrl_desc *desc, + uint32_t irq_id, + enum no_os_irq_trig_level level) +{ + return -ENOSYS; +} + +/** + * @brief Register a callback. + * @param desc - The IRQ controller descriptor. + * @param irq_id - Interrupt identifier. + * @param cb - Descriptor of the callback. + * @return 0 if successfull, negative error code otherwise. + */ +typedef void (*pUART_CallbackTypeDef)(UART_HandleTypeDef *huart); /*!< pointer to an UART callback function */ +typedef void (*pTIM_CallbackTypeDef)(TIM_HandleTypeDef *htim); /*!< pointer to the TIM callback function */ +int stm32_irq_register_callback(struct no_os_irq_ctrl_desc *desc, + uint32_t irq_id, + struct no_os_callback_desc *cb) +{ + int ret; + pUART_CallbackTypeDef pUartCallback; +#ifdef HAL_SAI_MODULE_ENABLED + pSAI_CallbackTypeDef pSaiDmaCallback; +#endif +#ifdef HAL_TIM_MODULE_ENABLED + pTIM_CallbackTypeDef pTimCallback; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + pLPTIM_CallbackTypeDef pLPTimCallback; +#endif + struct irq_action action_key = {.handle = cb->handle}; +#ifdef HAL_DMA_MODULE_ENABLED + DMA_HandleTypeDef pDmaCallback; +#endif + struct irq_action *li; + uint32_t hal_event = _events[cb->event].hal_event; + + switch (cb->peripheral) { + case NO_OS_UART_IRQ: + switch (hal_event) { + case HAL_UART_TX_COMPLETE_CB_ID: + pUartCallback = _TxCpltCallback; + break; + case HAL_UART_RX_COMPLETE_CB_ID: + pUartCallback = _RxCpltCallback; + break; + case HAL_UART_ERROR_CB_ID: + pUartCallback = _ErrorCallback; + break; + default: + return -EINVAL; + }; + + ret = HAL_UART_RegisterCallback(cb->handle, hal_event, pUartCallback); + if (ret != HAL_OK) + return -EFAULT; + + break; +#ifdef HAL_LPTIM_MODULE_ENABLED + case NO_OS_LPTIM_IRQ: + switch (hal_event) { + case HAL_LPTIM_COMPARE_MATCH_CB_ID: + pLPTimCallback = HAL_LPTIM_CompareMatchCallback; + break; + default: + return -EINVAL; + }; + + ret = HAL_LPTIM_RegisterCallback(cb->handle, hal_event, pLPTimCallback); + if (ret != HAL_OK) + return -EFAULT; + break; +#endif +#ifdef HAL_TIM_MODULE_ENABLED + case NO_OS_TIM_IRQ: + switch (hal_event) { + case HAL_TIM_PWM_PULSE_FINISHED_CB_ID: + pTimCallback = HAL_TIM_PWM_PulseFinishedCallback; + break; + case HAL_TIM_PERIOD_ELAPSED_CB_ID: + pTimCallback = HAL_TIM_PeriodElapsedCallback; + break; + default: + return -EINVAL; + }; + + ret = HAL_TIM_RegisterCallback(cb->handle, hal_event, pTimCallback); + if (ret != HAL_OK) + return -EFAULT; + break; +#endif +#if defined(HAL_DMA_MODULE_ENABLED) && defined(HAL_SAI_MODULE_ENABLED) + case NO_OS_TDM_DMA_IRQ: + switch (hal_event) { + case HAL_DMA_XFER_CPLT_CB_ID: + pSaiDmaCallback = _SAIRxCpltCallback; + ret = HAL_SAI_RegisterCallback(cb->handle, hal_event, pSaiDmaCallback); + if (ret != HAL_OK) + return -EFAULT; + + break; + case HAL_DMA_XFER_HALFCPLT_CB_ID: + pSaiDmaCallback = _SAI_RxHalfCpltCallback; + ret = HAL_SAI_RegisterCallback(cb->handle, hal_event, pSaiDmaCallback); + if (ret != HAL_OK) + return -EFAULT; + break; + } + break; +#endif +#if defined (HAL_TIM_MODULE_ENABLED) && defined(HAL_DMA_MODULE_ENABLED) + case NO_OS_TIM_DMA_IRQ: + switch (hal_event) { + case HAL_DMA_XFER_CPLT_CB_ID: + pDmaCallback.XferCpltCallback = _DMA_RX_CpltCallback; + ret = HAL_DMA_RegisterCallback(cb->handle, hal_event, + pDmaCallback.XferCpltCallback); + if (ret != HAL_OK) + return -EFAULT; + break; + case HAL_DMA_XFER_HALFCPLT_CB_ID: + pDmaCallback.XferHalfCpltCallback = _DMA_HalfCpltCallback; + ret = HAL_DMA_RegisterCallback(cb->handle, hal_event, + pDmaCallback.XferHalfCpltCallback); + if (ret != HAL_OK) + return -EFAULT; + break; + default: + return -EINVAL; + }; + break; +#endif +#if defined (HAL_DMA_MODULE_ENABLED) + case NO_OS_DMA_IRQ: + switch (hal_event) { + case HAL_DMA_XFER_CPLT_CB_ID: + if (cb->event == NO_OS_EVT_DMA_RX_COMPLETE) + pDmaCallback.XferCpltCallback = _DMA_RX_CpltCallback; + + else + pDmaCallback.XferCpltCallback = _DMA_TX_CpltCallback; + + ret = HAL_DMA_RegisterCallback((DMA_HandleTypeDef *)cb->handle, hal_event, + pDmaCallback.XferCpltCallback); + if (ret != HAL_OK) + return -EFAULT; + + break; + + default: + return -EINVAL; + }; + + break; +#endif + + default: + return -EINVAL; + } + + if (_events[cb->event].actions == NULL) { + ret = no_os_list_init(&_events[cb->event].actions, NO_OS_LIST_PRIORITY_LIST, + irq_action_cmp); + if (ret < 0) + return ret; + } + /* + * If an action with the same handle as the function parameter does not exists, insert a new one, + * otherwise update + */ + ret = no_os_list_read_find(_events[cb->event].actions, + (void**)&li, + &action_key); + if (ret) { + li = no_os_calloc(1, sizeof(struct irq_action)); + if (!li) + return -ENOMEM; + + li->handle = cb->handle; + li->callback = cb->callback; + li->ctx = cb->ctx; + ret = no_os_list_add_last(_events[cb->event].actions, li); + if (ret < 0) { + no_os_free(li); + return ret; + } + } else { + li->handle = cb->handle; + li->callback = cb->callback; + li->ctx = cb->ctx; + } + + return 0; +} + +/** + * @brief Unregister a callback. + * @param desc - Interrupt controller descriptor. + * @param irq_id - Id of the interrupt + * @param cb - Descriptor of the callback. + * @return 0 if successfull, negative error code otherwise. + */ +int stm32_irq_unregister_callback(struct no_os_irq_ctrl_desc *desc, + uint32_t irq_id, struct no_os_callback_desc *cb) +{ + int ret; + void *discard = NULL; + struct irq_action key; + uint32_t hal_event = _events[cb->event].hal_event; + + switch (cb->peripheral) { + case NO_OS_UART_IRQ: + key.handle = cb->handle; + ret = no_os_list_get_find(_events[cb->event].actions, &discard, &key); + if (ret < 0) + break; + ret = HAL_UART_UnRegisterCallback(cb->handle, hal_event); + if (ret != HAL_OK) + ret = -EFAULT; + break; +#ifdef HAL_TIM_MODULE_ENABLED + case NO_OS_TIM_IRQ: + key.handle = cb->handle; + ret = no_os_list_get_find(_events[cb->event].actions, &discard, &key); + if (ret < 0) + break; + ret = HAL_TIM_UnRegisterCallback(cb->handle, hal_event); + if (ret != HAL_OK) + ret = -EFAULT; + break; +#endif +#if defined(HAL_DMA_MODULE_ENABLED) && defined(HAL_SAI_MODULE_ENABLED) + case NO_OS_TDM_DMA_IRQ: + key.handle = cb->handle; + ret = no_os_list_get_find(_events[cb->event].actions, &discard, &key); + if (ret < 0) + break; + ret = HAL_SAI_UnRegisterCallback(cb->handle, hal_event); + if (ret != HAL_OK) + ret = -EFAULT; + break; +#endif +#if defined (HAL_TIM_MODULE_ENABLED) && defined(HAL_DMA_MODULE_ENABLED) + case NO_OS_TIM_DMA_IRQ: + case NO_OS_DMA_IRQ: + key.handle = cb->handle; + ret = no_os_list_get_find(_events[cb->event].actions, &discard, &key); + if (ret < 0) + break; + ret = HAL_DMA_UnRegisterCallback(cb->handle, hal_event); + if (ret != HAL_OK) + ret = -EFAULT; + break; +#endif + default: + ret = -EINVAL; + break; + } + + if (discard) + no_os_free(discard); + + return ret; +} + +/** + * @brief Enable all interrupts + * @param desc - Interrupt controller descriptor. + * @return 0 + */ +int stm32_irq_global_enable(struct no_os_irq_ctrl_desc *desc) +{ + __enable_irq(); + + return 0; +} + +/** + * @brief Disable all interrupts + * @param desc - Interrupt controller descriptor. + * @return 0 + */ +int stm32_irq_global_disable(struct no_os_irq_ctrl_desc *desc) +{ + __disable_irq(); + + return 0; +} + +/** + * @brief Enable a specific interrupt + * @param desc - Interrupt controller descriptor. + * @param irq_id - Interrupt identifier + * @return 0 in case of success, errno error codes otherwise. + */ +int stm32_irq_enable(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id) +{ + NVIC_EnableIRQ(irq_id); + + return 0; +} + +/** + * @brief Disable a specific interrupt + * @param desc - Interrupt controller descriptor. + * @param irq_id - Interrupt identifier + * @return 0 in case of success, -EINVAL otherwise. + */ +int stm32_irq_disable(struct no_os_irq_ctrl_desc *desc, uint32_t irq_id) +{ + NVIC_DisableIRQ(irq_id); + + return 0; +} + +/** + * @brief Set a priority level for an interrupt + * @param desc - Interrupt controller descriptor. + * @param irq_id - The interrupt vector entry id of the peripheral. + * @param priority_level - The interrupt priority level + * @return 0 + */ +static int stm32_irq_set_priority(struct no_os_irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t priority_level) +{ + HAL_NVIC_SetPriority(irq_id, priority_level, 0); + + return 0; +} + +/** + * @brief Get a priority level for an interrupt + * @param desc - Interrupt controller descriptor. + * @param irq_id - The interrupt vector entry id of the peripheral. + * @param priority_level - The interrupt priority level + * @return 0 + */ +static int stm32_irq_get_priority(struct no_os_irq_ctrl_desc *desc, + uint32_t irq_id, + uint32_t *priority_level) +{ + uint32_t priority_group, sub_priority; + priority_group = HAL_NVIC_GetPriorityGrouping(); + HAL_NVIC_GetPriority(irq_id, priority_group, priority_level, &sub_priority); + + return 0; +} + +/** + * @brief stm32 specific IRQ platform ops structure + */ +const struct no_os_irq_platform_ops stm32_irq_ops = { + .init = &stm32_irq_ctrl_init, + .trigger_level_set = &stm32_trigger_level_set, + .register_callback = &stm32_irq_register_callback, + .unregister_callback = &stm32_irq_unregister_callback, + .global_enable = &stm32_irq_global_enable, + .global_disable = &stm32_irq_global_disable, + .enable = &stm32_irq_enable, + .disable = &stm32_irq_disable, + .set_priority = &stm32_irq_set_priority, + .get_priority = &stm32_irq_get_priority, + .remove = &stm32_irq_ctrl_remove +}; diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_irq.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_irq.h new file mode 100644 index 0000000..5f7045e --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_irq.h @@ -0,0 +1,44 @@ +/***************************************************************************//** + * @file stm32/stm32_irq.h + * @brief Header file for stm32 irq specifics. + * @author Darius Berghe (darius.berghe@analog.com) +******************************************************************************** + * Copyright 2022(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef STM32_IRQ_H +#define STM32_IRQ_H + +#include "no_os_irq.h" +#include "stm32_hal.h" + +/** + * @brief stm32 platform specific irq platform ops structure + */ +extern const struct no_os_irq_platform_ops stm32_irq_ops; + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_pwm.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_pwm.c new file mode 100644 index 0000000..29fd49c --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_pwm.c @@ -0,0 +1,1114 @@ +/***************************************************************************//** + * @file stm32/stm32_pwm.c + * @brief Implementation of stm32 pwm driver. +******************************************************************************** + * Copyright 2023-25(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#include +#include +#include "no_os_util.h" +#include "no_os_gpio.h" +#include "no_os_pwm.h" +#include "stm32_gpio.h" +#include "stm32_pwm.h" +#include "stm32_irq.h" + +/* For 16-bit pwm timer */ +#define PWM_DEFAULT_PERIOD 0xffff +#define NO_OS_CHN_TO_STM32_CHN(x) (0x4*(x-1)) +#define FREQUENCY_HZ_TO_TIME_NS_FACTOR 1000000000.0 + +/** + * @brief Calculate the period in ticks. + * @param get_timer_clock - timer source clock function. + * @param clock_divider - timer clock divider. + * @param prescaler - timer prescaler. + * @param period_ns - timer period. + * @return return period value in ticks. + */ +static uint32_t _compute_period_ticks(uint32_t (*get_timer_clock)(void), + uint32_t clock_divider, + uint32_t prescaler, + uint32_t period_ns) +{ + float pwm_frequency; + uint32_t timer_frequency_hz; + uint32_t period; + + if (get_timer_clock) { + timer_frequency_hz = get_timer_clock(); + timer_frequency_hz *= clock_divider; + timer_frequency_hz /= (prescaler + 1); + + /* Formula for timer period count calculation: + * timer frequency = timer clock / (prescaler + 1) + * pwm frequency = 1 / pwm period (sec) + * timer period count = (timer frequency / pwm frequency) - 1 + * Example: + * Timer clock = 216Mhz, pwm period = 1000ns, prescaler = 1 + * timer frequency = 216 / (0+1) = 216Mhz + * pwm frequency = 1 / 1000ns = 1Mhz + * timer period count = (216 / 1) - 1 = 215 + **/ + /* Timer period is determined based on the timer peripheral frequency */ + pwm_frequency = (1.0 / period_ns); + period = (uint32_t)(timer_frequency_hz / (pwm_frequency * + FREQUENCY_HZ_TO_TIME_NS_FACTOR)) - 1; + } else { + period = PWM_DEFAULT_PERIOD - 1; + } + + return period; +} + +#ifdef HAL_TIM_MODULE_ENABLED +/** + * @brief Initialize the PWM Timer. + * @param desc - STM32 PWM descriptor. + * @param param - The structure containing PWM init parameters. + * @return 0 in case of success, negative error code otherwise. + * @note PWM Timer period is dependent upon the timer clock and prescaler value. + * CounterMode is UP for timer frequency generation in below function. + */ +static int32_t stm32_init_timer(struct stm32_pwm_desc *desc, + const struct no_os_pwm_init_param *param) +{ + int32_t ret; + uint32_t period; + TIM_TypeDef *base = NULL; + struct stm32_pwm_init_param *sparam = param->extra; + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + TIM_SlaveConfigTypeDef sSlaveConfig = {0}; + TIM_HandleTypeDef *htimer; + + /* Compute period ticks */ + period = _compute_period_ticks(sparam->get_timer_clock, sparam->clock_divider, + sparam->prescaler, param->period_ns); + + htimer = (TIM_HandleTypeDef *)sparam->htimer; + + switch (param->id) { +#if defined(TIM1) + case 1: + base = TIM1; + break; +#endif +#if defined(TIM2) + case 2: + base = TIM2; + break; +#endif +#if defined(TIM3) + case 3: + base = TIM3; + break; +#endif + break; +#if defined(TIM4) + case 4: + base = TIM4; + break; +#endif +#if defined(TIM5) + case 5: + base = TIM5; + break; +#endif +#if defined(TIM6) + case 6: + base = TIM6; + break; +#endif +#if defined(TIM7) + case 7: + base = TIM7; + break; +#endif +#if defined(TIM8) + case 8: + base = TIM8; + break; +#endif +#if defined(TIM9) + case 9: + base = TIM9; + break; +#endif +#if defined(TIM10) + case 10: + base = TIM10; + break; +#endif +#if defined(TIM11) + case 11: + base = TIM11; + break; +#endif +#if defined(TIM12) + case 12: + base = TIM12; + break; +#endif + default: + ret = -EINVAL; + goto error; + }; + + htimer->Instance = base; + htimer->Init.Prescaler = sparam->prescaler; + htimer->Init.CounterMode = TIM_COUNTERMODE_UP; + htimer->Init.Period = period; + htimer->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htimer->Init.AutoReloadPreload = sparam->timer_autoreload ? + TIM_AUTORELOAD_PRELOAD_ENABLE : TIM_MASTERSLAVEMODE_DISABLE; + htimer->Init.RepetitionCounter = sparam->repetitions; + htimer->State = HAL_TIM_STATE_RESET; + if (HAL_TIM_Base_Init(htimer) != HAL_OK) + return -EIO; + + if (!sparam->trigger_enable) { + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(htimer, &sClockSourceConfig) != HAL_OK) + return -EIO; + } + if (HAL_TIM_PWM_Init(htimer) != HAL_OK) + return -EIO; + if (sparam->onepulse_enable) + if (HAL_TIM_OnePulse_Init(htimer, TIM_OPMODE_SINGLE) != HAL_OK) + return -EIO; + if (sparam->trigger_enable) { + switch (sparam->trigger_source) { + case PWM_TS_ITR0: + sSlaveConfig.InputTrigger = TIM_TS_ITR0; + break; + case PWM_TS_ITR1: + sSlaveConfig.InputTrigger = TIM_TS_ITR1; + break; + case PWM_TS_ITR2: + sSlaveConfig.InputTrigger = TIM_TS_ITR2; + break; + case PWM_TS_ITR3: + sSlaveConfig.InputTrigger = TIM_TS_ITR3; + break; + default: + return -EINVAL; + } + sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER; + + if (HAL_TIM_SlaveConfigSynchro(htimer, &sSlaveConfig) != HAL_OK) + return -EIO; + } + + switch (sparam->trigger_output) { + case PWM_TRGO_RESET: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + break; + case PWM_TRGO_ENABLE: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_ENABLE; + break; + case PWM_TRGO_UPDATE: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; + break; + case PWM_TRGO_OC1: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1; + break; + case PWM_TRGO_OC1REF: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF; + break; + case PWM_TRGO_OC2REF: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC2REF; + break; + case PWM_TRGO_OC3REF: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC3REF; + break; + case PWM_TRGO_OC4REF: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC4REF; + break; + default: + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + } + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(htimer, + &sMasterConfig) != HAL_OK) + return -EIO; + + /* Store the timer specific configuration for later use.*/ + desc->htimer = htimer; + desc->pwm_timer = STM32_PWM_TIMER_TIM; + desc->prescaler = sparam->prescaler; + desc->get_timer_clock = sparam->get_timer_clock; + desc->clock_divider = sparam->clock_divider; + desc->timer_autoreload = sparam->timer_autoreload; + + if (param->pwm_callback) { + struct no_os_irq_init_param nvic_tim_cplt = { + .platform_ops = &stm32_irq_ops + }; + + ret = no_os_irq_ctrl_init(&desc->nvic_tim, &nvic_tim_cplt); + if (ret < 0) + goto error; + + sparam->timer_callback.callback = param->pwm_callback; + sparam->timer_callback.ctx = desc; + sparam->timer_callback.event = NO_OS_EVT_TIM_PWM_PULSE_FINISHED; + sparam->timer_callback.peripheral = NO_OS_TIM_IRQ; + sparam->timer_callback.handle = &desc->htimer; + + ret = no_os_irq_register_callback(desc->nvic_tim, param->irq_id, + &sparam->timer_callback); + if (ret < 0) + goto error_register; + + ret = no_os_irq_enable(desc->nvic_tim, param->irq_id); + if (ret < 0) + goto error_enable; + } + + return 0; +error_enable: + no_os_irq_unregister_callback(desc->nvic_tim, param->irq_id, + &sparam->timer_callback); +error_register: + no_os_irq_ctrl_remove(desc->nvic_tim); +error: + return ret; +} +#endif + +#ifdef HAL_LPTIM_MODULE_ENABLED +/** + * @brief Initialize the PWM LPTimer. + * @param desc - STM32 PWM descriptor. + * @param param - The structure containing PWM init parameters. + * @return 0 in case of success, negative error code otherwise. + * @note PWM Timer period is dependent upon the timer clock and prescaler value. + * CounterMode is UP for timer frequency generation in below function. + */ +static int32_t stm32_init_lptimer(struct stm32_pwm_desc *desc, + const struct no_os_pwm_init_param *param) +{ + int32_t ret; + uint32_t period; + LPTIM_TypeDef *base = NULL; + struct stm32_pwm_init_param *sparam = param->extra; + LPTIM_HandleTypeDef *hlptimer; + + /* Compute period ticks */ + period = _compute_period_ticks(sparam->get_timer_clock, sparam->clock_divider, + sparam->prescaler, param->period_ns); + hlptimer = (LPTIM_HandleTypeDef *) sparam->htimer; + + switch (param->id) { +#if defined(LPTIM1) + case 1: + base = LPTIM1; + break; +#endif +#if defined(LPTIM2) + case 2: + base = LPTIM2; + break; +#endif +#if defined(LPTIM3) + case 3: + base = LPTIM3; + break; +#endif + break; +#if defined(LPTIM4) + case 4: + base = LPTIM4; + break; +#endif +#if defined(LPTIM5) + case 5: + base = LPTIM5; + break; +#endif +#if defined(LPTIM6) + case 6: + base = LPTIM6; + break; +#endif +#if defined(LPTIM7) + case 7: + base = LPTIM7; + break; +#endif + default: + ret = -EINVAL; + goto error; + }; + + hlptimer->Instance = base; + hlptimer->Init.Period = period; + hlptimer->Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE; + hlptimer->Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL; + hlptimer->Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO; + hlptimer->Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO; + hlptimer->Init.RepetitionCounter = sparam->repetitions; + + hlptimer->Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC; + hlptimer->Init.Clock.Prescaler = sparam->prescaler; + hlptimer->State = HAL_LPTIM_STATE_RESET; + + if (sparam->trigger_enable) { + hlptimer->Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE; + hlptimer->Init.Trigger.ActiveEdge = LPTIM_ACTIVEEDGE_RISING; + hlptimer->Init.Trigger.SampleTime = LPTIM_TRIGSAMPLETIME_DIRECTTRANSITION; + } + + if (sparam->trigger_enable) { + switch (sparam->trigger_source) { + case PWM_TS_ITR0: + hlptimer->Init.Trigger.Source = LPTIM_TRIGSOURCE_0; + break; + case PWM_TS_ITR1: + hlptimer->Init.Trigger.Source = LPTIM_TRIGSOURCE_1; + break; + case PWM_TS_ITR2: + hlptimer->Init.Trigger.Source = LPTIM_TRIGSOURCE_2; + break; + case PWM_TS_ITR3: + hlptimer->Init.Trigger.Source = LPTIM_TRIGSOURCE_3; + break; + default: + return -EINVAL; + } + } + if (HAL_LPTIM_Init(hlptimer) != HAL_OK) + return -EIO; + + /* Store the timer specific configuration for later use.*/ + desc->htimer = hlptimer; + desc->pwm_timer = STM32_PWM_TIMER_LPTIM; + desc->prescaler = sparam->prescaler; + desc->get_timer_clock = sparam->get_timer_clock; + desc->clock_divider = sparam->clock_divider; + desc->timer_autoreload = sparam->timer_autoreload; + + if (param->pwm_callback) { + struct no_os_irq_init_param nvic_tim_cplt = { + .platform_ops = &stm32_irq_ops + }; + + ret = no_os_irq_ctrl_init(&desc->nvic_tim, &nvic_tim_cplt); + if (ret < 0) + goto error; + + sparam->timer_callback.callback = param->pwm_callback; + sparam->timer_callback.ctx = desc; + sparam->timer_callback.event = NO_OS_EVT_LPTIM_PWM_PULSE_FINISHED; + sparam->timer_callback.peripheral = NO_OS_LPTIM_IRQ; + sparam->timer_callback.handle = hlptimer; + + ret = no_os_irq_register_callback(desc->nvic_tim, param->irq_id, + &sparam->timer_callback); + if (ret < 0) + goto error_register; + + ret = no_os_irq_enable(desc->nvic_tim, param->irq_id); + if (ret < 0) + goto error_enable; + } + + return 0; +error_enable: + no_os_irq_unregister_callback(desc->nvic_tim, param->irq_id, + &sparam->timer_callback); +error_register: + no_os_irq_ctrl_remove(desc->nvic_tim); +error: + return ret; +} +#endif + +/** + * @brief Initialize the PWM. + * @param desc - STM32 PWM descriptor. + * @param param - The structure containing PWM init parameters. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t stm32_init_pwm(struct stm32_pwm_desc *desc, + const struct no_os_pwm_init_param *param) +{ + uint32_t pwm_pulse_width; + float duty_cycle_percentage; + uint32_t chn; + struct stm32_pwm_init_param *sparam = param->extra; + uint32_t period; +#ifdef HAL_LPTIM_MODULE_ENABLED + LPTIM_OC_ConfigTypeDef sLpTimerConfigOC = {0}; + LPTIM_HandleTypeDef *hlptimer; +#endif +#ifdef HAL_TIM_MODULE_ENABLED + TIM_OC_InitTypeDef sTimerConfigOC = {0}; + TIM_HandleTypeDef *htimer; +#endif + + switch (sparam->pwm_timer) { +#ifdef HAL_TIM_MODULE_ENABLED + case STM32_PWM_TIMER_TIM: + htimer = (TIM_HandleTypeDef *) sparam->htimer; + period = htimer->Init.Period; + switch (sparam->mode) { + case TIM_OC_TOGGLE: + sTimerConfigOC.OCMode = TIM_OCMODE_TOGGLE; + break; + case TIM_OC_PWM1: + sTimerConfigOC.OCMode = TIM_OCMODE_PWM1; + break; + case TIM_OC_PWM2: + sTimerConfigOC.OCMode = TIM_OCMODE_PWM2; + break; + default: + return -EINVAL; + } + + switch (sparam->timer_chn) { +#if defined(TIM_CHANNEL_1) + case 1: + chn = TIM_CHANNEL_1; + break; +#endif +#if defined(TIM_CHANNEL_2) + case 2: + chn = TIM_CHANNEL_2; + break; +#endif +#if defined(TIM_CHANNEL_3) + case 3: + chn = TIM_CHANNEL_3; + break; +#endif +#if defined(TIM_CHANNEL_4) + case 4: + chn = TIM_CHANNEL_4; + break; +#endif +#if defined(TIM_CHANNEL_5) + case 5: + chn = TIM_CHANNEL_5; + break; +#endif +#if defined(TIM_CHANNEL_6) + case 6: + chn = TIM_CHANNEL_6; + break; +#endif + default: + return -EINVAL; + }; + + /* Calculate the percentage duty cycle */ + duty_cycle_percentage = ((float)param->duty_cycle_ns / param->period_ns) * 100; + pwm_pulse_width = (uint32_t)((period + 1) * duty_cycle_percentage) / (100); + + sTimerConfigOC.Pulse = pwm_pulse_width; + switch (param->polarity) { + case NO_OS_PWM_POLARITY_HIGH: + sTimerConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + break; + case NO_OS_PWM_POLARITY_LOW: + sTimerConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; + break; + default: + return -EINVAL; + }; + + sTimerConfigOC.OCFastMode = TIM_OCFAST_DISABLE; + sTimerConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; + sTimerConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; + if (HAL_TIM_PWM_ConfigChannel(htimer, &sTimerConfigOC, chn) != HAL_OK) + return -EIO; + break; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + case STM32_PWM_TIMER_LPTIM: + hlptimer = (LPTIM_HandleTypeDef *) sparam->htimer; + period = hlptimer->Init.Period; + sparam->complementary_channel = false; + sparam->dma_enable = false; + + switch (sparam->timer_chn) { +#if defined(LPTIM_CHANNEL_1) + case 1: + chn = LPTIM_CHANNEL_1; + break; +#endif +#if defined(LPTIM_CHANNEL_2) + case 2: + chn = LPTIM_CHANNEL_2; + break; +#endif + default: + return -EINVAL; + }; + + /* Calculate the percentage duty cycle */ + duty_cycle_percentage = ((float)param->duty_cycle_ns / param->period_ns) * 100; + pwm_pulse_width = (uint32_t)((period + 1) * duty_cycle_percentage) / (100); + + sLpTimerConfigOC.Pulse = pwm_pulse_width; + switch (param->polarity) { + case NO_OS_PWM_POLARITY_HIGH: + sLpTimerConfigOC.OCPolarity = LPTIM_OCPOLARITY_HIGH; + break; + case NO_OS_PWM_POLARITY_LOW: + sLpTimerConfigOC.OCPolarity = LPTIM_OCPOLARITY_LOW; + break; + default: + return -EINVAL; + }; + + if (HAL_LPTIM_OC_ConfigChannel(hlptimer, &sLpTimerConfigOC, chn) != HAL_OK) + return -EIO; + + break; +#endif + default: + return -EINVAL; + } + + desc->mode = sparam->mode; + desc->timer_chn = sparam->timer_chn; + desc->complementary_channel = sparam->complementary_channel; + desc->dma_enable = sparam->dma_enable; + desc->repetitions = sparam->repetitions; + + return 0; +} + +/** + * @brief Initialize the PWM. + * @param desc - PWM descriptor. + * @param param - The structure containing PWM init parameters. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t stm32_pwm_init(struct no_os_pwm_desc **desc, + const struct no_os_pwm_init_param *param) +{ + struct no_os_pwm_desc *descriptor; + struct stm32_pwm_desc *extra; + struct stm32_pwm_init_param *sparam; + int32_t ret; + + if (!desc || !param) + return -EINVAL; + + descriptor = (struct no_os_pwm_desc *)calloc(1, sizeof(*descriptor)); + if (!descriptor) + return -ENOMEM; + + extra = (struct stm32_pwm_desc *)calloc(1, sizeof(*extra)); + if (!extra) { + ret = -ENOMEM; + goto error_desc; + } + + sparam = (struct stm32_pwm_init_param *)param->extra; + + /* Initialize the PWM timer */ + switch (sparam->pwm_timer) { +#ifdef HAL_TIM_MODULE_ENABLED + case STM32_PWM_TIMER_TIM: + ret = stm32_init_timer(extra, param); + if (ret) + goto error_extra; + break; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + case STM32_PWM_TIMER_LPTIM: + ret = stm32_init_lptimer(extra, param); + if (ret) + goto error_extra; + break; +#endif + default: + return -EINVAL; + } + + /* Initialize the PWM */ + ret = stm32_init_pwm(extra, param); + if (ret) + goto error_extra; + + /* Initialize the GPIO if timer output is required*/ + if (param->pwm_gpio) { + ret = no_os_gpio_get(&descriptor->pwm_gpio, param->pwm_gpio); + if (ret) + goto error_extra; + } + + descriptor->id = param->id; + descriptor->extra = extra; + descriptor->duty_cycle_ns = param->duty_cycle_ns; + descriptor->period_ns = param->period_ns; + descriptor->phase_ns = param->phase_ns; + descriptor->polarity = param->polarity; + descriptor->irq_id = param->irq_id; + *desc = descriptor; + + return 0; +error_extra: + free(extra); +error_desc: + free(descriptor); + + return ret; +} + +/** + * @brief Free the resources allocated by stm32_pwm_init() + * @param desc - PWM descriptor + * @return 0 in case of success, negative error code otherwise. + */ +int32_t stm32_pwm_remove(struct no_os_pwm_desc *desc) +{ + int32_t ret; + struct stm32_pwm_desc *extra; +#ifdef HAL_TIM_MODULE_ENABLED + TIM_HandleTypeDef *htimer; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + LPTIM_HandleTypeDef *hlptimer; +#endif + + if (!desc || !desc->extra) + return -EINVAL; + + extra = desc->extra; + switch (extra->pwm_timer) { +#ifdef HAL_TIM_MODULE_ENABLED + case STM32_PWM_TIMER_TIM: + htimer = (TIM_HandleTypeDef *) extra->htimer; + + if (HAL_TIM_Base_DeInit(htimer) != HAL_OK) + return -EIO; + + if (HAL_TIM_PWM_DeInit(htimer) != HAL_OK) + return -EIO; + break; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + case STM32_PWM_TIMER_LPTIM: + hlptimer = (LPTIM_HandleTypeDef *) extra->htimer; + + if (HAL_LPTIM_DeInit(hlptimer) != HAL_OK) + return -EIO; + break; +#endif + default: + return -EINVAL; + } + + ret = no_os_gpio_remove(extra->gpio); + if (ret) + return ret; + + if (desc->irq_id) { + ret = no_os_irq_unregister_callback(extra->nvic_tim, desc->irq_id, + &extra->timer_callback); + if (ret) + return ret; + + ret = no_os_irq_disable(extra->nvic_tim, desc->irq_id); + if (ret) + return ret; + + ret = no_os_irq_ctrl_remove(extra->nvic_tim); + if (ret) + return ret; + } + + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Enable the PWM + * @param desc - PWM descriptor + * @return 0 in case of success, negative error code otherwise. + */ +int32_t stm32_pwm_enable(struct no_os_pwm_desc *desc) +{ + int32_t ret; + uint32_t chn_num; + struct stm32_pwm_desc *sparam; + +#ifdef HAL_TIM_MODULE_ENABLED + TIM_HandleTypeDef *htimer; + const uint32_t timer_map[] = { + [1] = TIM_DMA_CC1, + [2] = TIM_DMA_CC2, + [3] = TIM_DMA_CC3, + [4] = TIM_DMA_CC4, + }; + +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + LPTIM_HandleTypeDef *hlptimer; + const uint32_t lptimer_map[] = { + [1] = LPTIM_DMA_CC1, + [2] = LPTIM_DMA_CC2, + }; +#endif + + if (!desc) + return -EINVAL; + + sparam = desc->extra; + chn_num = NO_OS_CHN_TO_STM32_CHN(sparam->timer_chn); + + switch (sparam->pwm_timer) { +#ifdef HAL_TIM_MODULE_ENABLED + case STM32_PWM_TIMER_TIM: + htimer = (TIM_HandleTypeDef *) sparam->htimer; + /* set counter to 0 to start from known state */ + __HAL_TIM_SET_COUNTER(htimer, 0); + + if (sparam->dma_enable) { + /*sw trigger to reload repetition counter from repetition register */ + htimer->Instance->RCR = sparam->repetitions; + htimer->Instance->EGR |= (1 << 0); + __HAL_TIM_ENABLE_DMA(htimer, timer_map[sparam->timer_chn]); + } + + if (desc->irq_id) { + if (sparam->complementary_channel) { + ret = HAL_TIMEx_PWMN_Start_IT(htimer, chn_num); + } else { + ret = HAL_TIM_PWM_Start_IT(htimer, chn_num); + } + } else { + if (sparam->complementary_channel) + ret = HAL_TIMEx_PWMN_Start(htimer, chn_num); + else + ret = HAL_TIM_PWM_Start(htimer, chn_num); + } + if (ret != HAL_OK) { + return -EIO; + } + + break; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + case STM32_PWM_TIMER_LPTIM: + hlptimer = (LPTIM_HandleTypeDef *) sparam->htimer; + + /* set counter to 0 to start from known state */ + __HAL_LPTIM_RESET_COUNTER(hlptimer); + + if (sparam->dma_enable) { + /*sw trigger to reload repetition counter from repetition register */ + hlptimer->Instance->RCR = sparam->repetitions; + hlptimer->Instance->CR |= (1 << 3); + __HAL_LPTIM_ENABLE_DMA(hlptimer, lptimer_map[sparam->timer_chn]); + } + + if (desc->irq_id) { + if (sparam->onepulse_enable) + ret = HAL_LPTIM_OnePulse_Start_IT(hlptimer, chn_num); + else + ret = HAL_LPTIM_PWM_Start_IT(hlptimer, chn_num); + } else { + if (sparam->onepulse_enable) + ret = HAL_LPTIM_OnePulse_Start(hlptimer, chn_num); + else + ret = HAL_LPTIM_PWM_Start(hlptimer, chn_num); + } + if (ret != HAL_OK) { + return -EIO; + } + + break; +#endif + default: + return -EINVAL; + } + + return 0; +} + +/** + * @brief Disable the PWM + * @param desc - PWM descriptor + * @return 0 in case of success, negative error otherwise. + */ +int32_t stm32_pwm_disable(struct no_os_pwm_desc *desc) +{ + int32_t ret; + uint32_t chn_num; + struct stm32_pwm_desc *sparam; + +#ifdef HAL_TIM_MODULE_ENABLED + TIM_HandleTypeDef *htimer; + const uint32_t timer_map[] = { + [1] = TIM_DMA_CC1, + [2] = TIM_DMA_CC2, + [3] = TIM_DMA_CC3, + [4] = TIM_DMA_CC4, + }; + +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + LPTIM_HandleTypeDef *hlptimer; + const uint32_t lptimer_map[] = { + [1] = LPTIM_DMA_CC1, + [2] = LPTIM_DMA_CC2, + }; +#endif + + if (!desc) + return -EINVAL; + + sparam = desc->extra; + chn_num = NO_OS_CHN_TO_STM32_CHN(sparam->timer_chn); + + switch (sparam->pwm_timer) { +#ifdef HAL_TIM_MODULE_ENABLED + case STM32_PWM_TIMER_TIM: + htimer = (TIM_HandleTypeDef *) sparam->htimer; + + if (sparam->dma_enable) + __HAL_TIM_DISABLE_DMA(htimer, timer_map[sparam->timer_chn]); + + if (sparam->complementary_channel) + ret = HAL_TIMEx_PWMN_Stop(htimer, chn_num); + else + ret = HAL_TIM_PWM_Stop(htimer, chn_num); + + if (ret != HAL_OK) { + return -EIO; + } + + break; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + case STM32_PWM_TIMER_LPTIM: + hlptimer = (LPTIM_HandleTypeDef *) sparam->htimer; + + if (sparam->dma_enable) + __HAL_LPTIM_DISABLE_DMA(hlptimer, lptimer_map[sparam->timer_chn]); + + if (desc->irq_id) { + if (sparam->onepulse_enable) + ret = HAL_LPTIM_OnePulse_Stop_IT(hlptimer, chn_num); + else + ret = HAL_LPTIM_PWM_Stop_IT(hlptimer, chn_num); + } else { + if (sparam->onepulse_enable) + ret = HAL_LPTIM_OnePulse_Stop(hlptimer, chn_num); + else + ret = HAL_LPTIM_PWM_Stop(hlptimer, chn_num); + } + + if (ret != HAL_OK) { + return -EIO; + } + break; +#endif + default: + return -EINVAL; + } + + return 0; +} + +/** + * @brief Set the PWM period. + * @param desc - Pointer where the configured instance is stored. + * @param period_ns - PWM period. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t stm32_pwm_set_period(struct no_os_pwm_desc *desc, + uint32_t period_ns) +{ + struct stm32_pwm_desc *sdesc; + uint32_t period; + +#ifdef HAL_TIM_MODULE_ENABLED + TIM_HandleTypeDef *htimer; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + LPTIM_HandleTypeDef *hlptimer; +#endif + + if (!desc || !desc->extra) + return -EINVAL; + + sdesc = desc->extra; + /* Compute period ticks */ + period = _compute_period_ticks(sdesc->get_timer_clock, sdesc->clock_divider, + sdesc->prescaler, period_ns); + + switch (sdesc->pwm_timer) { +#ifdef HAL_TIM_MODULE_ENABLED + case STM32_PWM_TIMER_TIM: + htimer = (TIM_HandleTypeDef *) sdesc->htimer; + + htimer->Init.AutoReloadPreload = sdesc->timer_autoreload ? + TIM_AUTORELOAD_PRELOAD_ENABLE : TIM_MASTERSLAVEMODE_DISABLE; + htimer->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htimer->Init.CounterMode = TIM_COUNTERMODE_UP; + htimer->Init.Prescaler = sdesc->prescaler; + htimer->Init.Period = period; + htimer->Init.RepetitionCounter = sdesc->repetitions; + + TIM_Base_SetConfig(htimer->Instance, &htimer->Init); + break; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + case STM32_PWM_TIMER_LPTIM: + hlptimer = (LPTIM_HandleTypeDef *) sdesc->htimer; + hlptimer->Init.Period = period; + + /* Change the LPTIM state */ + hlptimer->State = HAL_LPTIM_STATE_READY; + if (HAL_LPTIM_Init(hlptimer) != HAL_OK) + return -EIO; + break; +#endif + default: + return -EINVAL; + } + + desc->period_ns = period_ns; + + return 0; +} + +/** + * @brief Get the PWM period. + * @param desc - Pointer where the configured instance is stored. + * @param period_ns - PWM period. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t stm32_pwm_get_period(struct no_os_pwm_desc *desc, + uint32_t *period_ns) +{ + uint32_t timer_hz; + uint32_t period; + + if (!desc || !desc->extra || !period_ns) + return -EINVAL; + + struct stm32_pwm_desc *sparam = desc->extra; + + timer_hz = sparam->get_timer_clock() * sparam->clock_divider; + timer_hz /= (sparam->prescaler + 1); + + switch (sparam->pwm_timer) { +#ifdef HAL_TIM_MODULE_ENABLED + case STM32_PWM_TIMER_TIM: + period = ((TIM_HandleTypeDef *)sparam->htimer)->Init.Period; + *period_ns = (uint32_t)((period + 1) * + (FREQUENCY_HZ_TO_TIME_NS_FACTOR / timer_hz)); + break; +#endif +#ifdef HAL_LPTIM_MODULE_ENABLED + case STM32_PWM_TIMER_LPTIM: + period = ((LPTIM_HandleTypeDef *)sparam->htimer)->Init.Period; + *period_ns = (uint32_t)((period + 1) * + (FREQUENCY_HZ_TO_TIME_NS_FACTOR / timer_hz)); + break; +#endif + default: + return -EINVAL; + } + + return 0; +} + +/** + * @brief Set the PWM duty cycle. + * @param desc - Pointer where the configured instance is stored. + * @param duty_cycle_ns - PWM duty cycle. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t stm32_pwm_set_duty_cycle(struct no_os_pwm_desc *desc, + uint32_t duty_cycle_ns) +{ + int32_t ret; + struct no_os_pwm_init_param param = {0}; + struct stm32_pwm_init_param sparam = {0}; + + if (!desc || !desc->extra) + return -EINVAL; + + param.duty_cycle_ns = duty_cycle_ns; + param.period_ns = desc->period_ns; + param.phase_ns = desc->phase_ns; + sparam.htimer = ((struct stm32_pwm_desc *)desc->extra)->htimer; + sparam.pwm_timer = ((struct stm32_pwm_desc *)desc->extra)->pwm_timer; + sparam.mode = ((struct stm32_pwm_desc *)desc->extra)->mode; + sparam.timer_chn = ((struct stm32_pwm_desc *)desc->extra)->timer_chn; + sparam.complementary_channel = ((struct stm32_pwm_desc*) + desc->extra)->complementary_channel; + param.extra = &sparam; + + ret = stm32_init_pwm(desc->extra, ¶m); + if (ret != HAL_OK) + return -EIO; + + desc->duty_cycle_ns = param.duty_cycle_ns; + + return 0; +} + +/** + * @brief Get the PWM duty cycle. + * @param desc - Pointer where the configured instance is stored. + * @param duty_cycle_ns - PWM duty cycle. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t stm32_pwm_get_duty_cycle(struct no_os_pwm_desc *desc, + uint32_t *duty_cycle_ns) +{ + *duty_cycle_ns = desc->duty_cycle_ns; + + return 0; +} + +/** +* @brief STM32 platform specific PWM platform ops structure +*/ +const struct no_os_pwm_platform_ops stm32_pwm_ops = { + .pwm_ops_init = &stm32_pwm_init, + .pwm_ops_enable = &stm32_pwm_enable, + .pwm_ops_disable = &stm32_pwm_disable, + .pwm_ops_set_period = &stm32_pwm_set_period, + .pwm_ops_get_period = &stm32_pwm_get_period, + .pwm_ops_set_duty_cycle = &stm32_pwm_set_duty_cycle, + .pwm_ops_get_duty_cycle = &stm32_pwm_get_duty_cycle, + .pwm_ops_remove = &stm32_pwm_remove +}; diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_pwm.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_pwm.h new file mode 100644 index 0000000..b80092c --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_pwm.h @@ -0,0 +1,151 @@ +/***************************************************************************//** + * @file stm32/stm32_pwm.h + * @brief Header file for stm32 pwm specifics. +******************************************************************************** + * Copyright 2023(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef STM32_PWM_H_ +#define STM32_PWM_H_ + +#include +#include +#include "no_os_gpio.h" +#include "no_os_irq.h" +#include "stm32_gpio.h" +#include "stm32_hal.h" + +enum stm32_pwm_timer { + STM32_PWM_TIMER_TIM = 0, + STM32_PWM_TIMER_LPTIM = 1, +}; + +enum TimOCMode { + TIM_OC_TOGGLE = 0, + TIM_OC_PWM1 = 1, + TIM_OC_PWM2 = 2, +}; + +enum stm32_pwm_trigger { + PWM_TS_ITR0, + PWM_TS_ITR1, + PWM_TS_ITR2, + PWM_TS_ITR3, +}; + +enum stm32_pwm_trigger_out { + PWM_TRGO_RESET, + PWM_TRGO_ENABLE, + PWM_TRGO_UPDATE, + PWM_TRGO_OC1, + PWM_TRGO_OC1REF, + PWM_TRGO_OC2REF, + PWM_TRGO_OC3REF, + PWM_TRGO_OC4REF, +}; +/** + * @struct stm32_pwm_init_param + * @brief Structure holding the STM32 PWM parameters. + */ +struct stm32_pwm_init_param { + /** PWM Timer Handle */ + void *htimer; + /** Type of timer used for PWM */ + enum stm32_pwm_timer pwm_timer; + /** Timer prescaler (0 to 0xFFFF) */ + uint32_t prescaler; + /** Timer autoreload enable */ + bool timer_autoreload; + /** Timer output compare Mode */ + enum TimOCMode mode; + /** PWM timer channel */ + uint32_t timer_chn; + /** Complementary channel */ + bool complementary_channel; + /** Get timer source clock function */ + uint32_t (*get_timer_clock)(void); + /** Get timer source clock divider */ + uint32_t clock_divider; + /** Enable trigger source */ + bool trigger_enable; + /** Trigger source selection */ + enum stm32_pwm_trigger trigger_source; + /** Trigger out selection */ + enum stm32_pwm_trigger_out trigger_output; + /* Enable one pulse */ + bool onepulse_enable; + /* Number of pulse repetitions */ + uint32_t repetitions; + /* Enable dma */ + bool dma_enable; + /** Timer callback */ + struct no_os_callback_desc timer_callback; +}; + +/** + * @struct stm32_pwm_desc + * @brief Structure holding the STM32 PWM descriptor. + */ +struct stm32_pwm_desc { + /** PWM Timer Handle */ + void *htimer; + /** Type of timer used for PWM */ + enum stm32_pwm_timer pwm_timer; + /** Timer GPIO instance */ + struct no_os_gpio_desc *gpio; + /** Timer prescaler */ + uint32_t prescaler; + /** Timer autoreload enable */ + bool timer_autoreload; + /** Timer output compare Mode */ + enum TimOCMode mode; + /** PWM timer channel */ + uint32_t timer_chn; + /** Complementary channel */ + bool complementary_channel; + /** Get timer source clock function */ + uint32_t (*get_timer_clock)(void); + /** Get timer source clock divider */ + uint32_t clock_divider; + /** Interrupt controller descriptor */ + struct no_os_irq_ctrl_desc *nvic_tim; + /** Timer callback */ + struct no_os_callback_desc timer_callback; + /* Number of pulse repetitions */ + uint32_t repetitions; + /* Enable dma */ + bool dma_enable; + /* Enable one pulse */ + bool onepulse_enable; +}; + +/** + * @brief STM32 specific PWM platform ops structure + */ +extern const struct no_os_pwm_platform_ops stm32_pwm_ops; + +#endif // STM32_PWM_H_ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_spi.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_spi.c new file mode 100644 index 0000000..57c0acf --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_spi.c @@ -0,0 +1,53 @@ +#include "stm32_spi.h" +#include "no_os_error.h" +#include + +int32_t stm32_spi_init(struct no_os_spi_desc **desc, + const struct no_os_spi_init_param *param) +{ + if (!desc || !param) + return -EINVAL; + + *desc = calloc(1, sizeof(**desc)); + if (!*desc) + return -ENOMEM; + + /* store platform handle (HAL SPI_HandleTypeDef*) in extra */ + (*desc)->extra = param->extra; + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->mode = param->mode; + + return 0; +} + +int32_t stm32_spi_write_and_read(struct no_os_spi_desc *desc, + uint8_t *data, + uint32_t bytes_number) +{ + if (!desc || !data || bytes_number == 0) + return -EINVAL; + + SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)desc->extra; + if (!hspi) + return -EINVAL; + + if (HAL_SPI_TransmitReceive(hspi, data, data, bytes_number, 200) != HAL_OK) + return -EIO; + + return 0; +} + +int32_t stm32_spi_remove(struct no_os_spi_desc *desc) +{ + if (!desc) + return -EINVAL; + free(desc); + return 0; +} + +/* platform ops struct */ +const struct no_os_spi_platform_ops stm32_spi_ops = { + .init = &stm32_spi_init, + .write_and_read = &stm32_spi_write_and_read, + .remove = &stm32_spi_remove, +}; diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_spi.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_spi.h new file mode 100644 index 0000000..7a85977 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_spi.h @@ -0,0 +1,9 @@ +#ifndef _STM32_SPI_H_ +#define _STM32_SPI_H_ + +#include "no_os_spi.h" +#include "stm32f7xx_hal.h" + +extern const struct no_os_spi_platform_ops stm32_spi_ops; + +#endif /* _STM32_SPI_H_ */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_timer.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_timer.c new file mode 100644 index 0000000..c6c497f --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_timer.c @@ -0,0 +1,352 @@ +/***************************************************************************//** + * @file stm32/stm32_timer.c + * @brief Implementation of stm32 timer driver. + * @author RBolboac (ramona.bolboaca@analog.com) +******************************************************************************** + * Copyright 2022(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#include +#include +#include "no_os_util.h" +#include "no_os_timer.h" +#include "no_os_alloc.h" +#include "stm32_timer.h" + + +static int get_timer_base(uint32_t device_id, TIM_TypeDef **base, + uint32_t *clk_freq) +{ + uint32_t apb2_freq = HAL_RCC_GetPCLK2Freq(); + *clk_freq = HAL_RCC_GetPCLK1Freq(); + + switch (device_id) { +#if defined(TIM1) + case 1: + *base = TIM1; + *clk_freq = apb2_freq; + break; +#endif +#if defined(TIM2) + case 2: + *base = TIM2; + break; +#endif +#if defined(TIM3) + case 3: + *base = TIM3; + break; +#endif + break; +#if defined(TIM4) + case 4: + *base = TIM4; + break; +#endif +#if defined(TIM5) + case 5: + *base = TIM5; + break; +#endif +#if defined(TIM6) + case 6: + *base = TIM6; + break; +#endif +#if defined(TIM7) + case 7: + *base = TIM7; + break; +#endif +#if defined(TIM8) + case 8: + *base = TIM8; + *clk_freq = apb2_freq; + break; +#endif +#if defined(TIM9) + case 9: + *base = TIM9; + break; +#endif +#if defined(TIM10) + case 10: + *base = TIM10; + break; +#endif +#if defined(TIM11) + case 11: + *base = TIM11; + break; +#endif +#if defined(TIM12) + case 12: + *base = TIM12; + break; +#endif +#if defined(TIM13) + case 13: + *base = TIM13; + break; +#endif +#if defined(TIM14) + case 14: + *base = TIM14; + break; +#endif + default: + return -EINVAL; + }; + + return 0; +} + +/** + * @brief Initialize the timer peripheral. + * @param desc - The timer descriptor. + * @param param - The structure that contains the timer parameters. + * @return ret - Result of the init procedure. + */ +int32_t stm32_timer_init(struct no_os_timer_desc **desc, + const struct no_os_timer_init_param *param) +{ + int32_t ret; + struct no_os_timer_desc *no_os_desc; + struct stm32_timer_desc *stm_desc; + uint32_t src_freq; + TIM_TypeDef *base = NULL; + + if (!desc || !param) + return -EINVAL; + + no_os_desc = (struct no_os_timer_desc *)no_os_calloc(1, sizeof(*no_os_desc)); + if (!no_os_desc) + return -ENOMEM; + + stm_desc = param->extra; + + ret = get_timer_base(param->id, &base, &src_freq); + if (ret) + goto error; + /* Make sure the same id is used as the selected instance */ + if (base != stm_desc->htimer->Instance) { + ret = -EINVAL; + goto error; + } + + /* Make sure the selected frequency is in range */ + if (src_freq < param->freq_hz) { + ret = -EINVAL; + goto error; + } + + /* Overwrite generated values with given values */ + stm_desc->htimer->Init.Prescaler = src_freq / param->freq_hz; + stm_desc->htimer->Init.Period = param->ticks_count; + + ret = HAL_TIM_Base_Init(stm_desc->htimer); + if (ret != HAL_OK) { + ret = -EIO; + goto error; + } + + /* Copy settings to device descriptor */ + no_os_desc->extra = stm_desc->htimer; + no_os_desc->id = param->id; + no_os_desc->freq_hz = param->freq_hz; + no_os_desc->ticks_count = param->ticks_count; + *desc = no_os_desc; + + return 0; + +error: + no_os_free(no_os_desc); + return ret; +} + +/** + * @brief Free the resources allocated by no_os_timer_init(). + * @param desc - The timer descriptor. + * + * @return ret - Result of the remove procedure. + */ +int32_t stm32_timer_remove(struct no_os_timer_desc *desc) +{ + if (!desc) + return -EINVAL; + + if (!HAL_TIM_Base_DeInit(desc->extra)) { + no_os_free(desc); + return 0; + } + + return -1; +} + +/** + * @brief Start a timer. + * @param desc - Pointer to the device handler. + * + * @return ret - Result of the start procedure. + */ +int32_t stm32_timer_start(struct no_os_timer_desc *desc) +{ + if (!desc) + return -EINVAL; + + if (!HAL_TIM_Base_Start_IT((TIM_HandleTypeDef*)desc->extra)) + return 0; + + return -1; +} + +/** + * @brief Stop a timer from counting. + * @param desc - Pointer to the device handler. + * + * @return ret - Result of the stop procedure. + */ +int32_t stm32_timer_stop(struct no_os_timer_desc *desc) +{ + if (!desc) + return -EINVAL; + + if (!HAL_TIM_Base_Stop_IT((TIM_HandleTypeDef*)desc->extra)) + return 0; + + return -1; +} + +/** + * @brief Get the value of the counter register for the timer. + * @param [in] desc - Pointer to the device handler. + * @param [out] counter - Pointer to the counter value. + * @return 0 in case of success, error code otherwise. + */ +int32_t stm32_timer_counter_get(struct no_os_timer_desc *desc, + uint32_t *counter) +{ + if (!desc && !counter) + return -EINVAL; + + *counter = __HAL_TIM_GetCounter((TIM_HandleTypeDef*)desc->extra); + return 0; +} + +/** + * @brief Set the timer counter register value. + * @param [in] desc - Pointer to the device handler. + * @param [in] new_val - The new value of the counter register. + * @return 0 in case of success, error code otherwise. + */ +int32_t stm32_timer_counter_set(struct no_os_timer_desc *desc, uint32_t new_val) +{ + if (!desc || (new_val > desc->ticks_count)) + return -EINVAL; + + __HAL_TIM_SetCounter((TIM_HandleTypeDef*)desc->extra, new_val); + return 0; +} + +/** + * @brief Get the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [out] freq_hz - The value in Hz of the timer clock. + * @return 0 in case of success, error code otherwise. + */ +int32_t stm32_timer_count_clk_get(struct no_os_timer_desc *desc, + uint32_t *freq_hz) +{ + if (!desc || !freq_hz) + return -EINVAL; + + *freq_hz = desc->freq_hz; + return 0; +} + +/** + * @brief Set the timer clock frequency. + * @param [in] desc - Pointer to the device handler. + * @param [in] freq_hz - The value in Hz of the new timer clock. + * @return 0 in case of success, error code otherwise. + */ +int32_t stm32_timer_count_clk_set(struct no_os_timer_desc *desc, + uint32_t freq_hz) +{ + int ret; + uint32_t src_freq; + TIM_TypeDef *base = NULL; + TIM_HandleTypeDef* tim_desc; + + if (!desc) + return -EINVAL; + + ret = get_timer_base(desc->id, &base, &src_freq); + if (ret) + return -EINVAL; + + if (src_freq < freq_hz) + return -EINVAL; + + tim_desc = desc->extra; + + __HAL_TIM_SET_PRESCALER(tim_desc, src_freq / freq_hz); + tim_desc->Init.Prescaler = src_freq / freq_hz; + + desc->freq_hz = freq_hz; + + return 0; +} + +/** + * @brief Get the elapsed time in nsec for the timer. + * @param [in] desc - Pointer to the device handler. + * @param [in] elapsed_time - The elapsed time in nsec. + * @return 0 in case of success, error code otherwise. + */ +int32_t stm32_timer_get_elapsed_time_nsec(struct no_os_timer_desc *desc, + uint64_t *elapsed_time) +{ + /* Function not implemented because it is not needed at the moment */ + return -ENOSYS; +} + +/** + * @brief stm32 platform specific timer platform ops structure + */ +const struct no_os_timer_platform_ops stm32_timer_ops = { + .init = &stm32_timer_init, + .start = &stm32_timer_start, + .stop = &stm32_timer_stop, + .counter_get = &stm32_timer_counter_get, + .counter_set = &stm32_timer_counter_set, + .count_clk_get = &stm32_timer_count_clk_get, + .count_clk_set = &stm32_timer_count_clk_set, + .get_elapsed_time_nsec = &stm32_timer_get_elapsed_time_nsec, + .remove = &stm32_timer_remove +}; + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_timer.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_timer.h new file mode 100644 index 0000000..f3ae547 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_timer.h @@ -0,0 +1,63 @@ +/***************************************************************************//** + * @file stm32/stm32_timer.h + * @brief Header file for the stm32 timer driver. + * @author RBolboac (ramona.bolboaca@analog.com) +******************************************************************************** + * Copyright 2022(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef STM32_TIMER_H_ +#define STM32_TIMER_H_ + +#include +#include "no_os_timer.h" +#include "stm32_hal.h" + +/** + * @struct stm32_timer_init_param + * @brief Structure holding the initialization parameters for stm32 platform + * specific timer parameters. + */ +struct stm32_timer_init_param { + TIM_HandleTypeDef *htimer; +}; + +/** + * @struct stm32_timer_desc + * @brief stm32 platform specific timer descriptor + */ +struct stm32_timer_desc { + /** timer instance */ + TIM_HandleTypeDef *htimer; +}; + +/** + * @brief stm32 specific timer platform ops structure + */ +extern const struct no_os_timer_platform_ops stm32_timer_ops; + +#endif // STM32_TIMER_H_ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_uart.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_uart.c new file mode 100644 index 0000000..4eb9d12 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_uart.c @@ -0,0 +1,302 @@ +/***************************************************************************//** + * @file stm32/stm32_uart.c + * @brief Source file of UART driver for STM32 + * @author Darius Berghe (darius.berghe@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#include +#include +#include "no_os_uart.h" +#include "no_os_irq.h" +#include "no_os_lf256fifo.h" +#include "no_os_alloc.h" +#include "stm32_irq.h" +#include "stm32_uart.h" +#include "stm32_hal.h" + +static uint8_t c; + +void uart_rx_callback(void *context) +{ + struct no_os_uart_desc *d = context; + lf256fifo_write(d->rx_fifo, c); + HAL_UART_Receive_IT(((struct stm32_uart_desc *)d->extra)->huart, &c, 1); +} + +/** + * @brief Initialize the UART communication peripheral. + * @param desc - The UART descriptor. + * @param param - The structure that contains the UART parameters. + * @return 0 in case of success, error code otherwise. + */ +static int32_t stm32_uart_init(struct no_os_uart_desc **desc, + struct no_os_uart_init_param *param) +{ + struct stm32_uart_init_param *suip; + struct stm32_uart_desc *sud; + struct no_os_uart_desc *descriptor; + int ret; + + if (!desc || !param) + return -EINVAL; + + descriptor = (struct no_os_uart_desc *) no_os_calloc(1, sizeof(*descriptor)); + if (!descriptor) + return -ENOMEM; + + sud = (struct stm32_uart_desc *) no_os_calloc(1, + sizeof(struct stm32_uart_desc)); + if (!sud) { + ret = -ENOMEM; + goto error; + } + + descriptor->irq_id = param->irq_id; + descriptor->extra = sud; + suip = param->extra; + + sud->huart = suip->huart; + sud->huart->Init.BaudRate = param->baud_rate; + switch (param->size) { + case NO_OS_UART_CS_8: + sud->huart->Init.WordLength = UART_WORDLENGTH_8B; + break; + case NO_OS_UART_CS_9: + sud->huart->Init.WordLength = UART_WORDLENGTH_9B; + break; + default: + ret = -EINVAL; + goto error; + }; + switch (param->parity) { + case NO_OS_UART_PAR_NO: + sud->huart->Init.Parity = UART_PARITY_NONE; + break; + case NO_OS_UART_PAR_ODD: + sud->huart->Init.Parity = UART_PARITY_ODD; + break; + case NO_OS_UART_PAR_EVEN: + sud->huart->Init.Parity = UART_PARITY_EVEN; + break; + default: + ret = -EINVAL; + goto error; + }; + sud->huart->Init.StopBits = param->stop == NO_OS_UART_STOP_1_BIT ? + UART_STOPBITS_1 : + UART_STOPBITS_2; + sud->huart->Init.Mode = suip->huart->Init.Mode; + sud->huart->Init.HwFlowCtl = suip->huart->Init.HwFlowCtl; + sud->huart->Init.OverSampling = suip->huart->Init.OverSampling; + ret = HAL_UART_Init(sud->huart); + if (ret != HAL_OK) { + ret = -EIO; + goto error; + } + + sud->timeout = suip->timeout ? suip->timeout : HAL_MAX_DELAY; + + // nonblocking uart_read + if (param->asynchronous_rx) { + ret = lf256fifo_init(&descriptor->rx_fifo); + if (ret < 0) + goto error; + + struct no_os_irq_init_param nvic_ip = { + .platform_ops = &stm32_irq_ops, + .extra = sud->huart, + }; + ret = no_os_irq_ctrl_init(&sud->nvic, &nvic_ip); + if (ret < 0) + goto error; + + sud->rx_callback.callback = uart_rx_callback; + sud->rx_callback.ctx = descriptor; + sud->rx_callback.event = NO_OS_EVT_UART_RX_COMPLETE; + sud->rx_callback.peripheral = NO_OS_UART_IRQ; + sud->rx_callback.handle = sud->huart; + + ret = no_os_irq_register_callback(sud->nvic, descriptor->irq_id, + &sud->rx_callback); + if (ret < 0) + goto error_nvic; + + ret = no_os_irq_enable(sud->nvic, descriptor->irq_id); + if (ret < 0) + goto error_register; + + HAL_UART_Receive_IT(sud->huart, (uint8_t *)&c, 1); + if (ret != HAL_OK) { + ret = -EIO; + goto error_enable; + } + } + + descriptor->device_id = param->device_id; + descriptor->baud_rate = param->baud_rate; + + *desc = descriptor; + + return 0; +error_enable: + no_os_irq_disable(sud->nvic, descriptor->irq_id); +error_register: + no_os_irq_unregister_callback(sud->nvic, descriptor->irq_id, &sud->rx_callback); +error_nvic: + no_os_irq_ctrl_remove(sud->nvic); +error: + no_os_free(descriptor); + no_os_free(sud); + + return ret; +} + +/** + * @brief Free the resources allocated by stm32_uart_init(). + * @param desc - The UART descriptor. + * @return 0 in case of success, -1 otherwise. + */ +static int32_t stm32_uart_remove(struct no_os_uart_desc *desc) +{ + struct stm32_uart_desc *sud; + + if (!desc) + return -EINVAL; + + sud = desc->extra; + HAL_UART_DeInit(sud->huart); + if (desc->rx_fifo) { + no_os_irq_disable(sud->nvic, desc->irq_id); + lf256fifo_remove(desc->rx_fifo); + desc->rx_fifo = NULL; + no_os_irq_unregister_callback(sud->nvic, desc->irq_id, &sud->rx_callback); + no_os_irq_ctrl_remove(sud->nvic); + } + no_os_free(desc->extra); + no_os_free(desc); + + return 0; +}; + +/** + * @brief Write data to UART device. + * @param desc - Instance of UART. + * @param data - Pointer to buffer containing data. + * @param bytes_number - Number of bytes to read. + * @return 0 in case of success, -1 otherwise. + */ +static int32_t stm32_uart_write(struct no_os_uart_desc *desc, + const uint8_t *data, + uint32_t bytes_number) +{ + struct stm32_uart_desc *sud; + int32_t ret; + + if (!desc || !desc->extra || !data) + return -EINVAL; + + if (!bytes_number) + return 0; + + sud = desc->extra; + ret = HAL_UART_Transmit(sud->huart, (uint8_t *)data, bytes_number, + sud->timeout); + + switch (ret) { + case HAL_OK: + break; + case HAL_BUSY: + return -EBUSY; + case HAL_TIMEOUT: + return -ETIMEDOUT; + default: + return -EIO; + }; + + return bytes_number; +} + +/** + * @brief Read data from UART device. + * @param desc - Instance of UART. + * @param data - Pointer to buffer containing data. + * @param bytes_number - Number of bytes to read. + * @return positive number of received bytes in case of success, negative error code otherwise. + */ +static int32_t stm32_uart_read(struct no_os_uart_desc *desc, uint8_t *data, + uint32_t bytes_number) +{ + struct stm32_uart_desc *sud; + uint32_t i = 0; + int32_t ret; + + if (!desc || !desc->extra || !data) + return -EINVAL; + + if (!bytes_number) + return 0; + + sud = desc->extra; + + if (desc->rx_fifo) { + while (i < bytes_number) { + ret = lf256fifo_read(desc->rx_fifo, &data[i]); + if (ret < 0) + return i ? i : -EAGAIN; + i++; + } + return i; + } else { + ret = HAL_UART_Receive(sud->huart, (uint8_t *)data, bytes_number, + sud->timeout); + + switch (ret) { + case HAL_OK: + break; + case HAL_BUSY: + return -EBUSY; + case HAL_TIMEOUT: + return -ETIMEDOUT; + default: + return -EIO; + }; + } + + return bytes_number; +} + +/** + * @brief STM32 platform specific UART platform ops structure + */ +const struct no_os_uart_platform_ops stm32_uart_ops = { + .init = &stm32_uart_init, + .read = &stm32_uart_read, + .write = &stm32_uart_write, + .remove = &stm32_uart_remove +}; diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_uart.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_uart.h new file mode 100644 index 0000000..721d7f0 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32_uart.h @@ -0,0 +1,73 @@ +/***************************************************************************//** + * @file stm32/stm32_uart.h + * @brief Header file of UART driver for STM32 + * @author Darius Berghe (darius.berghe@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef _STM32_UART_H_ +#define _STM32_UART_H_ + +#include +#include +#include "no_os_uart.h" +#include "no_os_irq.h" +#include "stm32_hal.h" + +/** + * @struct stm32_uart_init_param + * @brief Specific initialization parameters for stm32 UART. + */ +struct stm32_uart_init_param { + /** UART instance */ + UART_HandleTypeDef *huart; + /** UART transaction timeout (HAL_IncTick() units) */ + uint32_t timeout; +}; + +/** + * @struct stm32_uart_desc + * @brief stm32 platform specific UART descriptor + */ +struct stm32_uart_desc { + /** UART instance */ + UART_HandleTypeDef *huart; + /** UART transaction timeout (HAL_IncTick() units) */ + uint32_t timeout; + /** Interrupt controller descriptor */ + struct no_os_irq_ctrl_desc *nvic; + /** RX complete callback */ + struct no_os_callback_desc rx_callback; +}; + +/** + * @brief STM32 specific UART platform ops structure + */ +extern const struct no_os_uart_platform_ops stm32_uart_ops; + +#endif diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_hal_conf.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_hal_conf.h new file mode 100644 index 0000000..073942b --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_hal_conf.h @@ -0,0 +1,484 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f7xx_hal_conf_template.h + * @author MCD Application Team + * @brief HAL configuration template file. + * This file should be copied to the application folder and renamed + * to stm32f7xx_hal_conf.h. + ****************************************************************************** + * @attention + * + * Copyright (c) 2017 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F7xx_HAL_CONF_H +#define __STM32F7xx_HAL_CONF_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* ########################## Module Selection ############################## */ +/** + * @brief This is the list of modules to be used in the HAL driver + */ +#define HAL_MODULE_ENABLED + + /* #define HAL_CRYP_MODULE_ENABLED */ +/* #define HAL_ADC_MODULE_ENABLED */ +/* #define HAL_CAN_MODULE_ENABLED */ +/* #define HAL_CEC_MODULE_ENABLED */ +/* #define HAL_CRC_MODULE_ENABLED */ +/* #define HAL_DAC_MODULE_ENABLED */ +/* #define HAL_DCMI_MODULE_ENABLED */ +/* #define HAL_DMA2D_MODULE_ENABLED */ +/* #define HAL_ETH_MODULE_ENABLED */ +/* #define HAL_ETH_LEGACY_MODULE_ENABLED */ +/* #define HAL_NAND_MODULE_ENABLED */ +/* #define HAL_NOR_MODULE_ENABLED */ +/* #define HAL_SRAM_MODULE_ENABLED */ +/* #define HAL_SDRAM_MODULE_ENABLED */ +/* #define HAL_HASH_MODULE_ENABLED */ +/* #define HAL_I2S_MODULE_ENABLED */ +/* #define HAL_IWDG_MODULE_ENABLED */ +/* #define HAL_LPTIM_MODULE_ENABLED */ +/* #define HAL_LTDC_MODULE_ENABLED */ +/* #define HAL_QSPI_MODULE_ENABLED */ +/* #define HAL_RNG_MODULE_ENABLED */ +/* #define HAL_RTC_MODULE_ENABLED */ +/* #define HAL_SAI_MODULE_ENABLED */ +/* #define HAL_SD_MODULE_ENABLED */ +/* #define HAL_MMC_MODULE_ENABLED */ +/* #define HAL_SPDIFRX_MODULE_ENABLED */ +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +/* #define HAL_USART_MODULE_ENABLED */ +/* #define HAL_IRDA_MODULE_ENABLED */ +/* #define HAL_SMARTCARD_MODULE_ENABLED */ +/* #define HAL_WWDG_MODULE_ENABLED */ +#define HAL_PCD_MODULE_ENABLED +/* #define HAL_HCD_MODULE_ENABLED */ +/* #define HAL_DFSDM_MODULE_ENABLED */ +/* #define HAL_DSI_MODULE_ENABLED */ +/* #define HAL_JPEG_MODULE_ENABLED */ +/* #define HAL_MDIOS_MODULE_ENABLED */ +/* #define HAL_SMBUS_MODULE_ENABLED */ +/* #define HAL_EXTI_MODULE_ENABLED */ +#define HAL_GPIO_MODULE_ENABLED +#define HAL_EXTI_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_I2C_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED + +/* ########################## HSE/HSI Values adaptation ##################### */ +/** + * @brief Adjust the value of External High Speed oscillator (HSE) used in your application. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSE is used as system clock source, directly or through the PLL). + */ +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSE_STARTUP_TIMEOUT) + #define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */ +#endif /* HSE_STARTUP_TIMEOUT */ + +/** + * @brief Internal High Speed oscillator (HSI) value. + * This value is used by the RCC HAL module to compute the system frequency + * (when HSI is used as system clock source, directly or through the PLL). + */ +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @brief Internal Low Speed oscillator (LSI) value. + */ +#if !defined (LSI_VALUE) + #define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/ +#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz + The real value may vary depending on the variations + in voltage and temperature. */ +/** + * @brief External Low Speed oscillator (LSE) value. + */ +#if !defined (LSE_VALUE) + #define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */ +#endif /* LSE_VALUE */ + +#if !defined (LSE_STARTUP_TIMEOUT) + #define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */ +#endif /* LSE_STARTUP_TIMEOUT */ + +/** + * @brief External clock source for I2S peripheral + * This value is used by the I2S HAL module to compute the I2S clock source + * frequency, this source is inserted directly through I2S_CKIN pad. + */ +#if !defined (EXTERNAL_CLOCK_VALUE) + #define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the Internal oscillator in Hz*/ +#endif /* EXTERNAL_CLOCK_VALUE */ + +/* Tip: To avoid modifying this file each time you need to use different HSE, + === you can define the HSE value in your toolchain compiler preprocessor. */ + +/* ########################### System Configuration ######################### */ +/** + * @brief This is the HAL system configuration section + */ +#define VDD_VALUE 3300U /*!< Value of VDD in mv */ +#define TICK_INT_PRIORITY ((uint32_t)15U) /*!< tick interrupt priority */ +#define USE_RTOS 0U +#define PREFETCH_ENABLE 0U +#define ART_ACCELERATOR_ENABLE 0U /* To enable instruction cache and prefetch */ + +#define USE_HAL_ADC_REGISTER_CALLBACKS 0U /* ADC register callback disabled */ +#define USE_HAL_CAN_REGISTER_CALLBACKS 0U /* CAN register callback disabled */ +#define USE_HAL_CEC_REGISTER_CALLBACKS 0U /* CEC register callback disabled */ +#define USE_HAL_CRYP_REGISTER_CALLBACKS 0U /* CRYP register callback disabled */ +#define USE_HAL_DAC_REGISTER_CALLBACKS 0U /* DAC register callback disabled */ +#define USE_HAL_DCMI_REGISTER_CALLBACKS 0U /* DCMI register callback disabled */ +#define USE_HAL_DFSDM_REGISTER_CALLBACKS 0U /* DFSDM register callback disabled */ +#define USE_HAL_DMA2D_REGISTER_CALLBACKS 0U /* DMA2D register callback disabled */ +#define USE_HAL_DSI_REGISTER_CALLBACKS 0U /* DSI register callback disabled */ +#define USE_HAL_ETH_REGISTER_CALLBACKS 0U /* ETH register callback disabled */ +#define USE_HAL_HASH_REGISTER_CALLBACKS 0U /* HASH register callback disabled */ +#define USE_HAL_HCD_REGISTER_CALLBACKS 0U /* HCD register callback disabled */ +#define USE_HAL_I2C_REGISTER_CALLBACKS 0U /* I2C register callback disabled */ +#define USE_HAL_I2S_REGISTER_CALLBACKS 0U /* I2S register callback disabled */ +#define USE_HAL_IRDA_REGISTER_CALLBACKS 0U /* IRDA register callback disabled */ +#define USE_HAL_JPEG_REGISTER_CALLBACKS 0U /* JPEG register callback disabled */ +#define USE_HAL_LPTIM_REGISTER_CALLBACKS 0U /* LPTIM register callback disabled */ +#define USE_HAL_LTDC_REGISTER_CALLBACKS 0U /* LTDC register callback disabled */ +#define USE_HAL_MDIOS_REGISTER_CALLBACKS 0U /* MDIOS register callback disabled */ +#define USE_HAL_MMC_REGISTER_CALLBACKS 0U /* MMC register callback disabled */ +#define USE_HAL_NAND_REGISTER_CALLBACKS 0U /* NAND register callback disabled */ +#define USE_HAL_NOR_REGISTER_CALLBACKS 0U /* NOR register callback disabled */ +#define USE_HAL_PCD_REGISTER_CALLBACKS 0U /* PCD register callback disabled */ +#define USE_HAL_QSPI_REGISTER_CALLBACKS 0U /* QSPI register callback disabled */ +#define USE_HAL_RNG_REGISTER_CALLBACKS 0U /* RNG register callback disabled */ +#define USE_HAL_RTC_REGISTER_CALLBACKS 0U /* RTC register callback disabled */ +#define USE_HAL_SAI_REGISTER_CALLBACKS 0U /* SAI register callback disabled */ +#define USE_HAL_SD_REGISTER_CALLBACKS 0U /* SD register callback disabled */ +#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS 0U /* SMARTCARD register callback disabled */ +#define USE_HAL_SDRAM_REGISTER_CALLBACKS 0U /* SDRAM register callback disabled */ +#define USE_HAL_SRAM_REGISTER_CALLBACKS 0U /* SRAM register callback disabled */ +#define USE_HAL_SPDIFRX_REGISTER_CALLBACKS 0U /* SPDIFRX register callback disabled */ +#define USE_HAL_SMBUS_REGISTER_CALLBACKS 0U /* SMBUS register callback disabled */ +#define USE_HAL_SPI_REGISTER_CALLBACKS 0U /* SPI register callback disabled */ +#define USE_HAL_TIM_REGISTER_CALLBACKS 0U /* TIM register callback disabled */ +#define USE_HAL_UART_REGISTER_CALLBACKS 0U /* UART register callback disabled */ +#define USE_HAL_USART_REGISTER_CALLBACKS 0U /* USART register callback disabled */ +#define USE_HAL_WWDG_REGISTER_CALLBACKS 0U /* WWDG register callback disabled */ + +/* ########################## Assert Selection ############################## */ +/** + * @brief Uncomment the line below to expanse the "assert_param" macro in the + * HAL drivers code + */ +/* #define USE_FULL_ASSERT 1U */ + +/* ################## Ethernet peripheral configuration ##################### */ + +/* Section 1 : Ethernet peripheral configuration */ + +/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */ +#define MAC_ADDR0 2U +#define MAC_ADDR1 0U +#define MAC_ADDR2 0U +#define MAC_ADDR3 0U +#define MAC_ADDR4 0U +#define MAC_ADDR5 0U + +/* Definition of the Ethernet driver buffers size and count */ +#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */ +#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */ +#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */ +#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */ + +/* Section 2: PHY configuration section */ + +/* DP83848_PHY_ADDRESS Address*/ +#define DP83848_PHY_ADDRESS +/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/ +#define PHY_RESET_DELAY ((uint32_t)0x000000FFU) +/* PHY Configuration delay */ +#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU) + +#define PHY_READ_TO ((uint32_t)0x0000FFFFU) +#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU) + +/* Section 3: Common PHY Registers */ + +#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */ +#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ + +#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */ +#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */ +#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */ +#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */ +#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */ +#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */ +#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */ +#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */ +#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */ +#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */ + +#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */ +#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ +#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */ + +/* Section 4: Extended PHY Registers */ +#define PHY_SR ((uint16_t)) /*!< PHY status register Offset */ + +#define PHY_SPEED_STATUS ((uint16_t)) /*!< PHY Speed mask */ +#define PHY_DUPLEX_STATUS ((uint16_t)) /*!< PHY Duplex mask */ + +/* ################## SPI peripheral configuration ########################## */ + +/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver +* Activated: CRC code is present inside driver +* Deactivated: CRC code cleaned from driver +*/ + +#define USE_SPI_CRC 0U + +/* Includes ------------------------------------------------------------------*/ +/** + * @brief Include module's header file + */ + +#ifdef HAL_RCC_MODULE_ENABLED + #include "stm32f7xx_hal_rcc.h" +#endif /* HAL_RCC_MODULE_ENABLED */ + +#ifdef HAL_EXTI_MODULE_ENABLED + #include "stm32f7xx_hal_exti.h" +#endif /* HAL_EXTI_MODULE_ENABLED */ + +#ifdef HAL_GPIO_MODULE_ENABLED + #include "stm32f7xx_hal_gpio.h" +#endif /* HAL_GPIO_MODULE_ENABLED */ + +#ifdef HAL_DMA_MODULE_ENABLED + #include "stm32f7xx_hal_dma.h" +#endif /* HAL_DMA_MODULE_ENABLED */ + +#ifdef HAL_CORTEX_MODULE_ENABLED + #include "stm32f7xx_hal_cortex.h" +#endif /* HAL_CORTEX_MODULE_ENABLED */ + +#ifdef HAL_ADC_MODULE_ENABLED + #include "stm32f7xx_hal_adc.h" +#endif /* HAL_ADC_MODULE_ENABLED */ + +#ifdef HAL_CAN_MODULE_ENABLED + #include "stm32f7xx_hal_can.h" +#endif /* HAL_CAN_MODULE_ENABLED */ + +#ifdef HAL_CEC_MODULE_ENABLED + #include "stm32f7xx_hal_cec.h" +#endif /* HAL_CEC_MODULE_ENABLED */ + +#ifdef HAL_CRC_MODULE_ENABLED + #include "stm32f7xx_hal_crc.h" +#endif /* HAL_CRC_MODULE_ENABLED */ + +#ifdef HAL_CRYP_MODULE_ENABLED + #include "stm32f7xx_hal_cryp.h" +#endif /* HAL_CRYP_MODULE_ENABLED */ + +#ifdef HAL_DMA2D_MODULE_ENABLED + #include "stm32f7xx_hal_dma2d.h" +#endif /* HAL_DMA2D_MODULE_ENABLED */ + +#ifdef HAL_DAC_MODULE_ENABLED + #include "stm32f7xx_hal_dac.h" +#endif /* HAL_DAC_MODULE_ENABLED */ + +#ifdef HAL_DCMI_MODULE_ENABLED + #include "stm32f7xx_hal_dcmi.h" +#endif /* HAL_DCMI_MODULE_ENABLED */ + +#ifdef HAL_ETH_MODULE_ENABLED + #include "stm32f7xx_hal_eth.h" +#endif /* HAL_ETH_MODULE_ENABLED */ + +#ifdef HAL_ETH_LEGACY_MODULE_ENABLED + #include "stm32f7xx_hal_eth_legacy.h" +#endif /* HAL_ETH_LEGACY_MODULE_ENABLED */ + +#ifdef HAL_FLASH_MODULE_ENABLED + #include "stm32f7xx_hal_flash.h" +#endif /* HAL_FLASH_MODULE_ENABLED */ + +#ifdef HAL_SRAM_MODULE_ENABLED + #include "stm32f7xx_hal_sram.h" +#endif /* HAL_SRAM_MODULE_ENABLED */ + +#ifdef HAL_NOR_MODULE_ENABLED + #include "stm32f7xx_hal_nor.h" +#endif /* HAL_NOR_MODULE_ENABLED */ + +#ifdef HAL_NAND_MODULE_ENABLED + #include "stm32f7xx_hal_nand.h" +#endif /* HAL_NAND_MODULE_ENABLED */ + +#ifdef HAL_SDRAM_MODULE_ENABLED + #include "stm32f7xx_hal_sdram.h" +#endif /* HAL_SDRAM_MODULE_ENABLED */ + +#ifdef HAL_HASH_MODULE_ENABLED + #include "stm32f7xx_hal_hash.h" +#endif /* HAL_HASH_MODULE_ENABLED */ + +#ifdef HAL_I2C_MODULE_ENABLED + #include "stm32f7xx_hal_i2c.h" +#endif /* HAL_I2C_MODULE_ENABLED */ + +#ifdef HAL_I2S_MODULE_ENABLED + #include "stm32f7xx_hal_i2s.h" +#endif /* HAL_I2S_MODULE_ENABLED */ + +#ifdef HAL_IWDG_MODULE_ENABLED + #include "stm32f7xx_hal_iwdg.h" +#endif /* HAL_IWDG_MODULE_ENABLED */ + +#ifdef HAL_LPTIM_MODULE_ENABLED + #include "stm32f7xx_hal_lptim.h" +#endif /* HAL_LPTIM_MODULE_ENABLED */ + +#ifdef HAL_LTDC_MODULE_ENABLED + #include "stm32f7xx_hal_ltdc.h" +#endif /* HAL_LTDC_MODULE_ENABLED */ + +#ifdef HAL_PWR_MODULE_ENABLED + #include "stm32f7xx_hal_pwr.h" +#endif /* HAL_PWR_MODULE_ENABLED */ + +#ifdef HAL_QSPI_MODULE_ENABLED + #include "stm32f7xx_hal_qspi.h" +#endif /* HAL_QSPI_MODULE_ENABLED */ + +#ifdef HAL_RNG_MODULE_ENABLED + #include "stm32f7xx_hal_rng.h" +#endif /* HAL_RNG_MODULE_ENABLED */ + +#ifdef HAL_RTC_MODULE_ENABLED + #include "stm32f7xx_hal_rtc.h" +#endif /* HAL_RTC_MODULE_ENABLED */ + +#ifdef HAL_SAI_MODULE_ENABLED + #include "stm32f7xx_hal_sai.h" +#endif /* HAL_SAI_MODULE_ENABLED */ + +#ifdef HAL_SD_MODULE_ENABLED + #include "stm32f7xx_hal_sd.h" +#endif /* HAL_SD_MODULE_ENABLED */ + +#ifdef HAL_MMC_MODULE_ENABLED + #include "stm32f7xx_hal_mmc.h" +#endif /* HAL_MMC_MODULE_ENABLED */ + +#ifdef HAL_SPDIFRX_MODULE_ENABLED + #include "stm32f7xx_hal_spdifrx.h" +#endif /* HAL_SPDIFRX_MODULE_ENABLED */ + +#ifdef HAL_SPI_MODULE_ENABLED + #include "stm32f7xx_hal_spi.h" +#endif /* HAL_SPI_MODULE_ENABLED */ + +#ifdef HAL_TIM_MODULE_ENABLED + #include "stm32f7xx_hal_tim.h" +#endif /* HAL_TIM_MODULE_ENABLED */ + +#ifdef HAL_UART_MODULE_ENABLED + #include "stm32f7xx_hal_uart.h" +#endif /* HAL_UART_MODULE_ENABLED */ + +#ifdef HAL_USART_MODULE_ENABLED + #include "stm32f7xx_hal_usart.h" +#endif /* HAL_USART_MODULE_ENABLED */ + +#ifdef HAL_IRDA_MODULE_ENABLED + #include "stm32f7xx_hal_irda.h" +#endif /* HAL_IRDA_MODULE_ENABLED */ + +#ifdef HAL_SMARTCARD_MODULE_ENABLED + #include "stm32f7xx_hal_smartcard.h" +#endif /* HAL_SMARTCARD_MODULE_ENABLED */ + +#ifdef HAL_WWDG_MODULE_ENABLED + #include "stm32f7xx_hal_wwdg.h" +#endif /* HAL_WWDG_MODULE_ENABLED */ + +#ifdef HAL_PCD_MODULE_ENABLED + #include "stm32f7xx_hal_pcd.h" +#endif /* HAL_PCD_MODULE_ENABLED */ + +#ifdef HAL_HCD_MODULE_ENABLED + #include "stm32f7xx_hal_hcd.h" +#endif /* HAL_HCD_MODULE_ENABLED */ + +#ifdef HAL_DFSDM_MODULE_ENABLED + #include "stm32f7xx_hal_dfsdm.h" +#endif /* HAL_DFSDM_MODULE_ENABLED */ + +#ifdef HAL_DSI_MODULE_ENABLED + #include "stm32f7xx_hal_dsi.h" +#endif /* HAL_DSI_MODULE_ENABLED */ + +#ifdef HAL_JPEG_MODULE_ENABLED + #include "stm32f7xx_hal_jpeg.h" +#endif /* HAL_JPEG_MODULE_ENABLED */ + +#ifdef HAL_MDIOS_MODULE_ENABLED + #include "stm32f7xx_hal_mdios.h" +#endif /* HAL_MDIOS_MODULE_ENABLED */ + +#ifdef HAL_SMBUS_MODULE_ENABLED + #include "stm32f7xx_hal_smbus.h" +#endif /* HAL_SMBUS_MODULE_ENABLED */ + +/* Exported macro ------------------------------------------------------------*/ +#ifdef USE_FULL_ASSERT +/** + * @brief The assert_param macro is used for function's parameters check. + * @param expr: If expr is false, it calls assert_failed function + * which reports the name of the source file and the source + * line number of the call that failed. + * If expr is true, it returns no value. + * @retval None + */ + #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__)) +/* Exported functions ------------------------------------------------------- */ + void assert_failed(uint8_t* file, uint32_t line); +#else + #define assert_param(expr) ((void)0U) +#endif /* USE_FULL_ASSERT */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F7xx_HAL_CONF_H */ + diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_hal_msp.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_hal_msp.c new file mode 100644 index 0000000..046b83a --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_hal_msp.c @@ -0,0 +1,567 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f7xx_hal_msp.c + * @brief This file provides code for the MSP Initialization + * and de-Initialization codes. + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN Define */ + +/* USER CODE END Define */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN Macro */ + +/* USER CODE END Macro */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* External functions --------------------------------------------------------*/ +/* USER CODE BEGIN ExternalFunctions */ + +/* USER CODE END ExternalFunctions */ + +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ +/** + * Initializes the Global MSP. + */ +void HAL_MspInit(void) +{ + + /* USER CODE BEGIN MspInit 0 */ + + /* USER CODE END MspInit 0 */ + + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_RCC_SYSCFG_CLK_ENABLE(); + + /* System interrupt init*/ + + /* USER CODE BEGIN MspInit 1 */ + + /* USER CODE END MspInit 1 */ +} + +/** + * @brief I2C MSP Initialization + * This function configures the hardware resources used in this example + * @param hi2c: I2C handle pointer + * @retval None + */ +void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + if(hi2c->Instance==I2C1) + { + /* USER CODE BEGIN I2C1_MspInit 0 */ + + /* USER CODE END I2C1_MspInit 0 */ + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C1; + PeriphClkInitStruct.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**I2C1 GPIO Configuration + PB6 ------> I2C1_SCL + PB7 ------> I2C1_SDA + */ + GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_I2C1_CLK_ENABLE(); + /* USER CODE BEGIN I2C1_MspInit 1 */ + + /* USER CODE END I2C1_MspInit 1 */ + } + else if(hi2c->Instance==I2C2) + { + /* USER CODE BEGIN I2C2_MspInit 0 */ + + /* USER CODE END I2C2_MspInit 0 */ + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C2; + PeriphClkInitStruct.I2c2ClockSelection = RCC_I2C2CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + + __HAL_RCC_GPIOF_CLK_ENABLE(); + /**I2C2 GPIO Configuration + PF0 ------> I2C2_SDA + PF1 ------> I2C2_SCL + */ + GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C2; + HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_I2C2_CLK_ENABLE(); + /* USER CODE BEGIN I2C2_MspInit 1 */ + + /* USER CODE END I2C2_MspInit 1 */ + } + else if(hi2c->Instance==I2C3) + { + /* USER CODE BEGIN I2C3_MspInit 0 */ + + /* USER CODE END I2C3_MspInit 0 */ + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2C3; + PeriphClkInitStruct.I2c3ClockSelection = RCC_I2C3CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**I2C3 GPIO Configuration + PC9 ------> I2C3_SDA + PA8 ------> I2C3_SCL + */ + GPIO_InitStruct.Pin = GPIO_PIN_9; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C3; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF4_I2C3; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* Peripheral clock enable */ + __HAL_RCC_I2C3_CLK_ENABLE(); + /* USER CODE BEGIN I2C3_MspInit 1 */ + + /* USER CODE END I2C3_MspInit 1 */ + } + +} + +/** + * @brief I2C MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param hi2c: I2C handle pointer + * @retval None + */ +void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) +{ + if(hi2c->Instance==I2C1) + { + /* USER CODE BEGIN I2C1_MspDeInit 0 */ + + /* USER CODE END I2C1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_I2C1_CLK_DISABLE(); + + /**I2C1 GPIO Configuration + PB6 ------> I2C1_SCL + PB7 ------> I2C1_SDA + */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6); + + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_7); + + /* USER CODE BEGIN I2C1_MspDeInit 1 */ + + /* USER CODE END I2C1_MspDeInit 1 */ + } + else if(hi2c->Instance==I2C2) + { + /* USER CODE BEGIN I2C2_MspDeInit 0 */ + + /* USER CODE END I2C2_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_I2C2_CLK_DISABLE(); + + /**I2C2 GPIO Configuration + PF0 ------> I2C2_SDA + PF1 ------> I2C2_SCL + */ + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_0); + + HAL_GPIO_DeInit(GPIOF, GPIO_PIN_1); + + /* USER CODE BEGIN I2C2_MspDeInit 1 */ + + /* USER CODE END I2C2_MspDeInit 1 */ + } + else if(hi2c->Instance==I2C3) + { + /* USER CODE BEGIN I2C3_MspDeInit 0 */ + + /* USER CODE END I2C3_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_I2C3_CLK_DISABLE(); + + /**I2C3 GPIO Configuration + PC9 ------> I2C3_SDA + PA8 ------> I2C3_SCL + */ + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_9); + + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_8); + + /* USER CODE BEGIN I2C3_MspDeInit 1 */ + + /* USER CODE END I2C3_MspDeInit 1 */ + } + +} + +/** + * @brief SPI MSP Initialization + * This function configures the hardware resources used in this example + * @param hspi: SPI handle pointer + * @retval None + */ +void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + if(hspi->Instance==SPI1) + { + /* USER CODE BEGIN SPI1_MspInit 0 */ + + /* USER CODE END SPI1_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_SPI1_CLK_ENABLE(); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + /**SPI1 GPIO Configuration + PA5 ------> SPI1_SCK + PA6 ------> SPI1_MISO + PA7 ------> SPI1_MOSI + */ + GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /* USER CODE BEGIN SPI1_MspInit 1 */ + + /* USER CODE END SPI1_MspInit 1 */ + } + else if(hspi->Instance==SPI4) + { + /* USER CODE BEGIN SPI4_MspInit 0 */ + + /* USER CODE END SPI4_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_SPI4_CLK_ENABLE(); + + __HAL_RCC_GPIOE_CLK_ENABLE(); + /**SPI4 GPIO Configuration + PE2 ------> SPI4_SCK + PE5 ------> SPI4_MISO + PE6 ------> SPI4_MOSI + */ + GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF5_SPI4; + HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); + + /* USER CODE BEGIN SPI4_MspInit 1 */ + + /* USER CODE END SPI4_MspInit 1 */ + } + +} + +/** + * @brief SPI MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param hspi: SPI handle pointer + * @retval None + */ +void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) +{ + if(hspi->Instance==SPI1) + { + /* USER CODE BEGIN SPI1_MspDeInit 0 */ + + /* USER CODE END SPI1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_SPI1_CLK_DISABLE(); + + /**SPI1 GPIO Configuration + PA5 ------> SPI1_SCK + PA6 ------> SPI1_MISO + PA7 ------> SPI1_MOSI + */ + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); + + /* USER CODE BEGIN SPI1_MspDeInit 1 */ + + /* USER CODE END SPI1_MspDeInit 1 */ + } + else if(hspi->Instance==SPI4) + { + /* USER CODE BEGIN SPI4_MspDeInit 0 */ + + /* USER CODE END SPI4_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_SPI4_CLK_DISABLE(); + + /**SPI4 GPIO Configuration + PE2 ------> SPI4_SCK + PE5 ------> SPI4_MISO + PE6 ------> SPI4_MOSI + */ + HAL_GPIO_DeInit(GPIOE, GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6); + + /* USER CODE BEGIN SPI4_MspDeInit 1 */ + + /* USER CODE END SPI4_MspDeInit 1 */ + } + +} + +/** + * @brief TIM_Base MSP Initialization + * This function configures the hardware resources used in this example + * @param htim_base: TIM_Base handle pointer + * @retval None + */ +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) +{ + if(htim_base->Instance==TIM1) + { + /* USER CODE BEGIN TIM1_MspInit 0 */ + + /* USER CODE END TIM1_MspInit 0 */ + /* Peripheral clock enable */ + __HAL_RCC_TIM1_CLK_ENABLE(); + /* USER CODE BEGIN TIM1_MspInit 1 */ + + /* USER CODE END TIM1_MspInit 1 */ + + } + +} + +/** + * @brief TIM_Base MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param htim_base: TIM_Base handle pointer + * @retval None + */ +void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) +{ + if(htim_base->Instance==TIM1) + { + /* USER CODE BEGIN TIM1_MspDeInit 0 */ + + /* USER CODE END TIM1_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_TIM1_CLK_DISABLE(); + /* USER CODE BEGIN TIM1_MspDeInit 1 */ + + /* USER CODE END TIM1_MspDeInit 1 */ + } + +} + +/** + * @brief UART MSP Initialization + * This function configures the hardware resources used in this example + * @param huart: UART handle pointer + * @retval None + */ +void HAL_UART_MspInit(UART_HandleTypeDef* huart) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + if(huart->Instance==UART5) + { + /* USER CODE BEGIN UART5_MspInit 0 */ + + /* USER CODE END UART5_MspInit 0 */ + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_UART5; + PeriphClkInitStruct.Uart5ClockSelection = RCC_UART5CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /* Peripheral clock enable */ + __HAL_RCC_UART5_CLK_ENABLE(); + + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + /**UART5 GPIO Configuration + PC12 ------> UART5_TX + PD2 ------> UART5_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_12; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF8_UART5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF8_UART5; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /* USER CODE BEGIN UART5_MspInit 1 */ + + /* USER CODE END UART5_MspInit 1 */ + } + else if(huart->Instance==USART3) + { + /* USER CODE BEGIN USART3_MspInit 0 */ + + /* USER CODE END USART3_MspInit 0 */ + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3; + PeriphClkInitStruct.Usart3ClockSelection = RCC_USART3CLKSOURCE_PCLK1; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /* Peripheral clock enable */ + __HAL_RCC_USART3_CLK_ENABLE(); + + __HAL_RCC_GPIOB_CLK_ENABLE(); + /**USART3 GPIO Configuration + PB10 ------> USART3_TX + PB11 ------> USART3_RX + */ + GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF7_USART3; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* USER CODE BEGIN USART3_MspInit 1 */ + + /* USER CODE END USART3_MspInit 1 */ + } + +} + +/** + * @brief UART MSP De-Initialization + * This function freeze the hardware resources used in this example + * @param huart: UART handle pointer + * @retval None + */ +void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) +{ + if(huart->Instance==UART5) + { + /* USER CODE BEGIN UART5_MspDeInit 0 */ + + /* USER CODE END UART5_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_UART5_CLK_DISABLE(); + + /**UART5 GPIO Configuration + PC12 ------> UART5_TX + PD2 ------> UART5_RX + */ + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12); + + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); + + /* USER CODE BEGIN UART5_MspDeInit 1 */ + + /* USER CODE END UART5_MspDeInit 1 */ + } + else if(huart->Instance==USART3) + { + /* USER CODE BEGIN USART3_MspDeInit 0 */ + + /* USER CODE END USART3_MspDeInit 0 */ + /* Peripheral clock disable */ + __HAL_RCC_USART3_CLK_DISABLE(); + + /**USART3 GPIO Configuration + PB10 ------> USART3_TX + PB11 ------> USART3_RX + */ + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); + + /* USER CODE BEGIN USART3_MspDeInit 1 */ + + /* USER CODE END USART3_MspDeInit 1 */ + } + +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_it.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_it.c new file mode 100644 index 0000000..4e8cbd6 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_it.c @@ -0,0 +1,217 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f7xx_it.c + * @brief Interrupt Service Routines. + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "stm32f7xx_it.h" +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN TD */ + +/* USER CODE END TD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ +/* USER CODE BEGIN PV */ + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +/* USER CODE BEGIN PFP */ + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/* External variables --------------------------------------------------------*/ +extern PCD_HandleTypeDef hpcd_USB_OTG_FS; +/* USER CODE BEGIN EV */ + +/* USER CODE END EV */ + +/******************************************************************************/ +/* Cortex-M7 Processor Interruption and Exception Handlers */ +/******************************************************************************/ +/** + * @brief This function handles Non maskable interrupt. + */ +void NMI_Handler(void) +{ + /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ + + /* USER CODE END NonMaskableInt_IRQn 0 */ + /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ + while (1) + { + } + /* USER CODE END NonMaskableInt_IRQn 1 */ +} + +/** + * @brief This function handles Hard fault interrupt. + */ +void HardFault_Handler(void) +{ + /* USER CODE BEGIN HardFault_IRQn 0 */ + + /* USER CODE END HardFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_HardFault_IRQn 0 */ + /* USER CODE END W1_HardFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Memory management fault. + */ +void MemManage_Handler(void) +{ + /* USER CODE BEGIN MemoryManagement_IRQn 0 */ + + /* USER CODE END MemoryManagement_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ + /* USER CODE END W1_MemoryManagement_IRQn 0 */ + } +} + +/** + * @brief This function handles Pre-fetch fault, memory access fault. + */ +void BusFault_Handler(void) +{ + /* USER CODE BEGIN BusFault_IRQn 0 */ + + /* USER CODE END BusFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_BusFault_IRQn 0 */ + /* USER CODE END W1_BusFault_IRQn 0 */ + } +} + +/** + * @brief This function handles Undefined instruction or illegal state. + */ +void UsageFault_Handler(void) +{ + /* USER CODE BEGIN UsageFault_IRQn 0 */ + + /* USER CODE END UsageFault_IRQn 0 */ + while (1) + { + /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ + /* USER CODE END W1_UsageFault_IRQn 0 */ + } +} + +/** + * @brief This function handles System service call via SWI instruction. + */ +void SVC_Handler(void) +{ + /* USER CODE BEGIN SVCall_IRQn 0 */ + + /* USER CODE END SVCall_IRQn 0 */ + /* USER CODE BEGIN SVCall_IRQn 1 */ + + /* USER CODE END SVCall_IRQn 1 */ +} + +/** + * @brief This function handles Debug monitor. + */ +void DebugMon_Handler(void) +{ + /* USER CODE BEGIN DebugMonitor_IRQn 0 */ + + /* USER CODE END DebugMonitor_IRQn 0 */ + /* USER CODE BEGIN DebugMonitor_IRQn 1 */ + + /* USER CODE END DebugMonitor_IRQn 1 */ +} + +/** + * @brief This function handles Pendable request for system service. + */ +void PendSV_Handler(void) +{ + /* USER CODE BEGIN PendSV_IRQn 0 */ + + /* USER CODE END PendSV_IRQn 0 */ + /* USER CODE BEGIN PendSV_IRQn 1 */ + + /* USER CODE END PendSV_IRQn 1 */ +} + +/** + * @brief This function handles System tick timer. + */ +void SysTick_Handler(void) +{ + /* USER CODE BEGIN SysTick_IRQn 0 */ + + /* USER CODE END SysTick_IRQn 0 */ + HAL_IncTick(); + /* USER CODE BEGIN SysTick_IRQn 1 */ + + /* USER CODE END SysTick_IRQn 1 */ +} + +/******************************************************************************/ +/* STM32F7xx Peripheral Interrupt Handlers */ +/* Add here the Interrupt Handlers for the used peripherals. */ +/* For the available peripheral interrupt handler names, */ +/* please refer to the startup file (startup_stm32f7xx.s). */ +/******************************************************************************/ + +/** + * @brief This function handles USB On The Go FS global interrupt. + */ +void OTG_FS_IRQHandler(void) +{ + /* USER CODE BEGIN OTG_FS_IRQn 0 */ + + /* USER CODE END OTG_FS_IRQn 0 */ + HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS); + /* USER CODE BEGIN OTG_FS_IRQn 1 */ + + /* USER CODE END OTG_FS_IRQn 1 */ +} + +/* USER CODE BEGIN 1 */ + +/* USER CODE END 1 */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_it.h b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_it.h new file mode 100644 index 0000000..964f2a5 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/stm32f7xx_it.h @@ -0,0 +1,67 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file stm32f7xx_it.h + * @brief This file contains the headers of the interrupt handlers. + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F7xx_IT_H +#define __STM32F7xx_IT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void NMI_Handler(void); +void HardFault_Handler(void); +void MemManage_Handler(void); +void BusFault_Handler(void); +void UsageFault_Handler(void); +void SVC_Handler(void); +void DebugMon_Handler(void); +void PendSV_Handler(void); +void SysTick_Handler(void); +void OTG_FS_IRQHandler(void); +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F7xx_IT_H */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/syscalls.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/syscalls.c new file mode 100644 index 0000000..8884b5a --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/syscalls.c @@ -0,0 +1,176 @@ +/** + ****************************************************************************** + * @file syscalls.c + * @author Auto-generated by STM32CubeIDE + * @brief STM32CubeIDE Minimal System calls file + * + * For more information about which c-functions + * need which of these lowlevel functions + * please consult the Newlib libc-manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2020-2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + + +/* Variables */ +extern int __io_putchar(int ch) __attribute__((weak)); +extern int __io_getchar(void) __attribute__((weak)); + + +char *__env[1] = { 0 }; +char **environ = __env; + + +/* Functions */ +void initialise_monitor_handles() +{ +} + +int _getpid(void) +{ + return 1; +} + +int _kill(int pid, int sig) +{ + (void)pid; + (void)sig; + errno = EINVAL; + return -1; +} + +void _exit (int status) +{ + _kill(status, -1); + while (1) {} /* Make sure we hang here */ +} + +__attribute__((weak)) int _read(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + *ptr++ = __io_getchar(); + } + + return len; +} + +__attribute__((weak)) int _write(int file, char *ptr, int len) +{ + (void)file; + int DataIdx; + + for (DataIdx = 0; DataIdx < len; DataIdx++) + { + __io_putchar(*ptr++); + } + return len; +} + +int _close(int file) +{ + (void)file; + return -1; +} + + +int _fstat(int file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _isatty(int file) +{ + (void)file; + return 1; +} + +int _lseek(int file, int ptr, int dir) +{ + (void)file; + (void)ptr; + (void)dir; + return 0; +} + +int _open(char *path, int flags, ...) +{ + (void)path; + (void)flags; + /* Pretend like we always fail */ + return -1; +} + +int _wait(int *status) +{ + (void)status; + errno = ECHILD; + return -1; +} + +int _unlink(char *name) +{ + (void)name; + errno = ENOENT; + return -1; +} + +int _times(struct tms *buf) +{ + (void)buf; + return -1; +} + +int _stat(char *file, struct stat *st) +{ + (void)file; + st->st_mode = S_IFCHR; + return 0; +} + +int _link(char *old, char *new) +{ + (void)old; + (void)new; + errno = EMLINK; + return -1; +} + +int _fork(void) +{ + errno = EAGAIN; + return -1; +} + +int _execve(char *name, char **argv, char **env) +{ + (void)name; + (void)argv; + (void)env; + errno = ENOMEM; + return -1; +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/sysmem.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/sysmem.c new file mode 100644 index 0000000..5d9f7e6 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/sysmem.c @@ -0,0 +1,79 @@ +/** + ****************************************************************************** + * @file sysmem.c + * @author Generated by STM32CubeIDE + * @brief STM32CubeIDE System Memory calls file + * + * For more information about which C functions + * need which of these lowlevel functions + * please consult the newlib libc manual + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/* Includes */ +#include +#include + +/** + * Pointer to the current high watermark of the heap usage + */ +static uint8_t *__sbrk_heap_end = NULL; + +/** + * @brief _sbrk() allocates memory to the newlib heap and is used by malloc + * and others from the C library + * + * @verbatim + * ############################################################################ + * # .data # .bss # newlib heap # MSP stack # + * # # # # Reserved by _Min_Stack_Size # + * ############################################################################ + * ^-- RAM start ^-- _end _estack, RAM end --^ + * @endverbatim + * + * This implementation starts allocating at the '_end' linker symbol + * The '_Min_Stack_Size' linker symbol reserves a memory for the MSP stack + * The implementation considers '_estack' linker symbol to be RAM end + * NOTE: If the MSP stack, at any point during execution, grows larger than the + * reserved size, please increase the '_Min_Stack_Size'. + * + * @param incr Memory size + * @return Pointer to allocated memory + */ +void *_sbrk(ptrdiff_t incr) +{ + extern uint8_t _end; /* Symbol defined in the linker script */ + extern uint8_t _estack; /* Symbol defined in the linker script */ + extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */ + const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size; + const uint8_t *max_heap = (uint8_t *)stack_limit; + uint8_t *prev_heap_end; + + /* Initialize heap end at first call */ + if (NULL == __sbrk_heap_end) + { + __sbrk_heap_end = &_end; + } + + /* Protect heap from growing into the reserved MSP stack */ + if (__sbrk_heap_end + incr > max_heap) + { + errno = ENOMEM; + return (void *)-1; + } + + prev_heap_end = __sbrk_heap_end; + __sbrk_heap_end += incr; + + return (void *)prev_heap_end; +} diff --git a/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/system_stm32f7xx.c b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/system_stm32f7xx.c new file mode 100644 index 0000000..1387051 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/system_stm32f7xx.c @@ -0,0 +1,259 @@ +/** + ****************************************************************************** + * @file system_stm32f7xx.c + * @author MCD Application Team + * @brief CMSIS Cortex-M7 Device Peripheral Access Layer System Source File. + * + * This file provides two functions and one global variable to be called from + * user application: + * - SystemInit(): This function is called at startup just after reset and + * before branch to main program. This call is made inside + * the "startup_stm32f7xx.s" file. + * + * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used + * by the user application to setup the SysTick + * timer or configure other parameters. + * + * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must + * be called whenever the core clock is changed + * during program execution. + * + * + ****************************************************************************** + * @attention + * + * Copyright (c) 2016 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ + +/** @addtogroup CMSIS + * @{ + */ + +/** @addtogroup stm32f7xx_system + * @{ + */ + +/** @addtogroup STM32F7xx_System_Private_Includes + * @{ + */ + +#include "stm32f7xx.h" + +#if !defined (HSE_VALUE) + #define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */ +#endif /* HSE_VALUE */ + +#if !defined (HSI_VALUE) + #define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/ +#endif /* HSI_VALUE */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_TypesDefinitions + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Defines + * @{ + */ + +/************************* Miscellaneous Configuration ************************/ + +/* Note: Following vector table addresses must be defined in line with linker + configuration. */ +/*!< Uncomment the following line if you need to relocate the vector table + anywhere in Flash or Sram, else the vector table is kept at the automatic + remap of boot address selected */ +/* #define USER_VECT_TAB_ADDRESS */ + +#if defined(USER_VECT_TAB_ADDRESS) +/*!< Uncomment the following line if you need to relocate your vector Table + in Sram else user remap will be done in Flash. */ +/* #define VECT_TAB_SRAM */ +#if defined(VECT_TAB_SRAM) +#define VECT_TAB_BASE_ADDRESS RAMDTCM_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#else +#define VECT_TAB_BASE_ADDRESS FLASH_BASE /*!< Vector Table base address field. + This value must be a multiple of 0x200. */ +#endif /* VECT_TAB_SRAM */ +#if !defined(VECT_TAB_OFFSET) +#define VECT_TAB_OFFSET 0x00000000U /*!< Vector Table offset field. + This value must be a multiple of 0x200. */ +#endif /* VECT_TAB_OFFSET */ +#endif /* USER_VECT_TAB_ADDRESS */ +/******************************************************************************/ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Macros + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Variables + * @{ + */ + + /* This variable is updated in three ways: + 1) by calling CMSIS function SystemCoreClockUpdate() + 2) by calling HAL API function HAL_RCC_GetHCLKFreq() + 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency + Note: If you use this function to configure the system clock; then there + is no need to call the 2 first functions listed above, since SystemCoreClock + variable is updated automatically. + */ + uint32_t SystemCoreClock = 16000000; + const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9}; + const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_FunctionPrototypes + * @{ + */ + +/** + * @} + */ + +/** @addtogroup STM32F7xx_System_Private_Functions + * @{ + */ + +/** + * @brief Setup the microcontroller system + * Initialize the Embedded Flash Interface, the PLL and update the + * SystemFrequency variable. + * @param None + * @retval None + */ +void SystemInit(void) +{ + /* FPU settings ------------------------------------------------------------*/ +#if (__FPU_PRESENT == 1) && (__FPU_USED == 1) + SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ +#endif + + /* Configure the Vector Table location -------------------------------------*/ +#if defined(USER_VECT_TAB_ADDRESS) + SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ +#endif /* USER_VECT_TAB_ADDRESS */ +} + +/** + * @brief Update SystemCoreClock variable according to Clock Register Values. + * The SystemCoreClock variable contains the core clock (HCLK), it can + * be used by the user application to setup the SysTick timer or configure + * other parameters. + * + * @note Each time the core clock (HCLK) changes, this function must be called + * to update SystemCoreClock variable value. Otherwise, any configuration + * based on this variable will be incorrect. + * + * @note - The system frequency computed by this function is not the real + * frequency in the chip. It is calculated based on the predefined + * constant and the selected clock source: + * + * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*) + * + * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**) + * + * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**) + * or HSI_VALUE(*) multiplied/divided by the PLL factors. + * + * (*) HSI_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value + * 16 MHz) but the real value may vary depending on the variations + * in voltage and temperature. + * + * (**) HSE_VALUE is a constant defined in stm32f7xx_hal_conf.h file (default value + * 25 MHz), user has to ensure that HSE_VALUE is same as the real + * frequency of the crystal used. Otherwise, this function may + * have wrong result. + * + * - The result of this function could be not correct when using fractional + * value for HSE crystal. + * + * @param None + * @retval None + */ +void SystemCoreClockUpdate(void) +{ + uint32_t tmp, pllvco, pllp, pllsource, pllm; + + /* Get SYSCLK source -------------------------------------------------------*/ + tmp = RCC->CFGR & RCC_CFGR_SWS; + + switch (tmp) + { + case 0x00: /* HSI used as system clock source */ + SystemCoreClock = HSI_VALUE; + break; + case 0x04: /* HSE used as system clock source */ + SystemCoreClock = HSE_VALUE; + break; + case 0x08: /* PLL used as system clock source */ + + /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N + SYSCLK = PLL_VCO / PLL_P + */ + pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22; + pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM; + + if (pllsource != 0) + { + /* HSE used as PLL clock source */ + pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + else + { + /* HSI used as PLL clock source */ + pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6); + } + + pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2; + SystemCoreClock = pllvco/pllp; + break; + default: + SystemCoreClock = HSI_VALUE; + break; + } + /* Compute HCLK frequency --------------------------------------------------*/ + /* Get HCLK prescaler */ + tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)]; + /* HCLK frequency */ + SystemCoreClock >>= tmp; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/9_Firmware/9_1_Microcontroller/9_1_2_C_Cpp_Algorithms/STM32_ALGO.docx b/9_Firmware/9_1_Microcontroller/9_1_2_C_Cpp_Algorithms/STM32_ALGO.docx new file mode 100644 index 0000000..e69de29 diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp new file mode 100644 index 0000000..0daa07d --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.cpp @@ -0,0 +1,2411 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.c + * @brief : Main program body + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ +/* Includes ------------------------------------------------------------------*/ +#include "main.h" +#include "usb_device.h" +#include "USBHandler.h" +#include "usbd_cdc_if.h" +#include "adar1000.h" +#include "ADAR1000_Manager.h" +extern "C" { +#include "ad9523.h" +} +#include "no_os_delay.h" +#include "no_os_alloc.h" +#include "no_os_print_log.h" +#include "no_os_error.h" +#include "no_os_units.h" +#include "no_os_dma.h" +#include "no_os_spi.h" +#include "no_os_uart.h" +#include "no_os_util.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "stm32_spi.h" +#include "stm32_delay.h" +#include "TinyGPSPlus.h" +extern "C" { +#include "GY_85_HAL.h" +} +#include "BMP180.h" +extern "C" { +#include "platform_noos_stm32.h" +} +extern "C" { + +#include "adf4382a_manager.h" +#include "adf4382.h" +#include "no_os_delay.h" +#include "no_os_error.h" +} +#include +#include "DAC5578.h" +#include "ADS7830.h" +#include "gps_handler.h" + +#include "stm32f7xx_hal.h" + + + + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Private typedef -----------------------------------------------------------*/ +/* USER CODE BEGIN PTD */ + + +/* USER CODE END PTD */ + +/* Private define ------------------------------------------------------------*/ +/* USER CODE BEGIN PD */ + + +/* -------- GPIO index mapping for no-OS interface -------- */ +#define GPIO_IDX_TX_CS 0 +#define GPIO_IDX_RX_CS 1 +#define GPIO_IDX_TX_DELSTR 2 +#define GPIO_IDX_TX_DELADJ 3 +#define GPIO_IDX_RX_DELSTR 4 +#define GPIO_IDX_RX_DELADJ 5 +#define GPIO_IDX_TX_CE 6 +#define GPIO_IDX_RX_CE 7 +#define GPIO_IDX_SW_SYNC 8 + +/* USER CODE END PD */ + +/* Private macro -------------------------------------------------------------*/ +/* USER CODE BEGIN PM */ + +/* USER CODE END PM */ + +/* Private variables ---------------------------------------------------------*/ + +I2C_HandleTypeDef hi2c1; +I2C_HandleTypeDef hi2c2; +I2C_HandleTypeDef hi2c3; + +SPI_HandleTypeDef hspi1; +SPI_HandleTypeDef hspi4; + +TIM_HandleTypeDef htim1; + +UART_HandleTypeDef huart5; +UART_HandleTypeDef huart3; + +/* USER CODE BEGIN PV */ +// The TinyGPSPlus object +TinyGPSPlus gps; + +// Global data structures +GPS_Data_t current_gps_data = {0}; + +// Global USB handler +USBHandler usbHandler; +extern USBD_HandleTypeDef hUsbDeviceFS; + +// Buffer for USB reception +uint8_t usb_rx_buffer[64]; + +//IMU variable +GY85_t imu; + +float Pitch_Sensor, Yaw_Sensor, Roll_Sensor; + +float abias[3] = {-0.108, -0.038, -0.006}, gbias[3] = {-10, 6, -12}, mbias[3]={0.0,0.0,0.0}; +float M11=1.0, M12=-0.0, M13=0.0, + M21=0.0, M22=1.0, M23=0.0, + M31=0.0, M32=-0.0, M33=1.0; +float ax, ay, az, gx, gy, gz, mx, my, mz,mxc,myc,mzc; // variables to hold latest sensor data values +float q[4] = {1.0f, 0.0f, 0.0f, 0.0f}; // vector to hold quaternion +float temperature; +float Mag_Declination = -0.61; //0° + +float RxAcc,RyAcc,RzAcc; +float Rate_Ayz_1,Rate_Axz_1,Rate_Axy_1; +float Axz_1,Ayz_1,Axy_1, Axz_0,Ayz_0,Axy_0; +float RxEst_0,RyEst_0,RzEst_0, RxEst_1,RyEst_1,RzEst_1,Azr_Est; +float RxGyro,RyGyro,RzGyro, R_Est; + +unsigned long now_timeperiod; +unsigned long lasttime_timeperiod = 0; +int Time_Period = 0; + +//Barometer BMP180 + +/*resolution: +BMP180_ULTRALOWPOWER - pressure oversampled 1 time & power consumption 3μA +BMP180_STANDARD - pressure oversampled 2 times & power consumption 5μA +BMP180_HIGHRES - pressure oversampled 4 times & power consumption 7μA +BMP180_ULTRAHIGHRES - pressure oversampled 8 times & power consumption 12μA, library default +*/ +BMP180 myBMP(BMP180_ULTRAHIGHRES); +float RADAR_Altitude; + +//GPS +double RADAR_Longitude = 0; +double RADAR_Latitude = 0; + +extern uint8_t GUI_start_flag_received; + + +//RADAR +// Radar parameters +const int m_max = 32; // Number of chirps per beam position +const int n_max = 31; // Number of beam positions +const float T1 = 30.0f; // Chirp duration in microseconds +const float PRI1 = 167.0f; // Pulse repetition interval in microseconds +const float T2 = 0.5f; // Short chirp duration in microseconds +const float PRI2 = 175.0f; // Short PRI in microseconds +const float Guard = 175.4f; // Guard time in microseconds + +uint8_t m = 1; // m = N° of chirp/ position = 16 (made of T1 and PRF1)+ Guard = 175µs +16 (made of T2 and PRF2) +uint8_t n = 1; // n =[1-31] N° of elevations/azimuth +uint8_t y = 1;// y = N° of azimuths/revolution = 50 controlled by a microcontroller connected to a stepper motor +uint8_t y_max = 50;// y = N° of azimuths/revolution +uint64_t IF_freq = 120000000ULL;//120MHz + +#define PowerAmplifier 1 + +//Stepper Motor +float Stepper_steps = 200.0f;//step per revolution + +// DAC5578 handles (RF Power Amplifier DAC controlling Vg) +DAC5578_HandleTypeDef hdac1, hdac2; +/* Phase accumulators */ +float phase_dac1[8] = {0}; +float phase_dac2[8] = {0}; +const uint32_t sampleRate = 370; // Sample rate in Hz +const uint32_t period = 2700; // Period in microseconds +uint8_t DAC_val = 126; + +// ADC handles (RF Power Amplifier ADC measuring Idq) +ADS7830_HandleTypeDef hadc1, hadc2; +uint8_t adc1_readings[8] = {0}; +uint8_t adc2_readings[8] = {0}; +float Idq_reading[16]={0.0f}; + + +// Global manager instance ADF4382A +ADF4382A_Manager lo_manager; +extern SPI_HandleTypeDef hspi4; + +//ADAR1000 + +ADAR1000Manager adarManager; +static uint8_t matrix1[15][16]; +static uint8_t matrix2[15][16]; +static uint8_t vector_0[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + +/* Radar parameters +const int m_max = 32; // Number of chirps per beam position +const int n_max = 31; // Number of beam positions +const float T1 = 30.0f; // Chirp duration in microseconds +const float PRI1 = 167.0f; // Pulse repetition interval in microseconds +const float T2 = 0.5f; // Short chirp duration in microseconds +const float T2 = 175.0f; // Short PRI in microseconds +const float Guard = 175.40f; // Guard time in microseconds*/ + +//Temperature Sensors +ADS7830_HandleTypeDef hadc3; +float Temperature_1 = 0.0f, Temperature_2 = 0.0f, Temperature_3 = 0.0f, Temperature_4 = 0.0f; +float Temperature_5 = 0.0f, Temperature_6 = 0.0f, Temperature_7 = 0.0f, Temperature_8 = 0.0f; + +// Phase differences for 31 beam positions +const float phase_differences[31] = { + 160.0f, 80.0f, 53.333f, 40.0f, 32.0f, 26.667f, 22.857f, 20.0f, 17.778f, 16.0f, + 14.545f, 13.333f, 12.308f, 11.429f, 10.667f, 0.0f, + -10.667f, -11.429f, -12.308f, -13.333f, -14.545f, -16.0f, -17.778f, -20.0f, + -22.857f, -26.667f, -32.0f, -40.0f, -53.333f, -80.0f, -160.0f +}; + +// Convenience HAL wrappers for AD9523 control pins (GPIOF as you said) +static inline void AD9523_PD(bool v) { HAL_GPIO_WritePin(GPIOF, AD9523_PD_Pin, v ? GPIO_PIN_SET : GPIO_PIN_RESET); } +static inline void AD9523_REF_SEL(bool v) { HAL_GPIO_WritePin(GPIOF, AD9523_REF_SEL_Pin, v ? GPIO_PIN_SET : GPIO_PIN_RESET); } +static inline void AD9523_SYNC_PULSE(void) { HAL_GPIO_WritePin(GPIOF, AD9523_SYNC_Pin, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(GPIOF, AD9523_SYNC_Pin, GPIO_PIN_RESET); } +static inline void AD9523_RESET_ASSERT() { HAL_GPIO_WritePin(GPIOF, AD9523_RESET_Pin, GPIO_PIN_RESET); } // check polarity +static inline void AD9523_RESET_RELEASE() { HAL_GPIO_WritePin(GPIOF, AD9523_RESET_Pin, GPIO_PIN_SET); } +static inline void AD9523_CS(bool v) { HAL_GPIO_WritePin(GPIOF, AD9523_CS_Pin, v ? GPIO_PIN_SET : GPIO_PIN_RESET); } +static inline void AD9523_EEPROM_SEL(bool v){ HAL_GPIO_WritePin(GPIOF, AD9523_EEPROM_SEL_Pin, v ? GPIO_PIN_SET : GPIO_PIN_RESET); } + +/* USER CODE END PV */ + +/* Private function prototypes -----------------------------------------------*/ +void SystemClock_Config(void); +void PeriphCommonClock_Config(void); +static void MPU_Config(void); +static void MX_GPIO_Init(void); +static void MX_TIM1_Init(void); +static void MX_I2C1_Init(void); +static void MX_I2C2_Init(void); +static void MX_I2C3_Init(void); +static void MX_SPI1_Init(void); +static void MX_SPI4_Init(void); +static void MX_UART5_Init(void); +static void MX_USART3_UART_Init(void); +/* USER CODE BEGIN PFP */ + +// Function prototypes +void systemPowerUpSequence(); +void systemPowerDownSequence(); +void initializeBeamMatrices(); +void runRadarPulseSequence(); +void executeChirpSequence(int num_chirps, uint32_t T1, uint32_t PRI1, uint32_t T2, uint32_t PRI2); +void printSystemStatus(); + +////////////////////////////////////////////// +////////////////////micros()////////////////// +////////////////////////////////////////////// +unsigned long micros(void){ +unsigned long Micros = __HAL_TIM_GET_COUNTER(&htim1); +return Micros; //Clock TIM1 -> AHB/APB1 is set to 72MHz/presc+1 presc = 71 +} + +////////////////////////////////////////////// +//////////////////Delay_us()////////////////// +////////////////////////////////////////////// + +void delay_us(volatile uint32_t us){ +__HAL_TIM_SET_COUNTER(&htim1,0); // set the counter value a +while (__HAL_TIM_GET_COUNTER(&htim1) < us); // //Clock TIMx -> AHB/APB1 is set to 72MHz/presc+1 presc = 71 +} + +////////////////////////////////////////////// +//////////////////delay_ns()////////////////// +////////////////////////////////////////////// +void delay_ns(uint32_t nanoseconds) +{ + // Get the starting cycle count + uint32_t start_cycles = DWT->CYCCNT; + + // Convert nanoseconds to the number of CPU clock cycles + // Use `SystemCoreClock` to get the current CPU frequency. + // Use 64-bit math to prevent overflow for large nanosecond values. + uint32_t cycles = (uint32_t)(((uint64_t)nanoseconds * SystemCoreClock) / 1000000000); + + // Busy-wait until the required number of cycles has passed + while ((DWT->CYCCNT - start_cycles) < cycles); +} + +////////////////////////////////////////////// +//////////////////////RADAR/////////////////// +////////////////////////////////////////////// +uint8_t degreesTo7BitPhase(float degrees) { + // Normalize to 0-360 range + while(degrees < 0) degrees += 360.0f; + while(degrees >= 360.0f) degrees -= 360.0f; + + // Convert to 7-bit (0-127) + uint8_t phase_7bit = (uint8_t)((degrees / 360.0f) * 128.0f); + + return phase_7bit % 128; +} + +extern "C" { + + // USB CDC receive callback (called by STM32 HAL) + void CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { + // Process received USB data + usbHandler.processUSBData(Buf, *Len); + + // Prepare for next reception + USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &usb_rx_buffer[0]); + USBD_CDC_ReceivePacket(&hUsbDeviceFS); + } +} + +void systemPowerUpSequence() { + uint8_t msg[] = "Starting Power Up Sequence...\r\n"; + HAL_UART_Transmit(&huart3, msg, sizeof(msg)-1, 1000); + + // Step 1: Initialize ADTR1107 power sequence + if (!adarManager.initializeADTR1107Sequence()) { + uint8_t err[] = "ERROR: ADTR1107 power sequence failed!\r\n"; + HAL_UART_Transmit(&huart3, err, sizeof(err)-1, 1000); + Error_Handler(); + } + + // Step 2: Initialize all ADAR1000 devices + if (!adarManager.initializeAllDevices()) { + uint8_t err[] = "ERROR: ADAR1000 initialization failed!\r\n"; + HAL_UART_Transmit(&huart3, err, sizeof(err)-1, 1000); + Error_Handler(); + } + + // Step 3: Perform system calibration + if (!adarManager.performSystemCalibration()) { + uint8_t warn[] = "WARNING: System calibration issues\r\n"; + HAL_UART_Transmit(&huart3, warn, sizeof(warn)-1, 1000); + } + + // Step 4: Set to safe TX mode + adarManager.setAllDevicesTXMode(); + + uint8_t success[] = "Power Up Sequence Completed Successfully\r\n"; + HAL_UART_Transmit(&huart3, success, sizeof(success)-1, 1000); +} + +void systemPowerDownSequence() { + uint8_t msg[] = "Starting Power Down Sequence...\r\n"; + HAL_UART_Transmit(&huart3, msg, sizeof(msg)-1, 1000); + + // Step 1: Set all devices to RX mode (safest state) + adarManager.setAllDevicesRXMode(); + HAL_Delay(10); + + // Step 2: Disable PA power supplies + HAL_GPIO_WritePin(EN_P_5V0_PA1_GPIO_Port, EN_P_5V0_PA1_Pin | EN_P_5V0_PA2_Pin | EN_P_5V0_PA3_Pin, GPIO_PIN_RESET); + HAL_Delay(10); + + // Step 3: Set PA biases to safe values + for (uint8_t dev = 0; dev < 4; dev++) { + adarManager.adarWrite(dev, REG_PA_CH1_BIAS_ON, 0x20, BROADCAST_OFF); + adarManager.adarWrite(dev, REG_PA_CH2_BIAS_ON, 0x20, BROADCAST_OFF); + adarManager.adarWrite(dev, REG_PA_CH3_BIAS_ON, 0x20, BROADCAST_OFF); + adarManager.adarWrite(dev, REG_PA_CH4_BIAS_ON, 0x20, BROADCAST_OFF); + } + HAL_Delay(10); + + // Step 4: Disable LNA power supply + HAL_GPIO_WritePin(EN_P_3V3_ADTR_GPIO_Port, EN_P_3V3_ADTR_Pin, GPIO_PIN_RESET); + HAL_Delay(10); + + // Step 5: Set LNA bias to safe value + for (uint8_t dev = 0; dev < 4; dev++) { + adarManager.adarWrite(dev, REG_LNA_BIAS_ON, 0x00, BROADCAST_OFF); + } + HAL_Delay(10); + + // Step 6: Disable switch power supplies + HAL_GPIO_WritePin(EN_P_3V3_VDD_SW_GPIO_Port, EN_P_3V3_VDD_SW_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(EN_P_3V3_SW_GPIO_Port, EN_P_3V3_SW_Pin, GPIO_PIN_RESET); + HAL_Delay(10); + + uint8_t success[] = "Power Down Sequence Completed\r\n"; + HAL_UART_Transmit(&huart3, success, sizeof(success)-1, 1000); +} + +void initializeBeamMatrices() { + uint8_t msg[] = "Initializing Beam Matrices...\r\n"; + HAL_UART_Transmit(&huart3, msg, sizeof(msg)-1, 1000); + + // Matrix1: Positions 1-15 (positive phase differences) + for(int beam_pos = 0; beam_pos < 15; beam_pos++) { + float phase_diff_degrees = phase_differences[beam_pos]; + + for(int element = 0; element < 16; element++) { + float cumulative_phase_degrees = element * phase_diff_degrees; + matrix1[beam_pos][element] = degreesTo7BitPhase(cumulative_phase_degrees); + } + } + + // Matrix2: Positions 17-31 (negative phase differences) + for(int beam_pos = 0; beam_pos < 15; beam_pos++) { + float phase_diff_degrees = phase_differences[beam_pos + 16]; + + for(int element = 0; element < 16; element++) { + float cumulative_phase_degrees = element * phase_diff_degrees; + matrix2[beam_pos][element] = degreesTo7BitPhase(cumulative_phase_degrees); + } + } + + // Vector_0: Position 16 (zero phase - broadside) + for(int element = 0; element < 16; element++) { + vector_0[element] = 0; // 0 in 7-bit = 0° phase + } + + uint8_t done[] = "Beam Matrices Initialized\r\n"; + HAL_UART_Transmit(&huart3, done, sizeof(done)-1, 1000); +} + +void executeChirpSequence(int num_chirps, float T1, float PRI1, float T2, float PRI2) { + // First chirp sequence (microsecond timing) + for(int i = 0; i < num_chirps; i++) { + HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_8); // New chirp signal to FPGA + adarManager.pulseTXMode(); + delay_us((uint32_t)T1); + adarManager.pulseRXMode(); + delay_us((uint32_t)(PRI1 - T1)); + } + + delay_us((uint32_t)Guard); + + // Second chirp sequence (nanosecond timing) + for(int i = 0; i < num_chirps; i++) { + HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_8); // New chirp signal to FPGA + adarManager.pulseTXMode(); + delay_ns((uint32_t)(T2 * 1000)); + adarManager.pulseRXMode(); + delay_ns((uint32_t)((PRI2 - T2) * 1000)); + + } +} + +void runRadarPulseSequence() { + static int sequence_count = 0; + char msg[50]; + + snprintf(msg, sizeof(msg), "Starting RADAR Sequence #%d\r\n", ++sequence_count); + HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 1000); + + // Configure for fast switching + adarManager.setFastSwitchMode(true); + + int m = 1; // Chirp counter + int n = 1; // Beam Elevation position counter + int y = 1; // Beam Azimuth counter + + // Main beam steering sequence + for(int beam_pos = 0; beam_pos < 15; beam_pos++) { + HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_9);// Notify FPGA of elevation change + // Pattern 1: matrix1 (positive steering angles) + adarManager.setCustomBeamPattern16(matrix1[beam_pos], ADAR1000Manager::BeamDirection::TX); + adarManager.setCustomBeamPattern16(matrix1[beam_pos], ADAR1000Manager::BeamDirection::RX); + + executeChirpSequence(m_max/2, T1, PRI1, T2, PRI2); + m += m_max/2; + + // Pattern 2: vector_0 (broadside) + adarManager.setCustomBeamPattern16(vector_0, ADAR1000Manager::BeamDirection::TX); + adarManager.setCustomBeamPattern16(vector_0, ADAR1000Manager::BeamDirection::RX); + + executeChirpSequence(m_max/2, T1, PRI1, T2, PRI2); + m += m_max/2; + + // Pattern 3: matrix2 (negative steering angles) + adarManager.setCustomBeamPattern16(matrix2[beam_pos], ADAR1000Manager::BeamDirection::TX); + adarManager.setCustomBeamPattern16(matrix2[beam_pos], ADAR1000Manager::BeamDirection::RX); + + executeChirpSequence(m_max/2, T1, PRI1, T2, PRI2); + m += m_max/2; + + // Reset chirp counter if needed + if(m > m_max) m = 1; + + n++; + if(n > n_max) n = 1; + + } + + HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_10);//Tell FPGA that there is a new azimuth + + y++; if(y>y_max)y=1; + //Rotate stepper to next y position + for(int k= 0;k<(int)(Stepper_steps/y_max);k++){ + HAL_GPIO_WritePin(STEPPER_CLK_P_GPIO_Port, STEPPER_CLK_P_Pin, GPIO_PIN_SET); + delay_us(500); + HAL_GPIO_WritePin(STEPPER_CLK_P_GPIO_Port, STEPPER_CLK_P_Pin, GPIO_PIN_RESET); + delay_us(500); + } + + + + snprintf(msg, sizeof(msg), "RADAR Sequence #%d Completed\r\n", sequence_count); + HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), 1000); +} + + + + +void printSystemStatus() { + char status_msg[100]; + + // Print device status + for(int i = 0; i < 4; i++) { + if(adarManager.verifyDeviceCommunication(i)) { + float temp = adarManager.readTemperature(i); + snprintf(status_msg, sizeof(status_msg), + "ADAR1000 #%d: OK, Temperature: %.1fC\r\n", i+1, temp); + HAL_UART_Transmit(&huart3, (uint8_t*)status_msg, strlen(status_msg), 1000); + } else { + snprintf(status_msg, sizeof(status_msg), + "ADAR1000 #%d: COMMUNICATION ERROR\r\n", i+1); + HAL_UART_Transmit(&huart3, (uint8_t*)status_msg, strlen(status_msg), 1000); + } + } + + // Print matrix info + snprintf(status_msg, sizeof(status_msg), + "Beam Matrices: 31 positions, %d chirps/position\r\n", m_max); + HAL_UART_Transmit(&huart3, (uint8_t*)status_msg, strlen(status_msg), 1000); +} + +/***************************************************************/ +/**********************SYSTEM ERROR HANDLER*********************/ +/***************************************************************/ + +typedef enum { + ERROR_NONE = 0, + ERROR_AD9523_CLOCK, + ERROR_ADF4382_TX_UNLOCK, + ERROR_ADF4382_RX_UNLOCK, + ERROR_ADAR1000_COMM, + ERROR_ADAR1000_TEMP, + ERROR_IMU_COMM, + ERROR_BMP180_COMM, + ERROR_GPS_COMM, + ERROR_RF_PA_OVERCURRENT, + ERROR_RF_PA_BIAS, + ERROR_STEPPER_MOTOR, + ERROR_FPGA_COMM, + ERROR_POWER_SUPPLY, + ERROR_TEMPERATURE_HIGH, + ERROR_MEMORY_ALLOC, + ERROR_WATCHDOG_TIMEOUT +} SystemError_t; + +static SystemError_t last_error = ERROR_NONE; +static uint32_t error_count = 0; +static bool system_emergency_state = false; + +// Error handler function +SystemError_t checkSystemHealth(void) { + SystemError_t current_error = ERROR_NONE; + + // 1. Check AD9523 Clock Generator + static uint32_t last_clock_check = 0; + if (HAL_GetTick() - last_clock_check > 5000) { + if (HAL_GPIO_ReadPin(AD9523_STATUS0_GPIO_Port, AD9523_STATUS0_Pin) == GPIO_PIN_RESET || + HAL_GPIO_ReadPin(AD9523_STATUS1_GPIO_Port, AD9523_STATUS1_Pin) == GPIO_PIN_RESET) { + current_error = ERROR_AD9523_CLOCK; + } + last_clock_check = HAL_GetTick(); + } + + // 2. Check ADF4382 Lock Status + bool tx_locked, rx_locked; + if (ADF4382A_CheckLockStatus(&lo_manager, &tx_locked, &rx_locked) == ADF4382A_MANAGER_OK) { + if (!tx_locked) current_error = ERROR_ADF4382_TX_UNLOCK; + if (!rx_locked) current_error = ERROR_ADF4382_RX_UNLOCK; + } + + // 3. Check ADAR1000 Communication and Temperature + for (int i = 0; i < 4; i++) { + if (!adarManager.verifyDeviceCommunication(i)) { + current_error = ERROR_ADAR1000_COMM; + break; + } + + float temp = adarManager.readTemperature(i); + if (temp > 85.0f) { + current_error = ERROR_ADAR1000_TEMP; + break; + } + } + + // 4. Check IMU Communication + static uint32_t last_imu_check = 0; + if (HAL_GetTick() - last_imu_check > 10000) { + GY85_Update(&imu); + if (isnan(imu.ax) || isnan(imu.ay) || isnan(imu.az)) { + current_error = ERROR_IMU_COMM; + } + last_imu_check = HAL_GetTick(); + } + + // 5. Check BMP180 Communication + static uint32_t last_bmp_check = 0; + if (HAL_GetTick() - last_bmp_check > 15000) { + double pressure = myBMP.getPressure(); + if (pressure < 30000.0 || pressure > 110000.0 || isnan(pressure)) { + current_error = ERROR_BMP180_COMM; + } + last_bmp_check = HAL_GetTick(); + } + + // 6. Check GPS Communication + static uint32_t last_gps_fix = 0; + if (gps.location.isUpdated()) { + last_gps_fix = HAL_GetTick(); + } + if (HAL_GetTick() - last_gps_fix > 30000) { + current_error = ERROR_GPS_COMM; + } + + // 7. Check RF Power Amplifier Current + if (PowerAmplifier) { + for (int i = 0; i < 16; i++) { + if (Idq_reading[i] > 2.5f) { + current_error = ERROR_RF_PA_OVERCURRENT; + break; + } + if (Idq_reading[i] < 0.1f) { + current_error = ERROR_RF_PA_BIAS; + break; + } + } + } + + // 8. Check System Temperature + if (temperature > 75.0f) { + current_error = ERROR_TEMPERATURE_HIGH; + } + + // 9. Simple watchdog check + static uint32_t last_health_check = 0; + if (HAL_GetTick() - last_health_check > 60000) { + current_error = ERROR_WATCHDOG_TIMEOUT; + } + last_health_check = HAL_GetTick(); + + return current_error; +} + +// Error recovery function +void attemptErrorRecovery(SystemError_t error) { + char recovery_msg[80]; + snprintf(recovery_msg, sizeof(recovery_msg), + "Attempting recovery from error: %d\r\n", error); + HAL_UART_Transmit(&huart3, (uint8_t*)recovery_msg, strlen(recovery_msg), 1000); + + switch (error) { + case ERROR_ADF4382_TX_UNLOCK: + case ERROR_ADF4382_RX_UNLOCK: + // Re-initialize LO + ADF4382A_Manager_Init(&lo_manager, SYNC_METHOD_TIMED); + HAL_Delay(100); + break; + + case ERROR_ADAR1000_COMM: + // Reset ADAR1000 communication + adarManager.initializeAllDevices(); + HAL_Delay(50); + break; + + case ERROR_IMU_COMM: + // Re-initialize IMU + GY85_Init(); + HAL_Delay(100); + break; + + case ERROR_GPS_COMM: + // GPS will auto-recover when signal returns + break; + + default: + // For other errors, just log and continue + break; + } + + snprintf(recovery_msg, sizeof(recovery_msg), + "Recovery attempt completed.\r\n"); + HAL_UART_Transmit(&huart3, (uint8_t*)recovery_msg, strlen(recovery_msg), 1000); +} + +//////////////////////////////////////////////////////////////////////////////// +//:::::RF POWER AMPLIFIER DAC5578 Emergency stop function using CLR pin///////// +//////////////////////////////////////////////////////////////////////////////// +void Emergency_Stop(void) { + /* Immediately clear all DAC outputs to zero using hardware CLR */ + DAC5578_ActivateClearPin(&hdac1); + DAC5578_ActivateClearPin(&hdac2); + + /* Keep outputs cleared until reset */ + while (1) { + HAL_Delay(100); + } +} + +// Error response function +void handleSystemError(SystemError_t error) { + if (error == ERROR_NONE) return; + + error_count++; + last_error = error; + + char error_msg[100]; + const char* error_strings[] = { + "No error", + "AD9523 Clock failure", + "ADF4382 TX LO unlocked", + "ADF4382 RX LO unlocked", + "ADAR1000 communication error", + "ADAR1000 temperature high", + "IMU communication error", + "BMP180 communication error", + "GPS communication lost", + "RF PA overcurrent detected", + "RF PA bias fault", + "Stepper motor fault", + "FPGA communication error", + "Power supply fault", + "System temperature high", + "Memory allocation failed", + "Watchdog timeout" + }; + + snprintf(error_msg, sizeof(error_msg), + "ERROR #%d: %s (Count: %lu)\r\n", + error, error_strings[error], error_count); + HAL_UART_Transmit(&huart3, (uint8_t*)error_msg, strlen(error_msg), 1000); + + // Blink LED pattern based on error code + for (int i = 0; i < (error % 5) + 1; i++) { + HAL_GPIO_TogglePin(LED_3_GPIO_Port, LED_3_Pin); + HAL_Delay(200); + } + + // Critical errors trigger emergency shutdown + if (error >= ERROR_RF_PA_OVERCURRENT && error <= ERROR_POWER_SUPPLY) { + snprintf(error_msg, sizeof(error_msg), + "CRITICAL ERROR! Initiating emergency shutdown.\r\n"); + HAL_UART_Transmit(&huart3, (uint8_t*)error_msg, strlen(error_msg), 1000); + + Emergency_Stop(); + system_emergency_state = true; + } + + // For non-critical errors, attempt recovery + if (!system_emergency_state) { + attemptErrorRecovery(error); + } +} + + +// System health monitoring function +bool checkSystemHealthStatus(void) { + SystemError_t error = checkSystemHealth(); + + if (error != ERROR_NONE) { + handleSystemError(error); + + // If we're in emergency state or too many errors, shutdown + if (system_emergency_state || error_count > 10) { + return false; + } + } + + return true; +} + +// Get system status for GUI +// Get system status for GUI with 8 temperature variables +void getSystemStatusForGUI(char* status_buffer, size_t buffer_size) { + char temp_buffer[200]; + char final_status[500] = "System Status: "; + + // Basic status + if (system_emergency_state) { + strcat(final_status, "EMERGENCY_STOP|"); + } else { + strcat(final_status, "NORMAL|"); + } + + // Error information + snprintf(temp_buffer, sizeof(temp_buffer), "LastError:%d|ErrorCount:%lu|", + last_error, error_count); + strcat(final_status, temp_buffer); + + // Sensor status + snprintf(temp_buffer, sizeof(temp_buffer), "IMU:%.1f,%.1f,%.1f|GPS:%.6f,%.6f|ALT:%.1f|", + Pitch_Sensor, Roll_Sensor, Yaw_Sensor, + RADAR_Latitude, RADAR_Longitude, RADAR_Altitude); + strcat(final_status, temp_buffer); + + // LO Status + bool tx_locked, rx_locked; + ADF4382A_CheckLockStatus(&lo_manager, &tx_locked, &rx_locked); + snprintf(temp_buffer, sizeof(temp_buffer), "LO_TX:%s|LO_RX:%s|", + tx_locked ? "LOCKED" : "UNLOCKED", + rx_locked ? "LOCKED" : "UNLOCKED"); + strcat(final_status, temp_buffer); + + // Temperature readings (8 variables) + // You'll need to populate these temperature values from your sensors + // For now, I'll show how to format them - replace with actual temperature readings + Temperature_1 = ADS7830_Measure_SingleEnded(&hadc3, 0); + Temperature_2 = ADS7830_Measure_SingleEnded(&hadc3, 1); + Temperature_3 = ADS7830_Measure_SingleEnded(&hadc3, 2); + Temperature_4 = ADS7830_Measure_SingleEnded(&hadc3, 3); + Temperature_5 = ADS7830_Measure_SingleEnded(&hadc3, 4); + Temperature_6 = ADS7830_Measure_SingleEnded(&hadc3, 5); + Temperature_7 = ADS7830_Measure_SingleEnded(&hadc3, 6); + Temperature_8 = ADS7830_Measure_SingleEnded(&hadc3, 7); + + // Format all 8 temperature variables + snprintf(temp_buffer, sizeof(temp_buffer), + "T1:%.1f|T2:%.1f|T3:%.1f|T4:%.1f|T5:%.1f|T6:%.1f|T7:%.1f|T8:%.1f|", + Temperature_1, Temperature_2, Temperature_3, Temperature_4, + Temperature_5, Temperature_6, Temperature_7, Temperature_8); + strcat(final_status, temp_buffer); + + // RF Power Amplifier status (if enabled) + if (PowerAmplifier) { + float avg_current = 0.0f; + for (int i = 0; i < 16; i++) { + avg_current += Idq_reading[i]; + } + avg_current /= 16.0f; + + snprintf(temp_buffer, sizeof(temp_buffer), "PA_AvgCurrent:%.2f|PA_Enabled:%d|", + avg_current, PowerAmplifier); + strcat(final_status, temp_buffer); + } + + // Radar operation status + snprintf(temp_buffer, sizeof(temp_buffer), "BeamPos:%d|Azimuth:%d|ChirpCount:%d|", + n, y, m); + strcat(final_status, temp_buffer); + + // Copy to output buffer + strncpy(status_buffer, final_status, buffer_size - 1); + status_buffer[buffer_size - 1] = '\0'; +} + +/* ---------- UART printing helpers ---------- */ +/* +static void uart_print(const char *msg) +{ + HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); +} + +static void uart_println(const char *msg) +{ + HAL_UART_Transmit(&huart3, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); + const char crlf[] = "\r\n"; + HAL_UART_Transmit(&huart3, (uint8_t*)crlf, 2, HAL_MAX_DELAY); +} +*/ + +/* ---------- Helper delay wrappers ---------- */ +static inline void delay_ms(uint32_t ms) { HAL_Delay(ms); } + + + +// This custom version of delay() ensures that the gps object +// is being "fed". +static void smartDelay(unsigned long ms) +{ + uint32_t start = HAL_GetTick(); + uint8_t ch; + + do { + // While there is new data available in UART (non-blocking) + if (HAL_UART_Receive(&huart5, &ch, 1, 0) == HAL_OK) { + gps.encode(ch); // Pass received byte to TinyGPS++ equivalent parser + } + } while (HAL_GetTick() - start < ms); +} + +// Small helper to enable DWT cycle counter for microdelay +static void DWT_Init(void) +{ + // Enable DWT CYCCNT + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CYCCNT = 0; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; +} + +// Configure and program AD9523 via no-os driver +static int configure_ad9523(void) +{ + int32_t ret; + struct ad9523_dev *dev = NULL; + + static struct ad9523_platform_data pdata; + memset(&pdata, 0, sizeof(pdata)); + + // VCXO + refs + pdata.vcxo_freq = 100000000; // 100 MHz VCXO on OSC_IN + pdata.refa_diff_rcv_en = 0; // REFA 10 MHz single-ended + pdata.refb_diff_rcv_en = 0; // REFB 100 MHz single-ended + pdata.osc_in_diff_en = 0; + + // PLL1: keep bypass disabled so VCXO can be used as reference cleanup if desired + pdata.pll1_bypass_en = 0; + pdata.refa_r_div = 1; + pdata.refb_r_div = 1; + + // PLL2: 100 MHz PFD (R2=1), N = 36 to get VCO = 3.6 GHz + pdata.pll2_ndiv_a_cnt = 0; + pdata.pll2_ndiv_b_cnt = 9; // 4*9 + 0 = 36 + pdata.pll2_r2_div = 0; // R2=1 + pdata.pll2_charge_pump_current_nA = 3500; // example + + // Loop filters: reasonable starting values from examples + pdata.rpole2 = RPOLE2_900_OHM; + pdata.rzero = RZERO_2000_OHM; + pdata.cpole1 = CPOLE1_24_PF; + pdata.rzero_bypass_en = 0; + + // Channels array (must allocate AD9523_NUM_CHAN entries) + static struct ad9523_channel_spec channels[AD9523_NUM_CHAN]; + pdata.channels = channels; + pdata.num_channels = AD9523_NUM_CHAN; + + // Initialize channels to disabled defaults + for (int i=0; i tx_sequence; + std::vector rx_sequence; + + // Create beam configurations for each pattern + // Matrix1 sequences (14 steps) + for(int i = 0; i < 14; i++) { + ADAR1000Manager::BeamConfig tx_config; + ADAR1000Manager::BeamConfig rx_config; + + // Calculate angles or use your matrix directly + // For now, we'll use a placeholder angle and set phases manually later + tx_config.angle_degrees = 0; // This would be calculated from your matrix + rx_config.angle_degrees = 0; + + // Copy phase settings from matrix1 + for(int ch = 0; ch < 16; ch++) { + if(ch < 4) { + tx_config.phase_settings[ch] = matrix1[i][ch]; + rx_config.phase_settings[ch] = matrix1[i][ch]; + } + } + + tx_sequence.push_back(tx_config); + rx_sequence.push_back(rx_config); + } + + // You would similarly add the zero phase and matrix2 sequences + + // Note: The beam sequence feature in the manager currently uses calculated phases + // You might need to modify the manager to support pre-calculated phase arrays +} +void setCustomBeamPattern(ADAR1000Manager& manager, uint8_t phase_pattern[16]) { + // Set TX phases for all 4 ADAR1000 devices + for(int dev = 0; dev < 4; dev++) { + for(int ch = 0; ch < 4; ch++) { + uint8_t phase = phase_pattern[dev * 4 + ch]; + manager.adarSetTxPhase(dev, ch + 1, phase, BROADCAST_OFF); + } + } + + // Set RX phases for all 4 ADAR1000 devices + for(int dev = 0; dev < 4; dev++) { + for(int ch = 0; ch < 4; ch++) { + uint8_t phase = phase_pattern[dev * 4 + ch]; + manager.adarSetRxPhase(dev, ch + 1, phase, BROADCAST_OFF); + } + } +} + +void initializeBeamMatricesWithSteeringAngles() { + const float wavelength = 0.02857f; // 10.5 GHz wavelength in meters + const float element_spacing = wavelength / 2.0f; + + // Calculate steering angles from phase differences + float steering_angles[31]; + for(int i = 0; i < 31; i++) { + float phase_diff_rad = phase_differences[i] * M_PI / 180.0f; + steering_angles[i] = asin((phase_diff_rad * wavelength) / (2 * M_PI * element_spacing)) * 180.0f / M_PI; + } + + // Matrix1: Positive angles (positions 1-15) + for(int beam_pos = 0; beam_pos < 15; beam_pos++) { + float angle = steering_angles[beam_pos]; + + for(int element = 0; element < 16; element++) { + // Calculate phase shift for linear array + float phase_shift_rad = (2 * M_PI * element_spacing * element * sin(angle * M_PI / 180.0f)) / wavelength; + float phase_degrees = phase_shift_rad * 180.0f / M_PI; + + // Wrap to 0-360 degrees + while(phase_degrees < 0) phase_degrees += 360; + while(phase_degrees >= 360) phase_degrees -= 360; + + matrix1[beam_pos][element] = (uint8_t)((phase_degrees / 360.0f) * 128); + } + } + + // Matrix2: Negative angles (positions 17-31) + for(int beam_pos = 0; beam_pos < 15; beam_pos++) { + float angle = steering_angles[beam_pos + 16]; + + for(int element = 0; element < 16; element++) { + float phase_shift_rad = (2 * M_PI * element_spacing * element * sin(angle * M_PI / 180.0f)) / wavelength; + float phase_degrees = phase_shift_rad * 180.0f / M_PI; + + while(phase_degrees < 0) phase_degrees += 360; + while(phase_degrees >= 360) phase_degrees -= 360; + + matrix2[beam_pos][element] = (uint8_t)((phase_degrees / 360.0f) * 128); + } + } +} + + + +/* USER CODE END PFP */ + +/* Private user code ---------------------------------------------------------*/ +/* USER CODE BEGIN 0 */ + +/* USER CODE END 0 */ + +/** + * @brief The application entry point. + * @retval int + */ +int main(void) +{ + + /* USER CODE BEGIN 1 */ + + /* USER CODE END 1 */ + + /* MPU Configuration--------------------------------------------------------*/ + MPU_Config(); + + /* MCU Configuration--------------------------------------------------------*/ + + /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ + HAL_Init(); + + /* USER CODE BEGIN Init */ + + /* USER CODE END Init */ + + /* Configure the system clock */ + SystemClock_Config(); + + /* Configure the peripherals common clocks */ + PeriphCommonClock_Config(); + + /* USER CODE BEGIN SysInit */ + + + /* USER CODE END SysInit */ + + /* Initialize all configured peripherals */ + MX_GPIO_Init(); + MX_TIM1_Init(); + MX_I2C1_Init(); + MX_I2C2_Init(); + MX_I2C3_Init(); + MX_SPI1_Init(); + MX_SPI4_Init(); + MX_UART5_Init(); + MX_USART3_UART_Init(); + MX_USB_DEVICE_Init(); + /* USER CODE BEGIN 2 */ + + HAL_TIM_Base_Start(&htim1); + + /* --- Enable DWT cycle counter for accurate microsecond delays --- */ + DWT_Init(); + //Wait for OCXO 3mn + HAL_Delay(180000); + HAL_GPIO_WritePin(AD9523_RESET_GPIO_Port,AD9523_RESET_Pin,GPIO_PIN_RESET); + + //Power sequencing AD9523 + HAL_GPIO_WritePin(EN_P_1V8_CLOCK_GPIO_Port,EN_P_1V8_CLOCK_Pin,GPIO_PIN_SET); + HAL_Delay(100); + HAL_GPIO_WritePin(EN_P_3V3_CLOCK_GPIO_Port,EN_P_3V3_CLOCK_Pin,GPIO_PIN_SET); + HAL_Delay(100); + HAL_GPIO_WritePin(AD9523_RESET_GPIO_Port,AD9523_RESET_Pin,GPIO_PIN_SET); + HAL_Delay(100); + + //Set planned Clocks on AD9523 + /* + o Channel 0 = 300MHz LVDS (ADF4382 TX) + o Channel 1 = 300MHz LVDS (ADF4382 RX) (Phase aligned with Channel 0) + o Channel 4 = 400MHz LVDS (ADC) + o Channel 5 = 400MHz LVDS (FPGA_ADC)(Phase aligned with Channel 4) + o Channel 6 = 100MHz LVCMOS (FPGA system clock) + o Channel 7 = 20MHz LVCMOS (FPGA test) + o Channel 8 = 60MHz LVDS (ADF4382 TX sync) + o Channel 9 = 60MHz LVDS (ADF4382 RX sync)(Phase aligned with Channel 8) + o Channel 10 = 120MHz LVCMOS + o Channel 11 = 120MHz LVCMOS (Phase aligned with Channel 10) + */ + + + // Ensure stm32_spi.c and stm32_delay.c are compiled and linked + + if (configure_ad9523() != 0) { + // configuration error - handle as needed + while (1) { HAL_Delay(1000); } + } + + //Power sequencing FPGA + HAL_GPIO_WritePin(EN_P_1V0_FPGA_GPIO_Port,EN_P_1V0_FPGA_Pin,GPIO_PIN_SET); + HAL_Delay(100); + HAL_GPIO_WritePin(EN_P_1V8_FPGA_GPIO_Port,EN_P_1V8_FPGA_Pin,GPIO_PIN_SET); + HAL_Delay(100); + HAL_GPIO_WritePin(EN_P_3V3_FPGA_GPIO_Port,EN_P_3V3_FPGA_Pin,GPIO_PIN_SET); + HAL_Delay(100); + + +// Initialize module IMU + GY85_Init(); + for(int i=0; i<10;i++){ + GY85_Update(&imu); + + ax = imu.ax; + ay = imu.ay; + az = imu.az; + gx = -imu.gx; + gy = -imu.gy; + gz = imu.gz; + mx = imu.mx; + my = imu.my; + mz = imu.mz; + + ax *= 6.10351e-5; //2.0 / 32768.0; + ay *= 6.10351e-5; + az *= 6.10351e-5; + + ax -= abias[0]; // Convert to g's, remove accelerometer biases + ay -= abias[1]; + az -= abias[2]; + + gx *= 0.0152588f; //500.0 / 32768.0; + gy *= 0.0152588f; + gz *= 0.0152588f; + + gx -= gbias[0]; // Convert to degrees per seconds, remove gyro biases + gy -= gbias[1]; + gz -= gbias[2]; + + mx *= 6.10351e-5; //2.0 / 32768.0; + my *= 6.10351e-5; + mz *= 6.10351e-5; + + mxc = M11*(mx-mbias[0]) + M12*(my-mbias[1]) +M13*(mz-mbias[2]); + myc = M21*(mx-mbias[0]) + M22*(my-mbias[1]) +M23*(mz-mbias[2]); + mzc = M31*(mx-mbias[0]) + M32*(my-mbias[1]) +M33*(mz-mbias[2]); + + mx = mxc; + my = myc; + mz = mzc; + + float norm = sqrt((mx*mx) + (my*my) + (mz*mz)); + mx /=norm; + my /=norm; + mz /=norm; + + /***************************************************************/ + /*********************IMU Complementary Filter******************/ + /***************************************************************/ + RxAcc = ax; + RyAcc = ay; + RzAcc = az; + + Rate_Ayz_1 = gx; + Rate_Axz_1 = gy; + Rate_Axy_1 = gz; + + Rate_Ayz_1 = Rate_Ayz_1*0.01745;//Convertion from °/s to Radians/s + Rate_Axz_1 = Rate_Axz_1*0.01745; + Rate_Axy_1 = Rate_Axy_1*0.01745; + + /*Combining Accelerometer & Gyroscope Data*/ + Axz_0 = atan2(RxEst_0,RzEst_0); + Ayz_0 = atan2(RyEst_0,RzEst_0); + Axy_0 = atan2(RxEst_0,RyEst_0); + + now_timeperiod = micros(); + + Time_Period = now_timeperiod - lasttime_timeperiod; + + Axz_1= Axz_0 + Rate_Axz_1*Time_Period*0.000001; + Ayz_1= Ayz_0 + Rate_Ayz_1*Time_Period*0.000001; + Axy_1= Axy_0 + Rate_Axy_1*Time_Period*0.000001; + + lasttime_timeperiod = now_timeperiod; + + RxGyro = sin(Axz_1)/(sqrt(1.0 + cos(Axz_1)*cos(Axz_1) * tan(Ayz_1)*tan(Ayz_1))); + RyGyro = sin(Ayz_1)/(sqrt(1.0 + cos(Ayz_1)*cos(Ayz_1) * tan(Axz_1)*tan(Axz_1))); + if(RzEst_0 >= 0){ + RzGyro = 1.0*sqrt(1 - RxGyro*RxGyro - RyGyro*RyGyro); + } + else { + RzGyro = -1*sqrt(1 - RxGyro*RxGyro - RyGyro*RyGyro); + } + + RxEst_1 = RxAcc*0.5 + RxGyro*0.5 ;// Weight of Gyro. over Acc. + RyEst_1 = RyAcc*0.5 + RyGyro*0.5 ; + RzEst_1 = RzAcc*0.5 + RzGyro*0.5 ; + + R_Est = sqrt(RxEst_1*RxEst_1+RyEst_1*RyEst_1+RzEst_1*RzEst_1); + + Pitch_Sensor = atan2(RxEst_1,sqrt(RyEst_1*RyEst_1)+(RzEst_1*RzEst_1))*180/PI; + Roll_Sensor = atan2(RyEst_1,sqrt(RxEst_1*RxEst_1)+(RzEst_1*RzEst_1))*180/PI; + + float magRawX = mx*cos(Pitch_Sensor*PI/180.0f) - mz*sin(Pitch_Sensor*PI/180.0f); + float magRawY = mx*sin(Roll_Sensor*PI/180.0f)*sin(Pitch_Sensor*PI/180.0f) + my*cos(Roll_Sensor*PI/180.0f)- mz*sin(Roll_Sensor*PI/180.0f)*cos(Pitch_Sensor*PI/180.0f); + Yaw_Sensor = (180*atan2(magRawY,magRawX)/PI) - Mag_Declination; + + if(Yaw_Sensor<0)Yaw_Sensor+=360; + RxEst_0 = RxEst_1; + RyEst_0 = RyEst_1; + RzEst_0 = RzEst_1; + + HAL_Delay(300); + + } + + /////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////BAROMETER BMP180//////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////// + for(int i = 0; i<5 ; i++){ + float BMP_Perssure = myBMP.getPressure(); + RADAR_Altitude = 44330*(1-(pow((BMP_Perssure/101325),(1/5.255)))); + HAL_Delay(100); + } + + /////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////ADF4382///////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////// + printf("Starting ADF4382A Radar LO System...\n"); + printf("Using SPI4 with TIMED SYNCHRONIZATION (60 MHz clocks)\n"); + + // Initialize LO manager with TIMED synchronization + int ret = ADF4382A_Manager_Init(&lo_manager, SYNC_METHOD_TIMED); + // Set phase shift (e.g., 500 ps for TX, 500 ps for RX) + ADF4382A_SetPhaseShift(&lo_manager, 500, 500); + + // Strobe to apply phase shifts + ADF4382A_StrobePhaseShift(&lo_manager, 0); // TX device + ADF4382A_StrobePhaseShift(&lo_manager, 1); // RX device + if (ret != ADF4382A_MANAGER_OK) { + printf("LO Manager initialization failed: %d\n", ret); + Error_Handler(); + } + + // Check initial lock status + bool tx_locked, rx_locked; + ret = ADF4382A_CheckLockStatus(&lo_manager, &tx_locked, &rx_locked); + if (ret == ADF4382A_MANAGER_OK) { + printf("Initial Lock Status - TX: %s, RX: %s\n", + tx_locked ? "LOCKED" : "UNLOCKED", + rx_locked ? "LOCKED" : "UNLOCKED"); + } + // Wait for both LOs to lock + uint32_t lock_timeout = 0; + while (!(tx_locked && rx_locked) && lock_timeout < 100) { + HAL_Delay(100); + ADF4382A_CheckLockStatus(&lo_manager, &tx_locked, &rx_locked); + lock_timeout++; + + if (lock_timeout % 10 == 0) { + printf("Waiting for LO lock... TX: %s, RX: %s\n", + tx_locked ? "LOCKED" : "UNLOCKED", + rx_locked ? "LOCKED" : "UNLOCKED"); + } + } + + if (tx_locked && rx_locked) { + printf("Both LOs locked successfully!\n"); + printf("Synchronization ready - 60 MHz clocks on SYNCP/SYNCN pins\n"); + // - 60 MHz phase-aligned clocks on SYNCP/SYNCN pins + // - SYNC pin connected for triggering + + // When ready to synchronize: + ADF4382A_TriggerTimedSync(&lo_manager); + // At this point, the SYNC pin can be toggled to trigger synchronization + } else { + printf("LO lock timeout! TX: %s, RX: %s\n", + tx_locked ? "LOCKED" : "UNLOCKED", + rx_locked ? "LOCKED" : "UNLOCKED"); + } + // check if there is a lock + if(HAL_GPIO_ReadPin (ADF4382_TX_LKDET_GPIO_Port, ADF4382_TX_LKDET_Pin)) + { + // Set The LED_1 ON! + HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_SET); + } + else + { + // Else .. Turn LED_1 OFF! + HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin, GPIO_PIN_RESET); + } + + if(HAL_GPIO_ReadPin (ADF4382_RX_LKDET_GPIO_Port, ADF4382_RX_LKDET_Pin)) + { + // Set The LED_2 ON! + HAL_GPIO_WritePin(LED_2_GPIO_Port, LED_2_Pin, GPIO_PIN_SET); + } + else + { + // Else .. Turn LED_2 OFF! + HAL_GPIO_WritePin(LED_2_GPIO_Port, LED_2_Pin, GPIO_PIN_RESET); + } + + + ////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////ADAR1000///////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////// + + //Power sequencing ADAR1000 + + //Tell FPGA to turn off TX RF signal by disabling Mixers + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET); + + HAL_GPIO_WritePin(EN_P_3V3_ADAR12_GPIO_Port,EN_P_3V3_ADAR12_Pin,GPIO_PIN_SET); + HAL_GPIO_WritePin(EN_P_3V3_ADAR34_GPIO_Port,EN_P_3V3_ADAR34_Pin,GPIO_PIN_SET); + HAL_Delay(500); + HAL_GPIO_WritePin(EN_P_5V0_ADAR_GPIO_Port,EN_P_5V0_ADAR_Pin,GPIO_PIN_SET); + HAL_Delay(500); + + // System startup message + uint8_t startup_msg[] = "Starting Phased Array RADAR System...\r\n"; + HAL_UART_Transmit(&huart3, startup_msg, sizeof(startup_msg)-1, 1000); + + // Power up sequence + systemPowerUpSequence(); + + // Initialize beam matrices + initializeBeamMatrices(); + + // Print system status + printSystemStatus(); + + ////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////GPS///////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////// + for(int i=0; i<10;i++){ + smartDelay(1000); + RADAR_Longitude = gps.location.lng(); + RADAR_Latitude = gps.location.lat(); + } + + //move Stepper to position 1 = 0° + HAL_GPIO_WritePin(STEPPER_CW_P_GPIO_Port, STEPPER_CW_P_Pin, GPIO_PIN_RESET);//Set stepper motor spinning direction to CCW + //Point Stepper to North + for(int i= 0;i<(int)(Yaw_Sensor*Stepper_steps/360);i++){ + HAL_GPIO_WritePin(STEPPER_CLK_P_GPIO_Port, STEPPER_CLK_P_Pin, GPIO_PIN_SET); + delay_us(500); + HAL_GPIO_WritePin(STEPPER_CLK_P_GPIO_Port, STEPPER_CLK_P_Pin, GPIO_PIN_RESET); + delay_us(500); + } + + /***************************************************************/ + /**********wait for GUI start flag and Send Lat/Long/alt********/ + /***************************************************************/ + + GPS_Data_t gps_data; + // Binary packet structure: + // [Header 4 bytes][Latitude 8 bytes][Longitude 8 bytes][Altitude 4 bytes][CRC 2 bytes] + gps_data = {RADAR_Latitude, RADAR_Longitude, RADAR_Altitude, Pitch_Sensor, HAL_GetTick()}; + GPS_SendBinaryToGUI(&gps_data); + + // Check if start flag was received and settings are ready + do{ + if (usbHandler.isStartFlagReceived() && + usbHandler.getState() == USBHandler::USBState::READY_FOR_DATA) { + + const RadarSettings& settings = usbHandler.getSettings(); + + // Use the settings to configure your radar system + /* + settings.getSystemFrequency(); + settings.getChirpDuration1(); + settings.getChirpDuration2(); + settings.getChirpsPerPosition(); + settings.getFreqMin(); + settings.getFreqMax(); + settings.getPRF1(); + settings.getPRF2(); + settings.getMaxDistance(); + */ + + + } + }while(!usbHandler.isStartFlagReceived()); + + /***************************************************************/ + /************RF Power Amplifier Powering up sequence************/ + /***************************************************************/ + if(PowerAmplifier){ + /* Initialize DACs */ + /* DAC1: Address 0b1001000 = 0x48 */ + if (!DAC5578_Init(&hdac1, &hi2c1, 0x48, 8, + DAC_1_VG_LDAC_GPIO_Port, DAC_1_VG_LDAC_Pin, + DAC_1_VG_CLR_GPIO_Port, DAC_1_VG_CLR_Pin)) { + Error_Handler(); + } + + /* DAC2: Address 0b1001001 = 0x49 */ + if (!DAC5578_Init(&hdac2, &hi2c1, 0x49, 8, + DAC_2_VG_LDAC_GPIO_Port, DAC_2_VG_LDAC_Pin, + DAC_2_VG_CLR_GPIO_Port, DAC_2_VG_CLR_Pin)) { + Error_Handler(); + } + /* Configure clear code behavior */ + DAC5578_SetClearCode(&hdac1, DAC5578_CLR_CODE_ZERO); // Clear to 0V on CLR pulse + DAC5578_SetClearCode(&hdac2, DAC5578_CLR_CODE_ZERO); // Clear to 0V on CLR pulse + + /* Configure LDAC so all channels update simultaneously on hardware LDAC */ + DAC5578_SetupLDAC(&hdac1, 0xFF); // All channels respond to LDAC + DAC5578_SetupLDAC(&hdac2, 0xFF); // All channels respond to LDAC + + //set Vg [1-8] to -3.98V -> input opamp = 1.63058V->126(8bits) + for(int channel = 0; channel < 8; channel++){ + DAC5578_WriteAndUpdateChannelValue(&hdac1, channel, DAC_val); + } + + //set Vg [9-16] to -3.98V -> input opamp = 1.63058V->126(8bits) + for(int channel = 0; channel < 8; channel++){ + DAC5578_WriteAndUpdateChannelValue(&hdac2, channel, DAC_val); + } + + /* Optional: Use hardware LDAC for simultaneous update of all channels */ + HAL_GPIO_WritePin(DAC_1_VG_LDAC_GPIO_Port, DAC_1_VG_LDAC_Pin, GPIO_PIN_RESET); + HAL_GPIO_WritePin(DAC_2_VG_LDAC_GPIO_Port, DAC_2_VG_LDAC_Pin, GPIO_PIN_RESET); + HAL_Delay(1); + HAL_GPIO_WritePin(DAC_1_VG_LDAC_GPIO_Port, DAC_1_VG_LDAC_Pin, GPIO_PIN_SET); + HAL_GPIO_WritePin(DAC_2_VG_LDAC_GPIO_Port, DAC_2_VG_LDAC_Pin, GPIO_PIN_SET); + + //Enable RF Power Amplifier VDD = 22V + HAL_GPIO_WritePin(EN_DIS_RFPA_VDD_GPIO_Port, EN_DIS_RFPA_VDD_Pin, GPIO_PIN_SET); + + /* Initialize ADCs with correct addresses */ + /* ADC1: Address 0x48, Single-Ended mode, Internal Ref ON + ADC ON */ + if (!ADS7830_Init(&hadc1, &hi2c2, 0x48, + ADS7830_SDMODE_SINGLE, ADS7830_PDIRON_ADON)) { + Error_Handler(); + } + + /* ADC2: Address 0x4A, Single-Ended mode, Internal Ref ON + ADC ON */ + if (!ADS7830_Init(&hadc2, &hi2c2, 0x4A, + ADS7830_SDMODE_SINGLE, ADS7830_PDIRON_ADON)) { + Error_Handler(); + } + + /* Read all 8 channels from ADC1 and calculate Idq */ + for (uint8_t channel = 0; channel < 8; channel++) { + adc1_readings[channel] = ADS7830_Measure_SingleEnded(&hadc1, channel); + Idq_reading[channel]= (3.3/255)*adc1_readings[channel]/(50*0.005);//Idq=Vadc/(GxRshunt)//G_INA241A3=50;Rshunt=5mOhms + } + + /* Read all 8 channels from ADC2 and calculate Idq*/ + for (uint8_t channel = 0; channel < 8; channel++) { + adc2_readings[channel] = ADS7830_Measure_SingleEnded(&hadc2, channel); + Idq_reading[channel+8]= (3.3/255)*adc2_readings[channel]/(50*0.005);//Idq=Vadc/(GxRshunt)//G_INA241A3=50;Rshunt=5mOhms + } + + for (uint8_t channel = 0; channel < 8; channel++){ + uint8_t safety_counter = 0; + DAC_val = 126; // Reset for each channel + + do { + if (safety_counter++ > 50) { // Prevent infinite loop + break; + } + DAC_val = DAC_val - 4; + DAC5578_WriteAndUpdateChannelValue(&hdac1, channel, DAC_val); + adc1_readings[channel] = ADS7830_Measure_SingleEnded(&hadc1, channel); + Idq_reading[channel] = (3.3/255) * adc1_readings[channel] / (50 * 0.005); + } while (DAC_val > 38 && abs(Idq_reading[channel] - 1.680) < 0.2); // Fixed logic + } + + for (uint8_t channel = 0; channel < 8; channel++){ + uint8_t safety_counter = 0; + DAC_val = 126; // Reset for each channel + + do { + if (safety_counter++ > 50) { // Prevent infinite loop + break; + } + DAC_val = DAC_val - 4; + DAC5578_WriteAndUpdateChannelValue(&hdac2, channel, DAC_val); + adc1_readings[channel] = ADS7830_Measure_SingleEnded(&hadc2, channel); + Idq_reading[channel+8] = (3.3/255) * adc2_readings[channel] / (50 * 0.005); + } while (DAC_val > 38 && abs(Idq_reading[channel+8] - 1.680) < 0.2); // Fixed logic + } + } + + //RESET FPGA + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET); + HAL_Delay(10); + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET); + + + + //Tell FPGA to apply TX RF by enabling Mixers + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_SET); + + /* T°C sensor TMP37 ADC3: Address 0x49, Single-Ended mode, Internal Ref ON + ADC ON */ + if (!ADS7830_Init(&hadc3, &hi2c2, 0x49, + ADS7830_SDMODE_SINGLE, ADS7830_PDIRON_ADON)) { + Error_Handler(); + } + + /***************************************************************/ + /************************ERRORS HANDLERS************************/ + /***************************************************************/ + + // Initialize error handler system + error_count = 0; + last_error = ERROR_NONE; + system_emergency_state = false; + + /***************************************************************/ + /*********************SEND TO GUI STATUS************************/ + /***************************************************************/ + + // Send initial status to GUI + char initial_status[500]; + getSystemStatusForGUI(initial_status, sizeof(initial_status)); + // Send via USB to GUI + CDC_Transmit_FS((uint8_t*)initial_status, strlen(initial_status)); + + + + + + + // main loop + + /* USER CODE END 2 */ + + /* Infinite loop */ + /* USER CODE BEGIN WHILE */ + while (1) + { + ////////////////////////////////////////////////////////////////////////////////////// + //////////////////////// Check system health at the start of each loop//////////////// + ////////////////////////////////////////////////////////////////////////////////////// + + if (!checkSystemHealthStatus()) { + // System is in bad state, enter safe mode + //Tell FPGA to turn off TX RF signal by disabling Mixers + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_11, GPIO_PIN_RESET); + systemPowerDownSequence(); + + char emergency_msg[] = "SYSTEM IN SAFE MODE - Manual intervention required\r\n"; + HAL_UART_Transmit(&huart3, (uint8_t*)emergency_msg, strlen(emergency_msg), 1000); + + // Blink all LEDs to indicate safe mode + while (system_emergency_state) { + HAL_GPIO_TogglePin(LED_1_GPIO_Port, LED_1_Pin); + HAL_GPIO_TogglePin(LED_2_GPIO_Port, LED_2_Pin); + HAL_GPIO_TogglePin(LED_3_GPIO_Port, LED_3_Pin); + HAL_GPIO_TogglePin(LED_4_GPIO_Port, LED_4_Pin); + } + } + ////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////// Monitor ADF4382A lock status periodically////////////////// + ////////////////////////////////////////////////////////////////////////////////////// + + // Monitor lock status periodically + static uint32_t last_check = 0; + if (HAL_GetTick() - last_check > 5000) { + ADF4382A_CheckLockStatus(&lo_manager, &tx_locked, &rx_locked); + + if (!tx_locked || !rx_locked) { + printf("LO Lock Lost! TX: %s, RX: %s\n", + tx_locked ? "LOCKED" : "UNLOCKED", + rx_locked ? "LOCKED" : "UNLOCKED"); + } + + last_check = HAL_GetTick(); + } + ////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////// Monitor Temperature Sensors periodically////////////////// + ////////////////////////////////////////////////////////////////////////////////////// + /* Read all 8 channels from ADC2 and calculate Idq*/ + // Monitor T°C periodically + static uint32_t last_check1 = 0; + if (HAL_GetTick() - last_check1 > 5000) { + //TMP37 3.3V-->165°C & ADS7830 3.3V-->255 => Temperature_n °C = ADC_val_n * 165/255 + Temperature_1 = ADS7830_Measure_SingleEnded(&hadc3, 0)*0.64705f; + Temperature_2 = ADS7830_Measure_SingleEnded(&hadc3, 1)*0.64705f; + Temperature_3 = ADS7830_Measure_SingleEnded(&hadc3, 2)*0.64705f; + Temperature_4 = ADS7830_Measure_SingleEnded(&hadc3, 3)*0.64705f; + Temperature_5 = ADS7830_Measure_SingleEnded(&hadc3, 4)*0.64705f; + Temperature_6 = ADS7830_Measure_SingleEnded(&hadc3, 5)*0.64705f; + Temperature_7 = ADS7830_Measure_SingleEnded(&hadc3, 6)*0.64705f; + Temperature_8 = ADS7830_Measure_SingleEnded(&hadc3, 7)*0.64705f; + + //(20 mV/°C on TMP37) QPA2962 RF amplifier Operating Temp. Range, TBASE min−40 normal+25 max+85 °C + int Max_Temp = 25; + if((Temperature_1>Max_Temp)||(Temperature_2>Max_Temp)||(Temperature_3>Max_Temp)||(Temperature_4>Max_Temp) + ||(Temperature_5>Max_Temp)||(Temperature_6>Max_Temp)||(Temperature_7>Max_Temp)||(Temperature_8>Max_Temp)) + { + HAL_GPIO_WritePin(EN_DIS_COOLING_GPIO_Port, EN_DIS_COOLING_Pin, GPIO_PIN_SET); + } + else{ + HAL_GPIO_WritePin(EN_DIS_COOLING_GPIO_Port, EN_DIS_COOLING_Pin, GPIO_PIN_RESET); + } + + + last_check = HAL_GetTick(); + } + ////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////ADAR1000///////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////// + //phase_step = 0 => phase = 0° + //phase_step = 127 => phase = 360° + //steering angle (rad)= arcsin(phase_dif/Pi) + + runRadarPulseSequence(); + + // Optional: Add system monitoring here + // Check temperatures, power levels, etc. + + + /* USER CODE END WHILE */ + + + + + /* USER CODE BEGIN 3 */ + } + /* USER CODE END 3 */ +} + +/** + * @brief System Clock Configuration + * @retval None + */ +void SystemClock_Config(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + + /** Configure LSE Drive Capability + */ + HAL_PWR_EnableBkUpAccess(); + + /** Configure the main internal regulator output voltage + */ + __HAL_RCC_PWR_CLK_ENABLE(); + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3); + + /** Initializes the RCC Oscillators according to the specified parameters + * in the RCC_OscInitTypeDef structure. + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = 25; + RCC_OscInitStruct.PLL.PLLN = 144; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = 3; + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) + { + Error_Handler(); + } + + /** Initializes the CPU, AHB and APB buses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK + |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief Peripherals Common Clock Configuration + * @retval None + */ +void PeriphCommonClock_Config(void) +{ + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_TIM; + PeriphClkInitStruct.TIMPresSelection = RCC_TIMPRES_ACTIVATED; + + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) + { + Error_Handler(); + } +} + +/** + * @brief I2C1 Initialization Function + * @param None + * @retval None + */ +static void MX_I2C1_Init(void) +{ + + /* USER CODE BEGIN I2C1_Init 0 */ + + /* USER CODE END I2C1_Init 0 */ + + /* USER CODE BEGIN I2C1_Init 1 */ + + /* USER CODE END I2C1_Init 1 */ + hi2c1.Instance = I2C1; + hi2c1.Init.Timing = 0x00808CD2; + hi2c1.Init.OwnAddress1 = 0; + hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c1.Init.OwnAddress2 = 0; + hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c1) != HAL_OK) + { + Error_Handler(); + } + + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) + { + Error_Handler(); + } + + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN I2C1_Init 2 */ + + /* USER CODE END I2C1_Init 2 */ + +} + +/** + * @brief I2C2 Initialization Function + * @param None + * @retval None + */ +static void MX_I2C2_Init(void) +{ + + /* USER CODE BEGIN I2C2_Init 0 */ + + /* USER CODE END I2C2_Init 0 */ + + /* USER CODE BEGIN I2C2_Init 1 */ + + /* USER CODE END I2C2_Init 1 */ + hi2c2.Instance = I2C2; + hi2c2.Init.Timing = 0x00808CD2; + hi2c2.Init.OwnAddress1 = 0; + hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c2.Init.OwnAddress2 = 0; + hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c2) != HAL_OK) + { + Error_Handler(); + } + + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK) + { + Error_Handler(); + } + + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN I2C2_Init 2 */ + + /* USER CODE END I2C2_Init 2 */ + +} + +/** + * @brief I2C3 Initialization Function + * @param None + * @retval None + */ +static void MX_I2C3_Init(void) +{ + + /* USER CODE BEGIN I2C3_Init 0 */ + + /* USER CODE END I2C3_Init 0 */ + + /* USER CODE BEGIN I2C3_Init 1 */ + + /* USER CODE END I2C3_Init 1 */ + hi2c3.Instance = I2C3; + hi2c3.Init.Timing = 0x00808CD2; + hi2c3.Init.OwnAddress1 = 0; + hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + hi2c3.Init.OwnAddress2 = 0; + hi2c3.Init.OwnAddress2Masks = I2C_OA2_NOMASK; + hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + if (HAL_I2C_Init(&hi2c3) != HAL_OK) + { + Error_Handler(); + } + + /** Configure Analogue filter + */ + if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != HAL_OK) + { + Error_Handler(); + } + + /** Configure Digital filter + */ + if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN I2C3_Init 2 */ + + /* USER CODE END I2C3_Init 2 */ + +} + +/** + * @brief SPI1 Initialization Function + * @param None + * @retval None + */ +static void MX_SPI1_Init(void) +{ + + /* USER CODE BEGIN SPI1_Init 0 */ + + /* USER CODE END SPI1_Init 0 */ + + /* USER CODE BEGIN SPI1_Init 1 */ + + /* USER CODE END SPI1_Init 1 */ + /* SPI1 parameter configuration*/ + hspi1.Instance = SPI1; + hspi1.Init.Mode = SPI_MODE_MASTER; + hspi1.Init.Direction = SPI_DIRECTION_2LINES; + hspi1.Init.DataSize = SPI_DATASIZE_8BIT; + hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi1.Init.NSS = SPI_NSS_SOFT; + hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi1.Init.TIMode = SPI_TIMODE_DISABLE; + hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + hspi1.Init.CRCPolynomial = 7; + hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; + hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; + if (HAL_SPI_Init(&hspi1) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN SPI1_Init 2 */ + + /* USER CODE END SPI1_Init 2 */ + +} + +/** + * @brief SPI4 Initialization Function + * @param None + * @retval None + */ +static void MX_SPI4_Init(void) +{ + + /* USER CODE BEGIN SPI4_Init 0 */ + + /* USER CODE END SPI4_Init 0 */ + + /* USER CODE BEGIN SPI4_Init 1 */ + + /* USER CODE END SPI4_Init 1 */ + /* SPI4 parameter configuration*/ + hspi4.Instance = SPI4; + hspi4.Init.Mode = SPI_MODE_MASTER; + hspi4.Init.Direction = SPI_DIRECTION_2LINES; + hspi4.Init.DataSize = SPI_DATASIZE_8BIT; + hspi4.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi4.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi4.Init.NSS = SPI_NSS_SOFT; + hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi4.Init.TIMode = SPI_TIMODE_DISABLE; + hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + hspi4.Init.CRCPolynomial = 7; + hspi4.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; + hspi4.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; + if (HAL_SPI_Init(&hspi4) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN SPI4_Init 2 */ + + /* USER CODE END SPI4_Init 2 */ + +} + +/** + * @brief TIM1 Initialization Function + * @param None + * @retval None + */ +static void MX_TIM1_Init(void) +{ + + /* USER CODE BEGIN TIM1_Init 0 */ + + /* USER CODE END TIM1_Init 0 */ + + TIM_ClockConfigTypeDef sClockSourceConfig = {0}; + TIM_MasterConfigTypeDef sMasterConfig = {0}; + + /* USER CODE BEGIN TIM1_Init 1 */ + + /* USER CODE END TIM1_Init 1 */ + htim1.Instance = TIM1; + htim1.Init.Prescaler = 71; + htim1.Init.CounterMode = TIM_COUNTERMODE_UP; + htim1.Init.Period = 0xffff-1; + htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + htim1.Init.RepetitionCounter = 0; + htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; + if (HAL_TIM_Base_Init(&htim1) != HAL_OK) + { + Error_Handler(); + } + sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; + if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) + { + Error_Handler(); + } + sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; + sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET; + sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; + if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN TIM1_Init 2 */ + + /* USER CODE END TIM1_Init 2 */ + +} + +/** + * @brief UART5 Initialization Function + * @param None + * @retval None + */ +static void MX_UART5_Init(void) +{ + + /* USER CODE BEGIN UART5_Init 0 */ + + /* USER CODE END UART5_Init 0 */ + + /* USER CODE BEGIN UART5_Init 1 */ + + /* USER CODE END UART5_Init 1 */ + huart5.Instance = UART5; + huart5.Init.BaudRate = 9600; + huart5.Init.WordLength = UART_WORDLENGTH_8B; + huart5.Init.StopBits = UART_STOPBITS_1; + huart5.Init.Parity = UART_PARITY_NONE; + huart5.Init.Mode = UART_MODE_TX_RX; + huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart5.Init.OverSampling = UART_OVERSAMPLING_16; + huart5.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + huart5.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + if (HAL_UART_Init(&huart5) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN UART5_Init 2 */ + + /* USER CODE END UART5_Init 2 */ + +} + +/** + * @brief USART3 Initialization Function + * @param None + * @retval None + */ +static void MX_USART3_UART_Init(void) +{ + + /* USER CODE BEGIN USART3_Init 0 */ + + /* USER CODE END USART3_Init 0 */ + + /* USER CODE BEGIN USART3_Init 1 */ + + /* USER CODE END USART3_Init 1 */ + huart3.Instance = USART3; + huart3.Init.BaudRate = 115200; + huart3.Init.WordLength = UART_WORDLENGTH_8B; + huart3.Init.StopBits = UART_STOPBITS_1; + huart3.Init.Parity = UART_PARITY_NONE; + huart3.Init.Mode = UART_MODE_TX_RX; + huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; + huart3.Init.OverSampling = UART_OVERSAMPLING_16; + huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; + huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; + if (HAL_UART_Init(&huart3) != HAL_OK) + { + Error_Handler(); + } + /* USER CODE BEGIN USART3_Init 2 */ + + /* USER CODE END USART3_Init 2 */ + +} + +/** + * @brief GPIO Initialization Function + * @param None + * @retval None + */ +static void MX_GPIO_Init(void) +{ + GPIO_InitTypeDef GPIO_InitStruct = {0}; + /* USER CODE BEGIN MX_GPIO_Init_1 */ + + /* USER CODE END MX_GPIO_Init_1 */ + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOF, AD9523_PD_Pin|AD9523_REF_SEL_Pin|AD9523_SYNC_Pin|AD9523_RESET_Pin + |AD9523_CS_Pin|AD9523_EEPROM_SEL_Pin|LED_1_Pin|LED_2_Pin + |LED_3_Pin|LED_4_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOA, ADAR_1_CS_3V3_Pin|ADAR_2_CS_3V3_Pin|ADAR_3_CS_3V3_Pin|ADAR_4_CS_3V3_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOG, EN_P_5V0_PA1_Pin|EN_P_5V0_PA2_Pin|EN_P_5V0_PA3_Pin|EN_P_5V5_PA_Pin + |EN_P_1V8_CLOCK_Pin|EN_P_3V3_CLOCK_Pin|ADF4382_RX_DELADJ_Pin|ADF4382_RX_DELSTR_Pin + |ADF4382_RX_CE_Pin|ADF4382_RX_CS_Pin|ADF4382_TX_DELSTR_Pin|ADF4382_TX_DELADJ_Pin + |ADF4382_TX_CS_Pin|ADF4382_TX_CE_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOE, EN_P_1V0_FPGA_Pin|EN_P_1V8_FPGA_Pin|EN_P_3V3_FPGA_Pin|EN_P_5V0_ADAR_Pin + |EN_P_3V3_ADAR12_Pin|EN_P_3V3_ADAR34_Pin|EN_P_3V3_ADTR_Pin|EN_P_3V3_SW_Pin + |EN_P_3V3_VDD_SW_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 + |STEPPER_CW_P_Pin|STEPPER_CLK_P_Pin|EN_DIS_RFPA_VDD_Pin|EN_DIS_COOLING_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pin Output Level */ + HAL_GPIO_WritePin(GPIOB, DAC_1_VG_CLR_Pin|DAC_1_VG_LDAC_Pin|DAC_2_VG_CLR_Pin|DAC_2_VG_LDAC_Pin, GPIO_PIN_RESET); + + /*Configure GPIO pins : AD9523_PD_Pin AD9523_REF_SEL_Pin AD9523_SYNC_Pin AD9523_RESET_Pin + AD9523_CS_Pin AD9523_EEPROM_SEL_Pin LED_1_Pin LED_2_Pin + LED_3_Pin LED_4_Pin */ + GPIO_InitStruct.Pin = AD9523_PD_Pin|AD9523_REF_SEL_Pin|AD9523_SYNC_Pin|AD9523_RESET_Pin + |AD9523_CS_Pin|AD9523_EEPROM_SEL_Pin|LED_1_Pin|LED_2_Pin + |LED_3_Pin|LED_4_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + /*Configure GPIO pins : AD9523_STATUS0_Pin AD9523_STATUS1_Pin */ + GPIO_InitStruct.Pin = AD9523_STATUS0_Pin|AD9523_STATUS1_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); + + /*Configure GPIO pins : ADAR_1_CS_3V3_Pin ADAR_2_CS_3V3_Pin ADAR_3_CS_3V3_Pin ADAR_4_CS_3V3_Pin */ + GPIO_InitStruct.Pin = ADAR_1_CS_3V3_Pin|ADAR_2_CS_3V3_Pin|ADAR_3_CS_3V3_Pin|ADAR_4_CS_3V3_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + + /*Configure GPIO pins : EN_P_5V0_PA1_Pin EN_P_5V0_PA2_Pin EN_P_5V0_PA3_Pin EN_P_5V5_PA_Pin + EN_P_1V8_CLOCK_Pin EN_P_3V3_CLOCK_Pin ADF4382_RX_DELADJ_Pin ADF4382_RX_DELSTR_Pin + ADF4382_RX_CE_Pin ADF4382_RX_CS_Pin ADF4382_TX_DELSTR_Pin ADF4382_TX_DELADJ_Pin + ADF4382_TX_CS_Pin ADF4382_TX_CE_Pin */ + GPIO_InitStruct.Pin = EN_P_5V0_PA1_Pin|EN_P_5V0_PA2_Pin|EN_P_5V0_PA3_Pin|EN_P_5V5_PA_Pin + |EN_P_1V8_CLOCK_Pin|EN_P_3V3_CLOCK_Pin|ADF4382_RX_DELADJ_Pin|ADF4382_RX_DELSTR_Pin + |ADF4382_RX_CE_Pin|ADF4382_RX_CS_Pin|ADF4382_TX_DELSTR_Pin|ADF4382_TX_DELADJ_Pin + |ADF4382_TX_CS_Pin|ADF4382_TX_CE_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + + /*Configure GPIO pins : EN_P_1V0_FPGA_Pin EN_P_1V8_FPGA_Pin EN_P_3V3_FPGA_Pin EN_P_5V0_ADAR_Pin + EN_P_3V3_ADAR12_Pin EN_P_3V3_ADAR34_Pin EN_P_3V3_ADTR_Pin EN_P_3V3_SW_Pin + EN_P_3V3_ADAR12EN_P_3V3_VDD_SW_Pin */ + GPIO_InitStruct.Pin = EN_P_1V0_FPGA_Pin|EN_P_1V8_FPGA_Pin|EN_P_3V3_FPGA_Pin|EN_P_5V0_ADAR_Pin + |EN_P_3V3_ADAR12_Pin|EN_P_3V3_ADAR34_Pin|EN_P_3V3_ADTR_Pin|EN_P_3V3_SW_Pin + |EN_P_3V3_VDD_SW_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); + + /*Configure GPIO pins : PD8 PD9 PD10 PD11 + STEPPER_CW_P_Pin STEPPER_CLK_P_Pin EN_DIS_RFPA_VDD_Pin EN_DIS_COOLING_Pin */ + GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12 + |STEPPER_CW_P_Pin|STEPPER_CLK_P_Pin|EN_DIS_RFPA_VDD_Pin|EN_DIS_COOLING_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /*Configure GPIO pins : PD12 PD13 PD14 PD15 */ + GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /*Configure GPIO pins : ADF4382_RX_LKDET_Pin ADF4382_TX_LKDET_Pin */ + GPIO_InitStruct.Pin = ADF4382_RX_LKDET_Pin|ADF4382_TX_LKDET_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + + /*Configure GPIO pins : MAG_DRDY_Pin ACC_INT_Pin GYR_INT_Pin */ + GPIO_InitStruct.Pin = MAG_DRDY_Pin|ACC_INT_Pin|GYR_INT_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_INPUT; + GPIO_InitStruct.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + /*Configure GPIO pins : DAC_1_VG_CLR_Pin DAC_1_VG_LDAC_Pin DAC_2_VG_CLR_Pin DAC_2_VG_LDAC_Pin */ + GPIO_InitStruct.Pin = DAC_1_VG_CLR_Pin|DAC_1_VG_LDAC_Pin|DAC_2_VG_CLR_Pin|DAC_2_VG_LDAC_Pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + + /* USER CODE BEGIN MX_GPIO_Init_2 */ + + /* USER CODE END MX_GPIO_Init_2 */ +} + +/* USER CODE BEGIN 4 */ +/* ============================================================ + * DEVICE INITIALIZATION + * ============================================================ */ + + + +/* USER CODE END 4 */ + + /* MPU Configuration */ + +void MPU_Config(void) +{ + MPU_Region_InitTypeDef MPU_InitStruct = {0}; + + /* Disables the MPU */ + HAL_MPU_Disable(); + + /** Initializes and configures the Region and the memory to be protected + */ + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = MPU_REGION_NUMBER0; + MPU_InitStruct.BaseAddress = 0x0; + MPU_InitStruct.Size = MPU_REGION_SIZE_4GB; + MPU_InitStruct.SubRegionDisable = 0x87; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; + MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + /* Enables the MPU */ + HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); + +} + +/** + * @brief This function is executed in case of error occurrence. + * @retval None + */ +void Error_Handler(void) +{ + /* USER CODE BEGIN Error_Handler_Debug */ + /* User can add his own implementation to report the HAL error return state */ + __disable_irq(); + while (1) + { + } + /* USER CODE END Error_Handler_Debug */ +} + +#ifdef USE_FULL_ASSERT +/** + * @brief Reports the name of the source file and the source line number + * where the assert_param error has occurred. + * @param file: pointer to the source file name + * @param line: assert_param error line source number + * @retval None + */ +void assert_failed(uint8_t *file, uint32_t line) +{ + /* USER CODE BEGIN 6 */ + /* User can add his own implementation to report the file name and line number, + ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ + /* USER CODE END 6 */ +} +#endif /* USE_FULL_ASSERT */ diff --git a/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.h b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.h new file mode 100644 index 0000000..e4dbaf5 --- /dev/null +++ b/9_Firmware/9_1_Microcontroller/9_1_3_C_Cpp_Code/main.h @@ -0,0 +1,175 @@ +/* USER CODE BEGIN Header */ +/** + ****************************************************************************** + * @file : main.h + * @brief : Header for main.c file. + * This file contains the common defines of the application. + ****************************************************************************** + * @attention + * + * Copyright (c) 2025 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/* USER CODE END Header */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __MAIN_H +#define __MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f7xx_hal.h" + +/* Private includes ----------------------------------------------------------*/ +/* USER CODE BEGIN Includes */ + +/* USER CODE END Includes */ + +/* Exported types ------------------------------------------------------------*/ +/* USER CODE BEGIN ET */ +extern uint8_t GUI_start_flag_received; +extern uint8_t USB_Buffer[64]; + +/* USER CODE END ET */ + +/* Exported constants --------------------------------------------------------*/ +/* USER CODE BEGIN EC */ + +/* USER CODE END EC */ + +/* Exported macro ------------------------------------------------------------*/ +/* USER CODE BEGIN EM */ + +/* USER CODE END EM */ + +/* Exported functions prototypes ---------------------------------------------*/ +void Error_Handler(void); + +/* USER CODE BEGIN EFP */ + +/* USER CODE END EFP */ + +/* Private defines -----------------------------------------------------------*/ +#define AD9523_PD_Pin GPIO_PIN_3 +#define AD9523_PD_GPIO_Port GPIOF +#define AD9523_REF_SEL_Pin GPIO_PIN_4 +#define AD9523_REF_SEL_GPIO_Port GPIOF +#define AD9523_SYNC_Pin GPIO_PIN_5 +#define AD9523_SYNC_GPIO_Port GPIOF +#define AD9523_RESET_Pin GPIO_PIN_6 +#define AD9523_RESET_GPIO_Port GPIOF +#define AD9523_CS_Pin GPIO_PIN_7 +#define AD9523_CS_GPIO_Port GPIOF +#define AD9523_STATUS0_Pin GPIO_PIN_8 +#define AD9523_STATUS0_GPIO_Port GPIOF +#define AD9523_STATUS1_Pin GPIO_PIN_9 +#define AD9523_STATUS1_GPIO_Port GPIOF +#define AD9523_EEPROM_SEL_Pin GPIO_PIN_10 +#define AD9523_EEPROM_SEL_GPIO_Port GPIOF +#define ADAR_1_CS_3V3_Pin GPIO_PIN_0 +#define ADAR_1_CS_3V3_GPIO_Port GPIOA +#define ADAR_2_CS_3V3_Pin GPIO_PIN_1 +#define ADAR_2_CS_3V3_GPIO_Port GPIOA +#define ADAR_3_CS_3V3_Pin GPIO_PIN_2 +#define ADAR_3_CS_3V3_GPIO_Port GPIOA +#define ADAR_4_CS_3V3_Pin GPIO_PIN_3 +#define ADAR_4_CS_3V3_GPIO_Port GPIOA +#define LED_1_Pin GPIO_PIN_12 +#define LED_1_GPIO_Port GPIOF +#define LED_2_Pin GPIO_PIN_13 +#define LED_2_GPIO_Port GPIOF +#define LED_3_Pin GPIO_PIN_14 +#define LED_3_GPIO_Port GPIOF +#define LED_4_Pin GPIO_PIN_15 +#define LED_4_GPIO_Port GPIOF +#define EN_P_5V0_PA1_Pin GPIO_PIN_0 +#define EN_P_5V0_PA1_GPIO_Port GPIOG +#define EN_P_5V0_PA2_Pin GPIO_PIN_1 +#define EN_P_5V0_PA2_GPIO_Port GPIOG +#define EN_P_1V0_FPGA_Pin GPIO_PIN_7 +#define EN_P_1V0_FPGA_GPIO_Port GPIOE +#define EN_P_1V8_FPGA_Pin GPIO_PIN_8 +#define EN_P_1V8_FPGA_GPIO_Port GPIOE +#define EN_P_3V3_FPGA_Pin GPIO_PIN_9 +#define EN_P_3V3_FPGA_GPIO_Port GPIOE +#define EN_P_5V0_ADAR_Pin GPIO_PIN_10 +#define EN_P_5V0_ADAR_GPIO_Port GPIOE +#define EN_P_3V3_ADAR12_Pin GPIO_PIN_11 +#define EN_P_3V3_ADAR12_GPIO_Port GPIOE +#define EN_P_3V3_ADAR34_Pin GPIO_PIN_12 +#define EN_P_3V3_ADAR34_GPIO_Port GPIOE +#define EN_P_3V3_ADTR_Pin GPIO_PIN_13 +#define EN_P_3V3_ADTR_GPIO_Port GPIOE +#define EN_P_3V3_SW_Pin GPIO_PIN_14 +#define EN_P_3V3_SW_GPIO_Port GPIOE +#define EN_P_3V3_VDD_SW_Pin GPIO_PIN_15 +#define EN_P_3V3_VDD_SW_GPIO_Port GPIOE +#define EN_P_5V0_PA3_Pin GPIO_PIN_2 +#define EN_P_5V0_PA3_GPIO_Port GPIOG +#define EN_P_5V5_PA_Pin GPIO_PIN_3 +#define EN_P_5V5_PA_GPIO_Port GPIOG +#define EN_P_1V8_CLOCK_Pin GPIO_PIN_4 +#define EN_P_1V8_CLOCK_GPIO_Port GPIOG +#define EN_P_3V3_CLOCK_Pin GPIO_PIN_5 +#define EN_P_3V3_CLOCK_GPIO_Port GPIOG +#define ADF4382_RX_LKDET_Pin GPIO_PIN_6 +#define ADF4382_RX_LKDET_GPIO_Port GPIOG +#define ADF4382_RX_DELADJ_Pin GPIO_PIN_7 +#define ADF4382_RX_DELADJ_GPIO_Port GPIOG +#define ADF4382_RX_DELSTR_Pin GPIO_PIN_8 +#define ADF4382_RX_DELSTR_GPIO_Port GPIOG +#define MAG_DRDY_Pin GPIO_PIN_6 +#define MAG_DRDY_GPIO_Port GPIOC +#define ACC_INT_Pin GPIO_PIN_7 +#define ACC_INT_GPIO_Port GPIOC +#define GYR_INT_Pin GPIO_PIN_8 +#define GYR_INT_GPIO_Port GPIOC +#define STEPPER_CW_P_Pin GPIO_PIN_4 +#define STEPPER_CW_P_GPIO_Port GPIOD +#define STEPPER_CLK_P_Pin GPIO_PIN_5 +#define STEPPER_CLK_P_GPIO_Port GPIOD +#define EN_DIS_RFPA_VDD_Pin GPIO_PIN_6 +#define EN_DIS_RFPA_VDD_GPIO_Port GPIOD +#define EN_DIS_COOLING_Pin GPIO_PIN_7 +#define EN_DIS_COOLING_GPIO_Port GPIOD +#define ADF4382_RX_CE_Pin GPIO_PIN_9 +#define ADF4382_RX_CE_GPIO_Port GPIOG +#define ADF4382_RX_CS_Pin GPIO_PIN_10 +#define ADF4382_RX_CS_GPIO_Port GPIOG +#define ADF4382_TX_LKDET_Pin GPIO_PIN_11 +#define ADF4382_TX_LKDET_GPIO_Port GPIOG +#define ADF4382_TX_DELSTR_Pin GPIO_PIN_12 +#define ADF4382_TX_DELSTR_GPIO_Port GPIOG +#define ADF4382_TX_DELADJ_Pin GPIO_PIN_13 +#define ADF4382_TX_DELADJ_GPIO_Port GPIOG +#define ADF4382_TX_CS_Pin GPIO_PIN_14 +#define ADF4382_TX_CS_GPIO_Port GPIOG +#define ADF4382_TX_CE_Pin GPIO_PIN_15 +#define ADF4382_TX_CE_GPIO_Port GPIOG +#define DAC_1_VG_CLR_Pin GPIO_PIN_4 +#define DAC_1_VG_CLR_GPIO_Port GPIOB +#define DAC_1_VG_LDAC_Pin GPIO_PIN_5 +#define DAC_1_VG_LDAC_GPIO_Port GPIOB +#define DAC_2_VG_CLR_Pin GPIO_PIN_8 +#define DAC_2_VG_CLR_GPIO_Port GPIOB +#define DAC_2_VG_LDAC_Pin GPIO_PIN_9 +#define DAC_2_VG_LDAC_GPIO_Port GPIOB + +/* USER CODE BEGIN Private defines */ + +/* USER CODE END Private defines */ + +#ifdef __cplusplus +} +#endif + +#endif /* __MAIN_H */ diff --git a/9_Firmware/9_2_FPGA/ad9484_interface_400m.v b/9_Firmware/9_2_FPGA/ad9484_interface_400m.v new file mode 100644 index 0000000..6e6782d --- /dev/null +++ b/9_Firmware/9_2_FPGA/ad9484_interface_400m.v @@ -0,0 +1,98 @@ +module ad9484_interface_400m ( + // ADC Physical Interface (LVDS) + input wire [7:0] adc_d_p, // ADC Data P + input wire [7:0] adc_d_n, // ADC Data N + input wire adc_dco_p, // Data Clock Output P (400MHz) + input wire adc_dco_n, // Data Clock Output N (400MHz) + + // System Interface + input wire sys_clk, // 100MHz system clock (for control only) + input wire reset_n, + + // Output at 400MHz domain + output wire [7:0] adc_data_400m, // ADC data at 400MHz + output wire adc_data_valid_400m // Valid at 400MHz +); + +// LVDS to single-ended conversion +wire [7:0] adc_data; +wire adc_dco; + +// IBUFDS for each data bit +genvar i; +generate + for (i = 0; i < 8; i = i + 1) begin : data_buffers + IBUFDS #( + .DIFF_TERM("TRUE"), + .IOSTANDARD("LVDS_25") + ) ibufds_data ( + .O(adc_data[i]), + .I(adc_d_p[i]), + .IB(adc_d_n[i]) + ); + end +endgenerate + +// IBUFDS for DCO +IBUFDS #( + .DIFF_TERM("TRUE"), + .IOSTANDARD("LVDS_25") +) ibufds_dco ( + .O(adc_dco), + .I(adc_dco_p), + .IB(adc_dco_n) +); + +// IDDR for capturing DDR data +wire [7:0] adc_data_rise; // Data on rising edge +wire [7:0] adc_data_fall; // Data on falling edge + +genvar j; +generate + for (j = 0; j < 8; j = j + 1) begin : iddr_gen + IDDR #( + .DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), + .INIT_Q1(1'b0), + .INIT_Q2(1'b0), + .SRTYPE("SYNC") + ) iddr_inst ( + .Q1(adc_data_rise[j]), // Rising edge data + .Q2(adc_data_fall[j]), // Falling edge data + .C(adc_dco), // 400MHz DCO + .CE(1'b1), + .D(adc_data[j]), + .R(1'b0), + .S(1'b0) + ); + end +endgenerate + +// Combine rising and falling edge data to get 400MSPS stream +reg [7:0] adc_data_400m_reg; +reg adc_data_valid_400m_reg; +reg dco_phase; + +always @(posedge adc_dco or negedge reset_n) begin + if (!reset_n) begin + adc_data_400m_reg <= 8'b0; + adc_data_valid_400m_reg <= 1'b0; + dco_phase <= 1'b0; + end else begin + dco_phase <= ~dco_phase; + + if (dco_phase) begin + // Output falling edge data (completes the 400MSPS stream) + adc_data_400m_reg <= adc_data_fall; + end else begin + // Output rising edge data + adc_data_400m_reg <= adc_data_rise; + end + + adc_data_valid_400m_reg <= 1'b1; // Always valid when ADC is running + end +end + +assign adc_data_400m = adc_data_400m_reg; +assign adc_data_valid_400m = adc_data_valid_400m_reg; + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/cdc_modules.v b/9_Firmware/9_2_FPGA/cdc_modules.v new file mode 100644 index 0000000..a070cf1 --- /dev/null +++ b/9_Firmware/9_2_FPGA/cdc_modules.v @@ -0,0 +1,237 @@ +`timescale 1ns / 1ps + +// ============================================================================ +// CDC FOR MULTI-BIT DATA (ADVANCED) +// ============================================================================ +module cdc_adc_to_processing #( + parameter WIDTH = 8, + parameter STAGES = 3 +)( + input wire src_clk, + input wire dst_clk, + input wire reset_n, + input wire [WIDTH-1:0] src_data, + input wire src_valid, + output wire [WIDTH-1:0] dst_data, + output wire dst_valid +); + + // Gray encoding for safe CDC + function [WIDTH-1:0] binary_to_gray; + input [WIDTH-1:0] binary; + binary_to_gray = binary ^ (binary >> 1); + endfunction + + function [WIDTH-1:0] gray_to_binary; + input [WIDTH-1:0] gray; + reg [WIDTH-1:0] binary; + integer i; + begin + binary[WIDTH-1] = gray[WIDTH-1]; + for (i = WIDTH-2; i >= 0; i = i - 1) begin + binary[i] = binary[i+1] ^ gray[i]; + end + gray_to_binary = binary; + end + endfunction + + // Source domain registers + reg [WIDTH-1:0] src_data_reg; + reg [1:0] src_toggle = 2'b00; + reg src_toggle_sync = 0; + + // Destination domain registers + reg [WIDTH-1:0] dst_data_gray [0:STAGES-1]; + reg [1:0] dst_toggle_sync [0:STAGES-1]; + reg [WIDTH-1:0] dst_data_reg; + reg dst_valid_reg = 0; + reg [1:0] prev_dst_toggle = 2'b00; + + always @(posedge src_clk or negedge reset_n) begin + if (!reset_n) begin + src_data_reg <= 0; + src_toggle <= 2'b00; + end else if (src_valid) begin + src_data_reg <= src_data; + src_toggle <= src_toggle + 1; + end + end + + // CDC synchronization chain for data + genvar i; + generate + for (i = 0; i < STAGES; i = i + 1) begin : data_sync_chain + always @(posedge dst_clk or negedge reset_n) begin + if (!reset_n) begin + if (i == 0) begin + dst_data_gray[i] <= 0; + end else begin + dst_data_gray[i] <= dst_data_gray[i-1]; + end + end else begin + if (i == 0) begin + // Convert to gray code at domain crossing + dst_data_gray[i] <= binary_to_gray(src_data_reg); + end else begin + dst_data_gray[i] <= dst_data_gray[i-1]; + end + end + end + end + + for (i = 0; i < STAGES; i = i + 1) begin : toggle_sync_chain + always @(posedge dst_clk or negedge reset_n) begin + if (!reset_n) begin + if (i == 0) begin + dst_toggle_sync[i] <= 2'b00; + end else begin + dst_toggle_sync[i] <= dst_toggle_sync[i-1]; + end + end else begin + if (i == 0) begin + dst_toggle_sync[i] <= src_toggle; + end else begin + dst_toggle_sync[i] <= dst_toggle_sync[i-1]; + end + end + end + end + endgenerate + + // Detect new data + always @(posedge dst_clk or negedge reset_n) begin + if (!reset_n) begin + dst_data_reg <= 0; + dst_valid_reg <= 0; + prev_dst_toggle <= 2'b00; + end else begin + // Convert from gray code + dst_data_reg <= gray_to_binary(dst_data_gray[STAGES-1]); + + // Check if toggle changed (new data) + if (dst_toggle_sync[STAGES-1] != prev_dst_toggle) begin + dst_valid_reg <= 1'b1; + prev_dst_toggle <= dst_toggle_sync[STAGES-1]; + end else begin + dst_valid_reg <= 1'b0; + end + end + end + + assign dst_data = dst_data_reg; + assign dst_valid = dst_valid_reg; + +endmodule + +// ============================================================================ +// CDC FOR SINGLE BIT SIGNALS +// ============================================================================ +module cdc_single_bit #( + parameter STAGES = 3 +)( + input wire src_clk, + input wire dst_clk, + input wire reset_n, + input wire src_signal, + output wire dst_signal +); + + reg [STAGES-1:0] sync_chain; + + always @(posedge dst_clk or negedge reset_n) begin + if (!reset_n) begin + sync_chain <= 0; + end else begin + sync_chain <= {sync_chain[STAGES-2:0], src_signal}; + end + end + + assign dst_signal = sync_chain[STAGES-1]; + +endmodule + +// ============================================================================ +// CDC FOR MULTI-BIT WITH HANDSHAKE +// ============================================================================ +module cdc_handshake #( + parameter WIDTH = 32 +)( + input wire src_clk, + input wire dst_clk, + input wire reset_n, + input wire [WIDTH-1:0] src_data, + input wire src_valid, + output wire src_ready, + output wire [WIDTH-1:0] dst_data, + output wire dst_valid, + input wire dst_ready +); + + // Source domain + reg [WIDTH-1:0] src_data_reg; + reg src_busy = 0; + reg src_ack_sync = 0; + reg [1:0] src_ack_sync_chain = 2'b00; + + // Destination domain + reg [WIDTH-1:0] dst_data_reg; + reg dst_valid_reg = 0; + reg dst_req_sync = 0; + reg [1:0] dst_req_sync_chain = 2'b00; + reg dst_ack = 0; + + // Source clock domain + always @(posedge src_clk or negedge reset_n) begin + if (!reset_n) begin + src_data_reg <= 0; + src_busy <= 0; + src_ack_sync <= 0; + src_ack_sync_chain <= 2'b00; + end else begin + // Sync acknowledge from destination + src_ack_sync_chain <= {src_ack_sync_chain[0], dst_ack}; + src_ack_sync <= src_ack_sync_chain[1]; + + if (!src_busy && src_valid) begin + src_data_reg <= src_data; + src_busy <= 1'b1; + end else if (src_busy && src_ack_sync) begin + src_busy <= 1'b0; + end + end + end + + // Destination clock domain + always @(posedge dst_clk or negedge reset_n) begin + if (!reset_n) begin + dst_data_reg <= 0; + dst_valid_reg <= 0; + dst_req_sync <= 0; + dst_req_sync_chain <= 2'b00; + dst_ack <= 0; + end else begin + // Sync request from source + dst_req_sync_chain <= {dst_req_sync_chain[0], src_busy}; + dst_req_sync <= dst_req_sync_chain[1]; + + // Capture data when request arrives + if (dst_req_sync && !dst_valid_reg) begin + dst_data_reg <= src_data_reg; + dst_valid_reg <= 1'b1; + dst_ack <= 1'b1; + end else if (dst_valid_reg && dst_ready) begin + dst_valid_reg <= 1'b0; + end + + // Clear acknowledge after source sees it + if (dst_ack && !dst_req_sync) begin + dst_ack <= 1'b0; + end + end + end + + assign src_ready = !src_busy; + assign dst_data = dst_data_reg; + assign dst_valid = dst_valid_reg; + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/chirp_lut_init.v b/9_Firmware/9_2_FPGA/chirp_lut_init.v new file mode 100644 index 0000000..444d075 --- /dev/null +++ b/9_Firmware/9_2_FPGA/chirp_lut_init.v @@ -0,0 +1,244 @@ +// Auto-generated LUT initialization for PLFM chirp controller +// Long chirp: 30us from 30MHz to 10MHz +// Short chirp: 0.5us from 30MHz to 10MHz + +// Long PLFM chirp LUT (30us, 30MHz to 10MHz) +initial begin + long_chirp_lut[ 0] = 8'd255; long_chirp_lut[ 1] = 8'd128; long_chirp_lut[ 2] = 8'd 1; long_chirp_lut[ 3] = 8'd127; long_chirp_lut[ 4] = 8'd254; long_chirp_lut[ 5] = 8'd128; long_chirp_lut[ 6] = 8'd 1; long_chirp_lut[ 7] = 8'd127; long_chirp_lut[ 8] = 8'd254; long_chirp_lut[ 9] = 8'd129; long_chirp_lut[ 10] = 8'd 1; long_chirp_lut[ 11] = 8'd125; long_chirp_lut[ 12] = 8'd254; long_chirp_lut[ 13] = 8'd131; long_chirp_lut[ 14] = 8'd 1; long_chirp_lut[ 15] = 8'd123; + long_chirp_lut[ 16] = 8'd254; long_chirp_lut[ 17] = 8'd133; long_chirp_lut[ 18] = 8'd 1; long_chirp_lut[ 19] = 8'd121; long_chirp_lut[ 20] = 8'd254; long_chirp_lut[ 21] = 8'd136; long_chirp_lut[ 22] = 8'd 1; long_chirp_lut[ 23] = 8'd118; long_chirp_lut[ 24] = 8'd254; long_chirp_lut[ 25] = 8'd139; long_chirp_lut[ 26] = 8'd 1; long_chirp_lut[ 27] = 8'd114; long_chirp_lut[ 28] = 8'd254; long_chirp_lut[ 29] = 8'd143; long_chirp_lut[ 30] = 8'd 2; long_chirp_lut[ 31] = 8'd110; + long_chirp_lut[ 32] = 8'd253; long_chirp_lut[ 33] = 8'd148; long_chirp_lut[ 34] = 8'd 2; long_chirp_lut[ 35] = 8'd105; long_chirp_lut[ 36] = 8'd252; long_chirp_lut[ 37] = 8'd153; long_chirp_lut[ 38] = 8'd 3; long_chirp_lut[ 39] = 8'd100; long_chirp_lut[ 40] = 8'd251; long_chirp_lut[ 41] = 8'd158; long_chirp_lut[ 42] = 8'd 5; long_chirp_lut[ 43] = 8'd 94; long_chirp_lut[ 44] = 8'd249; long_chirp_lut[ 45] = 8'd164; long_chirp_lut[ 46] = 8'd 6; long_chirp_lut[ 47] = 8'd 87; + long_chirp_lut[ 48] = 8'd247; long_chirp_lut[ 49] = 8'd171; long_chirp_lut[ 50] = 8'd 9; long_chirp_lut[ 51] = 8'd 81; long_chirp_lut[ 52] = 8'd245; long_chirp_lut[ 53] = 8'd178; long_chirp_lut[ 54] = 8'd 12; long_chirp_lut[ 55] = 8'd 73; long_chirp_lut[ 56] = 8'd242; long_chirp_lut[ 57] = 8'd185; long_chirp_lut[ 58] = 8'd 15; long_chirp_lut[ 59] = 8'd 66; long_chirp_lut[ 60] = 8'd237; long_chirp_lut[ 61] = 8'd193; long_chirp_lut[ 62] = 8'd 20; long_chirp_lut[ 63] = 8'd 58; + long_chirp_lut[ 64] = 8'd233; long_chirp_lut[ 65] = 8'd201; long_chirp_lut[ 66] = 8'd 25; long_chirp_lut[ 67] = 8'd 50; long_chirp_lut[ 68] = 8'd227; long_chirp_lut[ 69] = 8'd209; long_chirp_lut[ 70] = 8'd 31; long_chirp_lut[ 71] = 8'd 43; long_chirp_lut[ 72] = 8'd220; long_chirp_lut[ 73] = 8'd216; long_chirp_lut[ 74] = 8'd 39; long_chirp_lut[ 75] = 8'd 35; long_chirp_lut[ 76] = 8'd212; long_chirp_lut[ 77] = 8'd224; long_chirp_lut[ 78] = 8'd 47; long_chirp_lut[ 79] = 8'd 27; + long_chirp_lut[ 80] = 8'd203; long_chirp_lut[ 81] = 8'd231; long_chirp_lut[ 82] = 8'd 57; long_chirp_lut[ 83] = 8'd 20; long_chirp_lut[ 84] = 8'd193; long_chirp_lut[ 85] = 8'd238; long_chirp_lut[ 86] = 8'd 67; long_chirp_lut[ 87] = 8'd 14; long_chirp_lut[ 88] = 8'd182; long_chirp_lut[ 89] = 8'd244; long_chirp_lut[ 90] = 8'd 79; long_chirp_lut[ 91] = 8'd 9; long_chirp_lut[ 92] = 8'd170; long_chirp_lut[ 93] = 8'd248; long_chirp_lut[ 94] = 8'd 92; long_chirp_lut[ 95] = 8'd 5; + long_chirp_lut[ 96] = 8'd157; long_chirp_lut[ 97] = 8'd252; long_chirp_lut[ 98] = 8'd106; long_chirp_lut[ 99] = 8'd 2; long_chirp_lut[100] = 8'd142; long_chirp_lut[101] = 8'd254; long_chirp_lut[102] = 8'd120; long_chirp_lut[103] = 8'd 1; long_chirp_lut[104] = 8'd127; long_chirp_lut[105] = 8'd254; long_chirp_lut[106] = 8'd136; long_chirp_lut[107] = 8'd 1; long_chirp_lut[108] = 8'd112; long_chirp_lut[109] = 8'd253; long_chirp_lut[110] = 8'd151; long_chirp_lut[111] = 8'd 4; + long_chirp_lut[112] = 8'd 96; long_chirp_lut[113] = 8'd249; long_chirp_lut[114] = 8'd167; long_chirp_lut[115] = 8'd 8; long_chirp_lut[116] = 8'd 80; long_chirp_lut[117] = 8'd243; long_chirp_lut[118] = 8'd183; long_chirp_lut[119] = 8'd 15; long_chirp_lut[120] = 8'd 64; long_chirp_lut[121] = 8'd235; long_chirp_lut[122] = 8'd199; long_chirp_lut[123] = 8'd 25; long_chirp_lut[124] = 8'd 49; long_chirp_lut[125] = 8'd224; long_chirp_lut[126] = 8'd213; long_chirp_lut[127] = 8'd 37; + long_chirp_lut[128] = 8'd 35; long_chirp_lut[129] = 8'd211; long_chirp_lut[130] = 8'd226; long_chirp_lut[131] = 8'd 51; long_chirp_lut[132] = 8'd 23; long_chirp_lut[133] = 8'd196; long_chirp_lut[134] = 8'd237; long_chirp_lut[135] = 8'd 68; long_chirp_lut[136] = 8'd 13; long_chirp_lut[137] = 8'd178; long_chirp_lut[138] = 8'd246; long_chirp_lut[139] = 8'd 86; long_chirp_lut[140] = 8'd 6; long_chirp_lut[141] = 8'd159; long_chirp_lut[142] = 8'd252; long_chirp_lut[143] = 8'd106; + long_chirp_lut[144] = 8'd 2; long_chirp_lut[145] = 8'd138; long_chirp_lut[146] = 8'd254; long_chirp_lut[147] = 8'd128; long_chirp_lut[148] = 8'd 1; long_chirp_lut[149] = 8'd116; long_chirp_lut[150] = 8'd253; long_chirp_lut[151] = 8'd150; long_chirp_lut[152] = 8'd 4; long_chirp_lut[153] = 8'd 94; long_chirp_lut[154] = 8'd249; long_chirp_lut[155] = 8'd171; long_chirp_lut[156] = 8'd 10; long_chirp_lut[157] = 8'd 73; long_chirp_lut[158] = 8'd240; long_chirp_lut[159] = 8'd192; + long_chirp_lut[160] = 8'd 21; long_chirp_lut[161] = 8'd 53; long_chirp_lut[162] = 8'd227; long_chirp_lut[163] = 8'd212; long_chirp_lut[164] = 8'd 36; long_chirp_lut[165] = 8'd 35; long_chirp_lut[166] = 8'd210; long_chirp_lut[167] = 8'd228; long_chirp_lut[168] = 8'd 55; long_chirp_lut[169] = 8'd 20; long_chirp_lut[170] = 8'd189; long_chirp_lut[171] = 8'd241; long_chirp_lut[172] = 8'd 77; long_chirp_lut[173] = 8'd 9; long_chirp_lut[174] = 8'd166; long_chirp_lut[175] = 8'd250; + long_chirp_lut[176] = 8'd101; long_chirp_lut[177] = 8'd 2; long_chirp_lut[178] = 8'd141; long_chirp_lut[179] = 8'd254; long_chirp_lut[180] = 8'd127; long_chirp_lut[181] = 8'd 1; long_chirp_lut[182] = 8'd114; long_chirp_lut[183] = 8'd253; long_chirp_lut[184] = 8'd154; long_chirp_lut[185] = 8'd 5; long_chirp_lut[186] = 8'd 88; long_chirp_lut[187] = 8'd246; long_chirp_lut[188] = 8'd180; long_chirp_lut[189] = 8'd 15; long_chirp_lut[190] = 8'd 62; long_chirp_lut[191] = 8'd233; + long_chirp_lut[192] = 8'd204; long_chirp_lut[193] = 8'd 31; long_chirp_lut[194] = 8'd 40; long_chirp_lut[195] = 8'd214; long_chirp_lut[196] = 8'd225; long_chirp_lut[197] = 8'd 52; long_chirp_lut[198] = 8'd 21; long_chirp_lut[199] = 8'd191; long_chirp_lut[200] = 8'd241; long_chirp_lut[201] = 8'd 77; long_chirp_lut[202] = 8'd 8; long_chirp_lut[203] = 8'd164; long_chirp_lut[204] = 8'd251; long_chirp_lut[205] = 8'd106; long_chirp_lut[206] = 8'd 1; long_chirp_lut[207] = 8'd134; + long_chirp_lut[208] = 8'd254; long_chirp_lut[209] = 8'd136; long_chirp_lut[210] = 8'd 2; long_chirp_lut[211] = 8'd103; long_chirp_lut[212] = 8'd250; long_chirp_lut[213] = 8'd167; long_chirp_lut[214] = 8'd 9; long_chirp_lut[215] = 8'd 73; long_chirp_lut[216] = 8'd239; long_chirp_lut[217] = 8'd196; long_chirp_lut[218] = 8'd 25; long_chirp_lut[219] = 8'd 46; long_chirp_lut[220] = 8'd220; long_chirp_lut[221] = 8'd220; long_chirp_lut[222] = 8'd 47; long_chirp_lut[223] = 8'd 24; + long_chirp_lut[224] = 8'd195; long_chirp_lut[225] = 8'd240; long_chirp_lut[226] = 8'd 75; long_chirp_lut[227] = 8'd 9; long_chirp_lut[228] = 8'd164; long_chirp_lut[229] = 8'd251; long_chirp_lut[230] = 8'd107; long_chirp_lut[231] = 8'd 1; long_chirp_lut[232] = 8'd131; long_chirp_lut[233] = 8'd254; long_chirp_lut[234] = 8'd141; long_chirp_lut[235] = 8'd 3; long_chirp_lut[236] = 8'd 96; long_chirp_lut[237] = 8'd248; long_chirp_lut[238] = 8'd175; long_chirp_lut[239] = 8'd 13; + long_chirp_lut[240] = 8'd 64; long_chirp_lut[241] = 8'd233; long_chirp_lut[242] = 8'd206; long_chirp_lut[243] = 8'd 33; long_chirp_lut[244] = 8'd 36; long_chirp_lut[245] = 8'd209; long_chirp_lut[246] = 8'd231; long_chirp_lut[247] = 8'd 61; long_chirp_lut[248] = 8'd 15; long_chirp_lut[249] = 8'd178; long_chirp_lut[250] = 8'd247; long_chirp_lut[251] = 8'd 95; long_chirp_lut[252] = 8'd 3; long_chirp_lut[253] = 8'd142; long_chirp_lut[254] = 8'd254; long_chirp_lut[255] = 8'd132; + long_chirp_lut[256] = 8'd 1; long_chirp_lut[257] = 8'd105; long_chirp_lut[258] = 8'd250; long_chirp_lut[259] = 8'd169; long_chirp_lut[260] = 8'd 11; long_chirp_lut[261] = 8'd 69; long_chirp_lut[262] = 8'd235; long_chirp_lut[263] = 8'd203; long_chirp_lut[264] = 8'd 31; long_chirp_lut[265] = 8'd 37; long_chirp_lut[266] = 8'd210; long_chirp_lut[267] = 8'd230; long_chirp_lut[268] = 8'd 61; long_chirp_lut[269] = 8'd 14; long_chirp_lut[270] = 8'd176; long_chirp_lut[271] = 8'd248; + long_chirp_lut[272] = 8'd 98; long_chirp_lut[273] = 8'd 2; long_chirp_lut[274] = 8'd137; long_chirp_lut[275] = 8'd254; long_chirp_lut[276] = 8'd138; long_chirp_lut[277] = 8'd 2; long_chirp_lut[278] = 8'd 97; long_chirp_lut[279] = 8'd248; long_chirp_lut[280] = 8'd178; long_chirp_lut[281] = 8'd 15; long_chirp_lut[282] = 8'd 59; long_chirp_lut[283] = 8'd228; long_chirp_lut[284] = 8'd213; long_chirp_lut[285] = 8'd 41; long_chirp_lut[286] = 8'd 28; long_chirp_lut[287] = 8'd198; + long_chirp_lut[288] = 8'd239; long_chirp_lut[289] = 8'd 76; long_chirp_lut[290] = 8'd 8; long_chirp_lut[291] = 8'd159; long_chirp_lut[292] = 8'd253; long_chirp_lut[293] = 8'd117; long_chirp_lut[294] = 8'd 1; long_chirp_lut[295] = 8'd116; long_chirp_lut[296] = 8'd253; long_chirp_lut[297] = 8'd161; long_chirp_lut[298] = 8'd 8; long_chirp_lut[299] = 8'd 74; long_chirp_lut[300] = 8'd237; long_chirp_lut[301] = 8'd200; long_chirp_lut[302] = 8'd 30; long_chirp_lut[303] = 8'd 38; + long_chirp_lut[304] = 8'd209; long_chirp_lut[305] = 8'd232; long_chirp_lut[306] = 8'd 65; long_chirp_lut[307] = 8'd 12; long_chirp_lut[308] = 8'd170; long_chirp_lut[309] = 8'd251; long_chirp_lut[310] = 8'd107; long_chirp_lut[311] = 8'd 1; long_chirp_lut[312] = 8'd125; long_chirp_lut[313] = 8'd254; long_chirp_lut[314] = 8'd153; long_chirp_lut[315] = 8'd 6; long_chirp_lut[316] = 8'd 80; long_chirp_lut[317] = 8'd240; long_chirp_lut[318] = 8'd196; long_chirp_lut[319] = 8'd 27; + long_chirp_lut[320] = 8'd 40; long_chirp_lut[321] = 8'd211; long_chirp_lut[322] = 8'd230; long_chirp_lut[323] = 8'd 63; long_chirp_lut[324] = 8'd 13; long_chirp_lut[325] = 8'd171; long_chirp_lut[326] = 8'd251; long_chirp_lut[327] = 8'd108; long_chirp_lut[328] = 8'd 1; long_chirp_lut[329] = 8'd123; long_chirp_lut[330] = 8'd253; long_chirp_lut[331] = 8'd156; long_chirp_lut[332] = 8'd 7; long_chirp_lut[333] = 8'd 76; long_chirp_lut[334] = 8'd238; long_chirp_lut[335] = 8'd201; + long_chirp_lut[336] = 8'd 31; long_chirp_lut[337] = 8'd 36; long_chirp_lut[338] = 8'd206; long_chirp_lut[339] = 8'd235; long_chirp_lut[340] = 8'd 71; long_chirp_lut[341] = 8'd 9; long_chirp_lut[342] = 8'd161; long_chirp_lut[343] = 8'd253; long_chirp_lut[344] = 8'd119; long_chirp_lut[345] = 8'd 1; long_chirp_lut[346] = 8'd111; long_chirp_lut[347] = 8'd251; long_chirp_lut[348] = 8'd169; long_chirp_lut[349] = 8'd 12; long_chirp_lut[350] = 8'd 62; long_chirp_lut[351] = 8'd229; + long_chirp_lut[352] = 8'd213; long_chirp_lut[353] = 8'd 43; long_chirp_lut[354] = 8'd 24; long_chirp_lut[355] = 8'd191; long_chirp_lut[356] = 8'd244; long_chirp_lut[357] = 8'd 88; long_chirp_lut[358] = 8'd 3; long_chirp_lut[359] = 8'd141; long_chirp_lut[360] = 8'd255; long_chirp_lut[361] = 8'd141; long_chirp_lut[362] = 8'd 3; long_chirp_lut[363] = 8'd 88; long_chirp_lut[364] = 8'd243; long_chirp_lut[365] = 8'd191; long_chirp_lut[366] = 8'd 25; long_chirp_lut[367] = 8'd 42; + long_chirp_lut[368] = 8'd212; long_chirp_lut[369] = 8'd231; long_chirp_lut[370] = 8'd 66; long_chirp_lut[371] = 8'd 11; long_chirp_lut[372] = 8'd164; long_chirp_lut[373] = 8'd252; long_chirp_lut[374] = 8'd118; long_chirp_lut[375] = 8'd 1; long_chirp_lut[376] = 8'd110; long_chirp_lut[377] = 8'd251; long_chirp_lut[378] = 8'd172; long_chirp_lut[379] = 8'd 14; long_chirp_lut[380] = 8'd 58; long_chirp_lut[381] = 8'd225; long_chirp_lut[382] = 8'd219; long_chirp_lut[383] = 8'd 50; + long_chirp_lut[384] = 8'd 19; long_chirp_lut[385] = 8'd181; long_chirp_lut[386] = 8'd248; long_chirp_lut[387] = 8'd101; long_chirp_lut[388] = 8'd 1; long_chirp_lut[389] = 8'd125; long_chirp_lut[390] = 8'd253; long_chirp_lut[391] = 8'd158; long_chirp_lut[392] = 8'd 9; long_chirp_lut[393] = 8'd 70; long_chirp_lut[394] = 8'd233; long_chirp_lut[395] = 8'd209; long_chirp_lut[396] = 8'd 41; long_chirp_lut[397] = 8'd 26; long_chirp_lut[398] = 8'd191; long_chirp_lut[399] = 8'd244; + long_chirp_lut[400] = 8'd 91; long_chirp_lut[401] = 8'd 2; long_chirp_lut[402] = 8'd135; long_chirp_lut[403] = 8'd254; long_chirp_lut[404] = 8'd150; long_chirp_lut[405] = 8'd 6; long_chirp_lut[406] = 8'd 77; long_chirp_lut[407] = 8'd237; long_chirp_lut[408] = 8'd204; long_chirp_lut[409] = 8'd 36; long_chirp_lut[410] = 8'd 29; long_chirp_lut[411] = 8'd195; long_chirp_lut[412] = 8'd242; long_chirp_lut[413] = 8'd 87; long_chirp_lut[414] = 8'd 3; long_chirp_lut[415] = 8'd138; + long_chirp_lut[416] = 8'd254; long_chirp_lut[417] = 8'd148; long_chirp_lut[418] = 8'd 5; long_chirp_lut[419] = 8'd 78; long_chirp_lut[420] = 8'd237; long_chirp_lut[421] = 8'd204; long_chirp_lut[422] = 8'd 36; long_chirp_lut[423] = 8'd 29; long_chirp_lut[424] = 8'd195; long_chirp_lut[425] = 8'd243; long_chirp_lut[426] = 8'd 89; long_chirp_lut[427] = 8'd 3; long_chirp_lut[428] = 8'd135; long_chirp_lut[429] = 8'd254; long_chirp_lut[430] = 8'd151; long_chirp_lut[431] = 8'd 7; + long_chirp_lut[432] = 8'd 73; long_chirp_lut[433] = 8'd235; long_chirp_lut[434] = 8'd209; long_chirp_lut[435] = 8'd 41; long_chirp_lut[436] = 8'd 25; long_chirp_lut[437] = 8'd188; long_chirp_lut[438] = 8'd246; long_chirp_lut[439] = 8'd 97; long_chirp_lut[440] = 8'd 1; long_chirp_lut[441] = 8'd126; long_chirp_lut[442] = 8'd253; long_chirp_lut[443] = 8'd161; long_chirp_lut[444] = 8'd 10; long_chirp_lut[445] = 8'd 64; long_chirp_lut[446] = 8'd228; long_chirp_lut[447] = 8'd217; + long_chirp_lut[448] = 8'd 50; long_chirp_lut[449] = 8'd 18; long_chirp_lut[450] = 8'd176; long_chirp_lut[451] = 8'd250; long_chirp_lut[452] = 8'd111; long_chirp_lut[453] = 8'd 1; long_chirp_lut[454] = 8'd111; long_chirp_lut[455] = 8'd250; long_chirp_lut[456] = 8'd177; long_chirp_lut[457] = 8'd 18; long_chirp_lut[458] = 8'd 49; long_chirp_lut[459] = 8'd216; long_chirp_lut[460] = 8'd229; long_chirp_lut[461] = 8'd 66; long_chirp_lut[462] = 8'd 9; long_chirp_lut[463] = 8'd157; + long_chirp_lut[464] = 8'd254; long_chirp_lut[465] = 8'd132; long_chirp_lut[466] = 8'd 2; long_chirp_lut[467] = 8'd 90; long_chirp_lut[468] = 8'd242; long_chirp_lut[469] = 8'd197; long_chirp_lut[470] = 8'd 31; long_chirp_lut[471] = 8'd 32; long_chirp_lut[472] = 8'd198; long_chirp_lut[473] = 8'd242; long_chirp_lut[474] = 8'd 89; long_chirp_lut[475] = 8'd 2; long_chirp_lut[476] = 8'd132; long_chirp_lut[477] = 8'd254; long_chirp_lut[478] = 8'd158; long_chirp_lut[479] = 8'd 10; + long_chirp_lut[480] = 8'd 64; long_chirp_lut[481] = 8'd228; long_chirp_lut[482] = 8'd219; long_chirp_lut[483] = 8'd 53; long_chirp_lut[484] = 8'd 15; long_chirp_lut[485] = 8'd171; long_chirp_lut[486] = 8'd252; long_chirp_lut[487] = 8'd120; long_chirp_lut[488] = 8'd 1; long_chirp_lut[489] = 8'd100; long_chirp_lut[490] = 8'd246; long_chirp_lut[491] = 8'd189; long_chirp_lut[492] = 8'd 26; long_chirp_lut[493] = 8'd 37; long_chirp_lut[494] = 8'd203; long_chirp_lut[495] = 8'd240; + long_chirp_lut[496] = 8'd 84; long_chirp_lut[497] = 8'd 3; long_chirp_lut[498] = 8'd135; long_chirp_lut[499] = 8'd254; long_chirp_lut[500] = 8'd157; long_chirp_lut[501] = 8'd 9; long_chirp_lut[502] = 8'd 64; long_chirp_lut[503] = 8'd227; long_chirp_lut[504] = 8'd220; long_chirp_lut[505] = 8'd 55; long_chirp_lut[506] = 8'd 14; long_chirp_lut[507] = 8'd167; long_chirp_lut[508] = 8'd253; long_chirp_lut[509] = 8'd125; long_chirp_lut[510] = 8'd 2; long_chirp_lut[511] = 8'd 92; + long_chirp_lut[512] = 8'd243; long_chirp_lut[513] = 8'd197; long_chirp_lut[514] = 8'd 33; long_chirp_lut[515] = 8'd 30; long_chirp_lut[516] = 8'd193; long_chirp_lut[517] = 8'd245; long_chirp_lut[518] = 8'd 97; long_chirp_lut[519] = 8'd 1; long_chirp_lut[520] = 8'd120; long_chirp_lut[521] = 8'd252; long_chirp_lut[522] = 8'd172; long_chirp_lut[523] = 8'd 17; long_chirp_lut[524] = 8'd 49; long_chirp_lut[525] = 8'd214; long_chirp_lut[526] = 8'd232; long_chirp_lut[527] = 8'd 73; + long_chirp_lut[528] = 8'd 6; long_chirp_lut[529] = 8'd145; long_chirp_lut[530] = 8'd254; long_chirp_lut[531] = 8'd149; long_chirp_lut[532] = 8'd 7; long_chirp_lut[533] = 8'd 69; long_chirp_lut[534] = 8'd230; long_chirp_lut[535] = 8'd218; long_chirp_lut[536] = 8'd 53; long_chirp_lut[537] = 8'd 14; long_chirp_lut[538] = 8'd167; long_chirp_lut[539] = 8'd253; long_chirp_lut[540] = 8'd127; long_chirp_lut[541] = 8'd 2; long_chirp_lut[542] = 8'd 88; long_chirp_lut[543] = 8'd241; + long_chirp_lut[544] = 8'd202; long_chirp_lut[545] = 8'd 38; long_chirp_lut[546] = 8'd 24; long_chirp_lut[547] = 8'd184; long_chirp_lut[548] = 8'd249; long_chirp_lut[549] = 8'd109; long_chirp_lut[550] = 8'd 1; long_chirp_lut[551] = 8'd105; long_chirp_lut[552] = 8'd247; long_chirp_lut[553] = 8'd188; long_chirp_lut[554] = 8'd 27; long_chirp_lut[555] = 8'd 35; long_chirp_lut[556] = 8'd198; long_chirp_lut[557] = 8'd243; long_chirp_lut[558] = 8'd 94; long_chirp_lut[559] = 8'd 1; + long_chirp_lut[560] = 8'd120; long_chirp_lut[561] = 8'd251; long_chirp_lut[562] = 8'd175; long_chirp_lut[563] = 8'd 19; long_chirp_lut[564] = 8'd 45; long_chirp_lut[565] = 8'd209; long_chirp_lut[566] = 8'd237; long_chirp_lut[567] = 8'd 82; long_chirp_lut[568] = 8'd 3; long_chirp_lut[569] = 8'd132; long_chirp_lut[570] = 8'd253; long_chirp_lut[571] = 8'd165; long_chirp_lut[572] = 8'd 14; long_chirp_lut[573] = 8'd 53; long_chirp_lut[574] = 8'd216; long_chirp_lut[575] = 8'd232; + long_chirp_lut[576] = 8'd 73; long_chirp_lut[577] = 8'd 5; long_chirp_lut[578] = 8'd141; long_chirp_lut[579] = 8'd254; long_chirp_lut[580] = 8'd157; long_chirp_lut[581] = 8'd 11; long_chirp_lut[582] = 8'd 59; long_chirp_lut[583] = 8'd221; long_chirp_lut[584] = 8'd228; long_chirp_lut[585] = 8'd 68; long_chirp_lut[586] = 8'd 7; long_chirp_lut[587] = 8'd146; long_chirp_lut[588] = 8'd254; long_chirp_lut[589] = 8'd152; long_chirp_lut[590] = 8'd 9; long_chirp_lut[591] = 8'd 63; + long_chirp_lut[592] = 8'd224; long_chirp_lut[593] = 8'd225; long_chirp_lut[594] = 8'd 65; long_chirp_lut[595] = 8'd 8; long_chirp_lut[596] = 8'd149; long_chirp_lut[597] = 8'd254; long_chirp_lut[598] = 8'd150; long_chirp_lut[599] = 8'd 8; long_chirp_lut[600] = 8'd 64; long_chirp_lut[601] = 8'd225; long_chirp_lut[602] = 8'd225; long_chirp_lut[603] = 8'd 64; long_chirp_lut[604] = 8'd 8; long_chirp_lut[605] = 8'd149; long_chirp_lut[606] = 8'd254; long_chirp_lut[607] = 8'd150; + long_chirp_lut[608] = 8'd 9; long_chirp_lut[609] = 8'd 63; long_chirp_lut[610] = 8'd224; long_chirp_lut[611] = 8'd226; long_chirp_lut[612] = 8'd 66; long_chirp_lut[613] = 8'd 7; long_chirp_lut[614] = 8'd146; long_chirp_lut[615] = 8'd254; long_chirp_lut[616] = 8'd154; long_chirp_lut[617] = 8'd 10; long_chirp_lut[618] = 8'd 59; long_chirp_lut[619] = 8'd220; long_chirp_lut[620] = 8'd229; long_chirp_lut[621] = 8'd 71; long_chirp_lut[622] = 8'd 5; long_chirp_lut[623] = 8'd140; + long_chirp_lut[624] = 8'd254; long_chirp_lut[625] = 8'd161; long_chirp_lut[626] = 8'd 13; long_chirp_lut[627] = 8'd 53; long_chirp_lut[628] = 8'd215; long_chirp_lut[629] = 8'd234; long_chirp_lut[630] = 8'd 79; long_chirp_lut[631] = 8'd 3; long_chirp_lut[632] = 8'd131; long_chirp_lut[633] = 8'd253; long_chirp_lut[634] = 8'd170; long_chirp_lut[635] = 8'd 18; long_chirp_lut[636] = 8'd 45; long_chirp_lut[637] = 8'd207; long_chirp_lut[638] = 8'd240; long_chirp_lut[639] = 8'd 90; + long_chirp_lut[640] = 8'd 1; long_chirp_lut[641] = 8'd119; long_chirp_lut[642] = 8'd250; long_chirp_lut[643] = 8'd182; long_chirp_lut[644] = 8'd 25; long_chirp_lut[645] = 8'd 35; long_chirp_lut[646] = 8'd195; long_chirp_lut[647] = 8'd246; long_chirp_lut[648] = 8'd104; long_chirp_lut[649] = 8'd 1; long_chirp_lut[650] = 8'd104; long_chirp_lut[651] = 8'd246; long_chirp_lut[652] = 8'd196; long_chirp_lut[653] = 8'd 35; long_chirp_lut[654] = 8'd 24; long_chirp_lut[655] = 8'd181; + long_chirp_lut[656] = 8'd251; long_chirp_lut[657] = 8'd121; long_chirp_lut[658] = 8'd 2; long_chirp_lut[659] = 8'd 86; long_chirp_lut[660] = 8'd237; long_chirp_lut[661] = 8'd211; long_chirp_lut[662] = 8'd 49; long_chirp_lut[663] = 8'd 14; long_chirp_lut[664] = 8'd162; long_chirp_lut[665] = 8'd254; long_chirp_lut[666] = 8'd141; long_chirp_lut[667] = 8'd 6; long_chirp_lut[668] = 8'd 67; long_chirp_lut[669] = 8'd225; long_chirp_lut[670] = 8'd226; long_chirp_lut[671] = 8'd 68; + long_chirp_lut[672] = 8'd 6; long_chirp_lut[673] = 8'd140; long_chirp_lut[674] = 8'd254; long_chirp_lut[675] = 8'd164; long_chirp_lut[676] = 8'd 16; long_chirp_lut[677] = 8'd 47; long_chirp_lut[678] = 8'd208; long_chirp_lut[679] = 8'd240; long_chirp_lut[680] = 8'd 91; long_chirp_lut[681] = 8'd 1; long_chirp_lut[682] = 8'd114; long_chirp_lut[683] = 8'd249; long_chirp_lut[684] = 8'd189; long_chirp_lut[685] = 8'd 31; long_chirp_lut[686] = 8'd 28; long_chirp_lut[687] = 8'd185; + long_chirp_lut[688] = 8'd250; long_chirp_lut[689] = 8'd119; long_chirp_lut[690] = 8'd 2; long_chirp_lut[691] = 8'd 86; long_chirp_lut[692] = 8'd237; long_chirp_lut[693] = 8'd213; long_chirp_lut[694] = 8'd 52; long_chirp_lut[695] = 8'd 12; long_chirp_lut[696] = 8'd157; long_chirp_lut[697] = 8'd254; long_chirp_lut[698] = 8'd150; long_chirp_lut[699] = 8'd 9; long_chirp_lut[700] = 8'd 58; long_chirp_lut[701] = 8'd217; long_chirp_lut[702] = 8'd234; long_chirp_lut[703] = 8'd 81; + long_chirp_lut[704] = 8'd 2; long_chirp_lut[705] = 8'd123; long_chirp_lut[706] = 8'd251; long_chirp_lut[707] = 8'd182; long_chirp_lut[708] = 8'd 26; long_chirp_lut[709] = 8'd 32; long_chirp_lut[710] = 8'd189; long_chirp_lut[711] = 8'd249; long_chirp_lut[712] = 8'd115; long_chirp_lut[713] = 8'd 1; long_chirp_lut[714] = 8'd 88; long_chirp_lut[715] = 8'd237; long_chirp_lut[716] = 8'd213; long_chirp_lut[717] = 8'd 53; long_chirp_lut[718] = 8'd 11; long_chirp_lut[719] = 8'd154; + long_chirp_lut[720] = 8'd255; long_chirp_lut[721] = 8'd154; long_chirp_lut[722] = 8'd 12; long_chirp_lut[723] = 8'd 53; long_chirp_lut[724] = 8'd212; long_chirp_lut[725] = 8'd238; long_chirp_lut[726] = 8'd 89; long_chirp_lut[727] = 8'd 1; long_chirp_lut[728] = 8'd113; long_chirp_lut[729] = 8'd248; long_chirp_lut[730] = 8'd193; long_chirp_lut[731] = 8'd 35; long_chirp_lut[732] = 8'd 23; long_chirp_lut[733] = 8'd176; long_chirp_lut[734] = 8'd252; long_chirp_lut[735] = 8'd132; + long_chirp_lut[736] = 8'd 4; long_chirp_lut[737] = 8'd 71; long_chirp_lut[738] = 8'd227; long_chirp_lut[739] = 8'd226; long_chirp_lut[740] = 8'd 71; long_chirp_lut[741] = 8'd 4; long_chirp_lut[742] = 8'd132; long_chirp_lut[743] = 8'd252; long_chirp_lut[744] = 8'd177; long_chirp_lut[745] = 8'd 24; long_chirp_lut[746] = 8'd 34; long_chirp_lut[747] = 8'd191; long_chirp_lut[748] = 8'd249; long_chirp_lut[749] = 8'd116; long_chirp_lut[750] = 8'd 2; long_chirp_lut[751] = 8'd 84; + long_chirp_lut[752] = 8'd235; long_chirp_lut[753] = 8'd217; long_chirp_lut[754] = 8'd 60; long_chirp_lut[755] = 8'd 8; long_chirp_lut[756] = 8'd143; long_chirp_lut[757] = 8'd254; long_chirp_lut[758] = 8'd167; long_chirp_lut[759] = 8'd 18; long_chirp_lut[760] = 8'd 40; long_chirp_lut[761] = 8'd199; long_chirp_lut[762] = 8'd246; long_chirp_lut[763] = 8'd109; long_chirp_lut[764] = 8'd 1; long_chirp_lut[765] = 8'd 91; long_chirp_lut[766] = 8'd238; long_chirp_lut[767] = 8'd213; + long_chirp_lut[768] = 8'd 55; long_chirp_lut[769] = 8'd 10; long_chirp_lut[770] = 8'd148; long_chirp_lut[771] = 8'd254; long_chirp_lut[772] = 8'd164; long_chirp_lut[773] = 8'd 17; long_chirp_lut[774] = 8'd 42; long_chirp_lut[775] = 8'd200; long_chirp_lut[776] = 8'd245; long_chirp_lut[777] = 8'd108; long_chirp_lut[778] = 8'd 1; long_chirp_lut[779] = 8'd 90; long_chirp_lut[780] = 8'd237; long_chirp_lut[781] = 8'd214; long_chirp_lut[782] = 8'd 57; long_chirp_lut[783] = 8'd 9; + long_chirp_lut[784] = 8'd145; long_chirp_lut[785] = 8'd254; long_chirp_lut[786] = 8'd167; long_chirp_lut[787] = 8'd 19; long_chirp_lut[788] = 8'd 38; long_chirp_lut[789] = 8'd195; long_chirp_lut[790] = 8'd247; long_chirp_lut[791] = 8'd114; long_chirp_lut[792] = 8'd 2; long_chirp_lut[793] = 8'd 83; long_chirp_lut[794] = 8'd233; long_chirp_lut[795] = 8'd220; long_chirp_lut[796] = 8'd 64; long_chirp_lut[797] = 8'd 6; long_chirp_lut[798] = 8'd135; long_chirp_lut[799] = 8'd253; + long_chirp_lut[800] = 8'd178; long_chirp_lut[801] = 8'd 26; long_chirp_lut[802] = 8'd 30; long_chirp_lut[803] = 8'd184; long_chirp_lut[804] = 8'd251; long_chirp_lut[805] = 8'd128; long_chirp_lut[806] = 8'd 4; long_chirp_lut[807] = 8'd 70; long_chirp_lut[808] = 8'd224; long_chirp_lut[809] = 8'd230; long_chirp_lut[810] = 8'd 79; long_chirp_lut[811] = 8'd 2; long_chirp_lut[812] = 8'd117; long_chirp_lut[813] = 8'd248; long_chirp_lut[814] = 8'd194; long_chirp_lut[815] = 8'd 38; + long_chirp_lut[816] = 8'd 19; long_chirp_lut[817] = 8'd166; long_chirp_lut[818] = 8'd254; long_chirp_lut[819] = 8'd149; long_chirp_lut[820] = 8'd 11; long_chirp_lut[821] = 8'd 51; long_chirp_lut[822] = 8'd208; long_chirp_lut[823] = 8'd242; long_chirp_lut[824] = 8'd101; long_chirp_lut[825] = 8'd 1; long_chirp_lut[826] = 8'd 93; long_chirp_lut[827] = 8'd238; long_chirp_lut[828] = 8'd214; long_chirp_lut[829] = 8'd 58; long_chirp_lut[830] = 8'd 8; long_chirp_lut[831] = 8'd139; + long_chirp_lut[832] = 8'd253; long_chirp_lut[833] = 8'd176; long_chirp_lut[834] = 8'd 25; long_chirp_lut[835] = 8'd 30; long_chirp_lut[836] = 8'd183; long_chirp_lut[837] = 8'd252; long_chirp_lut[838] = 8'd132; long_chirp_lut[839] = 8'd 5; long_chirp_lut[840] = 8'd 64; long_chirp_lut[841] = 8'd219; long_chirp_lut[842] = 8'd235; long_chirp_lut[843] = 8'd 88; long_chirp_lut[844] = 8'd 1; long_chirp_lut[845] = 8'd105; long_chirp_lut[846] = 8'd243; long_chirp_lut[847] = 8'd206; + long_chirp_lut[848] = 8'd 50; long_chirp_lut[849] = 8'd 11; long_chirp_lut[850] = 8'd148; long_chirp_lut[851] = 8'd254; long_chirp_lut[852] = 8'd169; long_chirp_lut[853] = 8'd 21; long_chirp_lut[854] = 8'd 34; long_chirp_lut[855] = 8'd187; long_chirp_lut[856] = 8'd251; long_chirp_lut[857] = 8'd128; long_chirp_lut[858] = 8'd 5; long_chirp_lut[859] = 8'd 66; long_chirp_lut[860] = 8'd220; long_chirp_lut[861] = 8'd235; long_chirp_lut[862] = 8'd 88; long_chirp_lut[863] = 8'd 1; + long_chirp_lut[864] = 8'd104; long_chirp_lut[865] = 8'd242; long_chirp_lut[866] = 8'd209; long_chirp_lut[867] = 8'd 53; long_chirp_lut[868] = 8'd 9; long_chirp_lut[869] = 8'd143; long_chirp_lut[870] = 8'd253; long_chirp_lut[871] = 8'd175; long_chirp_lut[872] = 8'd 25; long_chirp_lut[873] = 8'd 29; long_chirp_lut[874] = 8'd180; long_chirp_lut[875] = 8'd253; long_chirp_lut[876] = 8'd138; long_chirp_lut[877] = 8'd 8; long_chirp_lut[878] = 8'd 56; long_chirp_lut[879] = 8'd211; + long_chirp_lut[880] = 8'd241; long_chirp_lut[881] = 8'd101; long_chirp_lut[882] = 8'd 1; long_chirp_lut[883] = 8'd 90; long_chirp_lut[884] = 8'd235; long_chirp_lut[885] = 8'd220; long_chirp_lut[886] = 8'd 67; long_chirp_lut[887] = 8'd 4; long_chirp_lut[888] = 8'd125; long_chirp_lut[889] = 8'd250; long_chirp_lut[890] = 8'd193; long_chirp_lut[891] = 8'd 39; long_chirp_lut[892] = 8'd 17; long_chirp_lut[893] = 8'd159; long_chirp_lut[894] = 8'd254; long_chirp_lut[895] = 8'd161; + long_chirp_lut[896] = 8'd 18; long_chirp_lut[897] = 8'd 38; long_chirp_lut[898] = 8'd191; long_chirp_lut[899] = 8'd250; long_chirp_lut[900] = 8'd127; long_chirp_lut[901] = 8'd 5; long_chirp_lut[902] = 8'd 64; long_chirp_lut[903] = 8'd217; long_chirp_lut[904] = 8'd238; long_chirp_lut[905] = 8'd 95; long_chirp_lut[906] = 8'd 1; long_chirp_lut[907] = 8'd 94; long_chirp_lut[908] = 8'd237; long_chirp_lut[909] = 8'd218; long_chirp_lut[910] = 8'd 66; long_chirp_lut[911] = 8'd 4; + long_chirp_lut[912] = 8'd125; long_chirp_lut[913] = 8'd249; long_chirp_lut[914] = 8'd194; long_chirp_lut[915] = 8'd 41; long_chirp_lut[916] = 8'd 15; long_chirp_lut[917] = 8'd155; long_chirp_lut[918] = 8'd254; long_chirp_lut[919] = 8'd167; long_chirp_lut[920] = 8'd 21; long_chirp_lut[921] = 8'd 32; long_chirp_lut[922] = 8'd183; long_chirp_lut[923] = 8'd252; long_chirp_lut[924] = 8'd138; long_chirp_lut[925] = 8'd 8; long_chirp_lut[926] = 8'd 54; long_chirp_lut[927] = 8'd207; + long_chirp_lut[928] = 8'd244; long_chirp_lut[929] = 8'd110; long_chirp_lut[930] = 8'd 2; long_chirp_lut[931] = 8'd 78; long_chirp_lut[932] = 8'd227; long_chirp_lut[933] = 8'd230; long_chirp_lut[934] = 8'd 83; long_chirp_lut[935] = 8'd 1; long_chirp_lut[936] = 8'd104; long_chirp_lut[937] = 8'd241; long_chirp_lut[938] = 8'd213; long_chirp_lut[939] = 8'd 60; long_chirp_lut[940] = 8'd 6; long_chirp_lut[941] = 8'd130; long_chirp_lut[942] = 8'd250; long_chirp_lut[943] = 8'd192; + long_chirp_lut[944] = 8'd 39; long_chirp_lut[945] = 8'd 15; long_chirp_lut[946] = 8'd155; long_chirp_lut[947] = 8'd254; long_chirp_lut[948] = 8'd169; long_chirp_lut[949] = 8'd 23; long_chirp_lut[950] = 8'd 29; long_chirp_lut[951] = 8'd178; long_chirp_lut[952] = 8'd253; long_chirp_lut[953] = 8'd146; long_chirp_lut[954] = 8'd 12; long_chirp_lut[955] = 8'd 46; long_chirp_lut[956] = 8'd198; long_chirp_lut[957] = 8'd248; long_chirp_lut[958] = 8'd123; long_chirp_lut[959] = 8'd 4; + long_chirp_lut[960] = 8'd 64; long_chirp_lut[961] = 8'd216; long_chirp_lut[962] = 8'd240; long_chirp_lut[963] = 8'd101; long_chirp_lut[964] = 8'd 1; long_chirp_lut[965] = 8'd 84; long_chirp_lut[966] = 8'd230; long_chirp_lut[967] = 8'd228; long_chirp_lut[968] = 8'd 81; long_chirp_lut[969] = 8'd 1; long_chirp_lut[970] = 8'd104; long_chirp_lut[971] = 8'd241; long_chirp_lut[972] = 8'd214; long_chirp_lut[973] = 8'd 63; long_chirp_lut[974] = 8'd 4; long_chirp_lut[975] = 8'd123; + long_chirp_lut[976] = 8'd248; long_chirp_lut[977] = 8'd199; long_chirp_lut[978] = 8'd 47; long_chirp_lut[979] = 8'd 11; long_chirp_lut[980] = 8'd142; long_chirp_lut[981] = 8'd253; long_chirp_lut[982] = 8'd183; long_chirp_lut[983] = 8'd 34; long_chirp_lut[984] = 8'd 19; long_chirp_lut[985] = 8'd160; long_chirp_lut[986] = 8'd254; long_chirp_lut[987] = 8'd167; long_chirp_lut[988] = 8'd 23; long_chirp_lut[989] = 8'd 29; long_chirp_lut[990] = 8'd176; long_chirp_lut[991] = 8'd254; + long_chirp_lut[992] = 8'd151; long_chirp_lut[993] = 8'd 14; long_chirp_lut[994] = 8'd 40; long_chirp_lut[995] = 8'd191; long_chirp_lut[996] = 8'd251; long_chirp_lut[997] = 8'd135; long_chirp_lut[998] = 8'd 8; long_chirp_lut[999] = 8'd 52; long_chirp_lut[1000] = 8'd203; long_chirp_lut[1001] = 8'd247; long_chirp_lut[1002] = 8'd120; long_chirp_lut[1003] = 8'd 4; long_chirp_lut[1004] = 8'd 64; long_chirp_lut[1005] = 8'd214; long_chirp_lut[1006] = 8'd241; long_chirp_lut[1007] = 8'd106; + long_chirp_lut[1008] = 8'd 2; long_chirp_lut[1009] = 8'd 76; long_chirp_lut[1010] = 8'd224; long_chirp_lut[1011] = 8'd235; long_chirp_lut[1012] = 8'd 94; long_chirp_lut[1013] = 8'd 1; long_chirp_lut[1014] = 8'd 88; long_chirp_lut[1015] = 8'd231; long_chirp_lut[1016] = 8'd228; long_chirp_lut[1017] = 8'd 82; long_chirp_lut[1018] = 8'd 1; long_chirp_lut[1019] = 8'd 99; long_chirp_lut[1020] = 8'd237; long_chirp_lut[1021] = 8'd220; long_chirp_lut[1022] = 8'd 72; long_chirp_lut[1023] = 8'd 2; + long_chirp_lut[1024] = 8'd110; long_chirp_lut[1025] = 8'd242; long_chirp_lut[1026] = 8'd213; long_chirp_lut[1027] = 8'd 63; long_chirp_lut[1028] = 8'd 4; long_chirp_lut[1029] = 8'd119; long_chirp_lut[1030] = 8'd246; long_chirp_lut[1031] = 8'd206; long_chirp_lut[1032] = 8'd 55; long_chirp_lut[1033] = 8'd 6; long_chirp_lut[1034] = 8'd128; long_chirp_lut[1035] = 8'd249; long_chirp_lut[1036] = 8'd199; long_chirp_lut[1037] = 8'd 48; long_chirp_lut[1038] = 8'd 9; long_chirp_lut[1039] = 8'd136; + long_chirp_lut[1040] = 8'd251; long_chirp_lut[1041] = 8'd192; long_chirp_lut[1042] = 8'd 43; long_chirp_lut[1043] = 8'd 12; long_chirp_lut[1044] = 8'd143; long_chirp_lut[1045] = 8'd252; long_chirp_lut[1046] = 8'd186; long_chirp_lut[1047] = 8'd 38; long_chirp_lut[1048] = 8'd 15; long_chirp_lut[1049] = 8'd150; long_chirp_lut[1050] = 8'd253; long_chirp_lut[1051] = 8'd181; long_chirp_lut[1052] = 8'd 34; long_chirp_lut[1053] = 8'd 17; long_chirp_lut[1054] = 8'd155; long_chirp_lut[1055] = 8'd254; + long_chirp_lut[1056] = 8'd177; long_chirp_lut[1057] = 8'd 31; long_chirp_lut[1058] = 8'd 20; long_chirp_lut[1059] = 8'd159; long_chirp_lut[1060] = 8'd254; long_chirp_lut[1061] = 8'd173; long_chirp_lut[1062] = 8'd 28; long_chirp_lut[1063] = 8'd 22; long_chirp_lut[1064] = 8'd162; long_chirp_lut[1065] = 8'd254; long_chirp_lut[1066] = 8'd170; long_chirp_lut[1067] = 8'd 27; long_chirp_lut[1068] = 8'd 23; long_chirp_lut[1069] = 8'd165; long_chirp_lut[1070] = 8'd254; long_chirp_lut[1071] = 8'd168; + long_chirp_lut[1072] = 8'd 25; long_chirp_lut[1073] = 8'd 24; long_chirp_lut[1074] = 8'd166; long_chirp_lut[1075] = 8'd254; long_chirp_lut[1076] = 8'd167; long_chirp_lut[1077] = 8'd 25; long_chirp_lut[1078] = 8'd 25; long_chirp_lut[1079] = 8'd167; long_chirp_lut[1080] = 8'd255; long_chirp_lut[1081] = 8'd167; long_chirp_lut[1082] = 8'd 25; long_chirp_lut[1083] = 8'd 25; long_chirp_lut[1084] = 8'd166; long_chirp_lut[1085] = 8'd254; long_chirp_lut[1086] = 8'd167; long_chirp_lut[1087] = 8'd 25; + long_chirp_lut[1088] = 8'd 24; long_chirp_lut[1089] = 8'd165; long_chirp_lut[1090] = 8'd254; long_chirp_lut[1091] = 8'd169; long_chirp_lut[1092] = 8'd 26; long_chirp_lut[1093] = 8'd 23; long_chirp_lut[1094] = 8'd163; long_chirp_lut[1095] = 8'd254; long_chirp_lut[1096] = 8'd171; long_chirp_lut[1097] = 8'd 28; long_chirp_lut[1098] = 8'd 21; long_chirp_lut[1099] = 8'd160; long_chirp_lut[1100] = 8'd254; long_chirp_lut[1101] = 8'd174; long_chirp_lut[1102] = 8'd 30; long_chirp_lut[1103] = 8'd 19; + long_chirp_lut[1104] = 8'd157; long_chirp_lut[1105] = 8'd254; long_chirp_lut[1106] = 8'd178; long_chirp_lut[1107] = 8'd 33; long_chirp_lut[1108] = 8'd 17; long_chirp_lut[1109] = 8'd152; long_chirp_lut[1110] = 8'd253; long_chirp_lut[1111] = 8'd183; long_chirp_lut[1112] = 8'd 37; long_chirp_lut[1113] = 8'd 14; long_chirp_lut[1114] = 8'd146; long_chirp_lut[1115] = 8'd252; long_chirp_lut[1116] = 8'd189; long_chirp_lut[1117] = 8'd 42; long_chirp_lut[1118] = 8'd 11; long_chirp_lut[1119] = 8'd139; + long_chirp_lut[1120] = 8'd251; long_chirp_lut[1121] = 8'd195; long_chirp_lut[1122] = 8'd 47; long_chirp_lut[1123] = 8'd 9; long_chirp_lut[1124] = 8'd132; long_chirp_lut[1125] = 8'd249; long_chirp_lut[1126] = 8'd201; long_chirp_lut[1127] = 8'd 54; long_chirp_lut[1128] = 8'd 6; long_chirp_lut[1129] = 8'd123; long_chirp_lut[1130] = 8'd246; long_chirp_lut[1131] = 8'd209; long_chirp_lut[1132] = 8'd 61; long_chirp_lut[1133] = 8'd 4; long_chirp_lut[1134] = 8'd114; long_chirp_lut[1135] = 8'd242; + long_chirp_lut[1136] = 8'd216; long_chirp_lut[1137] = 8'd 70; long_chirp_lut[1138] = 8'd 2; long_chirp_lut[1139] = 8'd103; long_chirp_lut[1140] = 8'd237; long_chirp_lut[1141] = 8'd223; long_chirp_lut[1142] = 8'd 80; long_chirp_lut[1143] = 8'd 1; long_chirp_lut[1144] = 8'd 92; long_chirp_lut[1145] = 8'd231; long_chirp_lut[1146] = 8'd231; long_chirp_lut[1147] = 8'd 91; long_chirp_lut[1148] = 8'd 1; long_chirp_lut[1149] = 8'd 81; long_chirp_lut[1150] = 8'd224; long_chirp_lut[1151] = 8'd237; + long_chirp_lut[1152] = 8'd104; long_chirp_lut[1153] = 8'd 2; long_chirp_lut[1154] = 8'd 69; long_chirp_lut[1155] = 8'd214; long_chirp_lut[1156] = 8'd244; long_chirp_lut[1157] = 8'd117; long_chirp_lut[1158] = 8'd 5; long_chirp_lut[1159] = 8'd 56; long_chirp_lut[1160] = 8'd203; long_chirp_lut[1161] = 8'd249; long_chirp_lut[1162] = 8'd132; long_chirp_lut[1163] = 8'd 9; long_chirp_lut[1164] = 8'd 45; long_chirp_lut[1165] = 8'd191; long_chirp_lut[1166] = 8'd252; long_chirp_lut[1167] = 8'd148; + long_chirp_lut[1168] = 8'd 16; long_chirp_lut[1169] = 8'd 33; long_chirp_lut[1170] = 8'd176; long_chirp_lut[1171] = 8'd254; long_chirp_lut[1172] = 8'd164; long_chirp_lut[1173] = 8'd 25; long_chirp_lut[1174] = 8'd 23; long_chirp_lut[1175] = 8'd160; long_chirp_lut[1176] = 8'd254; long_chirp_lut[1177] = 8'd180; long_chirp_lut[1178] = 8'd 36; long_chirp_lut[1179] = 8'd 14; long_chirp_lut[1180] = 8'd142; long_chirp_lut[1181] = 8'd251; long_chirp_lut[1182] = 8'd196; long_chirp_lut[1183] = 8'd 50; + long_chirp_lut[1184] = 8'd 7; long_chirp_lut[1185] = 8'd123; long_chirp_lut[1186] = 8'd246; long_chirp_lut[1187] = 8'd212; long_chirp_lut[1188] = 8'd 66; long_chirp_lut[1189] = 8'd 2; long_chirp_lut[1190] = 8'd104; long_chirp_lut[1191] = 8'd237; long_chirp_lut[1192] = 8'd226; long_chirp_lut[1193] = 8'd 85; long_chirp_lut[1194] = 8'd 1; long_chirp_lut[1195] = 8'd 84; long_chirp_lut[1196] = 8'd225; long_chirp_lut[1197] = 8'd238; long_chirp_lut[1198] = 8'd106; long_chirp_lut[1199] = 8'd 2; + long_chirp_lut[1200] = 8'd 64; long_chirp_lut[1201] = 8'd209; long_chirp_lut[1202] = 8'd247; long_chirp_lut[1203] = 8'd128; long_chirp_lut[1204] = 8'd 8; long_chirp_lut[1205] = 8'd 46; long_chirp_lut[1206] = 8'd190; long_chirp_lut[1207] = 8'd253; long_chirp_lut[1208] = 8'd151; long_chirp_lut[1209] = 8'd 18; long_chirp_lut[1210] = 8'd 29; long_chirp_lut[1211] = 8'd169; long_chirp_lut[1212] = 8'd254; long_chirp_lut[1213] = 8'd174; long_chirp_lut[1214] = 8'd 33; long_chirp_lut[1215] = 8'd 15; + long_chirp_lut[1216] = 8'd145; long_chirp_lut[1217] = 8'd252; long_chirp_lut[1218] = 8'd196; long_chirp_lut[1219] = 8'd 51; long_chirp_lut[1220] = 8'd 6; long_chirp_lut[1221] = 8'd119; long_chirp_lut[1222] = 8'd243; long_chirp_lut[1223] = 8'd216; long_chirp_lut[1224] = 8'd 73; long_chirp_lut[1225] = 8'd 1; long_chirp_lut[1226] = 8'd 93; long_chirp_lut[1227] = 8'd230; long_chirp_lut[1228] = 8'd233; long_chirp_lut[1229] = 8'd 99; long_chirp_lut[1230] = 8'd 2; long_chirp_lut[1231] = 8'd 68; + long_chirp_lut[1232] = 8'd212; long_chirp_lut[1233] = 8'd246; long_chirp_lut[1234] = 8'd127; long_chirp_lut[1235] = 8'd 8; long_chirp_lut[1236] = 8'd 45; long_chirp_lut[1237] = 8'd188; long_chirp_lut[1238] = 8'd253; long_chirp_lut[1239] = 8'd155; long_chirp_lut[1240] = 8'd 21; long_chirp_lut[1241] = 8'd 25; long_chirp_lut[1242] = 8'd161; long_chirp_lut[1243] = 8'd254; long_chirp_lut[1244] = 8'd183; long_chirp_lut[1245] = 8'd 41; long_chirp_lut[1246] = 8'd 10; long_chirp_lut[1247] = 8'd131; + long_chirp_lut[1248] = 8'd247; long_chirp_lut[1249] = 8'd209; long_chirp_lut[1250] = 8'd 66; long_chirp_lut[1251] = 8'd 2; long_chirp_lut[1252] = 8'd100; long_chirp_lut[1253] = 8'd234; long_chirp_lut[1254] = 8'd231; long_chirp_lut[1255] = 8'd 95; long_chirp_lut[1256] = 8'd 1; long_chirp_lut[1257] = 8'd 70; long_chirp_lut[1258] = 8'd212; long_chirp_lut[1259] = 8'd246; long_chirp_lut[1260] = 8'd128; long_chirp_lut[1261] = 8'd 9; long_chirp_lut[1262] = 8'd 42; long_chirp_lut[1263] = 8'd185; + long_chirp_lut[1264] = 8'd254; long_chirp_lut[1265] = 8'd161; long_chirp_lut[1266] = 8'd 25; long_chirp_lut[1267] = 8'd 20; long_chirp_lut[1268] = 8'd153; long_chirp_lut[1269] = 8'd253; long_chirp_lut[1270] = 8'd193; long_chirp_lut[1271] = 8'd 49; long_chirp_lut[1272] = 8'd 6; long_chirp_lut[1273] = 8'd118; long_chirp_lut[1274] = 8'd242; long_chirp_lut[1275] = 8'd220; long_chirp_lut[1276] = 8'd 80; long_chirp_lut[1277] = 8'd 1; long_chirp_lut[1278] = 8'd 83; long_chirp_lut[1279] = 8'd222; + long_chirp_lut[1280] = 8'd241; long_chirp_lut[1281] = 8'd116; long_chirp_lut[1282] = 8'd 5; long_chirp_lut[1283] = 8'd 50; long_chirp_lut[1284] = 8'd193; long_chirp_lut[1285] = 8'd253; long_chirp_lut[1286] = 8'd153; long_chirp_lut[1287] = 8'd 21; long_chirp_lut[1288] = 8'd 24; long_chirp_lut[1289] = 8'd158; long_chirp_lut[1290] = 8'd253; long_chirp_lut[1291] = 8'd189; long_chirp_lut[1292] = 8'd 47; long_chirp_lut[1293] = 8'd 7; long_chirp_lut[1294] = 8'd119; long_chirp_lut[1295] = 8'd242; + long_chirp_lut[1296] = 8'd220; long_chirp_lut[1297] = 8'd 81; long_chirp_lut[1298] = 8'd 1; long_chirp_lut[1299] = 8'd 81; long_chirp_lut[1300] = 8'd220; long_chirp_lut[1301] = 8'd243; long_chirp_lut[1302] = 8'd120; long_chirp_lut[1303] = 8'd 7; long_chirp_lut[1304] = 8'd 46; long_chirp_lut[1305] = 8'd187; long_chirp_lut[1306] = 8'd254; long_chirp_lut[1307] = 8'd161; long_chirp_lut[1308] = 8'd 26; long_chirp_lut[1309] = 8'd 19; long_chirp_lut[1310] = 8'd148; long_chirp_lut[1311] = 8'd251; + long_chirp_lut[1312] = 8'd199; long_chirp_lut[1313] = 8'd 57; long_chirp_lut[1314] = 8'd 3; long_chirp_lut[1315] = 8'd105; long_chirp_lut[1316] = 8'd235; long_chirp_lut[1317] = 8'd230; long_chirp_lut[1318] = 8'd 97; long_chirp_lut[1319] = 8'd 2; long_chirp_lut[1320] = 8'd 64; long_chirp_lut[1321] = 8'd206; long_chirp_lut[1322] = 8'd250; long_chirp_lut[1323] = 8'd141; long_chirp_lut[1324] = 8'd 16; long_chirp_lut[1325] = 8'd 30; long_chirp_lut[1326] = 8'd166; long_chirp_lut[1327] = 8'd254; + long_chirp_lut[1328] = 8'd184; long_chirp_lut[1329] = 8'd 44; long_chirp_lut[1330] = 8'd 8; long_chirp_lut[1331] = 8'd121; long_chirp_lut[1332] = 8'd242; long_chirp_lut[1333] = 8'd221; long_chirp_lut[1334] = 8'd 83; long_chirp_lut[1335] = 8'd 1; long_chirp_lut[1336] = 8'd 76; long_chirp_lut[1337] = 8'd215; long_chirp_lut[1338] = 8'd246; long_chirp_lut[1339] = 8'd130; long_chirp_lut[1340] = 8'd 11; long_chirp_lut[1341] = 8'd 37; long_chirp_lut[1342] = 8'd175; long_chirp_lut[1343] = 8'd254; + long_chirp_lut[1344] = 8'd177; long_chirp_lut[1345] = 8'd 38; long_chirp_lut[1346] = 8'd 10; long_chirp_lut[1347] = 8'd127; long_chirp_lut[1348] = 8'd245; long_chirp_lut[1349] = 8'd217; long_chirp_lut[1350] = 8'd 79; long_chirp_lut[1351] = 8'd 1; long_chirp_lut[1352] = 8'd 79; long_chirp_lut[1353] = 8'd217; long_chirp_lut[1354] = 8'd245; long_chirp_lut[1355] = 8'd128; long_chirp_lut[1356] = 8'd 10; long_chirp_lut[1357] = 8'd 37; long_chirp_lut[1358] = 8'd175; long_chirp_lut[1359] = 8'd254; + long_chirp_lut[1360] = 8'd178; long_chirp_lut[1361] = 8'd 39; long_chirp_lut[1362] = 8'd 9; long_chirp_lut[1363] = 8'd124; long_chirp_lut[1364] = 8'd243; long_chirp_lut[1365] = 8'd220; long_chirp_lut[1366] = 8'd 83; long_chirp_lut[1367] = 8'd 1; long_chirp_lut[1368] = 8'd 73; long_chirp_lut[1369] = 8'd212; long_chirp_lut[1370] = 8'd247; long_chirp_lut[1371] = 8'd136; long_chirp_lut[1372] = 8'd 14; long_chirp_lut[1373] = 8'd 31; long_chirp_lut[1374] = 8'd166; long_chirp_lut[1375] = 8'd254; + long_chirp_lut[1376] = 8'd187; long_chirp_lut[1377] = 8'd 48; long_chirp_lut[1378] = 8'd 5; long_chirp_lut[1379] = 8'd112; long_chirp_lut[1380] = 8'd237; long_chirp_lut[1381] = 8'd229; long_chirp_lut[1382] = 8'd 97; long_chirp_lut[1383] = 8'd 2; long_chirp_lut[1384] = 8'd 60; long_chirp_lut[1385] = 8'd200; long_chirp_lut[1386] = 8'd252; long_chirp_lut[1387] = 8'd153; long_chirp_lut[1388] = 8'd 23; long_chirp_lut[1389] = 8'd 20; long_chirp_lut[1390] = 8'd148; long_chirp_lut[1391] = 8'd251; + long_chirp_lut[1392] = 8'd204; long_chirp_lut[1393] = 8'd 65; long_chirp_lut[1394] = 8'd 1; long_chirp_lut[1395] = 8'd 91; long_chirp_lut[1396] = 8'd225; long_chirp_lut[1397] = 8'd241; long_chirp_lut[1398] = 8'd120; long_chirp_lut[1399] = 8'd 8; long_chirp_lut[1400] = 8'd 40; long_chirp_lut[1401] = 8'd178; long_chirp_lut[1402] = 8'd254; long_chirp_lut[1403] = 8'd178; long_chirp_lut[1404] = 8'd 41; long_chirp_lut[1405] = 8'd 8; long_chirp_lut[1406] = 8'd119; long_chirp_lut[1407] = 8'd241; + long_chirp_lut[1408] = 8'd226; long_chirp_lut[1409] = 8'd 93; long_chirp_lut[1410] = 8'd 2; long_chirp_lut[1411] = 8'd 62; long_chirp_lut[1412] = 8'd201; long_chirp_lut[1413] = 8'd252; long_chirp_lut[1414] = 8'd153; long_chirp_lut[1415] = 8'd 24; long_chirp_lut[1416] = 8'd 19; long_chirp_lut[1417] = 8'd144; long_chirp_lut[1418] = 8'd250; long_chirp_lut[1419] = 8'd209; long_chirp_lut[1420] = 8'd 71; long_chirp_lut[1421] = 8'd 1; long_chirp_lut[1422] = 8'd 83; long_chirp_lut[1423] = 8'd218; + long_chirp_lut[1424] = 8'd245; long_chirp_lut[1425] = 8'd132; long_chirp_lut[1426] = 8'd 13; long_chirp_lut[1427] = 8'd 31; long_chirp_lut[1428] = 8'd164; long_chirp_lut[1429] = 8'd254; long_chirp_lut[1430] = 8'd193; long_chirp_lut[1431] = 8'd 54; long_chirp_lut[1432] = 8'd 3; long_chirp_lut[1433] = 8'd100; long_chirp_lut[1434] = 8'd230; long_chirp_lut[1435] = 8'd238; long_chirp_lut[1436] = 8'd115; long_chirp_lut[1437] = 8'd 7; long_chirp_lut[1438] = 8'd 42; long_chirp_lut[1439] = 8'd179; + long_chirp_lut[1440] = 8'd255; long_chirp_lut[1441] = 8'd179; long_chirp_lut[1442] = 8'd 43; long_chirp_lut[1443] = 8'd 7; long_chirp_lut[1444] = 8'd114; long_chirp_lut[1445] = 8'd237; long_chirp_lut[1446] = 8'd231; long_chirp_lut[1447] = 8'd102; long_chirp_lut[1448] = 8'd 4; long_chirp_lut[1449] = 8'd 52; long_chirp_lut[1450] = 8'd189; long_chirp_lut[1451] = 8'd254; long_chirp_lut[1452] = 8'd169; long_chirp_lut[1453] = 8'd 35; long_chirp_lut[1454] = 8'd 10; long_chirp_lut[1455] = 8'd123; + long_chirp_lut[1456] = 8'd242; long_chirp_lut[1457] = 8'd225; long_chirp_lut[1458] = 8'd 94; long_chirp_lut[1459] = 8'd 2; long_chirp_lut[1460] = 8'd 58; long_chirp_lut[1461] = 8'd195; long_chirp_lut[1462] = 8'd253; long_chirp_lut[1463] = 8'd163; long_chirp_lut[1464] = 8'd 31; long_chirp_lut[1465] = 8'd 12; long_chirp_lut[1466] = 8'd128; long_chirp_lut[1467] = 8'd243; long_chirp_lut[1468] = 8'd223; long_chirp_lut[1469] = 8'd 90; long_chirp_lut[1470] = 8'd 2; long_chirp_lut[1471] = 8'd 60; + long_chirp_lut[1472] = 8'd198; long_chirp_lut[1473] = 8'd253; long_chirp_lut[1474] = 8'd162; long_chirp_lut[1475] = 8'd 31; long_chirp_lut[1476] = 8'd 13; long_chirp_lut[1477] = 8'd129; long_chirp_lut[1478] = 8'd243; long_chirp_lut[1479] = 8'd223; long_chirp_lut[1480] = 8'd 91; long_chirp_lut[1481] = 8'd 2; long_chirp_lut[1482] = 8'd 59; long_chirp_lut[1483] = 8'd196; long_chirp_lut[1484] = 8'd253; long_chirp_lut[1485] = 8'd164; long_chirp_lut[1486] = 8'd 33; long_chirp_lut[1487] = 8'd 11; + long_chirp_lut[1488] = 8'd125; long_chirp_lut[1489] = 8'd242; long_chirp_lut[1490] = 8'd226; long_chirp_lut[1491] = 8'd 96; long_chirp_lut[1492] = 8'd 3; long_chirp_lut[1493] = 8'd 54; long_chirp_lut[1494] = 8'd190; long_chirp_lut[1495] = 8'd254; long_chirp_lut[1496] = 8'd171; long_chirp_lut[1497] = 8'd 38; long_chirp_lut[1498] = 8'd 8; long_chirp_lut[1499] = 8'd116; long_chirp_lut[1500] = 8'd237; long_chirp_lut[1501] = 8'd232; long_chirp_lut[1502] = 8'd106; long_chirp_lut[1503] = 8'd 5; + long_chirp_lut[1504] = 8'd 46; long_chirp_lut[1505] = 8'd181; long_chirp_lut[1506] = 8'd254; long_chirp_lut[1507] = 8'd182; long_chirp_lut[1508] = 8'd 47; long_chirp_lut[1509] = 8'd 4; long_chirp_lut[1510] = 8'd104; long_chirp_lut[1511] = 8'd230; long_chirp_lut[1512] = 8'd239; long_chirp_lut[1513] = 8'd120; long_chirp_lut[1514] = 8'd 9; long_chirp_lut[1515] = 8'd 35; long_chirp_lut[1516] = 8'd166; long_chirp_lut[1517] = 8'd253; long_chirp_lut[1518] = 8'd196; long_chirp_lut[1519] = 8'd 60; + long_chirp_lut[1520] = 8'd 1; long_chirp_lut[1521] = 8'd 87; long_chirp_lut[1522] = 8'd219; long_chirp_lut[1523] = 8'd246; long_chirp_lut[1524] = 8'd138; long_chirp_lut[1525] = 8'd 18; long_chirp_lut[1526] = 8'd 23; long_chirp_lut[1527] = 8'd147; long_chirp_lut[1528] = 8'd249; long_chirp_lut[1529] = 8'd212; long_chirp_lut[1530] = 8'd 79; long_chirp_lut[1531] = 8'd 1; long_chirp_lut[1532] = 8'd 67; long_chirp_lut[1533] = 8'd202; long_chirp_lut[1534] = 8'd252; long_chirp_lut[1535] = 8'd161; + long_chirp_lut[1536] = 8'd 31; long_chirp_lut[1537] = 8'd 11; long_chirp_lut[1538] = 8'd123; long_chirp_lut[1539] = 8'd240; long_chirp_lut[1540] = 8'd229; long_chirp_lut[1541] = 8'd103; long_chirp_lut[1542] = 8'd 5; long_chirp_lut[1543] = 8'd 45; long_chirp_lut[1544] = 8'd179; long_chirp_lut[1545] = 8'd254; long_chirp_lut[1546] = 8'd186; long_chirp_lut[1547] = 8'd 52; long_chirp_lut[1548] = 8'd 3; long_chirp_lut[1549] = 8'd 95; long_chirp_lut[1550] = 8'd224; long_chirp_lut[1551] = 8'd244; + long_chirp_lut[1552] = 8'd133; long_chirp_lut[1553] = 8'd 16; long_chirp_lut[1554] = 8'd 24; long_chirp_lut[1555] = 8'd149; long_chirp_lut[1556] = 8'd249; long_chirp_lut[1557] = 8'd213; long_chirp_lut[1558] = 8'd 80; long_chirp_lut[1559] = 8'd 1; long_chirp_lut[1560] = 8'd 64; long_chirp_lut[1561] = 8'd199; long_chirp_lut[1562] = 8'd253; long_chirp_lut[1563] = 8'd167; long_chirp_lut[1564] = 8'd 36; long_chirp_lut[1565] = 8'd 8; long_chirp_lut[1566] = 8'd114; long_chirp_lut[1567] = 8'd235; + long_chirp_lut[1568] = 8'd236; long_chirp_lut[1569] = 8'd116; long_chirp_lut[1570] = 8'd 9; long_chirp_lut[1571] = 8'd 35; long_chirp_lut[1572] = 8'd164; long_chirp_lut[1573] = 8'd253; long_chirp_lut[1574] = 8'd201; long_chirp_lut[1575] = 8'd 68; long_chirp_lut[1576] = 8'd 1; long_chirp_lut[1577] = 8'd 75; long_chirp_lut[1578] = 8'd208; long_chirp_lut[1579] = 8'd251; long_chirp_lut[1580] = 8'd157; long_chirp_lut[1581] = 8'd 30; long_chirp_lut[1582] = 8'd 11; long_chirp_lut[1583] = 8'd122; + long_chirp_lut[1584] = 8'd239; long_chirp_lut[1585] = 8'd232; long_chirp_lut[1586] = 8'd109; long_chirp_lut[1587] = 8'd 7; long_chirp_lut[1588] = 8'd 38; long_chirp_lut[1589] = 8'd169; long_chirp_lut[1590] = 8'd253; long_chirp_lut[1591] = 8'd199; long_chirp_lut[1592] = 8'd 65; long_chirp_lut[1593] = 8'd 1; long_chirp_lut[1594] = 8'd 77; long_chirp_lut[1595] = 8'd209; long_chirp_lut[1596] = 8'd251; long_chirp_lut[1597] = 8'd157; long_chirp_lut[1598] = 8'd 30; long_chirp_lut[1599] = 8'd 11; + long_chirp_lut[1600] = 8'd120; long_chirp_lut[1601] = 8'd237; long_chirp_lut[1602] = 8'd234; long_chirp_lut[1603] = 8'd113; long_chirp_lut[1604] = 8'd 8; long_chirp_lut[1605] = 8'd 35; long_chirp_lut[1606] = 8'd163; long_chirp_lut[1607] = 8'd252; long_chirp_lut[1608] = 8'd204; long_chirp_lut[1609] = 8'd 72; long_chirp_lut[1610] = 8'd 1; long_chirp_lut[1611] = 8'd 69; long_chirp_lut[1612] = 8'd201; long_chirp_lut[1613] = 8'd253; long_chirp_lut[1614] = 8'd167; long_chirp_lut[1615] = 8'd 38; + long_chirp_lut[1616] = 8'd 7; long_chirp_lut[1617] = 8'd107; long_chirp_lut[1618] = 8'd230; long_chirp_lut[1619] = 8'd241; long_chirp_lut[1620] = 8'd127; long_chirp_lut[1621] = 8'd 14; long_chirp_lut[1622] = 8'd 25; long_chirp_lut[1623] = 8'd147; long_chirp_lut[1624] = 8'd248; long_chirp_lut[1625] = 8'd218; long_chirp_lut[1626] = 8'd 89; long_chirp_lut[1627] = 8'd 2; long_chirp_lut[1628] = 8'd 52; long_chirp_lut[1629] = 8'd184; long_chirp_lut[1630] = 8'd254; long_chirp_lut[1631] = 8'd187; + long_chirp_lut[1632] = 8'd 55; long_chirp_lut[1633] = 8'd 2; long_chirp_lut[1634] = 8'd 85; long_chirp_lut[1635] = 8'd214; long_chirp_lut[1636] = 8'd250; long_chirp_lut[1637] = 8'd153; long_chirp_lut[1638] = 8'd 28; long_chirp_lut[1639] = 8'd 11; long_chirp_lut[1640] = 8'd120; long_chirp_lut[1641] = 8'd237; long_chirp_lut[1642] = 8'd235; long_chirp_lut[1643] = 8'd117; long_chirp_lut[1644] = 8'd 10; long_chirp_lut[1645] = 8'd 30; long_chirp_lut[1646] = 8'd155; long_chirp_lut[1647] = 8'd250; + long_chirp_lut[1648] = 8'd213; long_chirp_lut[1649] = 8'd 84; long_chirp_lut[1650] = 8'd 2; long_chirp_lut[1651] = 8'd 55; long_chirp_lut[1652] = 8'd186; long_chirp_lut[1653] = 8'd254; long_chirp_lut[1654] = 8'd186; long_chirp_lut[1655] = 8'd 55; long_chirp_lut[1656] = 8'd 2; long_chirp_lut[1657] = 8'd 83; long_chirp_lut[1658] = 8'd212; long_chirp_lut[1659] = 8'd251; long_chirp_lut[1660] = 8'd157; long_chirp_lut[1661] = 8'd 32; long_chirp_lut[1662] = 8'd 9; long_chirp_lut[1663] = 8'd113; + long_chirp_lut[1664] = 8'd233; long_chirp_lut[1665] = 8'd240; long_chirp_lut[1666] = 8'd127; long_chirp_lut[1667] = 8'd 15; long_chirp_lut[1668] = 8'd 23; long_chirp_lut[1669] = 8'd143; long_chirp_lut[1670] = 8'd246; long_chirp_lut[1671] = 8'd223; long_chirp_lut[1672] = 8'd 98; long_chirp_lut[1673] = 8'd 4; long_chirp_lut[1674] = 8'd 42; long_chirp_lut[1675] = 8'd171; long_chirp_lut[1676] = 8'd253; long_chirp_lut[1677] = 8'd202; long_chirp_lut[1678] = 8'd 72; long_chirp_lut[1679] = 8'd 1; + long_chirp_lut[1680] = 8'd 64; long_chirp_lut[1681] = 8'd195; long_chirp_lut[1682] = 8'd254; long_chirp_lut[1683] = 8'd179; long_chirp_lut[1684] = 8'd 50; long_chirp_lut[1685] = 8'd 2; long_chirp_lut[1686] = 8'd 88; long_chirp_lut[1687] = 8'd215; long_chirp_lut[1688] = 8'd250; long_chirp_lut[1689] = 8'd155; long_chirp_lut[1690] = 8'd 31; long_chirp_lut[1691] = 8'd 9; long_chirp_lut[1692] = 8'd112; long_chirp_lut[1693] = 8'd231; long_chirp_lut[1694] = 8'd241; long_chirp_lut[1695] = 8'd132; + long_chirp_lut[1696] = 8'd 18; long_chirp_lut[1697] = 8'd 19; long_chirp_lut[1698] = 8'd135; long_chirp_lut[1699] = 8'd243; long_chirp_lut[1700] = 8'd229; long_chirp_lut[1701] = 8'd109; long_chirp_lut[1702] = 8'd 8; long_chirp_lut[1703] = 8'd 33; long_chirp_lut[1704] = 8'd157; long_chirp_lut[1705] = 8'd250; long_chirp_lut[1706] = 8'd215; long_chirp_lut[1707] = 8'd 88; long_chirp_lut[1708] = 8'd 3; long_chirp_lut[1709] = 8'd 48; long_chirp_lut[1710] = 8'd176; long_chirp_lut[1711] = 8'd254; + long_chirp_lut[1712] = 8'd199; long_chirp_lut[1713] = 8'd 70; long_chirp_lut[1714] = 8'd 1; long_chirp_lut[1715] = 8'd 64; long_chirp_lut[1716] = 8'd193; long_chirp_lut[1717] = 8'd254; long_chirp_lut[1718] = 8'd183; long_chirp_lut[1719] = 8'd 54; long_chirp_lut[1720] = 8'd 1; long_chirp_lut[1721] = 8'd 80; long_chirp_lut[1722] = 8'd208; long_chirp_lut[1723] = 8'd252; long_chirp_lut[1724] = 8'd167; long_chirp_lut[1725] = 8'd 41; long_chirp_lut[1726] = 8'd 4; long_chirp_lut[1727] = 8'd 96; + long_chirp_lut[1728] = 8'd220; long_chirp_lut[1729] = 8'd248; long_chirp_lut[1730] = 8'd151; long_chirp_lut[1731] = 8'd 30; long_chirp_lut[1732] = 8'd 9; long_chirp_lut[1733] = 8'd111; long_chirp_lut[1734] = 8'd230; long_chirp_lut[1735] = 8'd243; long_chirp_lut[1736] = 8'd137; long_chirp_lut[1737] = 8'd 21; long_chirp_lut[1738] = 8'd 15; long_chirp_lut[1739] = 8'd125; long_chirp_lut[1740] = 8'd237; long_chirp_lut[1741] = 8'd236; long_chirp_lut[1742] = 8'd123; long_chirp_lut[1743] = 8'd 14; + long_chirp_lut[1744] = 8'd 22; long_chirp_lut[1745] = 8'd138; long_chirp_lut[1746] = 8'd243; long_chirp_lut[1747] = 8'd229; long_chirp_lut[1748] = 8'd111; long_chirp_lut[1749] = 8'd 9; long_chirp_lut[1750] = 8'd 29; long_chirp_lut[1751] = 8'd150; long_chirp_lut[1752] = 8'd247; long_chirp_lut[1753] = 8'd222; long_chirp_lut[1754] = 8'd100; long_chirp_lut[1755] = 8'd 6; long_chirp_lut[1756] = 8'd 36; long_chirp_lut[1757] = 8'd159; long_chirp_lut[1758] = 8'd250; long_chirp_lut[1759] = 8'd216; + long_chirp_lut[1760] = 8'd 91; long_chirp_lut[1761] = 8'd 4; long_chirp_lut[1762] = 8'd 42; long_chirp_lut[1763] = 8'd168; long_chirp_lut[1764] = 8'd252; long_chirp_lut[1765] = 8'd209; long_chirp_lut[1766] = 8'd 83; long_chirp_lut[1767] = 8'd 2; long_chirp_lut[1768] = 8'd 48; long_chirp_lut[1769] = 8'd175; long_chirp_lut[1770] = 8'd253; long_chirp_lut[1771] = 8'd204; long_chirp_lut[1772] = 8'd 77; long_chirp_lut[1773] = 8'd 1; long_chirp_lut[1774] = 8'd 54; long_chirp_lut[1775] = 8'd181; + long_chirp_lut[1776] = 8'd254; long_chirp_lut[1777] = 8'd199; long_chirp_lut[1778] = 8'd 72; long_chirp_lut[1779] = 8'd 1; long_chirp_lut[1780] = 8'd 58; long_chirp_lut[1781] = 8'd185; long_chirp_lut[1782] = 8'd254; long_chirp_lut[1783] = 8'd196; long_chirp_lut[1784] = 8'd 68; long_chirp_lut[1785] = 8'd 1; long_chirp_lut[1786] = 8'd 61; long_chirp_lut[1787] = 8'd188; long_chirp_lut[1788] = 8'd254; long_chirp_lut[1789] = 8'd193; long_chirp_lut[1790] = 8'd 66; long_chirp_lut[1791] = 8'd 1; + long_chirp_lut[1792] = 8'd 63; long_chirp_lut[1793] = 8'd190; long_chirp_lut[1794] = 8'd254; long_chirp_lut[1795] = 8'd191; long_chirp_lut[1796] = 8'd 64; long_chirp_lut[1797] = 8'd 1; long_chirp_lut[1798] = 8'd 64; long_chirp_lut[1799] = 8'd191; long_chirp_lut[1800] = 8'd255; long_chirp_lut[1801] = 8'd191; long_chirp_lut[1802] = 8'd 64; long_chirp_lut[1803] = 8'd 1; long_chirp_lut[1804] = 8'd 64; long_chirp_lut[1805] = 8'd191; long_chirp_lut[1806] = 8'd254; long_chirp_lut[1807] = 8'd192; + long_chirp_lut[1808] = 8'd 65; long_chirp_lut[1809] = 8'd 1; long_chirp_lut[1810] = 8'd 62; long_chirp_lut[1811] = 8'd189; long_chirp_lut[1812] = 8'd254; long_chirp_lut[1813] = 8'd194; long_chirp_lut[1814] = 8'd 67; long_chirp_lut[1815] = 8'd 1; long_chirp_lut[1816] = 8'd 60; long_chirp_lut[1817] = 8'd186; long_chirp_lut[1818] = 8'd254; long_chirp_lut[1819] = 8'd197; long_chirp_lut[1820] = 8'd 71; long_chirp_lut[1821] = 8'd 1; long_chirp_lut[1822] = 8'd 56; long_chirp_lut[1823] = 8'd182; + long_chirp_lut[1824] = 8'd254; long_chirp_lut[1825] = 8'd201; long_chirp_lut[1826] = 8'd 75; long_chirp_lut[1827] = 8'd 1; long_chirp_lut[1828] = 8'd 52; long_chirp_lut[1829] = 8'd177; long_chirp_lut[1830] = 8'd253; long_chirp_lut[1831] = 8'd206; long_chirp_lut[1832] = 8'd 81; long_chirp_lut[1833] = 8'd 2; long_chirp_lut[1834] = 8'd 46; long_chirp_lut[1835] = 8'd171; long_chirp_lut[1836] = 8'd252; long_chirp_lut[1837] = 8'd212; long_chirp_lut[1838] = 8'd 88; long_chirp_lut[1839] = 8'd 4; + long_chirp_lut[1840] = 8'd 40; long_chirp_lut[1841] = 8'd162; long_chirp_lut[1842] = 8'd250; long_chirp_lut[1843] = 8'd218; long_chirp_lut[1844] = 8'd 97; long_chirp_lut[1845] = 8'd 6; long_chirp_lut[1846] = 8'd 34; long_chirp_lut[1847] = 8'd153; long_chirp_lut[1848] = 8'd247; long_chirp_lut[1849] = 8'd225; long_chirp_lut[1850] = 8'd107; long_chirp_lut[1851] = 8'd 9; long_chirp_lut[1852] = 8'd 27; long_chirp_lut[1853] = 8'd142; long_chirp_lut[1854] = 8'd243; long_chirp_lut[1855] = 8'd232; + long_chirp_lut[1856] = 8'd119; long_chirp_lut[1857] = 8'd 14; long_chirp_lut[1858] = 8'd 20; long_chirp_lut[1859] = 8'd130; long_chirp_lut[1860] = 8'd237; long_chirp_lut[1861] = 8'd239; long_chirp_lut[1862] = 8'd132; long_chirp_lut[1863] = 8'd 21; long_chirp_lut[1864] = 8'd 13; long_chirp_lut[1865] = 8'd116; long_chirp_lut[1866] = 8'd230; long_chirp_lut[1867] = 8'd245; long_chirp_lut[1868] = 8'd146; long_chirp_lut[1869] = 8'd 30; long_chirp_lut[1870] = 8'd 8; long_chirp_lut[1871] = 8'd101; + long_chirp_lut[1872] = 8'd220; long_chirp_lut[1873] = 8'd250; long_chirp_lut[1874] = 8'd162; long_chirp_lut[1875] = 8'd 41; long_chirp_lut[1876] = 8'd 3; long_chirp_lut[1877] = 8'd 85; long_chirp_lut[1878] = 8'd208; long_chirp_lut[1879] = 8'd253; long_chirp_lut[1880] = 8'd178; long_chirp_lut[1881] = 8'd 54; long_chirp_lut[1882] = 8'd 1; long_chirp_lut[1883] = 8'd 69; long_chirp_lut[1884] = 8'd193; long_chirp_lut[1885] = 8'd254; long_chirp_lut[1886] = 8'd194; long_chirp_lut[1887] = 8'd 70; + long_chirp_lut[1888] = 8'd 1; long_chirp_lut[1889] = 8'd 53; long_chirp_lut[1890] = 8'd176; long_chirp_lut[1891] = 8'd253; long_chirp_lut[1892] = 8'd210; long_chirp_lut[1893] = 8'd 88; long_chirp_lut[1894] = 8'd 4; long_chirp_lut[1895] = 8'd 37; long_chirp_lut[1896] = 8'd157; long_chirp_lut[1897] = 8'd248; long_chirp_lut[1898] = 8'd225; long_chirp_lut[1899] = 8'd109; long_chirp_lut[1900] = 8'd 11; long_chirp_lut[1901] = 8'd 23; long_chirp_lut[1902] = 8'd135; long_chirp_lut[1903] = 8'd239; + long_chirp_lut[1904] = 8'd238; long_chirp_lut[1905] = 8'd132; long_chirp_lut[1906] = 8'd 22; long_chirp_lut[1907] = 8'd 12; long_chirp_lut[1908] = 8'd112; long_chirp_lut[1909] = 8'd226; long_chirp_lut[1910] = 8'd247; long_chirp_lut[1911] = 8'd155; long_chirp_lut[1912] = 8'd 37; long_chirp_lut[1913] = 8'd 4; long_chirp_lut[1914] = 8'd 88; long_chirp_lut[1915] = 8'd209; long_chirp_lut[1916] = 8'd253; long_chirp_lut[1917] = 8'd179; long_chirp_lut[1918] = 8'd 57; long_chirp_lut[1919] = 8'd 1; + long_chirp_lut[1920] = 8'd 64; long_chirp_lut[1921] = 8'd187; long_chirp_lut[1922] = 8'd254; long_chirp_lut[1923] = 8'd202; long_chirp_lut[1924] = 8'd 80; long_chirp_lut[1925] = 8'd 3; long_chirp_lut[1926] = 8'd 42; long_chirp_lut[1927] = 8'd162; long_chirp_lut[1928] = 8'd249; long_chirp_lut[1929] = 8'd223; long_chirp_lut[1930] = 8'd107; long_chirp_lut[1931] = 8'd 11; long_chirp_lut[1932] = 8'd 23; long_chirp_lut[1933] = 8'd133; long_chirp_lut[1934] = 8'd238; long_chirp_lut[1935] = 8'd240; + long_chirp_lut[1936] = 8'd137; long_chirp_lut[1937] = 8'd 25; long_chirp_lut[1938] = 8'd 9; long_chirp_lut[1939] = 8'd103; long_chirp_lut[1940] = 8'd220; long_chirp_lut[1941] = 8'd251; long_chirp_lut[1942] = 8'd167; long_chirp_lut[1943] = 8'd 47; long_chirp_lut[1944] = 8'd 2; long_chirp_lut[1945] = 8'd 73; long_chirp_lut[1946] = 8'd195; long_chirp_lut[1947] = 8'd254; long_chirp_lut[1948] = 8'd196; long_chirp_lut[1949] = 8'd 74; long_chirp_lut[1950] = 8'd 2; long_chirp_lut[1951] = 8'd 46; + long_chirp_lut[1952] = 8'd166; long_chirp_lut[1953] = 8'd250; long_chirp_lut[1954] = 8'd221; long_chirp_lut[1955] = 8'd106; long_chirp_lut[1956] = 8'd 10; long_chirp_lut[1957] = 8'd 23; long_chirp_lut[1958] = 8'd132; long_chirp_lut[1959] = 8'd237; long_chirp_lut[1960] = 8'd241; long_chirp_lut[1961] = 8'd141; long_chirp_lut[1962] = 8'd 28; long_chirp_lut[1963] = 8'd 7; long_chirp_lut[1964] = 8'd 96; long_chirp_lut[1965] = 8'd214; long_chirp_lut[1966] = 8'd252; long_chirp_lut[1967] = 8'd176; + long_chirp_lut[1968] = 8'd 55; long_chirp_lut[1969] = 8'd 1; long_chirp_lut[1970] = 8'd 62; long_chirp_lut[1971] = 8'd184; long_chirp_lut[1972] = 8'd254; long_chirp_lut[1973] = 8'd208; long_chirp_lut[1974] = 8'd 89; long_chirp_lut[1975] = 8'd 5; long_chirp_lut[1976] = 8'd 33; long_chirp_lut[1977] = 8'd147; long_chirp_lut[1978] = 8'd243; long_chirp_lut[1979] = 8'd234; long_chirp_lut[1980] = 8'd127; long_chirp_lut[1981] = 8'd 21; long_chirp_lut[1982] = 8'd 11; long_chirp_lut[1983] = 8'd107; + long_chirp_lut[1984] = 8'd222; long_chirp_lut[1985] = 8'd250; long_chirp_lut[1986] = 8'd167; long_chirp_lut[1987] = 8'd 48; long_chirp_lut[1988] = 8'd 1; long_chirp_lut[1989] = 8'd 69; long_chirp_lut[1990] = 8'd189; long_chirp_lut[1991] = 8'd254; long_chirp_lut[1992] = 8'd204; long_chirp_lut[1993] = 8'd 85; long_chirp_lut[1994] = 8'd 4; long_chirp_lut[1995] = 8'd 35; long_chirp_lut[1996] = 8'd149; long_chirp_lut[1997] = 8'd244; long_chirp_lut[1998] = 8'd234; long_chirp_lut[1999] = 8'd128; + long_chirp_lut[2000] = 8'd 21; long_chirp_lut[2001] = 8'd 11; long_chirp_lut[2002] = 8'd105; long_chirp_lut[2003] = 8'd220; long_chirp_lut[2004] = 8'd251; long_chirp_lut[2005] = 8'd171; long_chirp_lut[2006] = 8'd 52; long_chirp_lut[2007] = 8'd 1; long_chirp_lut[2008] = 8'd 63; long_chirp_lut[2009] = 8'd183; long_chirp_lut[2010] = 8'd253; long_chirp_lut[2011] = 8'd211; long_chirp_lut[2012] = 8'd 94; long_chirp_lut[2013] = 8'd 7; long_chirp_lut[2014] = 8'd 28; long_chirp_lut[2015] = 8'd138; + long_chirp_lut[2016] = 8'd239; long_chirp_lut[2017] = 8'd240; long_chirp_lut[2018] = 8'd141; long_chirp_lut[2019] = 8'd 30; long_chirp_lut[2020] = 8'd 6; long_chirp_lut[2021] = 8'd 90; long_chirp_lut[2022] = 8'd208; long_chirp_lut[2023] = 8'd254; long_chirp_lut[2024] = 8'd187; long_chirp_lut[2025] = 8'd 68; long_chirp_lut[2026] = 8'd 1; long_chirp_lut[2027] = 8'd 47; long_chirp_lut[2028] = 8'd164; long_chirp_lut[2029] = 8'd249; long_chirp_lut[2030] = 8'd226; long_chirp_lut[2031] = 8'd116; + long_chirp_lut[2032] = 8'd 16; long_chirp_lut[2033] = 8'd 15; long_chirp_lut[2034] = 8'd114; long_chirp_lut[2035] = 8'd224; long_chirp_lut[2036] = 8'd250; long_chirp_lut[2037] = 8'd167; long_chirp_lut[2038] = 8'd 49; long_chirp_lut[2039] = 8'd 1; long_chirp_lut[2040] = 8'd 64; long_chirp_lut[2041] = 8'd183; long_chirp_lut[2042] = 8'd253; long_chirp_lut[2043] = 8'd213; long_chirp_lut[2044] = 8'd 97; long_chirp_lut[2045] = 8'd 8; long_chirp_lut[2046] = 8'd 24; long_chirp_lut[2047] = 8'd131; + long_chirp_lut[2048] = 8'd235; long_chirp_lut[2049] = 8'd244; long_chirp_lut[2050] = 8'd151; long_chirp_lut[2051] = 8'd 38; long_chirp_lut[2052] = 8'd 3; long_chirp_lut[2053] = 8'd 77; long_chirp_lut[2054] = 8'd195; long_chirp_lut[2055] = 8'd254; long_chirp_lut[2056] = 8'd202; long_chirp_lut[2057] = 8'd 85; long_chirp_lut[2058] = 8'd 5; long_chirp_lut[2059] = 8'd 32; long_chirp_lut[2060] = 8'd142; long_chirp_lut[2061] = 8'd240; long_chirp_lut[2062] = 8'd240; long_chirp_lut[2063] = 8'd142; + long_chirp_lut[2064] = 8'd 31; long_chirp_lut[2065] = 8'd 5; long_chirp_lut[2066] = 8'd 85; long_chirp_lut[2067] = 8'd202; long_chirp_lut[2068] = 8'd254; long_chirp_lut[2069] = 8'd197; long_chirp_lut[2070] = 8'd 79; long_chirp_lut[2071] = 8'd 3; long_chirp_lut[2072] = 8'd 35; long_chirp_lut[2073] = 8'd147; long_chirp_lut[2074] = 8'd242; long_chirp_lut[2075] = 8'd238; long_chirp_lut[2076] = 8'd138; long_chirp_lut[2077] = 8'd 29; long_chirp_lut[2078] = 8'd 5; long_chirp_lut[2079] = 8'd 87; + long_chirp_lut[2080] = 8'd203; long_chirp_lut[2081] = 8'd254; long_chirp_lut[2082] = 8'd196; long_chirp_lut[2083] = 8'd 79; long_chirp_lut[2084] = 8'd 3; long_chirp_lut[2085] = 8'd 35; long_chirp_lut[2086] = 8'd146; long_chirp_lut[2087] = 8'd241; long_chirp_lut[2088] = 8'd239; long_chirp_lut[2089] = 8'd141; long_chirp_lut[2090] = 8'd 31; long_chirp_lut[2091] = 8'd 4; long_chirp_lut[2092] = 8'd 83; long_chirp_lut[2093] = 8'd200; long_chirp_lut[2094] = 8'd254; long_chirp_lut[2095] = 8'd201; + long_chirp_lut[2096] = 8'd 84; long_chirp_lut[2097] = 8'd 5; long_chirp_lut[2098] = 8'd 30; long_chirp_lut[2099] = 8'd139; long_chirp_lut[2100] = 8'd237; long_chirp_lut[2101] = 8'd243; long_chirp_lut[2102] = 8'd150; long_chirp_lut[2103] = 8'd 38; long_chirp_lut[2104] = 8'd 2; long_chirp_lut[2105] = 8'd 73; long_chirp_lut[2106] = 8'd190; long_chirp_lut[2107] = 8'd254; long_chirp_lut[2108] = 8'd210; long_chirp_lut[2109] = 8'd 96; long_chirp_lut[2110] = 8'd 9; long_chirp_lut[2111] = 8'd 22; + long_chirp_lut[2112] = 8'd125; long_chirp_lut[2113] = 8'd230; long_chirp_lut[2114] = 8'd248; long_chirp_lut[2115] = 8'd164; long_chirp_lut[2116] = 8'd 50; long_chirp_lut[2117] = 8'd 1; long_chirp_lut[2118] = 8'd 59; long_chirp_lut[2119] = 8'd175; long_chirp_lut[2120] = 8'd251; long_chirp_lut[2121] = 8'd223; long_chirp_lut[2122] = 8'd114; long_chirp_lut[2123] = 8'd 17; long_chirp_lut[2124] = 8'd 13; long_chirp_lut[2125] = 8'd105; long_chirp_lut[2126] = 8'd216; long_chirp_lut[2127] = 8'd253; + long_chirp_lut[2128] = 8'd184; long_chirp_lut[2129] = 8'd 68; long_chirp_lut[2130] = 8'd 2; long_chirp_lut[2131] = 8'd 41; long_chirp_lut[2132] = 8'd153; long_chirp_lut[2133] = 8'd243; long_chirp_lut[2134] = 8'd237; long_chirp_lut[2135] = 8'd139; long_chirp_lut[2136] = 8'd 31; long_chirp_lut[2137] = 8'd 4; long_chirp_lut[2138] = 8'd 80; long_chirp_lut[2139] = 8'd195; long_chirp_lut[2140] = 8'd254; long_chirp_lut[2141] = 8'd207; long_chirp_lut[2142] = 8'd 94; long_chirp_lut[2143] = 8'd 8; + long_chirp_lut[2144] = 8'd 22; long_chirp_lut[2145] = 8'd123; long_chirp_lut[2146] = 8'd228; long_chirp_lut[2147] = 8'd249; long_chirp_lut[2148] = 8'd169; long_chirp_lut[2149] = 8'd 55; long_chirp_lut[2150] = 8'd 1; long_chirp_lut[2151] = 8'd 52; long_chirp_lut[2152] = 8'd166; long_chirp_lut[2153] = 8'd248; long_chirp_lut[2154] = 8'd231; long_chirp_lut[2155] = 8'd128; long_chirp_lut[2156] = 8'd 25; long_chirp_lut[2157] = 8'd 7; long_chirp_lut[2158] = 8'd 88; long_chirp_lut[2159] = 8'd202; + long_chirp_lut[2160] = 8'd255; long_chirp_lut[2161] = 8'd202; long_chirp_lut[2162] = 8'd 88; long_chirp_lut[2163] = 8'd 7; long_chirp_lut[2164] = 8'd 25; long_chirp_lut[2165] = 8'd127; long_chirp_lut[2166] = 8'd230; long_chirp_lut[2167] = 8'd249; long_chirp_lut[2168] = 8'd168; long_chirp_lut[2169] = 8'd 54; long_chirp_lut[2170] = 8'd 1; long_chirp_lut[2171] = 8'd 51; long_chirp_lut[2172] = 8'd164; long_chirp_lut[2173] = 8'd247; long_chirp_lut[2174] = 8'd232; long_chirp_lut[2175] = 8'd132; + long_chirp_lut[2176] = 8'd 28; long_chirp_lut[2177] = 8'd 5; long_chirp_lut[2178] = 8'd 83; long_chirp_lut[2179] = 8'd197; long_chirp_lut[2180] = 8'd254; long_chirp_lut[2181] = 8'd209; long_chirp_lut[2182] = 8'd 97; long_chirp_lut[2183] = 8'd 10; long_chirp_lut[2184] = 8'd 19; long_chirp_lut[2185] = 8'd116; long_chirp_lut[2186] = 8'd222; long_chirp_lut[2187] = 8'd252; long_chirp_lut[2188] = 8'd180; long_chirp_lut[2189] = 8'd 66; long_chirp_lut[2190] = 8'd 2; long_chirp_lut[2191] = 8'd 39; + long_chirp_lut[2192] = 8'd148; long_chirp_lut[2193] = 8'd241; long_chirp_lut[2194] = 8'd241; long_chirp_lut[2195] = 8'd150; long_chirp_lut[2196] = 8'd 41; long_chirp_lut[2197] = 8'd 1; long_chirp_lut[2198] = 8'd 64; long_chirp_lut[2199] = 8'd178; long_chirp_lut[2200] = 8'd251; long_chirp_lut[2201] = 8'd225; long_chirp_lut[2202] = 8'd120; long_chirp_lut[2203] = 8'd 21; long_chirp_lut[2204] = 8'd 8; long_chirp_lut[2205] = 8'd 91; long_chirp_lut[2206] = 8'd203; long_chirp_lut[2207] = 8'd254; + long_chirp_lut[2208] = 8'd204; long_chirp_lut[2209] = 8'd 93; long_chirp_lut[2210] = 8'd 9; long_chirp_lut[2211] = 8'd 20; long_chirp_lut[2212] = 8'd117; long_chirp_lut[2213] = 8'd223; long_chirp_lut[2214] = 8'd252; long_chirp_lut[2215] = 8'd182; long_chirp_lut[2216] = 8'd 68; long_chirp_lut[2217] = 8'd 2; long_chirp_lut[2218] = 8'd 36; long_chirp_lut[2219] = 8'd143; long_chirp_lut[2220] = 8'd237; long_chirp_lut[2221] = 8'd244; long_chirp_lut[2222] = 8'd158; long_chirp_lut[2223] = 8'd 48; + long_chirp_lut[2224] = 8'd 1; long_chirp_lut[2225] = 8'd 54; long_chirp_lut[2226] = 8'd166; long_chirp_lut[2227] = 8'd247; long_chirp_lut[2228] = 8'd233; long_chirp_lut[2229] = 8'd136; long_chirp_lut[2230] = 8'd 31; long_chirp_lut[2231] = 8'd 3; long_chirp_lut[2232] = 8'd 73; long_chirp_lut[2233] = 8'd186; long_chirp_lut[2234] = 8'd253; long_chirp_lut[2235] = 8'd220; long_chirp_lut[2236] = 8'd115; long_chirp_lut[2237] = 8'd 19; long_chirp_lut[2238] = 8'd 9; long_chirp_lut[2239] = 8'd 92; + long_chirp_lut[2240] = 8'd203; long_chirp_lut[2241] = 8'd254; long_chirp_lut[2242] = 8'd206; long_chirp_lut[2243] = 8'd 96; long_chirp_lut[2244] = 8'd 10; long_chirp_lut[2245] = 8'd 17; long_chirp_lut[2246] = 8'd111; long_chirp_lut[2247] = 8'd217; long_chirp_lut[2248] = 8'd253; long_chirp_lut[2249] = 8'd191; long_chirp_lut[2250] = 8'd 79; long_chirp_lut[2251] = 8'd 5; long_chirp_lut[2252] = 8'd 27; long_chirp_lut[2253] = 8'd127; long_chirp_lut[2254] = 8'd228; long_chirp_lut[2255] = 8'd250; + long_chirp_lut[2256] = 8'd177; long_chirp_lut[2257] = 8'd 65; long_chirp_lut[2258] = 8'd 2; long_chirp_lut[2259] = 8'd 37; long_chirp_lut[2260] = 8'd142; long_chirp_lut[2261] = 8'd236; long_chirp_lut[2262] = 8'd246; long_chirp_lut[2263] = 8'd163; long_chirp_lut[2264] = 8'd 53; long_chirp_lut[2265] = 8'd 1; long_chirp_lut[2266] = 8'd 46; long_chirp_lut[2267] = 8'd155; long_chirp_lut[2268] = 8'd242; long_chirp_lut[2269] = 8'd241; long_chirp_lut[2270] = 8'd151; long_chirp_lut[2271] = 8'd 44; + long_chirp_lut[2272] = 8'd 1; long_chirp_lut[2273] = 8'd 56; long_chirp_lut[2274] = 8'd166; long_chirp_lut[2275] = 8'd247; long_chirp_lut[2276] = 8'd235; long_chirp_lut[2277] = 8'd141; long_chirp_lut[2278] = 8'd 36; long_chirp_lut[2279] = 8'd 2; long_chirp_lut[2280] = 8'd 64; long_chirp_lut[2281] = 8'd175; long_chirp_lut[2282] = 8'd250; long_chirp_lut[2283] = 8'd230; long_chirp_lut[2284] = 8'd132; long_chirp_lut[2285] = 8'd 31; long_chirp_lut[2286] = 8'd 3; long_chirp_lut[2287] = 8'd 71; + long_chirp_lut[2288] = 8'd182; long_chirp_lut[2289] = 8'd251; long_chirp_lut[2290] = 8'd226; long_chirp_lut[2291] = 8'd125; long_chirp_lut[2292] = 8'd 26; long_chirp_lut[2293] = 8'd 5; long_chirp_lut[2294] = 8'd 77; long_chirp_lut[2295] = 8'd187; long_chirp_lut[2296] = 8'd253; long_chirp_lut[2297] = 8'd222; long_chirp_lut[2298] = 8'd120; long_chirp_lut[2299] = 8'd 23; long_chirp_lut[2300] = 8'd 6; long_chirp_lut[2301] = 8'd 81; long_chirp_lut[2302] = 8'd191; long_chirp_lut[2303] = 8'd253; + long_chirp_lut[2304] = 8'd220; long_chirp_lut[2305] = 8'd117; long_chirp_lut[2306] = 8'd 22; long_chirp_lut[2307] = 8'd 7; long_chirp_lut[2308] = 8'd 83; long_chirp_lut[2309] = 8'd193; long_chirp_lut[2310] = 8'd253; long_chirp_lut[2311] = 8'd219; long_chirp_lut[2312] = 8'd115; long_chirp_lut[2313] = 8'd 21; long_chirp_lut[2314] = 8'd 7; long_chirp_lut[2315] = 8'd 84; long_chirp_lut[2316] = 8'd193; long_chirp_lut[2317] = 8'd253; long_chirp_lut[2318] = 8'd219; long_chirp_lut[2319] = 8'd116; + long_chirp_lut[2320] = 8'd 21; long_chirp_lut[2321] = 8'd 7; long_chirp_lut[2322] = 8'd 83; long_chirp_lut[2323] = 8'd192; long_chirp_lut[2324] = 8'd253; long_chirp_lut[2325] = 8'd220; long_chirp_lut[2326] = 8'd118; long_chirp_lut[2327] = 8'd 23; long_chirp_lut[2328] = 8'd 6; long_chirp_lut[2329] = 8'd 80; long_chirp_lut[2330] = 8'd189; long_chirp_lut[2331] = 8'd253; long_chirp_lut[2332] = 8'd223; long_chirp_lut[2333] = 8'd122; long_chirp_lut[2334] = 8'd 25; long_chirp_lut[2335] = 8'd 5; + long_chirp_lut[2336] = 8'd 76; long_chirp_lut[2337] = 8'd185; long_chirp_lut[2338] = 8'd252; long_chirp_lut[2339] = 8'd226; long_chirp_lut[2340] = 8'd128; long_chirp_lut[2341] = 8'd 29; long_chirp_lut[2342] = 8'd 3; long_chirp_lut[2343] = 8'd 70; long_chirp_lut[2344] = 8'd179; long_chirp_lut[2345] = 8'd250; long_chirp_lut[2346] = 8'd231; long_chirp_lut[2347] = 8'd135; long_chirp_lut[2348] = 8'd 34; long_chirp_lut[2349] = 8'd 2; long_chirp_lut[2350] = 8'd 62; long_chirp_lut[2351] = 8'd171; + long_chirp_lut[2352] = 8'd247; long_chirp_lut[2353] = 8'd236; long_chirp_lut[2354] = 8'd144; long_chirp_lut[2355] = 8'd 41; long_chirp_lut[2356] = 8'd 1; long_chirp_lut[2357] = 8'd 54; long_chirp_lut[2358] = 8'd161; long_chirp_lut[2359] = 8'd244; long_chirp_lut[2360] = 8'd241; long_chirp_lut[2361] = 8'd155; long_chirp_lut[2362] = 8'd 49; long_chirp_lut[2363] = 8'd 1; long_chirp_lut[2364] = 8'd 45; long_chirp_lut[2365] = 8'd149; long_chirp_lut[2366] = 8'd238; long_chirp_lut[2367] = 8'd246; + long_chirp_lut[2368] = 8'd168; long_chirp_lut[2369] = 8'd 60; long_chirp_lut[2370] = 8'd 2; long_chirp_lut[2371] = 8'd 35; long_chirp_lut[2372] = 8'd135; long_chirp_lut[2373] = 8'd230; long_chirp_lut[2374] = 8'd251; long_chirp_lut[2375] = 8'd182; long_chirp_lut[2376] = 8'd 73; long_chirp_lut[2377] = 8'd 4; long_chirp_lut[2378] = 8'd 25; long_chirp_lut[2379] = 8'd119; long_chirp_lut[2380] = 8'd220; long_chirp_lut[2381] = 8'd254; long_chirp_lut[2382] = 8'd196; long_chirp_lut[2383] = 8'd 89; + long_chirp_lut[2384] = 8'd 10; long_chirp_lut[2385] = 8'd 15; long_chirp_lut[2386] = 8'd102; long_chirp_lut[2387] = 8'd207; long_chirp_lut[2388] = 8'd254; long_chirp_lut[2389] = 8'd211; long_chirp_lut[2390] = 8'd107; long_chirp_lut[2391] = 8'd 18; long_chirp_lut[2392] = 8'd 8; long_chirp_lut[2393] = 8'd 83; long_chirp_lut[2394] = 8'd190; long_chirp_lut[2395] = 8'd252; long_chirp_lut[2396] = 8'd225; long_chirp_lut[2397] = 8'd128; long_chirp_lut[2398] = 8'd 30; long_chirp_lut[2399] = 8'd 2; + long_chirp_lut[2400] = 8'd 64; long_chirp_lut[2401] = 8'd171; long_chirp_lut[2402] = 8'd247; long_chirp_lut[2403] = 8'd238; long_chirp_lut[2404] = 8'd150; long_chirp_lut[2405] = 8'd 46; long_chirp_lut[2406] = 8'd 1; long_chirp_lut[2407] = 8'd 45; long_chirp_lut[2408] = 8'd148; long_chirp_lut[2409] = 8'd237; long_chirp_lut[2410] = 8'd247; long_chirp_lut[2411] = 8'd173; long_chirp_lut[2412] = 8'd 66; long_chirp_lut[2413] = 8'd 3; long_chirp_lut[2414] = 8'd 28; long_chirp_lut[2415] = 8'd123; + long_chirp_lut[2416] = 8'd222; long_chirp_lut[2417] = 8'd253; long_chirp_lut[2418] = 8'd196; long_chirp_lut[2419] = 8'd 90; long_chirp_lut[2420] = 8'd 11; long_chirp_lut[2421] = 8'd 14; long_chirp_lut[2422] = 8'd 97; long_chirp_lut[2423] = 8'd201; long_chirp_lut[2424] = 8'd254; long_chirp_lut[2425] = 8'd218; long_chirp_lut[2426] = 8'd118; long_chirp_lut[2427] = 8'd 25; long_chirp_lut[2428] = 8'd 4; long_chirp_lut[2429] = 8'd 70; long_chirp_lut[2430] = 8'd176; long_chirp_lut[2431] = 8'd248; + long_chirp_lut[2432] = 8'd236; long_chirp_lut[2433] = 8'd148; long_chirp_lut[2434] = 8'd 45; long_chirp_lut[2435] = 8'd 1; long_chirp_lut[2436] = 8'd 45; long_chirp_lut[2437] = 8'd146; long_chirp_lut[2438] = 8'd235; long_chirp_lut[2439] = 8'd249; long_chirp_lut[2440] = 8'd178; long_chirp_lut[2441] = 8'd 72; long_chirp_lut[2442] = 8'd 5; long_chirp_lut[2443] = 8'd 23; long_chirp_lut[2444] = 8'd114; long_chirp_lut[2445] = 8'd214; long_chirp_lut[2446] = 8'd254; long_chirp_lut[2447] = 8'd206; + long_chirp_lut[2448] = 8'd104; long_chirp_lut[2449] = 8'd 18; long_chirp_lut[2450] = 8'd 8; long_chirp_lut[2451] = 8'd 81; long_chirp_lut[2452] = 8'd186; long_chirp_lut[2453] = 8'd251; long_chirp_lut[2454] = 8'd231; long_chirp_lut[2455] = 8'd139; long_chirp_lut[2456] = 8'd 39; long_chirp_lut[2457] = 8'd 1; long_chirp_lut[2458] = 8'd 49; long_chirp_lut[2459] = 8'd152; long_chirp_lut[2460] = 8'd237; long_chirp_lut[2461] = 8'd248; long_chirp_lut[2462] = 8'd175; long_chirp_lut[2463] = 8'd 70; + long_chirp_lut[2464] = 8'd 4; long_chirp_lut[2465] = 8'd 23; long_chirp_lut[2466] = 8'd114; long_chirp_lut[2467] = 8'd213; long_chirp_lut[2468] = 8'd254; long_chirp_lut[2469] = 8'd209; long_chirp_lut[2470] = 8'd107; long_chirp_lut[2471] = 8'd 20; long_chirp_lut[2472] = 8'd 6; long_chirp_lut[2473] = 8'd 75; long_chirp_lut[2474] = 8'd180; long_chirp_lut[2475] = 8'd249; long_chirp_lut[2476] = 8'd235; long_chirp_lut[2477] = 8'd148; long_chirp_lut[2478] = 8'd 47; long_chirp_lut[2479] = 8'd 1; + long_chirp_lut[2480] = 8'd 40; long_chirp_lut[2481] = 8'd139; long_chirp_lut[2482] = 8'd230; long_chirp_lut[2483] = 8'd251; long_chirp_lut[2484] = 8'd189; long_chirp_lut[2485] = 8'd 84; long_chirp_lut[2486] = 8'd 9; long_chirp_lut[2487] = 8'd 14; long_chirp_lut[2488] = 8'd 96; long_chirp_lut[2489] = 8'd199; long_chirp_lut[2490] = 8'd253; long_chirp_lut[2491] = 8'd223; long_chirp_lut[2492] = 8'd129; long_chirp_lut[2493] = 8'd 33; long_chirp_lut[2494] = 8'd 1; long_chirp_lut[2495] = 8'd 54; + long_chirp_lut[2496] = 8'd157; long_chirp_lut[2497] = 8'd239; long_chirp_lut[2498] = 8'd247; long_chirp_lut[2499] = 8'd174; long_chirp_lut[2500] = 8'd 71; long_chirp_lut[2501] = 8'd 5; long_chirp_lut[2502] = 8'd 21; long_chirp_lut[2503] = 8'd109; long_chirp_lut[2504] = 8'd209; long_chirp_lut[2505] = 8'd254; long_chirp_lut[2506] = 8'd215; long_chirp_lut[2507] = 8'd117; long_chirp_lut[2508] = 8'd 26; long_chirp_lut[2509] = 8'd 3; long_chirp_lut[2510] = 8'd 62; long_chirp_lut[2511] = 8'd165; + long_chirp_lut[2512] = 8'd243; long_chirp_lut[2513] = 8'd244; long_chirp_lut[2514] = 8'd167; long_chirp_lut[2515] = 8'd 64; long_chirp_lut[2516] = 8'd 3; long_chirp_lut[2517] = 8'd 25; long_chirp_lut[2518] = 8'd114; long_chirp_lut[2519] = 8'd212; long_chirp_lut[2520] = 8'd255; long_chirp_lut[2521] = 8'd212; long_chirp_lut[2522] = 8'd114; long_chirp_lut[2523] = 8'd 25; long_chirp_lut[2524] = 8'd 3; long_chirp_lut[2525] = 8'd 64; long_chirp_lut[2526] = 8'd166; long_chirp_lut[2527] = 8'd243; + long_chirp_lut[2528] = 8'd244; long_chirp_lut[2529] = 8'd168; long_chirp_lut[2530] = 8'd 66; long_chirp_lut[2531] = 8'd 4; long_chirp_lut[2532] = 8'd 23; long_chirp_lut[2533] = 8'd111; long_chirp_lut[2534] = 8'd210; long_chirp_lut[2535] = 8'd254; long_chirp_lut[2536] = 8'd216; long_chirp_lut[2537] = 8'd120; long_chirp_lut[2538] = 8'd 28; long_chirp_lut[2539] = 8'd 2; long_chirp_lut[2540] = 8'd 58; long_chirp_lut[2541] = 8'd159; long_chirp_lut[2542] = 8'd240; long_chirp_lut[2543] = 8'd247; + long_chirp_lut[2544] = 8'd177; long_chirp_lut[2545] = 8'd 74; long_chirp_lut[2546] = 8'd 6; long_chirp_lut[2547] = 8'd 17; long_chirp_lut[2548] = 8'd100; long_chirp_lut[2549] = 8'd200; long_chirp_lut[2550] = 8'd253; long_chirp_lut[2551] = 8'd225; long_chirp_lut[2552] = 8'd133; long_chirp_lut[2553] = 8'd 38; long_chirp_lut[2554] = 8'd 1; long_chirp_lut[2555] = 8'd 46; long_chirp_lut[2556] = 8'd143; long_chirp_lut[2557] = 8'd231; long_chirp_lut[2558] = 8'd252; long_chirp_lut[2559] = 8'd192; + long_chirp_lut[2560] = 8'd 91; long_chirp_lut[2561] = 8'd 13; long_chirp_lut[2562] = 8'd 9; long_chirp_lut[2563] = 8'd 81; long_chirp_lut[2564] = 8'd183; long_chirp_lut[2565] = 8'd249; long_chirp_lut[2566] = 8'd237; long_chirp_lut[2567] = 8'd155; long_chirp_lut[2568] = 8'd 55; long_chirp_lut[2569] = 8'd 2; long_chirp_lut[2570] = 8'd 29; long_chirp_lut[2571] = 8'd119; long_chirp_lut[2572] = 8'd215; long_chirp_lut[2573] = 8'd254; long_chirp_lut[2574] = 8'd213; long_chirp_lut[2575] = 8'd117; + long_chirp_lut[2576] = 8'd 28; long_chirp_lut[2577] = 8'd 2; long_chirp_lut[2578] = 8'd 56; long_chirp_lut[2579] = 8'd156; long_chirp_lut[2580] = 8'd237; long_chirp_lut[2581] = 8'd249; long_chirp_lut[2582] = 8'd183; long_chirp_lut[2583] = 8'd 82; long_chirp_lut[2584] = 8'd 10; long_chirp_lut[2585] = 8'd 12; long_chirp_lut[2586] = 8'd 88; long_chirp_lut[2587] = 8'd188; long_chirp_lut[2588] = 8'd250; long_chirp_lut[2589] = 8'd235; long_chirp_lut[2590] = 8'd151; long_chirp_lut[2591] = 8'd 53; + long_chirp_lut[2592] = 8'd 2; long_chirp_lut[2593] = 8'd 30; long_chirp_lut[2594] = 8'd119; long_chirp_lut[2595] = 8'd214; long_chirp_lut[2596] = 8'd254; long_chirp_lut[2597] = 8'd215; long_chirp_lut[2598] = 8'd120; long_chirp_lut[2599] = 8'd 30; long_chirp_lut[2600] = 8'd 1; long_chirp_lut[2601] = 8'd 52; long_chirp_lut[2602] = 8'd149; long_chirp_lut[2603] = 8'd234; long_chirp_lut[2604] = 8'd251; long_chirp_lut[2605] = 8'd191; long_chirp_lut[2606] = 8'd 92; long_chirp_lut[2607] = 8'd 14; + long_chirp_lut[2608] = 8'd 8; long_chirp_lut[2609] = 8'd 76; long_chirp_lut[2610] = 8'd176; long_chirp_lut[2611] = 8'd246; long_chirp_lut[2612] = 8'd242; long_chirp_lut[2613] = 8'd167; long_chirp_lut[2614] = 8'd 67; long_chirp_lut[2615] = 8'd 5; long_chirp_lut[2616] = 8'd 19; long_chirp_lut[2617] = 8'd100; long_chirp_lut[2618] = 8'd198; long_chirp_lut[2619] = 8'd253; long_chirp_lut[2620] = 8'd229; long_chirp_lut[2621] = 8'd143; long_chirp_lut[2622] = 8'd 47; long_chirp_lut[2623] = 8'd 1; + long_chirp_lut[2624] = 8'd 33; long_chirp_lut[2625] = 8'd123; long_chirp_lut[2626] = 8'd216; long_chirp_lut[2627] = 8'd254; long_chirp_lut[2628] = 8'd214; long_chirp_lut[2629] = 8'd121; long_chirp_lut[2630] = 8'd 31; long_chirp_lut[2631] = 8'd 1; long_chirp_lut[2632] = 8'd 48; long_chirp_lut[2633] = 8'd144; long_chirp_lut[2634] = 8'd230; long_chirp_lut[2635] = 8'd253; long_chirp_lut[2636] = 8'd199; long_chirp_lut[2637] = 8'd101; long_chirp_lut[2638] = 8'd 20; long_chirp_lut[2639] = 8'd 4; + long_chirp_lut[2640] = 8'd 64; long_chirp_lut[2641] = 8'd162; long_chirp_lut[2642] = 8'd240; long_chirp_lut[2643] = 8'd248; long_chirp_lut[2644] = 8'd183; long_chirp_lut[2645] = 8'd 84; long_chirp_lut[2646] = 8'd 12; long_chirp_lut[2647] = 8'd 9; long_chirp_lut[2648] = 8'd 79; long_chirp_lut[2649] = 8'd178; long_chirp_lut[2650] = 8'd246; long_chirp_lut[2651] = 8'd243; long_chirp_lut[2652] = 8'd169; long_chirp_lut[2653] = 8'd 71; long_chirp_lut[2654] = 8'd 6; long_chirp_lut[2655] = 8'd 15; + long_chirp_lut[2656] = 8'd 92; long_chirp_lut[2657] = 8'd190; long_chirp_lut[2658] = 8'd250; long_chirp_lut[2659] = 8'd236; long_chirp_lut[2660] = 8'd157; long_chirp_lut[2661] = 8'd 60; long_chirp_lut[2662] = 8'd 3; long_chirp_lut[2663] = 8'd 22; long_chirp_lut[2664] = 8'd104; long_chirp_lut[2665] = 8'd200; long_chirp_lut[2666] = 8'd253; long_chirp_lut[2667] = 8'd230; long_chirp_lut[2668] = 8'd146; long_chirp_lut[2669] = 8'd 51; long_chirp_lut[2670] = 8'd 2; long_chirp_lut[2671] = 8'd 27; + long_chirp_lut[2672] = 8'd113; long_chirp_lut[2673] = 8'd207; long_chirp_lut[2674] = 8'd254; long_chirp_lut[2675] = 8'd225; long_chirp_lut[2676] = 8'd138; long_chirp_lut[2677] = 8'd 45; long_chirp_lut[2678] = 8'd 1; long_chirp_lut[2679] = 8'd 32; long_chirp_lut[2680] = 8'd120; long_chirp_lut[2681] = 8'd212; long_chirp_lut[2682] = 8'd254; long_chirp_lut[2683] = 8'd221; long_chirp_lut[2684] = 8'd132; long_chirp_lut[2685] = 8'd 41; long_chirp_lut[2686] = 8'd 1; long_chirp_lut[2687] = 8'd 36; + long_chirp_lut[2688] = 8'd125; long_chirp_lut[2689] = 8'd216; long_chirp_lut[2690] = 8'd254; long_chirp_lut[2691] = 8'd218; long_chirp_lut[2692] = 8'd129; long_chirp_lut[2693] = 8'd 38; long_chirp_lut[2694] = 8'd 1; long_chirp_lut[2695] = 8'd 37; long_chirp_lut[2696] = 8'd127; long_chirp_lut[2697] = 8'd217; long_chirp_lut[2698] = 8'd254; long_chirp_lut[2699] = 8'd217; long_chirp_lut[2700] = 8'd128; long_chirp_lut[2701] = 8'd 38; long_chirp_lut[2702] = 8'd 1; long_chirp_lut[2703] = 8'd 38; + long_chirp_lut[2704] = 8'd127; long_chirp_lut[2705] = 8'd217; long_chirp_lut[2706] = 8'd254; long_chirp_lut[2707] = 8'd218; long_chirp_lut[2708] = 8'd129; long_chirp_lut[2709] = 8'd 39; long_chirp_lut[2710] = 8'd 1; long_chirp_lut[2711] = 8'd 36; long_chirp_lut[2712] = 8'd125; long_chirp_lut[2713] = 8'd215; long_chirp_lut[2714] = 8'd254; long_chirp_lut[2715] = 8'd220; long_chirp_lut[2716] = 8'd132; long_chirp_lut[2717] = 8'd 42; long_chirp_lut[2718] = 8'd 1; long_chirp_lut[2719] = 8'd 33; + long_chirp_lut[2720] = 8'd120; long_chirp_lut[2721] = 8'd211; long_chirp_lut[2722] = 8'd254; long_chirp_lut[2723] = 8'd224; long_chirp_lut[2724] = 8'd138; long_chirp_lut[2725] = 8'd 46; long_chirp_lut[2726] = 8'd 1; long_chirp_lut[2727] = 8'd 29; long_chirp_lut[2728] = 8'd113; long_chirp_lut[2729] = 8'd206; long_chirp_lut[2730] = 8'd253; long_chirp_lut[2731] = 8'd229; long_chirp_lut[2732] = 8'd146; long_chirp_lut[2733] = 8'd 53; long_chirp_lut[2734] = 8'd 2; long_chirp_lut[2735] = 8'd 23; + long_chirp_lut[2736] = 8'd104; long_chirp_lut[2737] = 8'd198; long_chirp_lut[2738] = 8'd252; long_chirp_lut[2739] = 8'd235; long_chirp_lut[2740] = 8'd157; long_chirp_lut[2741] = 8'd 62; long_chirp_lut[2742] = 8'd 5; long_chirp_lut[2743] = 8'd 17; long_chirp_lut[2744] = 8'd 92; long_chirp_lut[2745] = 8'd187; long_chirp_lut[2746] = 8'd249; long_chirp_lut[2747] = 8'd241; long_chirp_lut[2748] = 8'd169; long_chirp_lut[2749] = 8'd 74; long_chirp_lut[2750] = 8'd 9; long_chirp_lut[2751] = 8'd 11; + long_chirp_lut[2752] = 8'd 79; long_chirp_lut[2753] = 8'd174; long_chirp_lut[2754] = 8'd243; long_chirp_lut[2755] = 8'd247; long_chirp_lut[2756] = 8'd183; long_chirp_lut[2757] = 8'd 88; long_chirp_lut[2758] = 8'd 15; long_chirp_lut[2759] = 8'd 5; long_chirp_lut[2760] = 8'd 64; long_chirp_lut[2761] = 8'd158; long_chirp_lut[2762] = 8'd235; long_chirp_lut[2763] = 8'd252; long_chirp_lut[2764] = 8'd199; long_chirp_lut[2765] = 8'd106; long_chirp_lut[2766] = 8'd 25; long_chirp_lut[2767] = 8'd 2; + long_chirp_lut[2768] = 8'd 48; long_chirp_lut[2769] = 8'd139; long_chirp_lut[2770] = 8'd224; long_chirp_lut[2771] = 8'd254; long_chirp_lut[2772] = 8'd214; long_chirp_lut[2773] = 8'd126; long_chirp_lut[2774] = 8'd 39; long_chirp_lut[2775] = 8'd 1; long_chirp_lut[2776] = 8'd 33; long_chirp_lut[2777] = 8'd118; long_chirp_lut[2778] = 8'd208; long_chirp_lut[2779] = 8'd254; long_chirp_lut[2780] = 8'd229; long_chirp_lut[2781] = 8'd149; long_chirp_lut[2782] = 8'd 57; long_chirp_lut[2783] = 8'd 3; + long_chirp_lut[2784] = 8'd 19; long_chirp_lut[2785] = 8'd 94; long_chirp_lut[2786] = 8'd188; long_chirp_lut[2787] = 8'd248; long_chirp_lut[2788] = 8'd242; long_chirp_lut[2789] = 8'd173; long_chirp_lut[2790] = 8'd 79; long_chirp_lut[2791] = 8'd 11; long_chirp_lut[2792] = 8'd 8; long_chirp_lut[2793] = 8'd 70; long_chirp_lut[2794] = 8'd163; long_chirp_lut[2795] = 8'd237; long_chirp_lut[2796] = 8'd251; long_chirp_lut[2797] = 8'd197; long_chirp_lut[2798] = 8'd106; long_chirp_lut[2799] = 8'd 26; + long_chirp_lut[2800] = 8'd 1; long_chirp_lut[2801] = 8'd 46; long_chirp_lut[2802] = 8'd135; long_chirp_lut[2803] = 8'd220; long_chirp_lut[2804] = 8'd254; long_chirp_lut[2805] = 8'd220; long_chirp_lut[2806] = 8'd136; long_chirp_lut[2807] = 8'd 47; long_chirp_lut[2808] = 8'd 2; long_chirp_lut[2809] = 8'd 25; long_chirp_lut[2810] = 8'd104; long_chirp_lut[2811] = 8'd195; long_chirp_lut[2812] = 8'd250; long_chirp_lut[2813] = 8'd239; long_chirp_lut[2814] = 8'd167; long_chirp_lut[2815] = 8'd 74; + long_chirp_lut[2816] = 8'd 10; long_chirp_lut[2817] = 8'd 9; long_chirp_lut[2818] = 8'd 72; long_chirp_lut[2819] = 8'd165; long_chirp_lut[2820] = 8'd237; long_chirp_lut[2821] = 8'd251; long_chirp_lut[2822] = 8'd199; long_chirp_lut[2823] = 8'd108; long_chirp_lut[2824] = 8'd 28; long_chirp_lut[2825] = 8'd 1; long_chirp_lut[2826] = 8'd 42; long_chirp_lut[2827] = 8'd129; long_chirp_lut[2828] = 8'd215; long_chirp_lut[2829] = 8'd254; long_chirp_lut[2830] = 8'd226; long_chirp_lut[2831] = 8'd145; + long_chirp_lut[2832] = 8'd 55; long_chirp_lut[2833] = 8'd 3; long_chirp_lut[2834] = 8'd 18; long_chirp_lut[2835] = 8'd 91; long_chirp_lut[2836] = 8'd183; long_chirp_lut[2837] = 8'd246; long_chirp_lut[2838] = 8'd246; long_chirp_lut[2839] = 8'd183; long_chirp_lut[2840] = 8'd 91; long_chirp_lut[2841] = 8'd 18; long_chirp_lut[2842] = 8'd 3; long_chirp_lut[2843] = 8'd 54; long_chirp_lut[2844] = 8'd143; long_chirp_lut[2845] = 8'd224; long_chirp_lut[2846] = 8'd254; long_chirp_lut[2847] = 8'd217; + long_chirp_lut[2848] = 8'd133; long_chirp_lut[2849] = 8'd 46; long_chirp_lut[2850] = 8'd 2; long_chirp_lut[2851] = 8'd 23; long_chirp_lut[2852] = 8'd100; long_chirp_lut[2853] = 8'd191; long_chirp_lut[2854] = 8'd249; long_chirp_lut[2855] = 8'd243; long_chirp_lut[2856] = 8'd177; long_chirp_lut[2857] = 8'd 85; long_chirp_lut[2858] = 8'd 15; long_chirp_lut[2859] = 8'd 4; long_chirp_lut[2860] = 8'd 58; long_chirp_lut[2861] = 8'd147; long_chirp_lut[2862] = 8'd227; long_chirp_lut[2863] = 8'd254; + long_chirp_lut[2864] = 8'd216; long_chirp_lut[2865] = 8'd132; long_chirp_lut[2866] = 8'd 45; long_chirp_lut[2867] = 8'd 2; long_chirp_lut[2868] = 8'd 23; long_chirp_lut[2869] = 8'd 99; long_chirp_lut[2870] = 8'd189; long_chirp_lut[2871] = 8'd248; long_chirp_lut[2872] = 8'd244; long_chirp_lut[2873] = 8'd180; long_chirp_lut[2874] = 8'd 89; long_chirp_lut[2875] = 8'd 18; long_chirp_lut[2876] = 8'd 3; long_chirp_lut[2877] = 8'd 53; long_chirp_lut[2878] = 8'd141; long_chirp_lut[2879] = 8'd222; + long_chirp_lut[2880] = 8'd255; long_chirp_lut[2881] = 8'd222; long_chirp_lut[2882] = 8'd141; long_chirp_lut[2883] = 8'd 53; long_chirp_lut[2884] = 8'd 3; long_chirp_lut[2885] = 8'd 17; long_chirp_lut[2886] = 8'd 88; long_chirp_lut[2887] = 8'd178; long_chirp_lut[2888] = 8'd243; long_chirp_lut[2889] = 8'd249; long_chirp_lut[2890] = 8'd193; long_chirp_lut[2891] = 8'd103; long_chirp_lut[2892] = 8'd 26; long_chirp_lut[2893] = 8'd 1; long_chirp_lut[2894] = 8'd 40; long_chirp_lut[2895] = 8'd123; + long_chirp_lut[2896] = 8'd209; long_chirp_lut[2897] = 8'd253; long_chirp_lut[2898] = 8'd234; long_chirp_lut[2899] = 8'd160; long_chirp_lut[2900] = 8'd 71; long_chirp_lut[2901] = 8'd 9; long_chirp_lut[2902] = 8'd 8; long_chirp_lut[2903] = 8'd 67; long_chirp_lut[2904] = 8'd157; long_chirp_lut[2905] = 8'd231; long_chirp_lut[2906] = 8'd254; long_chirp_lut[2907] = 8'd213; long_chirp_lut[2908] = 8'd129; long_chirp_lut[2909] = 8'd 44; long_chirp_lut[2910] = 8'd 2; long_chirp_lut[2911] = 8'd 22; + long_chirp_lut[2912] = 8'd 96; long_chirp_lut[2913] = 8'd185; long_chirp_lut[2914] = 8'd246; long_chirp_lut[2915] = 8'd247; long_chirp_lut[2916] = 8'd189; long_chirp_lut[2917] = 8'd100; long_chirp_lut[2918] = 8'd 25; long_chirp_lut[2919] = 8'd 1; long_chirp_lut[2920] = 8'd 40; long_chirp_lut[2921] = 8'd123; long_chirp_lut[2922] = 8'd208; long_chirp_lut[2923] = 8'd253; long_chirp_lut[2924] = 8'd235; long_chirp_lut[2925] = 8'd164; long_chirp_lut[2926] = 8'd 75; long_chirp_lut[2927] = 8'd 12; + long_chirp_lut[2928] = 8'd 6; long_chirp_lut[2929] = 8'd 60; long_chirp_lut[2930] = 8'd148; long_chirp_lut[2931] = 8'd225; long_chirp_lut[2932] = 8'd254; long_chirp_lut[2933] = 8'd221; long_chirp_lut[2934] = 8'd141; long_chirp_lut[2935] = 8'd 55; long_chirp_lut[2936] = 8'd 4; long_chirp_lut[2937] = 8'd 14; long_chirp_lut[2938] = 8'd 80; long_chirp_lut[2939] = 8'd169; long_chirp_lut[2940] = 8'd237; long_chirp_lut[2941] = 8'd252; long_chirp_lut[2942] = 8'd206; long_chirp_lut[2943] = 8'd121; + long_chirp_lut[2944] = 8'd 39; long_chirp_lut[2945] = 8'd 1; long_chirp_lut[2946] = 8'd 24; long_chirp_lut[2947] = 8'd 98; long_chirp_lut[2948] = 8'd186; long_chirp_lut[2949] = 8'd246; long_chirp_lut[2950] = 8'd247; long_chirp_lut[2951] = 8'd191; long_chirp_lut[2952] = 8'd104; long_chirp_lut[2953] = 8'd 28; long_chirp_lut[2954] = 8'd 1; long_chirp_lut[2955] = 8'd 35; long_chirp_lut[2956] = 8'd114; long_chirp_lut[2957] = 8'd200; long_chirp_lut[2958] = 8'd250; long_chirp_lut[2959] = 8'd242; + long_chirp_lut[2960] = 8'd178; long_chirp_lut[2961] = 8'd 90; long_chirp_lut[2962] = 8'd 20; long_chirp_lut[2963] = 8'd 2; long_chirp_lut[2964] = 8'd 45; long_chirp_lut[2965] = 8'd127; long_chirp_lut[2966] = 8'd210; long_chirp_lut[2967] = 8'd253; long_chirp_lut[2968] = 8'd236; long_chirp_lut[2969] = 8'd167; long_chirp_lut[2970] = 8'd 79; long_chirp_lut[2971] = 8'd 14; long_chirp_lut[2972] = 8'd 4; long_chirp_lut[2973] = 8'd 53; long_chirp_lut[2974] = 8'd137; long_chirp_lut[2975] = 8'd217; + long_chirp_lut[2976] = 8'd254; long_chirp_lut[2977] = 8'd231; long_chirp_lut[2978] = 8'd158; long_chirp_lut[2979] = 8'd 71; long_chirp_lut[2980] = 8'd 11; long_chirp_lut[2981] = 8'd 6; long_chirp_lut[2982] = 8'd 59; long_chirp_lut[2983] = 8'd144; long_chirp_lut[2984] = 8'd222; long_chirp_lut[2985] = 8'd254; long_chirp_lut[2986] = 8'd227; long_chirp_lut[2987] = 8'd153; long_chirp_lut[2988] = 8'd 66; long_chirp_lut[2989] = 8'd 9; long_chirp_lut[2990] = 8'd 8; long_chirp_lut[2991] = 8'd 63; + long_chirp_lut[2992] = 8'd148; long_chirp_lut[2993] = 8'd224; long_chirp_lut[2994] = 8'd254; long_chirp_lut[2995] = 8'd225; long_chirp_lut[2996] = 8'd150; long_chirp_lut[2997] = 8'd 64; long_chirp_lut[2998] = 8'd 8; long_chirp_lut[2999] = 8'd 8; long_chirp_lut[3000] = 8'd 64; long_chirp_lut[3001] = 8'd150; long_chirp_lut[3002] = 8'd225; long_chirp_lut[3003] = 8'd254; long_chirp_lut[3004] = 8'd225; long_chirp_lut[3005] = 8'd150; long_chirp_lut[3006] = 8'd 65; long_chirp_lut[3007] = 8'd 8; + long_chirp_lut[3008] = 8'd 8; long_chirp_lut[3009] = 8'd 63; long_chirp_lut[3010] = 8'd148; long_chirp_lut[3011] = 8'd223; long_chirp_lut[3012] = 8'd254; long_chirp_lut[3013] = 8'd227; long_chirp_lut[3014] = 8'd153; long_chirp_lut[3015] = 8'd 68; long_chirp_lut[3016] = 8'd 10; long_chirp_lut[3017] = 8'd 6; long_chirp_lut[3018] = 8'd 59; long_chirp_lut[3019] = 8'd143; long_chirp_lut[3020] = 8'd220; long_chirp_lut[3021] = 8'd254; long_chirp_lut[3022] = 8'd230; long_chirp_lut[3023] = 8'd159; + long_chirp_lut[3024] = 8'd 73; long_chirp_lut[3025] = 8'd 13; long_chirp_lut[3026] = 8'd 4; long_chirp_lut[3027] = 8'd 53; long_chirp_lut[3028] = 8'd135; long_chirp_lut[3029] = 8'd214; long_chirp_lut[3030] = 8'd253; long_chirp_lut[3031] = 8'd235; long_chirp_lut[3032] = 8'd168; long_chirp_lut[3033] = 8'd 82; long_chirp_lut[3034] = 8'd 17; long_chirp_lut[3035] = 8'd 2; long_chirp_lut[3036] = 8'd 45; long_chirp_lut[3037] = 8'd124; long_chirp_lut[3038] = 8'd206; long_chirp_lut[3039] = 8'd251; + long_chirp_lut[3040] = 8'd241; long_chirp_lut[3041] = 8'd179; long_chirp_lut[3042] = 8'd 94; long_chirp_lut[3043] = 8'd 24; long_chirp_lut[3044] = 8'd 1; long_chirp_lut[3045] = 8'd 35; long_chirp_lut[3046] = 8'd111; long_chirp_lut[3047] = 8'd194; long_chirp_lut[3048] = 8'd247; long_chirp_lut[3049] = 8'd247; long_chirp_lut[3050] = 8'd193; long_chirp_lut[3051] = 8'd109; long_chirp_lut[3052] = 8'd 34; long_chirp_lut[3053] = 8'd 1; long_chirp_lut[3054] = 8'd 24; long_chirp_lut[3055] = 8'd 94; + long_chirp_lut[3056] = 8'd179; long_chirp_lut[3057] = 8'd241; long_chirp_lut[3058] = 8'd252; long_chirp_lut[3059] = 8'd207; long_chirp_lut[3060] = 8'd128; long_chirp_lut[3061] = 8'd 48; long_chirp_lut[3062] = 8'd 3; long_chirp_lut[3063] = 8'd 14; long_chirp_lut[3064] = 8'd 76; long_chirp_lut[3065] = 8'd160; long_chirp_lut[3066] = 8'd230; long_chirp_lut[3067] = 8'd254; long_chirp_lut[3068] = 8'd223; long_chirp_lut[3069] = 8'd149; long_chirp_lut[3070] = 8'd 66; long_chirp_lut[3071] = 8'd 10; + long_chirp_lut[3072] = 8'd 6; long_chirp_lut[3073] = 8'd 56; long_chirp_lut[3074] = 8'd137; long_chirp_lut[3075] = 8'd214; long_chirp_lut[3076] = 8'd253; long_chirp_lut[3077] = 8'd237; long_chirp_lut[3078] = 8'd172; long_chirp_lut[3079] = 8'd 88; long_chirp_lut[3080] = 8'd 21; long_chirp_lut[3081] = 8'd 1; long_chirp_lut[3082] = 8'd 36; long_chirp_lut[3083] = 8'd111; long_chirp_lut[3084] = 8'd193; long_chirp_lut[3085] = 8'd247; long_chirp_lut[3086] = 8'd248; long_chirp_lut[3087] = 8'd197; + long_chirp_lut[3088] = 8'd115; long_chirp_lut[3089] = 8'd 39; long_chirp_lut[3090] = 8'd 2; long_chirp_lut[3091] = 8'd 19; long_chirp_lut[3092] = 8'd 83; long_chirp_lut[3093] = 8'd167; long_chirp_lut[3094] = 8'd233; long_chirp_lut[3095] = 8'd254; long_chirp_lut[3096] = 8'd220; long_chirp_lut[3097] = 8'd146; long_chirp_lut[3098] = 8'd 64; long_chirp_lut[3099] = 8'd 9; long_chirp_lut[3100] = 8'd 6; long_chirp_lut[3101] = 8'd 55; long_chirp_lut[3102] = 8'd135; long_chirp_lut[3103] = 8'd212; + long_chirp_lut[3104] = 8'd253; long_chirp_lut[3105] = 8'd240; long_chirp_lut[3106] = 8'd178; long_chirp_lut[3107] = 8'd 96; long_chirp_lut[3108] = 8'd 26; long_chirp_lut[3109] = 8'd 1; long_chirp_lut[3110] = 8'd 29; long_chirp_lut[3111] = 8'd100; long_chirp_lut[3112] = 8'd182; long_chirp_lut[3113] = 8'd241; long_chirp_lut[3114] = 8'd252; long_chirp_lut[3115] = 8'd209; long_chirp_lut[3116] = 8'd132; long_chirp_lut[3117] = 8'd 53; long_chirp_lut[3118] = 8'd 5; long_chirp_lut[3119] = 8'd 10; + long_chirp_lut[3120] = 8'd 64; long_chirp_lut[3121] = 8'd145; long_chirp_lut[3122] = 8'd219; long_chirp_lut[3123] = 8'd254; long_chirp_lut[3124] = 8'd235; long_chirp_lut[3125] = 8'd171; long_chirp_lut[3126] = 8'd 89; long_chirp_lut[3127] = 8'd 23; long_chirp_lut[3128] = 8'd 1; long_chirp_lut[3129] = 8'd 32; long_chirp_lut[3130] = 8'd104; long_chirp_lut[3131] = 8'd185; long_chirp_lut[3132] = 8'd242; long_chirp_lut[3133] = 8'd251; long_chirp_lut[3134] = 8'd209; long_chirp_lut[3135] = 8'd132; + long_chirp_lut[3136] = 8'd 53; long_chirp_lut[3137] = 8'd 6; long_chirp_lut[3138] = 8'd 9; long_chirp_lut[3139] = 8'd 62; long_chirp_lut[3140] = 8'd142; long_chirp_lut[3141] = 8'd216; long_chirp_lut[3142] = 8'd253; long_chirp_lut[3143] = 8'd238; long_chirp_lut[3144] = 8'd177; long_chirp_lut[3145] = 8'd 95; long_chirp_lut[3146] = 8'd 27; long_chirp_lut[3147] = 8'd 1; long_chirp_lut[3148] = 8'd 27; long_chirp_lut[3149] = 8'd 95; long_chirp_lut[3150] = 8'd176; long_chirp_lut[3151] = 8'd237; + long_chirp_lut[3152] = 8'd253; long_chirp_lut[3153] = 8'd217; long_chirp_lut[3154] = 8'd144; long_chirp_lut[3155] = 8'd 64; long_chirp_lut[3156] = 8'd 10; long_chirp_lut[3157] = 8'd 5; long_chirp_lut[3158] = 8'd 49; long_chirp_lut[3159] = 8'd126; long_chirp_lut[3160] = 8'd203; long_chirp_lut[3161] = 8'd250; long_chirp_lut[3162] = 8'd246; long_chirp_lut[3163] = 8'd194; long_chirp_lut[3164] = 8'd115; long_chirp_lut[3165] = 8'd 41; long_chirp_lut[3166] = 8'd 2; long_chirp_lut[3167] = 8'd 15; + long_chirp_lut[3168] = 8'd 73; long_chirp_lut[3169] = 8'd154; long_chirp_lut[3170] = 8'd224; long_chirp_lut[3171] = 8'd254; long_chirp_lut[3172] = 8'd233; long_chirp_lut[3173] = 8'd170; long_chirp_lut[3174] = 8'd 89; long_chirp_lut[3175] = 8'd 24; long_chirp_lut[3176] = 8'd 1; long_chirp_lut[3177] = 8'd 29; long_chirp_lut[3178] = 8'd 97; long_chirp_lut[3179] = 8'd177; long_chirp_lut[3180] = 8'd237; long_chirp_lut[3181] = 8'd254; long_chirp_lut[3182] = 8'd219; long_chirp_lut[3183] = 8'd148; + long_chirp_lut[3184] = 8'd 68; long_chirp_lut[3185] = 8'd 13; long_chirp_lut[3186] = 8'd 3; long_chirp_lut[3187] = 8'd 43; long_chirp_lut[3188] = 8'd117; long_chirp_lut[3189] = 8'd195; long_chirp_lut[3190] = 8'd246; long_chirp_lut[3191] = 8'd250; long_chirp_lut[3192] = 8'd204; long_chirp_lut[3193] = 8'd128; long_chirp_lut[3194] = 8'd 52; long_chirp_lut[3195] = 8'd 6; long_chirp_lut[3196] = 8'd 8; long_chirp_lut[3197] = 8'd 58; long_chirp_lut[3198] = 8'd135; long_chirp_lut[3199] = 8'd209; + long_chirp_lut[3200] = 8'd251; long_chirp_lut[3201] = 8'd244; long_chirp_lut[3202] = 8'd191; long_chirp_lut[3203] = 8'd113; long_chirp_lut[3204] = 8'd 41; long_chirp_lut[3205] = 8'd 3; long_chirp_lut[3206] = 8'd 14; long_chirp_lut[3207] = 8'd 70; long_chirp_lut[3208] = 8'd148; long_chirp_lut[3209] = 8'd219; long_chirp_lut[3210] = 8'd253; long_chirp_lut[3211] = 8'd239; long_chirp_lut[3212] = 8'd180; long_chirp_lut[3213] = 8'd101; long_chirp_lut[3214] = 8'd 33; long_chirp_lut[3215] = 8'd 1; + long_chirp_lut[3216] = 8'd 19; long_chirp_lut[3217] = 8'd 79; long_chirp_lut[3218] = 8'd158; long_chirp_lut[3219] = 8'd225; long_chirp_lut[3220] = 8'd254; long_chirp_lut[3221] = 8'd234; long_chirp_lut[3222] = 8'd172; long_chirp_lut[3223] = 8'd 93; long_chirp_lut[3224] = 8'd 28; long_chirp_lut[3225] = 8'd 1; long_chirp_lut[3226] = 8'd 23; long_chirp_lut[3227] = 8'd 85; long_chirp_lut[3228] = 8'd164; long_chirp_lut[3229] = 8'd229; long_chirp_lut[3230] = 8'd254; long_chirp_lut[3231] = 8'd231; + long_chirp_lut[3232] = 8'd168; long_chirp_lut[3233] = 8'd 89; long_chirp_lut[3234] = 8'd 25; long_chirp_lut[3235] = 8'd 1; long_chirp_lut[3236] = 8'd 25; long_chirp_lut[3237] = 8'd 88; long_chirp_lut[3238] = 8'd167; long_chirp_lut[3239] = 8'd230; long_chirp_lut[3240] = 8'd255; long_chirp_lut[3241] = 8'd230; long_chirp_lut[3242] = 8'd167; long_chirp_lut[3243] = 8'd 88; long_chirp_lut[3244] = 8'd 25; long_chirp_lut[3245] = 8'd 1; long_chirp_lut[3246] = 8'd 24; long_chirp_lut[3247] = 8'd 87; + long_chirp_lut[3248] = 8'd166; long_chirp_lut[3249] = 8'd229; long_chirp_lut[3250] = 8'd254; long_chirp_lut[3251] = 8'd232; long_chirp_lut[3252] = 8'd169; long_chirp_lut[3253] = 8'd 91; long_chirp_lut[3254] = 8'd 27; long_chirp_lut[3255] = 8'd 1; long_chirp_lut[3256] = 8'd 22; long_chirp_lut[3257] = 8'd 83; long_chirp_lut[3258] = 8'd161; long_chirp_lut[3259] = 8'd226; long_chirp_lut[3260] = 8'd254; long_chirp_lut[3261] = 8'd235; long_chirp_lut[3262] = 8'd175; long_chirp_lut[3263] = 8'd 98; + long_chirp_lut[3264] = 8'd 31; long_chirp_lut[3265] = 8'd 1; long_chirp_lut[3266] = 8'd 18; long_chirp_lut[3267] = 8'd 76; long_chirp_lut[3268] = 8'd153; long_chirp_lut[3269] = 8'd220; long_chirp_lut[3270] = 8'd253; long_chirp_lut[3271] = 8'd240; long_chirp_lut[3272] = 8'd184; long_chirp_lut[3273] = 8'd108; long_chirp_lut[3274] = 8'd 39; long_chirp_lut[3275] = 8'd 3; long_chirp_lut[3276] = 8'd 13; long_chirp_lut[3277] = 8'd 65; long_chirp_lut[3278] = 8'd141; long_chirp_lut[3279] = 8'd211; + long_chirp_lut[3280] = 8'd251; long_chirp_lut[3281] = 8'd245; long_chirp_lut[3282] = 8'd196; long_chirp_lut[3283] = 8'd122; long_chirp_lut[3284] = 8'd 50; long_chirp_lut[3285] = 8'd 6; long_chirp_lut[3286] = 8'd 7; long_chirp_lut[3287] = 8'd 52; long_chirp_lut[3288] = 8'd125; long_chirp_lut[3289] = 8'd199; long_chirp_lut[3290] = 8'd246; long_chirp_lut[3291] = 8'd251; long_chirp_lut[3292] = 8'd210; long_chirp_lut[3293] = 8'd139; long_chirp_lut[3294] = 8'd 65; long_chirp_lut[3295] = 8'd 13; + long_chirp_lut[3296] = 8'd 2; long_chirp_lut[3297] = 8'd 38; long_chirp_lut[3298] = 8'd105; long_chirp_lut[3299] = 8'd181; long_chirp_lut[3300] = 8'd237; long_chirp_lut[3301] = 8'd254; long_chirp_lut[3302] = 8'd225; long_chirp_lut[3303] = 8'd161; long_chirp_lut[3304] = 8'd 84; long_chirp_lut[3305] = 8'd 24; long_chirp_lut[3306] = 8'd 1; long_chirp_lut[3307] = 8'd 23; long_chirp_lut[3308] = 8'd 83; long_chirp_lut[3309] = 8'd159; long_chirp_lut[3310] = 8'd224; long_chirp_lut[3311] = 8'd254; + long_chirp_lut[3312] = 8'd239; long_chirp_lut[3313] = 8'd184; long_chirp_lut[3314] = 8'd109; long_chirp_lut[3315] = 8'd 41; long_chirp_lut[3316] = 8'd 3; long_chirp_lut[3317] = 8'd 10; long_chirp_lut[3318] = 8'd 59; long_chirp_lut[3319] = 8'd132; long_chirp_lut[3320] = 8'd203; long_chirp_lut[3321] = 8'd248; long_chirp_lut[3322] = 8'd250; long_chirp_lut[3323] = 8'd208; long_chirp_lut[3324] = 8'd138; long_chirp_lut[3325] = 8'd 64; long_chirp_lut[3326] = 8'd 13; long_chirp_lut[3327] = 8'd 2; + long_chirp_lut[3328] = 8'd 35; long_chirp_lut[3329] = 8'd101; long_chirp_lut[3330] = 8'd176; long_chirp_lut[3331] = 8'd234; long_chirp_lut[3332] = 8'd254; long_chirp_lut[3333] = 8'd230; long_chirp_lut[3334] = 8'd170; long_chirp_lut[3335] = 8'd 95; long_chirp_lut[3336] = 8'd 31; long_chirp_lut[3337] = 8'd 1; long_chirp_lut[3338] = 8'd 15; long_chirp_lut[3339] = 8'd 69; long_chirp_lut[3340] = 8'd142; long_chirp_lut[3341] = 8'd211; long_chirp_lut[3342] = 8'd250; long_chirp_lut[3343] = 8'd247; + long_chirp_lut[3344] = 8'd202; long_chirp_lut[3345] = 8'd132; long_chirp_lut[3346] = 8'd 60; long_chirp_lut[3347] = 8'd 11; long_chirp_lut[3348] = 8'd 3; long_chirp_lut[3349] = 8'd 38; long_chirp_lut[3350] = 8'd104; long_chirp_lut[3351] = 8'd178; long_chirp_lut[3352] = 8'd235; long_chirp_lut[3353] = 8'd254; long_chirp_lut[3354] = 8'd231; long_chirp_lut[3355] = 8'd171; long_chirp_lut[3356] = 8'd 97; long_chirp_lut[3357] = 8'd 33; long_chirp_lut[3358] = 8'd 2; long_chirp_lut[3359] = 8'd 13; + long_chirp_lut[3360] = 8'd 64; long_chirp_lut[3361] = 8'd136; long_chirp_lut[3362] = 8'd206; long_chirp_lut[3363] = 8'd248; long_chirp_lut[3364] = 8'd250; long_chirp_lut[3365] = 8'd209; long_chirp_lut[3366] = 8'd141; long_chirp_lut[3367] = 8'd 69; long_chirp_lut[3368] = 8'd 16; long_chirp_lut[3369] = 8'd 1; long_chirp_lut[3370] = 8'd 29; long_chirp_lut[3371] = 8'd 90; long_chirp_lut[3372] = 8'd164; long_chirp_lut[3373] = 8'd226; long_chirp_lut[3374] = 8'd254; long_chirp_lut[3375] = 8'd240; + long_chirp_lut[3376] = 8'd187; long_chirp_lut[3377] = 8'd115; long_chirp_lut[3378] = 8'd 47; long_chirp_lut[3379] = 8'd 6; long_chirp_lut[3380] = 8'd 6; long_chirp_lut[3381] = 8'd 46; long_chirp_lut[3382] = 8'd114; long_chirp_lut[3383] = 8'd186; long_chirp_lut[3384] = 8'd239; long_chirp_lut[3385] = 8'd254; long_chirp_lut[3386] = 8'd227; long_chirp_lut[3387] = 8'd167; long_chirp_lut[3388] = 8'd 94; long_chirp_lut[3389] = 8'd 32; long_chirp_lut[3390] = 8'd 2; long_chirp_lut[3391] = 8'd 13; + long_chirp_lut[3392] = 8'd 63; long_chirp_lut[3393] = 8'd134; long_chirp_lut[3394] = 8'd203; long_chirp_lut[3395] = 8'd247; long_chirp_lut[3396] = 8'd251; long_chirp_lut[3397] = 8'd215; long_chirp_lut[3398] = 8'd150; long_chirp_lut[3399] = 8'd 77; long_chirp_lut[3400] = 8'd 21; long_chirp_lut[3401] = 8'd 1; long_chirp_lut[3402] = 8'd 21; long_chirp_lut[3403] = 8'd 77; long_chirp_lut[3404] = 8'd149; long_chirp_lut[3405] = 8'd214; long_chirp_lut[3406] = 8'd251; long_chirp_lut[3407] = 8'd247; + long_chirp_lut[3408] = 8'd204; long_chirp_lut[3409] = 8'd136; long_chirp_lut[3410] = 8'd 66; long_chirp_lut[3411] = 8'd 15; long_chirp_lut[3412] = 8'd 1; long_chirp_lut[3413] = 8'd 28; long_chirp_lut[3414] = 8'd 88; long_chirp_lut[3415] = 8'd160; long_chirp_lut[3416] = 8'd222; long_chirp_lut[3417] = 8'd253; long_chirp_lut[3418] = 8'd244; long_chirp_lut[3419] = 8'd197; long_chirp_lut[3420] = 8'd128; long_chirp_lut[3421] = 8'd 58; long_chirp_lut[3422] = 8'd 12; long_chirp_lut[3423] = 8'd 2; + long_chirp_lut[3424] = 8'd 33; long_chirp_lut[3425] = 8'd 94; long_chirp_lut[3426] = 8'd166; long_chirp_lut[3427] = 8'd226; long_chirp_lut[3428] = 8'd254; long_chirp_lut[3429] = 8'd241; long_chirp_lut[3430] = 8'd193; long_chirp_lut[3431] = 8'd123; long_chirp_lut[3432] = 8'd 55; long_chirp_lut[3433] = 8'd 10; long_chirp_lut[3434] = 8'd 3; long_chirp_lut[3435] = 8'd 35; long_chirp_lut[3436] = 8'd 96; long_chirp_lut[3437] = 8'd168; long_chirp_lut[3438] = 8'd227; long_chirp_lut[3439] = 8'd254; + long_chirp_lut[3440] = 8'd241; long_chirp_lut[3441] = 8'd192; long_chirp_lut[3442] = 8'd123; long_chirp_lut[3443] = 8'd 55; long_chirp_lut[3444] = 8'd 10; long_chirp_lut[3445] = 8'd 2; long_chirp_lut[3446] = 8'd 34; long_chirp_lut[3447] = 8'd 94; long_chirp_lut[3448] = 8'd166; long_chirp_lut[3449] = 8'd225; long_chirp_lut[3450] = 8'd253; long_chirp_lut[3451] = 8'd243; long_chirp_lut[3452] = 8'd196; long_chirp_lut[3453] = 8'd128; long_chirp_lut[3454] = 8'd 60; long_chirp_lut[3455] = 8'd 13; + long_chirp_lut[3456] = 8'd 2; long_chirp_lut[3457] = 8'd 30; long_chirp_lut[3458] = 8'd 88; long_chirp_lut[3459] = 8'd159; long_chirp_lut[3460] = 8'd220; long_chirp_lut[3461] = 8'd252; long_chirp_lut[3462] = 8'd246; long_chirp_lut[3463] = 8'd203; long_chirp_lut[3464] = 8'd137; long_chirp_lut[3465] = 8'd 68; long_chirp_lut[3466] = 8'd 17; long_chirp_lut[3467] = 8'd 1; long_chirp_lut[3468] = 8'd 23; long_chirp_lut[3469] = 8'd 78; long_chirp_lut[3470] = 8'd148; long_chirp_lut[3471] = 8'd211; + long_chirp_lut[3472] = 8'd249; long_chirp_lut[3473] = 8'd250; long_chirp_lut[3474] = 8'd213; long_chirp_lut[3475] = 8'd150; long_chirp_lut[3476] = 8'd 80; long_chirp_lut[3477] = 8'd 25; long_chirp_lut[3478] = 8'd 1; long_chirp_lut[3479] = 8'd 15; long_chirp_lut[3480] = 8'd 64; long_chirp_lut[3481] = 8'd132; long_chirp_lut[3482] = 8'd198; long_chirp_lut[3483] = 8'd243; long_chirp_lut[3484] = 8'd253; long_chirp_lut[3485] = 8'd225; long_chirp_lut[3486] = 8'd167; long_chirp_lut[3487] = 8'd 98; + long_chirp_lut[3488] = 8'd 37; long_chirp_lut[3489] = 8'd 4; long_chirp_lut[3490] = 8'd 8; long_chirp_lut[3491] = 8'd 48; long_chirp_lut[3492] = 8'd112; long_chirp_lut[3493] = 8'd180; long_chirp_lut[3494] = 8'd233; long_chirp_lut[3495] = 8'd254; long_chirp_lut[3496] = 8'd238; long_chirp_lut[3497] = 8'd188; long_chirp_lut[3498] = 8'd120; long_chirp_lut[3499] = 8'd 55; long_chirp_lut[3500] = 8'd 11; long_chirp_lut[3501] = 8'd 2; long_chirp_lut[3502] = 8'd 30; long_chirp_lut[3503] = 8'd 87; + long_chirp_lut[3504] = 8'd157; long_chirp_lut[3505] = 8'd217; long_chirp_lut[3506] = 8'd251; long_chirp_lut[3507] = 8'd248; long_chirp_lut[3508] = 8'd210; long_chirp_lut[3509] = 8'd147; long_chirp_lut[3510] = 8'd 79; long_chirp_lut[3511] = 8'd 25; long_chirp_lut[3512] = 8'd 1; long_chirp_lut[3513] = 8'd 14; long_chirp_lut[3514] = 8'd 61; long_chirp_lut[3515] = 8'd127; long_chirp_lut[3516] = 8'd193; long_chirp_lut[3517] = 8'd240; long_chirp_lut[3518] = 8'd254; long_chirp_lut[3519] = 8'd231; + long_chirp_lut[3520] = 8'd178; long_chirp_lut[3521] = 8'd110; long_chirp_lut[3522] = 8'd 47; long_chirp_lut[3523] = 8'd 8; long_chirp_lut[3524] = 8'd 3; long_chirp_lut[3525] = 8'd 35; long_chirp_lut[3526] = 8'd 93; long_chirp_lut[3527] = 8'd162; long_chirp_lut[3528] = 8'd220; long_chirp_lut[3529] = 8'd252; long_chirp_lut[3530] = 8'd247; long_chirp_lut[3531] = 8'd209; long_chirp_lut[3532] = 8'd146; long_chirp_lut[3533] = 8'd 79; long_chirp_lut[3534] = 8'd 25; long_chirp_lut[3535] = 8'd 1; + long_chirp_lut[3536] = 8'd 13; long_chirp_lut[3537] = 8'd 58; long_chirp_lut[3538] = 8'd123; long_chirp_lut[3539] = 8'd189; long_chirp_lut[3540] = 8'd237; long_chirp_lut[3541] = 8'd254; long_chirp_lut[3542] = 8'd235; long_chirp_lut[3543] = 8'd185; long_chirp_lut[3544] = 8'd119; long_chirp_lut[3545] = 8'd 55; long_chirp_lut[3546] = 8'd 12; long_chirp_lut[3547] = 8'd 1; long_chirp_lut[3548] = 8'd 27; long_chirp_lut[3549] = 8'd 81; long_chirp_lut[3550] = 8'd148; long_chirp_lut[3551] = 8'd209; + long_chirp_lut[3552] = 8'd247; long_chirp_lut[3553] = 8'd252; long_chirp_lut[3554] = 8'd221; long_chirp_lut[3555] = 8'd164; long_chirp_lut[3556] = 8'd 97; long_chirp_lut[3557] = 8'd 38; long_chirp_lut[3558] = 8'd 5; long_chirp_lut[3559] = 8'd 5; long_chirp_lut[3560] = 8'd 40; long_chirp_lut[3561] = 8'd100; long_chirp_lut[3562] = 8'd167; long_chirp_lut[3563] = 8'd223; long_chirp_lut[3564] = 8'd252; long_chirp_lut[3565] = 8'd247; long_chirp_lut[3566] = 8'd209; long_chirp_lut[3567] = 8'd148; + long_chirp_lut[3568] = 8'd 81; long_chirp_lut[3569] = 8'd 27; long_chirp_lut[3570] = 8'd 2; long_chirp_lut[3571] = 8'd 11; long_chirp_lut[3572] = 8'd 52; long_chirp_lut[3573] = 8'd114; long_chirp_lut[3574] = 8'd180; long_chirp_lut[3575] = 8'd231; long_chirp_lut[3576] = 8'd254; long_chirp_lut[3577] = 8'd242; long_chirp_lut[3578] = 8'd199; long_chirp_lut[3579] = 8'd136; long_chirp_lut[3580] = 8'd 71; long_chirp_lut[3581] = 8'd 21; long_chirp_lut[3582] = 8'd 1; long_chirp_lut[3583] = 8'd 15; + long_chirp_lut[3584] = 8'd 60; long_chirp_lut[3585] = 8'd123; long_chirp_lut[3586] = 8'd188; long_chirp_lut[3587] = 8'd236; long_chirp_lut[3588] = 8'd254; long_chirp_lut[3589] = 8'd239; long_chirp_lut[3590] = 8'd193; long_chirp_lut[3591] = 8'd129; long_chirp_lut[3592] = 8'd 65; long_chirp_lut[3593] = 8'd 18; long_chirp_lut[3594] = 8'd 1; long_chirp_lut[3595] = 8'd 17; long_chirp_lut[3596] = 8'd 64; long_chirp_lut[3597] = 8'd127; long_chirp_lut[3598] = 8'd191; long_chirp_lut[3599] = 8'd237; +end + +// Short PLFM chirp LUT (0.5us, 30MHz to 10MHz) +initial begin + short_chirp_lut[ 0] = 8'd255; short_chirp_lut[ 1] = 8'd129; short_chirp_lut[ 2] = 8'd 1; short_chirp_lut[ 3] = 8'd118; short_chirp_lut[ 4] = 8'd253; short_chirp_lut[ 5] = 8'd155; short_chirp_lut[ 6] = 8'd 7; short_chirp_lut[ 7] = 8'd 75; + short_chirp_lut[ 8] = 8'd235; short_chirp_lut[ 9] = 8'd210; short_chirp_lut[10] = 8'd 46; short_chirp_lut[11] = 8'd 17; short_chirp_lut[12] = 8'd167; short_chirp_lut[13] = 8'd254; short_chirp_lut[14] = 8'd145; short_chirp_lut[15] = 8'd 10; + short_chirp_lut[16] = 8'd 49; short_chirp_lut[17] = 8'd201; short_chirp_lut[18] = 8'd248; short_chirp_lut[19] = 8'd129; short_chirp_lut[20] = 8'd 8; short_chirp_lut[21] = 8'd 45; short_chirp_lut[22] = 8'd187; short_chirp_lut[23] = 8'd254; + short_chirp_lut[24] = 8'd167; short_chirp_lut[25] = 8'd 34; short_chirp_lut[26] = 8'd 10; short_chirp_lut[27] = 8'd118; short_chirp_lut[28] = 8'd235; short_chirp_lut[29] = 8'd238; short_chirp_lut[30] = 8'd127; short_chirp_lut[31] = 8'd 18; + short_chirp_lut[32] = 8'd 15; short_chirp_lut[33] = 8'd118; short_chirp_lut[34] = 8'd228; short_chirp_lut[35] = 8'd249; short_chirp_lut[36] = 8'd167; short_chirp_lut[37] = 8'd 54; short_chirp_lut[38] = 8'd 1; short_chirp_lut[39] = 8'd 45; + short_chirp_lut[40] = 8'd150; short_chirp_lut[41] = 8'd237; short_chirp_lut[42] = 8'd248; short_chirp_lut[43] = 8'd180; short_chirp_lut[44] = 8'd 80; short_chirp_lut[45] = 8'd 10; short_chirp_lut[46] = 8'd 10; short_chirp_lut[47] = 8'd 75; + short_chirp_lut[48] = 8'd167; short_chirp_lut[49] = 8'd237; short_chirp_lut[50] = 8'd253; short_chirp_lut[51] = 8'd210; short_chirp_lut[52] = 8'd132; short_chirp_lut[53] = 8'd 54; short_chirp_lut[54] = 8'd 7; short_chirp_lut[55] = 8'd 6; + short_chirp_lut[56] = 8'd 49; short_chirp_lut[57] = 8'd118; short_chirp_lut[58] = 8'd187; short_chirp_lut[59] = 8'd237; +end diff --git a/9_Firmware/9_2_FPGA/chirp_memory_loader_param.v b/9_Firmware/9_2_FPGA/chirp_memory_loader_param.v new file mode 100644 index 0000000..90e9a44 --- /dev/null +++ b/9_Firmware/9_2_FPGA/chirp_memory_loader_param.v @@ -0,0 +1,130 @@ +`timescale 1ns / 1ps +module chirp_memory_loader_param #( + parameter LONG_I_FILE_SEG0 = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/long_chirp_seg0_i.mem", + parameter LONG_Q_FILE_SEG0 = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/long_chirp_seg0_q.mem", + parameter LONG_I_FILE_SEG1 = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/long_chirp_seg1_i.mem", + parameter LONG_Q_FILE_SEG1 = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/long_chirp_seg1_q.mem", + parameter LONG_I_FILE_SEG2 = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/long_chirp_seg2_i.mem", + parameter LONG_Q_FILE_SEG2 = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/long_chirp_seg2_q.mem", + parameter LONG_I_FILE_SEG3 = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/long_chirp_seg3_i.mem", + parameter LONG_Q_FILE_SEG3 = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/long_chirp_seg3_q.mem", + parameter SHORT_I_FILE = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/short_chirp_i.mem", + parameter SHORT_Q_FILE = "C:/Users/dell/Desktop/ASUS/RADAR_V5/Firmware/FPGA/PLFM_RADAR_Xilinx_ISE_V2/Python/mem_files/fpga_mem_files/short_chirp_q.mem", + parameter DEBUG = 1 +)( + input wire clk, + input wire reset_n, + input wire [1:0] segment_select, + input wire mem_request, + input wire use_long_chirp, + input wire [9:0] sample_addr, + output reg [15:0] ref_i, + output reg [15:0] ref_q, + output reg mem_ready +); + +// Memory declarations - now 4096 samples for 4 segments +(* ram_style = "block" *) reg [15:0] long_chirp_i [0:4095]; +(* ram_style = "block" *) reg [15:0] long_chirp_q [0:4095]; +(* ram_style = "block" *) reg [15:0] short_chirp_i [0:1023]; +(* ram_style = "block" *) reg [15:0] short_chirp_q [0:1023]; + +// Initialize memory +integer i; +reg [799:0] debug_msg; + +initial begin + if (DEBUG) begin + $display("[MEM] Starting memory initialization for 4 long chirp segments"); + end + + // === LOAD LONG CHIRP - 4 SEGMENTS === + // Segment 0 (addresses 0-1023) + $readmemh(LONG_I_FILE_SEG0, long_chirp_i, 0, 1023); + $readmemh(LONG_Q_FILE_SEG0, long_chirp_q, 0, 1023); + if (DEBUG) $display("[MEM] Loaded long chirp segment 0 (0-1023)"); + + // Segment 1 (addresses 1024-2047) + $readmemh(LONG_I_FILE_SEG1, long_chirp_i, 1024, 2047); + $readmemh(LONG_Q_FILE_SEG1, long_chirp_q, 1024, 2047); + if (DEBUG) $display("[MEM] Loaded long chirp segment 1 (1024-2047)"); + + // Segment 2 (addresses 2048-3071) + $readmemh(LONG_I_FILE_SEG2, long_chirp_i, 2048, 3071); + $readmemh(LONG_Q_FILE_SEG2, long_chirp_q, 2048, 3071); + if (DEBUG) $display("[MEM] Loaded long chirp segment 2 (2048-3071)"); + + // Segment 3 (addresses 3072-4095) + $readmemh(LONG_I_FILE_SEG3, long_chirp_i, 3072, 4095); + $readmemh(LONG_Q_FILE_SEG3, long_chirp_q, 3072, 4095); + if (DEBUG) $display("[MEM] Loaded long chirp segment 3 (3072-4095)"); + + // === LOAD SHORT CHIRP === + // Load first 50 samples (0-49) + $readmemh(SHORT_I_FILE, short_chirp_i); + $readmemh(SHORT_Q_FILE, short_chirp_q); + if (DEBUG) $display("[MEM] Loaded short chirp (0-49)"); + + // Zero pad remaining 974 samples (50-1023) + for (i = 50; i < 1024; i = i + 1) begin + short_chirp_i[i] = 16'h0000; + short_chirp_q[i] = 16'h0000; + end + if (DEBUG) $display("[MEM] Zero-padded short chirp from 50-1023"); + + // === VERIFICATION === + if (DEBUG) begin + $display("[MEM] Memory loading complete. Verification samples:"); + $display(" Long[0]: I=%h Q=%h", long_chirp_i[0], long_chirp_q[0]); + $display(" Long[1023]: I=%h Q=%h", long_chirp_i[1023], long_chirp_q[1023]); + $display(" Long[1024]: I=%h Q=%h", long_chirp_i[1024], long_chirp_q[1024]); + $display(" Long[2047]: I=%h Q=%h", long_chirp_i[2047], long_chirp_q[2047]); + $display(" Long[2048]: I=%h Q=%h", long_chirp_i[2048], long_chirp_q[2048]); + $display(" Long[3071]: I=%h Q=%h", long_chirp_i[3071], long_chirp_q[3071]); + $display(" Long[3072]: I=%h Q=%h", long_chirp_i[3072], long_chirp_q[3072]); + $display(" Long[4095]: I=%h Q=%h", long_chirp_i[4095], long_chirp_q[4095]); + $display(" Short[0]: I=%h Q=%h", short_chirp_i[0], short_chirp_q[0]); + $display(" Short[49]: I=%h Q=%h", short_chirp_i[49], short_chirp_q[49]); + $display(" Short[50]: I=%h Q=%h (zero-padded)", short_chirp_i[50], short_chirp_q[50]); + end +end + +// Memory access logic +reg [11:0] long_addr; + +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + ref_i <= 16'd0; + ref_q <= 16'd0; + mem_ready <= 1'b0; + end else begin + if (mem_request) begin + if (use_long_chirp) begin + // Direct addressing for 4 segments + long_addr = {segment_select, sample_addr}; // segment_select[1:0] + sample_addr[9:0] + ref_i <= long_chirp_i[long_addr]; + ref_q <= long_chirp_q[long_addr]; + + if (DEBUG && $time < 100) begin + $display("[MEM @%0t] Long chirp: seg=%b, addr=%d, I=%h, Q=%h", + $time, segment_select, long_addr, + long_chirp_i[long_addr], long_chirp_q[long_addr]); + end + end else begin + // Short chirp (0-1023) + ref_i <= short_chirp_i[sample_addr]; + ref_q <= short_chirp_q[sample_addr]; + + if (DEBUG && $time < 100) begin + $display("[MEM @%0t] Short chirp: addr=%d, I=%h, Q=%h", + $time, sample_addr, short_chirp_i[sample_addr], short_chirp_q[sample_addr]); + end + end + mem_ready <= 1'b1; + end else begin + mem_ready <= 1'b0; + end + end +end + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/cic_decimator_4x_enhanced.v b/9_Firmware/9_2_FPGA/cic_decimator_4x_enhanced.v new file mode 100644 index 0000000..42d3ff7 --- /dev/null +++ b/9_Firmware/9_2_FPGA/cic_decimator_4x_enhanced.v @@ -0,0 +1,300 @@ +module cic_decimator_4x_enhanced ( + input wire clk, // 400MHz input clock + input wire reset_n, + input wire signed [17:0] data_in, // 18-bit input + input wire data_valid, + output reg signed [17:0] data_out, // 18-bit output + output reg data_out_valid, // Valid at 100MHz + // Enhanced monitoring outputs + output reg saturation_detected, // Latched saturation indicator + output reg [7:0] max_value_monitor, // For gain control + input wire reset_monitors // Clear saturation and max value +); + +parameter STAGES = 5; +parameter DECIMATION = 4; +parameter COMB_DELAY = 1; + +// Increased bit width for 18-bit input with headroom +reg signed [35:0] integrator [0:STAGES-1]; // 36-bit for better dynamic range +reg signed [35:0] comb [0:STAGES-1]; +reg signed [35:0] comb_delay [0:STAGES-1][0:COMB_DELAY-1]; + +// Enhanced control and monitoring +reg [1:0] decimation_counter; +reg data_valid_delayed; +reg data_valid_comb; +reg [7:0] output_counter; +reg [35:0] max_integrator_value; +reg overflow_detected; +reg overflow_latched; // Latched overflow indicator + +// Diagnostic registers +reg [7:0] saturation_event_count; +reg [31:0] sample_count; + +// Temporary signals for calculations +reg signed [35:0] abs_integrator_value; +reg signed [35:0] temp_scaled_output; +reg signed [17:0] temp_output; // Temporary output for proper range checking + +integer i, j; + +// Initialize +initial begin + for (i = 0; i < STAGES; i = i + 1) begin + integrator[i] = 0; + comb[i] = 0; + for (j = 0; j < COMB_DELAY; j = j + 1) begin + comb_delay[i][j] = 0; + end + end + decimation_counter = 0; + data_valid_delayed = 0; + data_valid_comb = 0; + output_counter = 0; + max_integrator_value = 0; + overflow_detected = 0; + overflow_latched = 0; + saturation_detected = 0; + saturation_event_count = 0; + sample_count = 0; + max_value_monitor = 0; + data_out = 0; + data_out_valid = 0; + abs_integrator_value = 0; + temp_scaled_output = 0; + temp_output = 0; +end + +// Enhanced integrator section with proper saturation monitoring +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + for (i = 0; i < STAGES; i = i + 1) begin + integrator[i] <= 0; + end + decimation_counter <= 0; + data_valid_delayed <= 0; + data_valid_comb <= 0; + max_integrator_value <= 0; + overflow_detected <= 0; + sample_count <= 0; + abs_integrator_value <= 0; + + if (reset_monitors) begin + overflow_latched <= 0; + saturation_detected <= 0; + saturation_event_count <= 0; + max_value_monitor <= 0; + end + end else if (data_valid) begin + sample_count <= sample_count + 1; + + // First integrator stage with enhanced saturation detection + if (integrator[0] + $signed({{18{data_in[17]}}, data_in}) > (2**35 - 1)) begin + integrator[0] <= (2**35 - 1); + overflow_detected <= 1'b1; + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + saturation_event_count <= saturation_event_count + 1; + $display("CIC_SATURATION: Positive overflow at sample %0d", sample_count); + end else if (integrator[0] + $signed({{18{data_in[17]}}, data_in}) < -(2**35)) begin + integrator[0] <= -(2**35); + overflow_detected <= 1'b1; + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + saturation_event_count <= saturation_event_count + 1; + $display("CIC_SATURATION: Negative overflow at sample %0d", sample_count); + end else begin + integrator[0] <= integrator[0] + $signed({{18{data_in[17]}}, data_in}); + overflow_detected <= 1'b0; // Only clear immediate detection, not latched + end + + // Calculate absolute value for monitoring + abs_integrator_value <= (integrator[0][35]) ? -integrator[0] : integrator[0]; + + // Track maximum integrator value for gain monitoring (absolute value) + if (abs_integrator_value > max_integrator_value) begin + max_integrator_value <= abs_integrator_value; + max_value_monitor <= abs_integrator_value[31:24]; // Fixed: use the calculated absolute value + end + + // Remaining integrator stages with saturation protection + for (i = 1; i < STAGES; i = i + 1) begin + if (integrator[i] + integrator[i-1] > (2**35 - 1)) begin + integrator[i] <= (2**35 - 1); + overflow_detected <= 1'b1; + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + end else if (integrator[i] + integrator[i-1] < -(2**35)) begin + integrator[i] <= -(2**35); + overflow_detected <= 1'b1; + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + end else begin + integrator[i] <= integrator[i] + integrator[i-1]; + end + end + + // Enhanced decimation control + if (decimation_counter == DECIMATION - 1) begin + decimation_counter <= 0; + data_valid_delayed <= 1; + output_counter <= output_counter + 1; + + /*// Debug output for first few samples + if (output_counter < 10) begin + $display("CIC_DECIM: sample=%0d, integrator[%0d]=%h, max_val=%h, sat=%b", + output_counter, STAGES-1, integrator[STAGES-1], + max_integrator_value, saturation_detected); + end + */ + end else begin + decimation_counter <= decimation_counter + 1; + data_valid_delayed <= 0; + end + end else begin + data_valid_delayed <= 0; + overflow_detected <= 1'b0; // Clear immediate detection when no data + end + + // Monitor control - clear latched saturation on reset_monitors + if (reset_monitors) begin + overflow_latched <= 0; + saturation_detected <= 0; + max_integrator_value <= 0; + max_value_monitor <= 0; + saturation_event_count <= 0; + end +end + +// Pipeline the valid signal for comb section +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + data_valid_comb <= 0; + end else begin + data_valid_comb <= data_valid_delayed; + end +end + +// Enhanced comb section with FIXED scaling and saturation monitoring +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + for (i = 0; i < STAGES; i = i + 1) begin + comb[i] <= 0; + for (j = 0; j < COMB_DELAY; j = j + 1) begin + comb_delay[i][j] <= 0; + end + end + data_out <= 0; + data_out_valid <= 0; + temp_scaled_output <= 0; + temp_output <= 0; + end else if (data_valid_comb) begin + // Enhanced comb processing with saturation check + for (i = 0; i < STAGES; i = i + 1) begin + if (i == 0) begin + // Check for comb stage saturation + if (integrator[STAGES-1] - comb_delay[0][COMB_DELAY-1] > (2**35 - 1)) begin + comb[0] <= (2**35 - 1); + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + end else if (integrator[STAGES-1] - comb_delay[0][COMB_DELAY-1] < -(2**35)) begin + comb[0] <= -(2**35); + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + end else begin + comb[0] <= integrator[STAGES-1] - comb_delay[0][COMB_DELAY-1]; + end + + // Update delay line for first stage + for (j = COMB_DELAY-1; j > 0; j = j - 1) begin + comb_delay[0][j] <= comb_delay[0][j-1]; + end + comb_delay[0][0] <= integrator[STAGES-1]; + end else begin + // Check for comb stage saturation + if (comb[i-1] - comb_delay[i][COMB_DELAY-1] > (2**35 - 1)) begin + comb[i] <= (2**35 - 1); + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + end else if (comb[i-1] - comb_delay[i][COMB_DELAY-1] < -(2**35)) begin + comb[i] <= -(2**35); + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + end else begin + comb[i] <= comb[i-1] - comb_delay[i][COMB_DELAY-1]; + end + + // Update delay line + for (j = COMB_DELAY-1; j > 0; j = j - 1) begin + comb_delay[i][j] <= comb_delay[i][j-1]; + end + comb_delay[i][0] <= comb[i-1]; + end + end + + // FIXED: Use proper scaling for 5 stages and decimation by 4 + // Gain = (4^5) = 1024 = 2^10, so scale by 2^10 to normalize + temp_scaled_output <= comb[STAGES-1] >>> 10; + + // FIXED: Extract 18-bit output properly + temp_output <= temp_scaled_output[17:0]; + + // FIXED: Proper saturation detection for 18-bit signed range + // Check if the 18-bit truncated value matches the intended value + if (temp_scaled_output > 131071) begin // 2^17 - 1 + data_out <= 131071; + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + saturation_event_count <= saturation_event_count + 1; + $display("CIC_OUTPUT_SAT: TRUE Positive saturation, raw=%h, scaled=%h, temp_out=%d, final_out=%d", + comb[STAGES-1], temp_scaled_output, temp_output, 131071); + end else if (temp_scaled_output < -131072) begin // -2^17 + data_out <= -131072; + overflow_latched <= 1'b1; + saturation_detected <= 1'b1; + saturation_event_count <= saturation_event_count + 1; + $display("CIC_OUTPUT_SAT: TRUE Negative saturation, raw=%h, scaled=%h, temp_out=%d, final_out=%d", + comb[STAGES-1], temp_scaled_output, temp_output, -131072); + end else begin + // FIXED: Use the properly truncated 18-bit value + data_out <= temp_output; + overflow_latched <= 1'b0; + saturation_detected <= 1'b0; + if (output_counter < 20) begin + //$display("CIC_OUTPUT_GOOD: raw=%h, scaled=%h, temp_out=%d, final_out=%d", + // comb[STAGES-1], temp_scaled_output, temp_output, data_out); + end + end + + data_out_valid <= 1; + + // Debug output for first samples + if (output_counter < 10) begin + // $display("CIC_DEBUG: sample=%0d, raw=%h, scaled=%h, out=%d, sat=%b", + // output_counter, comb[STAGES-1], temp_scaled_output, data_out, saturation_detected); + end + end else begin + data_out_valid <= 0; + end +end + +// Continuous monitoring of saturation status +always @(posedge clk) begin + if (overflow_detected && sample_count < 100) begin + $display("CIC_OVERFLOW: Immediate detection at sample %0d", sample_count); + end +end + +// Clear saturation on external reset +always @(posedge reset_monitors) begin + if (reset_monitors) begin + overflow_latched <= 0; + saturation_detected <= 0; + saturation_event_count <= 0; + //$display("CIC_MONITORS: All monitors reset"); + end +end + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/dac_interface_single.v b/9_Firmware/9_2_FPGA/dac_interface_single.v new file mode 100644 index 0000000..f912111 --- /dev/null +++ b/9_Firmware/9_2_FPGA/dac_interface_single.v @@ -0,0 +1,26 @@ +module dac_interface_enhanced ( + input wire clk_120m, + input wire reset_n, + input wire [7:0] chirp_data, + input wire chirp_valid, + output reg [7:0] dac_data, + output wire dac_clk, + output wire dac_sleep +); + +// Register DAC data to meet timing +always @(posedge clk_120m or negedge reset_n) begin + if (!reset_n) begin + dac_data <= 8'd128; // Center value + end else if (chirp_valid) begin + dac_data <= chirp_data; + end else begin + dac_data <= 8'd128; // Default to center when no chirp + end +end + +// DAC clock is same as input clock (120MHz) +assign dac_clk = clk_120m; +assign dac_sleep = 1'b0; + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/ddc_400m.v b/9_Firmware/9_2_FPGA/ddc_400m.v new file mode 100644 index 0000000..1ebbd35 --- /dev/null +++ b/9_Firmware/9_2_FPGA/ddc_400m.v @@ -0,0 +1,425 @@ +`timescale 1ns / 1ps + +module ddc_400m_enhanced ( + input wire clk_400m, // 400MHz clock from ADC DCO + input wire clk_100m, // 100MHz system clock + input wire reset_n, + input wire mixers_enable, + input wire [7:0] adc_data, // ADC data at 400MHz + input wire adc_data_valid_i, // Valid at 400MHz + input wire adc_data_valid_q, + output wire signed [17:0] baseband_i, + output wire signed [17:0] baseband_q, + output wire baseband_valid_i, + output wire baseband_valid_q, + + output wire [1:0] ddc_status, + // Enhanced interfaces + output wire [7:0] ddc_diagnostics, + output wire mixer_saturation, + output wire filter_overflow, + input wire bypass_mode, // Test mode + + input wire [1:0] test_mode, + input wire [15:0] test_phase_inc, + input wire force_saturation, + input wire reset_monitors, + output wire [31:0] debug_sample_count, + output wire [17:0] debug_internal_i, + output wire [17:0] debug_internal_q +); + +// Parameters for numerical precision +parameter ADC_WIDTH = 8; +parameter NCO_WIDTH = 16; +parameter MIXER_WIDTH = 18; +parameter OUTPUT_WIDTH = 18; + +// IF frequency parameters +parameter IF_FREQ = 120000000; +parameter FS = 400000000; +parameter PHASE_WIDTH = 32; + +// Internal signals +wire signed [15:0] sin_out, cos_out; +wire nco_ready; +wire cic_valid; +wire fir_valid; +wire [17:0] cic_i_out, cic_q_out; +wire signed [17:0] fir_i_out, fir_q_out; + + +// Diagnostic registers +reg [2:0] saturation_count; +reg overflow_detected; +reg [7:0] error_counter; + +// CDC synchronization for control signals +reg mixers_enable_sync; +reg bypass_mode_sync; + +// Debug monitoring signals +reg [31:0] sample_counter; +wire signed [17:0] debug_mixed_i_trunc; +wire signed [17:0] debug_mixed_q_trunc; + +// Real-time status monitoring +reg [7:0] signal_power_i, signal_power_q; + +// Enhanced saturation injection for testing +reg force_saturation_sync; + +// Internal mixing signals +reg signed [MIXER_WIDTH-1:0] adc_signed; +reg signed [MIXER_WIDTH + NCO_WIDTH -1:0] mixed_i, mixed_q; +reg mixed_valid; +reg mixer_overflow_i, mixer_overflow_q; + +// Output stage registers +reg signed [17:0] baseband_i_reg, baseband_q_reg; +reg baseband_valid_reg; + +// ============================================================================ +// Phase Dithering Signals +// ============================================================================ +wire [7:0] phase_dither_bits; +wire [31:0] phase_inc_dithered; + + + +// ============================================================================ +// Debug Signal Assignments +// ============================================================================ +assign debug_internal_i = mixed_i[25:8]; +assign debug_internal_q = mixed_q[25:8]; +assign debug_sample_count = sample_counter; +assign debug_mixed_i_trunc = mixed_i[25:8]; +assign debug_mixed_q_trunc = mixed_q[25:8]; + +// ============================================================================ +// Clock Domain Crossing for Control Signals +// ============================================================================ +always @(posedge clk_400m or negedge reset_n) begin + if (!reset_n) begin + mixers_enable_sync <= 1'b0; + bypass_mode_sync <= 1'b0; + force_saturation_sync <= 1'b0; + end else begin + mixers_enable_sync <= mixers_enable; + bypass_mode_sync <= bypass_mode; + force_saturation_sync <= force_saturation; + end +end + +// ============================================================================ +// Sample Counter and Debug Monitoring +// ============================================================================ +always @(posedge clk_400m or negedge reset_n) begin + if (!reset_n || reset_monitors) begin + sample_counter <= 0; + saturation_count <= 0; + error_counter <= 0; + end else if (adc_data_valid_i && adc_data_valid_q ) begin + sample_counter <= sample_counter + 1; + end +end + + +// ============================================================================ +// Enhanced Phase Dithering Instance +// ============================================================================ +lfsr_dither_enhanced #( + .DITHER_WIDTH(8) +) phase_dither_gen ( + .clk(clk_400m), + .reset_n(reset_n), + .enable(nco_ready), + .dither_out(phase_dither_bits) +); + +// ============================================================================ +// Phase Increment Calculation with Dithering +// ============================================================================ +// Calculate phase increment for 120MHz IF at 400MHz sampling +localparam PHASE_INC_120MHZ = 32'h4CCCCCCD; + +// Apply dithering to reduce spurious tones +assign phase_inc_dithered = PHASE_INC_120MHZ + {24'b0, phase_dither_bits}; + +// ============================================================================ +// Enhanced NCO with Diagnostics +// ============================================================================ +nco_400m_enhanced nco_core ( + .clk_400m(clk_400m), + .reset_n(reset_n), + .frequency_tuning_word(phase_inc_dithered), + .phase_valid(mixers_enable), + .phase_offset(16'h0000), + .sin_out(sin_out), + .cos_out(cos_out), + .dds_ready(nco_ready) +); + +// ============================================================================ +// Enhanced Mixing Stage with AGC +// ============================================================================ +always @(posedge clk_400m or negedge reset_n) begin + if (!reset_n) begin + adc_signed <= 0; + mixed_i <= 0; + mixed_q <= 0; + mixed_valid <= 0; + mixer_overflow_i <= 0; + mixer_overflow_q <= 0; + saturation_count <= 0; + overflow_detected <= 0; + end else if (nco_ready && adc_data_valid_i && adc_data_valid_q) begin + // Convert ADC data to signed with extended precision + adc_signed <= {1'b0, adc_data, {(MIXER_WIDTH-ADC_WIDTH-1){1'b0}}} - + {1'b0, {ADC_WIDTH{1'b1}}, {(MIXER_WIDTH-ADC_WIDTH-1){1'b0}}} / 2; + + // Force saturation for testing + if (force_saturation_sync) begin + mixed_i <= 34'h1FFFFFFFF; // Force positive saturation + mixed_q <= 34'h200000000; // Force negative saturation + mixer_overflow_i <= 1'b1; + mixer_overflow_q <= 1'b1; + end else begin + + // Normal mixing + mixed_i <= $signed(adc_signed) * $signed(cos_out); + mixed_q <= $signed(adc_signed) * $signed(sin_out); + + + // Enhanced overflow detection with counting + mixer_overflow_i <= (mixed_i > (2**(MIXER_WIDTH+NCO_WIDTH-2)-1)) || + (mixed_i < -(2**(MIXER_WIDTH+NCO_WIDTH-2))); + mixer_overflow_q <= (mixed_q > (2**(MIXER_WIDTH+NCO_WIDTH-2)-1)) || + (mixed_q < -(2**(MIXER_WIDTH+NCO_WIDTH-2))); + end + + mixed_valid <= 1; + + if (mixer_overflow_i || mixer_overflow_q) begin + saturation_count <= saturation_count + 1; + overflow_detected <= 1'b1; + end else begin + overflow_detected <= 1'b0; + end + + end else begin + mixed_valid <= 0; + mixer_overflow_i <= 0; + mixer_overflow_q <= 0; + overflow_detected <= 1'b0; + end +end + +// ============================================================================ +// Enhanced CIC Decimators +// ============================================================================ +wire cic_valid_i, cic_valid_q; + +cic_decimator_4x_enhanced cic_i_inst ( + .clk(clk_400m), + .reset_n(reset_n), + .data_in(mixed_i[33:16]), + .data_valid(mixed_valid), + .data_out(cic_i_out), + .data_out_valid(cic_valid_i) +); + +cic_decimator_4x_enhanced cic_q_inst ( + .clk(clk_400m), + .reset_n(reset_n), + .data_in(mixed_q[33:16]), + .data_valid(mixed_valid), + .data_out(cic_q_out), + .data_out_valid(cic_valid_q) +); + +assign cic_valid = cic_valid_i & cic_valid_q; + +cdc_adc_to_processing #( + .WIDTH(18), + .STAGES(3) +)CDC_FIR_i( + .src_clk(clk_400m), + .dst_clk(clk_100m), + .reset_n(reset_n), + .src_data(cic_i_out), + .src_valid(cic_valid_i), + .dst_data(fir_d_in_i), + .dst_valid(fir_in_valid_i) +); + +cdc_adc_to_processing #( + .WIDTH(18), + .STAGES(3) +)CDC_FIR_q( + .src_clk(clk_400m), + .dst_clk(clk_100m), + .reset_n(reset_n), + .src_data(cic_q_out), + .src_valid(cic_valid_q), + .dst_data(fir_d_in_q), + .dst_valid(fir_in_valid_q) +); + +// ============================================================================ +// Enhanced FIR Filters with FIXED valid signal handling +// ============================================================================ +wire fir_in_valid_i, fir_in_valid_q; +wire fir_valid_i, fir_valid_q; +wire fir_i_ready, fir_q_ready; +wire [17:0] fir_d_in_i, fir_d_in_q; + +// FIR I channel +fir_lowpass_parallel_enhanced fir_i_inst ( + .clk(clk_100m), + .reset_n(reset_n), + .data_in(fir_d_in_i), // Use synchronized data + .data_valid(fir_in_valid_i), // Use synchronized valid + .data_out(fir_i_out), + .data_out_valid(fir_valid_i), + .fir_ready(fir_i_ready), + .filter_overflow() +); + +// FIR Q channel +fir_lowpass_parallel_enhanced fir_q_inst ( + .clk(clk_100m), + .reset_n(reset_n), + .data_in(fir_d_in_q), // Use synchronized data + .data_valid(fir_in_valid_q), // Use synchronized valid + .data_out(fir_q_out), + .data_out_valid(fir_valid_q), + .fir_ready(fir_q_ready), + .filter_overflow() +); + +assign fir_valid = fir_valid_i & fir_valid_q; + +// ============================================================================ +// Enhanced Output Stage +// ============================================================================ +always @(negedge clk_100m or negedge reset_n) begin + if (!reset_n) begin + baseband_i_reg <= 0; + baseband_q_reg <= 0; + baseband_valid_reg <= 0; + end else if (fir_valid) begin + baseband_i_reg <= fir_i_out; + baseband_q_reg <= fir_q_out; + baseband_valid_reg <= 1; + end else begin + baseband_valid_reg <= 0; + end +end + + +// ============================================================================ +// Output Assignments +// ============================================================================ +assign baseband_i = baseband_i_reg; +assign baseband_q = baseband_q_reg; +assign baseband_valid_i = baseband_valid_reg; +assign baseband_valid_q = baseband_valid_reg; +assign ddc_status = {mixer_overflow_i | mixer_overflow_q, nco_ready}; +assign mixer_saturation = overflow_detected; +assign ddc_diagnostics = {saturation_count, error_counter[4:0]}; + +// ============================================================================ +// Enhanced Debug and Monitoring +// ============================================================================ +reg [31:0] debug_cic_count, debug_fir_count, debug_bb_count; + +always @(posedge clk_100m) begin + + if (fir_valid_i && debug_fir_count < 20) begin + debug_fir_count <= debug_fir_count + 1; + $display("FIR_OUTPUT: fir_i=%6d, fir_q=%6d", fir_i_out, fir_q_out); + end + + if (adc_data_valid_i && adc_data_valid_q && debug_bb_count < 20) begin + debug_bb_count <= debug_bb_count + 1; + $display("BASEBAND_OUT: i=%6d, q=%6d, count=%0d", + baseband_i, baseband_q, debug_bb_count); + end +end + +// In ddc_400m.v, add these debug signals: + +// Debug monitoring +reg [31:0] debug_adc_count = 0; +reg [31:0] debug_baseband_count = 0; + +always @(posedge clk_400m) begin + if (adc_data_valid_i && adc_data_valid_q && debug_adc_count < 10) begin + debug_adc_count <= debug_adc_count + 1; + $display("DDC_ADC: data=%0d, count=%0d, time=%t", + adc_data, debug_adc_count, $time); + end +end + +always @(posedge clk_100m) begin + if (baseband_valid_i && baseband_valid_q && debug_baseband_count < 10) begin + debug_baseband_count <= debug_baseband_count + 1; + $display("DDC_BASEBAND: i=%0d, q=%0d, count=%0d, time=%t", + baseband_i, baseband_q, debug_baseband_count, $time); + end +end + + +endmodule + +// ============================================================================ +// Enhanced Phase Dithering Module +// ============================================================================ +`timescale 1ns / 1ps + +module lfsr_dither_enhanced #( + parameter DITHER_WIDTH = 8 // Increased for better dithering +)( + input wire clk, + input wire reset_n, + input wire enable, + output wire [DITHER_WIDTH-1:0] dither_out +); + +reg [DITHER_WIDTH-1:0] lfsr_reg; +reg [15:0] cycle_counter; +reg lock_detected; + +// Polynomial for better randomness: x^8 + x^6 + x^5 + x^4 + 1 +wire feedback; + +generate + if (DITHER_WIDTH == 4) begin + assign feedback = lfsr_reg[3] ^ lfsr_reg[2]; + end else if (DITHER_WIDTH == 8) begin + assign feedback = lfsr_reg[7] ^ lfsr_reg[5] ^ lfsr_reg[4] ^ lfsr_reg[3]; + end else begin + assign feedback = lfsr_reg[DITHER_WIDTH-1] ^ lfsr_reg[DITHER_WIDTH-2]; + end +endgenerate + +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + lfsr_reg <= {DITHER_WIDTH{1'b1}}; // Non-zero initial state + cycle_counter <= 0; + lock_detected <= 0; + end else if (enable) begin + lfsr_reg <= {lfsr_reg[DITHER_WIDTH-2:0], feedback}; + cycle_counter <= cycle_counter + 1; + + // Detect LFSR lock after sufficient cycles + if (cycle_counter > (2**DITHER_WIDTH * 8)) begin + lock_detected <= 1'b1; + end + end +end + +assign dither_out = lfsr_reg; + +endmodule diff --git a/9_Firmware/9_2_FPGA/ddc_input_interface.v b/9_Firmware/9_2_FPGA/ddc_input_interface.v new file mode 100644 index 0000000..135a9cc --- /dev/null +++ b/9_Firmware/9_2_FPGA/ddc_input_interface.v @@ -0,0 +1,55 @@ +`timescale 1ns / 1ps +// ddc_input_interface.v +module ddc_input_interface ( + input wire clk, // 100MHz + input wire reset_n, + + // DDC Input (18-bit) + input wire signed [17:0] ddc_i, + input wire signed [17:0] ddc_q, + input wire valid_i, + input wire valid_q, + + // Scaled output (16-bit) + output reg signed [15:0] adc_i, + output reg signed [15:0] adc_q, + output reg adc_valid, + + // Status + output wire data_sync_error +); + +// Synchronize valid signals +reg valid_i_reg, valid_q_reg; +reg valid_sync; + +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + valid_i_reg <= 1'b0; + valid_q_reg <= 1'b0; + valid_sync <= 1'b0; + adc_valid <= 1'b0; + end else begin + valid_i_reg <= valid_i; + valid_q_reg <= valid_q; + + // Require both I and Q valid simultaneously + valid_sync <= valid_i_reg && valid_q_reg; + adc_valid <= valid_sync; + end +end + +// Scale 18-bit to 16-bit with rounding +// Option: Keep most significant 16 bits with rounding +always @(posedge clk) begin + if (valid_sync) begin + // Round to nearest: add 0.5 LSB before truncation + adc_i <= ddc_i[17:2] + ddc_i[1]; // Rounding + adc_q <= ddc_q[17:2] + ddc_q[1]; // Rounding + end +end + +// Error detection +assign data_sync_error = (valid_i_reg ^ valid_q_reg); + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/doppler_processor.v b/9_Firmware/9_2_FPGA/doppler_processor.v new file mode 100644 index 0000000..a1f2e18 --- /dev/null +++ b/9_Firmware/9_2_FPGA/doppler_processor.v @@ -0,0 +1,305 @@ +`timescale 1ns / 1ps + +module doppler_processor_optimized #( + parameter DOPPLER_FFT_SIZE = 32, + parameter RANGE_BINS = 64, + parameter CHIRPS_PER_FRAME = 32, + parameter WINDOW_TYPE = 0, // 0=Hamming, 1=Rectangular + parameter DATA_WIDTH = 16 +)( + input wire clk, + input wire reset_n, + input wire [31:0] range_data, + input wire data_valid, + input wire new_chirp_frame, + output reg [31:0] doppler_output, + output reg doppler_valid, + output reg [4:0] doppler_bin, + output reg [5:0] range_bin, + output wire processing_active, + output wire frame_complete, + output reg [3:0] status +); + +// ============================================== +// Window Coefficients (Simple Implementation) +// ============================================== +reg [DATA_WIDTH-1:0] window_coeff [0:31]; + +// Generate window coefficients +integer w; +initial begin + if (WINDOW_TYPE == 0) begin + // Pre-calculated Hamming window (Q15 format) + window_coeff[0] = 16'h0800; window_coeff[1] = 16'h0862; + window_coeff[2] = 16'h09CB; window_coeff[3] = 16'h0C3B; + window_coeff[4] = 16'h0FB2; window_coeff[5] = 16'h142F; + window_coeff[6] = 16'h19B2; window_coeff[7] = 16'h2039; + window_coeff[8] = 16'h27C4; window_coeff[9] = 16'h3050; + window_coeff[10] = 16'h39DB; window_coeff[11] = 16'h4462; + window_coeff[12] = 16'h4FE3; window_coeff[13] = 16'h5C5A; + window_coeff[14] = 16'h69C4; window_coeff[15] = 16'h781D; + window_coeff[16] = 16'h7FFF; // Peak + window_coeff[17] = 16'h781D; window_coeff[18] = 16'h69C4; + window_coeff[19] = 16'h5C5A; window_coeff[20] = 16'h4FE3; + window_coeff[21] = 16'h4462; window_coeff[22] = 16'h39DB; + window_coeff[23] = 16'h3050; window_coeff[24] = 16'h27C4; + window_coeff[25] = 16'h2039; window_coeff[26] = 16'h19B2; + window_coeff[27] = 16'h142F; window_coeff[28] = 16'h0FB2; + window_coeff[29] = 16'h0C3B; window_coeff[30] = 16'h09CB; + window_coeff[31] = 16'h0862; + end else begin + // Rectangular window (all ones) + for (w = 0; w < 32; w = w + 1) begin + window_coeff[w] = 16'h7FFF; + end + end +end + +// ============================================== +// Memory Declaration - FIXED SIZE +// ============================================== +localparam MEM_DEPTH = RANGE_BINS * CHIRPS_PER_FRAME; +(* ram_style = "block" *) reg [DATA_WIDTH-1:0] doppler_i_mem [0:MEM_DEPTH-1]; +(* ram_style = "block" *) reg [DATA_WIDTH-1:0] doppler_q_mem [0:MEM_DEPTH-1]; + +// ============================================== +// Control Registers +// ============================================== +reg [5:0] write_range_bin; // Changed to match RANGE_BINS width +reg [4:0] write_chirp_index; // Changed to match CHIRPS_PER_FRAME width +reg [5:0] read_range_bin; +reg [4:0] read_doppler_index; // Changed name for clarity +reg frame_buffer_full; +reg [9:0] chirps_received; // Enough for up to 1024 chirps +reg [1:0] chirp_state; // Track chirp accumulation state + + +// ============================================== +// FFT Interface +// ============================================== +reg fft_start; +wire fft_ready; +reg [DATA_WIDTH-1:0] fft_input_i; +reg [DATA_WIDTH-1:0] fft_input_q; +reg signed [31:0] mult_i, mult_q; // 32-bit to avoid overflow + +reg fft_input_valid; +reg fft_input_last; +wire [DATA_WIDTH-1:0] fft_output_i; +wire [DATA_WIDTH-1:0] fft_output_q; +wire fft_output_valid; +wire fft_output_last; + +// ============================================== +// Addressing +// ============================================== +wire [10:0] mem_write_addr; +wire [10:0] mem_read_addr; + +// Proper address calculation using parameters +assign mem_write_addr = (write_chirp_index * RANGE_BINS) + write_range_bin; +assign mem_read_addr = (read_doppler_index * RANGE_BINS) + read_range_bin; + +// Alternative organization (choose one): +// If you want range-major organization (all chirps for one range bin together): +// assign mem_write_addr = (write_range_bin * CHIRPS_PER_FRAME) + write_chirp_index; +// assign mem_read_addr = (read_range_bin * CHIRPS_PER_FRAME) + read_doppler_index; + +// ============================================== +// State Machine +// ============================================== +reg [2:0] state; +localparam S_IDLE = 3'b000; +localparam S_ACCUMULATE = 3'b001; +localparam S_LOAD_FFT = 3'b010; +localparam S_FFT_WAIT = 3'b011; +localparam S_OUTPUT = 3'b100; + +// Frame sync detection +reg new_chirp_frame_d1; +always @(posedge clk or negedge reset_n) begin + if (!reset_n) new_chirp_frame_d1 <= 0; + else new_chirp_frame_d1 <= new_chirp_frame; +end +wire frame_start_pulse = new_chirp_frame & ~new_chirp_frame_d1; + +// ============================================== +// Main State Machine - FIXED +// ============================================== +reg [5:0] fft_sample_counter; +reg [9:0] processing_timeout; + +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + state <= S_IDLE; + write_range_bin <= 0; + write_chirp_index <= 0; + read_range_bin <= 0; + read_doppler_index <= 0; + frame_buffer_full <= 0; + doppler_valid <= 0; + fft_start <= 0; + fft_input_valid <= 0; + fft_input_last <= 0; + fft_sample_counter <= 0; + processing_timeout <= 0; + status <= 0; + chirps_received <= 0; + chirp_state <= 0; + end else begin + doppler_valid <= 0; + fft_input_valid <= 0; + fft_input_last <= 0; + + if (processing_timeout > 0) begin + processing_timeout <= processing_timeout - 1; + end + + case (state) + S_IDLE: begin + if (frame_start_pulse) begin + // Start new frame + write_chirp_index <= 0; + write_range_bin <= 0; + frame_buffer_full <= 0; + chirps_received <= 0; + //chirp_state <= 1; // Start accumulating + end + + if (data_valid && !frame_buffer_full) begin + state <= S_ACCUMULATE; + write_range_bin <= 0; + end + end + + S_ACCUMULATE: begin + if (data_valid) begin + // Store with proper addressing + doppler_i_mem[mem_write_addr] <= range_data[15:0]; + doppler_q_mem[mem_write_addr] <= range_data[31:16]; + + // Debug output to see what's being written + // $display("Time=%t: Write addr=%d (chirp=%d, range=%d), Data=%h", + // $time, mem_write_addr, write_chirp_index, write_range_bin, range_data); + + // Increment range bin + if (write_range_bin < RANGE_BINS - 1) begin + write_range_bin <= write_range_bin + 1; + end else begin + // Completed one chirp + write_range_bin <= 0; + write_chirp_index <= write_chirp_index + 1; + chirps_received <= chirps_received + 1; + + // Check if frame is complete + if (write_chirp_index >= CHIRPS_PER_FRAME - 1) begin + frame_buffer_full <= 1; + chirp_state <= 0; // Stop accumulating + // Could automatically start processing here: + state <= S_LOAD_FFT; + read_range_bin <= 0; + read_doppler_index <= 0; + fft_sample_counter <= 0; + fft_start <= 1; + end + end + end + end + + // [Rest of S_LOAD_FFT, S_FFT_WAIT, S_OUTPUT states remain similar] + // But with fixed addressing in S_LOAD_FFT: + S_LOAD_FFT: begin + fft_start <= 0; + + if (fft_sample_counter < DOPPLER_FFT_SIZE) begin + // Use correct addressing for reading + mult_i <= $signed(doppler_i_mem[mem_read_addr]) * + $signed(window_coeff[read_doppler_index]); + mult_q <= $signed(doppler_q_mem[mem_read_addr]) * + $signed(window_coeff[read_doppler_index]); + + // Round instead of truncate + fft_input_i <= (mult_i + (1 << 14)) >>> 15; // Round to nearest + fft_input_q <= (mult_q + (1 << 14)) >>> 15; + + fft_input_valid <= 1; + + if (fft_sample_counter == DOPPLER_FFT_SIZE - 1) begin + fft_input_last <= 1; + end + + // Increment chirp index for next sample + read_doppler_index <= read_doppler_index + 1; + fft_sample_counter <= fft_sample_counter + 1; + end else begin + state <= S_FFT_WAIT; + fft_sample_counter <= 0; + processing_timeout <= 100; + end + end + + S_FFT_WAIT: begin + if (fft_output_valid) begin + doppler_output <= {fft_output_q[15:0], fft_output_i[15:0]}; + doppler_bin <= fft_sample_counter; + range_bin <= read_range_bin; + doppler_valid <= 1; + + fft_sample_counter <= fft_sample_counter + 1; + + if (fft_output_last) begin + state <= S_OUTPUT; + fft_sample_counter <= 0; + end + end + + if (processing_timeout == 0) begin + state <= S_OUTPUT; + end + end + + S_OUTPUT: begin + if (read_range_bin < RANGE_BINS - 1) begin + read_range_bin <= read_range_bin + 1; + read_doppler_index <= 0; + state <= S_LOAD_FFT; + fft_start <= 1; + end else begin + state <= S_IDLE; + frame_buffer_full <= 0; + end + end + + endcase + + status <= {state, frame_buffer_full}; + end +end + +// ============================================== +// FFT Module +// ============================================== +xfft_32 fft_inst ( + .aclk(clk), + .aresetn(reset_n), + .s_axis_config_tdata(8'h01), + .s_axis_config_tvalid(fft_start), + .s_axis_config_tready(fft_ready), + .s_axis_data_tdata({fft_input_q, fft_input_i}), + .s_axis_data_tvalid(fft_input_valid), + .s_axis_data_tlast(fft_input_last), + .m_axis_data_tdata({fft_output_q, fft_output_i}), + .m_axis_data_tvalid(fft_output_valid), + .m_axis_data_tlast(fft_output_last), + .m_axis_data_tready(1'b1) +); + +// ============================================== +// Status Outputs +// ============================================== +assign processing_active = (state != S_IDLE); +assign frame_complete = (state == S_IDLE && frame_buffer_full == 0); + + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/edge_detector.v b/9_Firmware/9_2_FPGA/edge_detector.v new file mode 100644 index 0000000..707f492 --- /dev/null +++ b/9_Firmware/9_2_FPGA/edge_detector.v @@ -0,0 +1,26 @@ +module edge_detector_enhanced ( + input wire clk, + input wire reset_n, + input wire signal_in, + output wire rising_falling_edge +); + +reg signal_in_prev; +reg signal_in_prev2; + +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + signal_in_prev <= 1'b0; + signal_in_prev2 <= 1'b0; + end else begin + signal_in_prev <= signal_in; + signal_in_prev2 <= signal_in_prev; + end +end + +// Rising edge: was low, now high (with synchronization) signal_in_prev & ~signal_in_prev2; +//Falling edge: was high, now low (with synchronization) falling_edge = ~signal_in_prev & signal_in_prev2 +assign rising_falling_edge = (signal_in_prev & ~signal_in_prev2)|(~signal_in_prev & signal_in_prev2); + + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/fft_1024_forward.v b/9_Firmware/9_2_FPGA/fft_1024_forward.v new file mode 100644 index 0000000..55d8cec --- /dev/null +++ b/9_Firmware/9_2_FPGA/fft_1024_forward.v @@ -0,0 +1,124 @@ +`timescale 1ns / 1ps + +module fft_1024_forward_enhanced ( + input wire clk, + input wire reset_n, + input wire [15:0] data_i, + input wire [15:0] data_q, + input wire data_valid, + output wire [15:0] fft_i, + output wire [15:0] fft_q, + output wire fft_valid +); + +// ========== MATCH YOUR FFT IP CONFIGURATION ========== +wire [15:0] s_axis_config_tdata; // 16-bit for your IP +wire s_axis_config_tvalid; +wire s_axis_config_tready; +wire [31:0] s_axis_data_tdata; // 32-bit for your IP {Q[15:0],I[15:0]} +wire s_axis_data_tvalid; +wire s_axis_data_tready; +wire s_axis_data_tlast; +wire [31:0] m_axis_data_tdata; // 32-bit for your IP +wire m_axis_data_tvalid; +wire m_axis_data_tready; +wire m_axis_data_tlast; + +// Configuration: 16-bit, bit 0 = 1 for forward FFT... +assign s_axis_config_tdata = 16'h0001; +assign s_axis_config_tvalid = 1'b1; // Keep valid until accepted + + +assign s_axis_data_tdata = {data_q, data_i}; // {Q, I} +assign s_axis_data_tvalid = data_valid; + +// Frame counter for tlast +reg [9:0] sample_count; +reg frame_active; +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + sample_count <= 0; + frame_active <= 0; + end else begin + if (data_valid && !frame_active) begin + frame_active <= 1'b1; + sample_count <= 0; + end + + if (frame_active && data_valid) begin + if (sample_count == 1023) begin + sample_count <= 0; + frame_active <= 0; + end else begin + sample_count <= sample_count + 1; + end + end + end +end +assign s_axis_data_tlast = (sample_count == 1023) && data_valid; + +// Output: Extract from 64-bit output +// Assuming output format is also {Q[31:0], I[31:0]} +assign fft_i = m_axis_data_tdata[15:0]; // Lower 16 bits = I +assign fft_q = m_axis_data_tdata[31:16]; // Upper 16 bits = Q +assign fft_valid = m_axis_data_tvalid; +assign m_axis_data_tready = 1'b1; + +// ========== DEBUG ========== +/* +reg [31:0] debug_counter = 0; +always @(posedge clk) begin + debug_counter <= debug_counter + 1; + + // Monitor first 2000 cycles + if (debug_counter < 2000) begin + // Configuration + if (s_axis_config_tvalid && s_axis_config_tready) begin + $display("[FFT_CORRECTED @%d] CONFIG ACCEPTED! tdata=%h", + debug_counter, s_axis_config_tdata); + end + + // Data input + if (s_axis_data_tvalid && s_axis_data_tready && debug_counter < 1050) begin + $display("[FFT_CORRECTED @%d] Data in: I=%h Q=%h count=%d tlast=%b", + debug_counter, data_i, data_q, sample_count, s_axis_data_tlast); + end + + // Data output + if (m_axis_data_tvalid && debug_counter < 3000) begin + $display("[FFT_CORRECTED @%d] FFT OUT: I=%h Q=%h", + debug_counter, fft_i, fft_q); + end + + // Stuck detection + if (debug_counter == 100 && !s_axis_config_tready) begin + $display("[FFT_CORRECTED] WARNING: config_tready still 0 after 100 cycles"); + end + end +end +*/ +// ========== FFT IP INSTANCE ========== +// This must match the name in your project +FFT_enhanced fft_forward_inst ( + .aclk(clk), + .aresetn(reset_n), // Active-low reset + + // Configuration (16-bit) + .s_axis_config_tdata(s_axis_config_tdata), + .s_axis_config_tvalid(s_axis_config_tvalid), + .s_axis_config_tready(s_axis_config_tready), + + // Data input (64-bit) + .s_axis_data_tdata(s_axis_data_tdata), + .s_axis_data_tvalid(s_axis_data_tvalid), + .s_axis_data_tready(s_axis_data_tready), + .s_axis_data_tlast(s_axis_data_tlast), + + // Data output (64-bit) + .m_axis_data_tdata(m_axis_data_tdata), + .m_axis_data_tvalid(m_axis_data_tvalid), + .m_axis_data_tlast(m_axis_data_tlast) + +); + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/fft_1024_inverse.v b/9_Firmware/9_2_FPGA/fft_1024_inverse.v new file mode 100644 index 0000000..34dd03c --- /dev/null +++ b/9_Firmware/9_2_FPGA/fft_1024_inverse.v @@ -0,0 +1,97 @@ +`timescale 1ns / 1ps + +module fft_1024_inverse_enhanced ( + input wire clk, + input wire reset_n, + input wire [15:0] data_i, + input wire [15:0] data_q, + input wire data_valid, + output wire [15:0] ifft_i, + output wire [15:0] ifft_q, + output wire ifft_valid +); + +// ========== MATCH YOUR FFT IP CONFIGURATION ========== +wire [15:0] s_axis_config_tdata; // 16-bit +wire s_axis_config_tvalid; +wire s_axis_config_tready; +wire [31:0] s_axis_data_tdata; // 32-bit for your IP {Q[15:0],I[15:0]} +wire s_axis_data_tvalid; +wire s_axis_data_tready; +wire s_axis_data_tlast; +wire [31:0] m_axis_data_tdata; // 32-bit +wire m_axis_data_tvalid; +wire m_axis_data_tready; +wire m_axis_data_tlast; + +// Configuration: bit 0 = 0 for inverse FFT +assign s_axis_config_tdata = 16'h0000; +assign s_axis_config_tvalid = 1'b1; + + +assign s_axis_data_tdata = {data_q, data_i}; +assign s_axis_data_tvalid = data_valid; + +// Frame counter +reg [9:0] sample_count; +reg frame_active; +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + sample_count <= 0; + frame_active <= 0; + end else begin + if (data_valid && !frame_active) begin + frame_active <= 1'b1; + sample_count <= 0; + end + + if (frame_active && data_valid) begin + if (sample_count == 1023) begin + sample_count <= 0; + frame_active <= 0; + end else begin + sample_count <= sample_count + 1; + end + end + end +end +assign s_axis_data_tlast = (sample_count == 1023) && data_valid; +// Output +assign ifft_i = m_axis_data_tdata[15:0]; // I = lower 16 bits +assign ifft_q = m_axis_data_tdata[31:16]; // Q = upper 16 bits +assign ifft_valid = m_axis_data_tvalid; +assign m_axis_data_tready = 1'b1; + +// Debug +reg [31:0] debug_counter; +always @(posedge clk) begin + debug_counter <= debug_counter + 1; + + if (debug_counter < 1000) begin + if (s_axis_config_tvalid && s_axis_config_tready) begin + $display("[IFFT_CORRECTED @%d] CONFIG ACCEPTED!", debug_counter); + end + end +end + +// IFFT IP instance +FFT_enhanced ifft_inverse_inst ( // Same IP core, different configuration + .aclk(clk), + .aresetn(reset_n), + + .s_axis_config_tdata(s_axis_config_tdata), + .s_axis_config_tvalid(s_axis_config_tvalid), + .s_axis_config_tready(s_axis_config_tready), + + .s_axis_data_tdata(s_axis_data_tdata), + .s_axis_data_tvalid(s_axis_data_tvalid), + .s_axis_data_tready(s_axis_data_tready), + .s_axis_data_tlast(s_axis_data_tlast), + + .m_axis_data_tdata(m_axis_data_tdata), + .m_axis_data_tvalid(m_axis_data_tvalid), + .m_axis_data_tlast(m_axis_data_tlast) + +); + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/fir_lowpass.v b/9_Firmware/9_2_FPGA/fir_lowpass.v new file mode 100644 index 0000000..87a38e9 --- /dev/null +++ b/9_Firmware/9_2_FPGA/fir_lowpass.v @@ -0,0 +1,124 @@ +`timescale 1ns / 1ps + +module fir_lowpass_parallel_enhanced ( + input wire clk, + input wire reset_n, + input wire signed [17:0] data_in, + input wire data_valid, + output reg signed [17:0] data_out, + output reg data_out_valid, + output wire fir_ready, + output wire filter_overflow +); + +parameter TAPS = 32; +parameter COEFF_WIDTH = 18; +parameter DATA_WIDTH = 18; +parameter ACCUM_WIDTH = 36; + +// Filter coefficients +reg signed [COEFF_WIDTH-1:0] coeff [0:TAPS-1]; + +// Parallel delay line +reg signed [DATA_WIDTH-1:0] delay_line [0:TAPS-1]; + +// Parallel multiply-accumulate structure +wire signed [DATA_WIDTH+COEFF_WIDTH-1:0] mult_result [0:TAPS-1]; + +// Wires for parallel addition (combinatorial) +wire signed [ACCUM_WIDTH-1:0] sum_stage1_0, sum_stage1_1, sum_stage1_2, sum_stage1_3; +wire signed [ACCUM_WIDTH-1:0] sum_stage2_0, sum_stage2_1; +wire signed [ACCUM_WIDTH-1:0] sum_stage3; + +// Registered accumulator +reg signed [ACCUM_WIDTH-1:0] accumulator_reg; + +// Initialize coefficients +initial begin + // Proper low-pass filter coefficients + coeff[ 0] = 18'sh00AD; coeff[ 1] = 18'sh00CE; coeff[ 2] = 18'sh3FD87; coeff[ 3] = 18'sh02A6; + coeff[ 4] = 18'sh00E0; coeff[ 5] = 18'sh3F8C0; coeff[ 6] = 18'sh0A45; coeff[ 7] = 18'sh3FD82; + coeff[ 8] = 18'sh3F0B5; coeff[ 9] = 18'sh1CAD; coeff[10] = 18'sh3EE59; coeff[11] = 18'sh3E821; + coeff[12] = 18'sh4841; coeff[13] = 18'sh3B340; coeff[14] = 18'sh3E299; coeff[15] = 18'sh1FFFF; + coeff[16] = 18'sh1FFFF; coeff[17] = 18'sh3E299; coeff[18] = 18'sh3B340; coeff[19] = 18'sh4841; + coeff[20] = 18'sh3E821; coeff[21] = 18'sh3EE59; coeff[22] = 18'sh1CAD; coeff[23] = 18'sh3F0B5; + coeff[24] = 18'sh3FD82; coeff[25] = 18'sh0A45; coeff[26] = 18'sh3F8C0; coeff[27] = 18'sh00E0; + coeff[28] = 18'sh02A6; coeff[29] = 18'sh3FD87; coeff[30] = 18'sh00CE; coeff[31] = 18'sh00AD; +end + +// Generate parallel multipliers +genvar k; +generate + for (k = 0; k < TAPS; k = k + 1) begin : mult_gen + assign mult_result[k] = delay_line[k] * coeff[k]; + end +endgenerate + +// COMBINATORIAL PARALLEL ADDITION TREE +// Stage 1: Group of 8 +assign sum_stage1_0 = mult_result[0] + mult_result[1] + mult_result[2] + mult_result[3] + + mult_result[4] + mult_result[5] + mult_result[6] + mult_result[7]; +assign sum_stage1_1 = mult_result[8] + mult_result[9] + mult_result[10] + mult_result[11] + + mult_result[12] + mult_result[13] + mult_result[14] + mult_result[15]; +assign sum_stage1_2 = mult_result[16] + mult_result[17] + mult_result[18] + mult_result[19] + + mult_result[20] + mult_result[21] + mult_result[22] + mult_result[23]; +assign sum_stage1_3 = mult_result[24] + mult_result[25] + mult_result[26] + mult_result[27] + + mult_result[28] + mult_result[29] + mult_result[30] + mult_result[31]; + +// Stage 2: Combine groups of 2 +assign sum_stage2_0 = sum_stage1_0 + sum_stage1_1; +assign sum_stage2_1 = sum_stage1_2 + sum_stage1_3; + +// Stage 3: Final sum +assign sum_stage3 = sum_stage2_0 + sum_stage2_1; + +integer i; + +// SINGLE-CYCLE PIPELINE PROCESSING +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + // Reset delay line + for (i = 0; i < TAPS; i = i + 1) begin + delay_line[i] <= 0; + end + accumulator_reg <= 0; + data_out <= 0; + data_out_valid <= 0; + end else begin + // Always shift in new data when valid + if (data_valid) begin + // Shift delay line + for (i = TAPS-1; i > 0; i = i - 1) begin + delay_line[i] <= delay_line[i-1]; + end + delay_line[0] <= data_in; + + // Register the combinatorial sum + accumulator_reg <= sum_stage3; + + // Output with 1-cycle latency + data_out_valid <= 1'b1; + end else begin + data_out_valid <= 1'b0; + end + + // Output saturation logic (registered) + if (accumulator_reg > (2**(ACCUM_WIDTH-2)-1)) begin + data_out <= (2**(DATA_WIDTH-1))-1; + end else if (accumulator_reg < -(2**(ACCUM_WIDTH-2))) begin + data_out <= -(2**(DATA_WIDTH-1)); + end else begin + // Round and truncate (keep middle bits) + data_out <= accumulator_reg[ACCUM_WIDTH-2:DATA_WIDTH-1]; + end + end +end + +// Always ready to accept new data +assign fir_ready = 1'b1; + +// Overflow detection (simplified) +assign filter_overflow = (accumulator_reg > (2**(ACCUM_WIDTH-2)-1)) || + (accumulator_reg < -(2**(ACCUM_WIDTH-2))); + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/frequency_matched_filter.v b/9_Firmware/9_2_FPGA/frequency_matched_filter.v new file mode 100644 index 0000000..be5ce9d --- /dev/null +++ b/9_Firmware/9_2_FPGA/frequency_matched_filter.v @@ -0,0 +1,137 @@ +`timescale 1ns / 1ps + +// frequency_matched_filter_conjugate.v +module frequency_matched_filter ( + input wire clk, + input wire reset_n, + + // Input from Forward FFT (16-bit Q15) + input wire signed [15:0] fft_real_in, + input wire signed [15:0] fft_imag_in, + input wire fft_valid_in, + + // Reference Chirp (16-bit Q15) - assumed to be FFT of transmitted chirp + + input wire signed [15:0] ref_chirp_real, + input wire signed [15:0] ref_chirp_imag, + + // Output (16-bit Q15) - FFT(input) ? conj(FFT(reference)) + output wire signed [15:0] filtered_real, + output wire signed [15:0] filtered_imag, + output wire filtered_valid, + + output wire [1:0] state +); + +// Complex multiplication: (a + jb) ? (c - jd) = (ac + bd) + j(bc - ad) +// Note: We use CONJUGATE of reference for matched filter + +// Pipeline registers +reg signed [15:0] a_reg, b_reg, c_reg, d_reg; +reg valid_p1; +reg signed [31:0] ac_reg, bd_reg, bc_reg, ad_reg; +reg valid_p2; +reg signed [31:0] real_sum, imag_sum; +reg valid_p3; +reg signed [15:0] real_out, imag_out; +reg valid_out; + +// Address counter +reg [9:0] addr_counter; + + +// ========== PIPELINE STAGE 1: REGISTER INPUTS ========== +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + a_reg <= 16'd0; b_reg <= 16'd0; + c_reg <= 16'd0; d_reg <= 16'd0; + valid_p1 <= 1'b0; + end else begin + if (fft_valid_in) begin + a_reg <= fft_real_in; // a + b_reg <= fft_imag_in; // b + c_reg <= ref_chirp_real; // c + d_reg <= ref_chirp_imag; // d + end + valid_p1 <= fft_valid_in; + end +end + +// ========== PIPELINE STAGE 2: MULTIPLICATIONS ========== +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + ac_reg <= 32'd0; bd_reg <= 32'd0; + bc_reg <= 32'd0; ad_reg <= 32'd0; + valid_p2 <= 1'b0; + end else begin + // Q15 ? Q15 = Q30 + ac_reg <= a_reg * c_reg; // ac + bd_reg <= b_reg * d_reg; // bd + bc_reg <= b_reg * c_reg; // bc + ad_reg <= a_reg * d_reg; // ad + + valid_p2 <= valid_p1; + end +end + +// ========== PIPELINE STAGE 3: ADDITIONS ========== +// For conjugate multiplication: (ac + bd) + j(bc - ad) +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + real_sum <= 32'd0; + imag_sum <= 32'd0; + valid_p3 <= 1'b0; + end else begin + real_sum <= ac_reg + bd_reg; // ac + bd + imag_sum <= bc_reg - ad_reg; // bc - ad + + valid_p3 <= valid_p2; + end +end + +// ========== PIPELINE STAGE 4: SATURATION ========== +function automatic signed [15:0] saturate_and_scale; + input signed [31:0] q30_value; + reg signed [15:0] result; + reg signed [31:0] rounded; + begin + // Round to nearest: add 0.5 LSB (bit 14) + rounded = q30_value + (1 << 14); + + // Check for overflow + if (rounded > 32'sh3FFF8000) begin // > 32767.5 in Q30 + result = 16'h7FFF; + end else if (rounded < 32'shC0008000) begin // < -32768.5 in Q30 + result = 16'h8000; + end else begin + // Take bits [30:15] for Q15 + result = rounded[30:15]; + end + + saturate_and_scale = result; + end +endfunction + +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + real_out <= 16'd0; + imag_out <= 16'd0; + valid_out <= 1'b0; + end else begin + if (valid_p3) begin + real_out <= saturate_and_scale(real_sum); + imag_out <= saturate_and_scale(imag_sum); + end + valid_out <= valid_p3; + end +end + +// ========== OUTPUT ASSIGNMENTS ========== +assign filtered_real = real_out; +assign filtered_imag = imag_out; +assign filtered_valid = valid_out; + +// Simple state output +assign state = {valid_out, valid_p3}; + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/latency_buffer_2159.v b/9_Firmware/9_2_FPGA/latency_buffer_2159.v new file mode 100644 index 0000000..968903a --- /dev/null +++ b/9_Firmware/9_2_FPGA/latency_buffer_2159.v @@ -0,0 +1,107 @@ +`timescale 1ns / 1ps + +// latency_buffer_2159_fixed.v +module latency_buffer_2159 #( + parameter DATA_WIDTH = 32, + parameter LATENCY = 3187 +) ( + input wire clk, + input wire reset_n, + input wire [DATA_WIDTH-1:0] data_in, + input wire valid_in, + output wire [DATA_WIDTH-1:0] data_out, + output wire valid_out +); + +// ========== FIXED PARAMETERS ========== +localparam ADDR_WIDTH = 12; // Enough for 4096 entries (>2159) + +// ========== FIXED LOGIC ========== +(* ram_style = "block" *) reg [DATA_WIDTH-1:0] bram [0:4095]; +reg [ADDR_WIDTH-1:0] write_ptr; +reg [ADDR_WIDTH-1:0] read_ptr; +reg valid_out_reg; + +// Delay counter to track when LATENCY cycles have passed +reg [ADDR_WIDTH-1:0] delay_counter; +reg buffer_has_data; // Flag when buffer has accumulated LATENCY samples + +// ========== FIXED INITIALIZATION ========== +integer k; +initial begin + for (k = 0; k < 4096; k = k + 1) begin + bram[k] = {DATA_WIDTH{1'b0}}; + end + write_ptr = 0; + read_ptr = 0; + valid_out_reg = 0; + delay_counter = 0; + buffer_has_data = 0; +end + +// ========== FIXED STATE MACHINE ========== +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + write_ptr <= 0; + read_ptr <= 0; + valid_out_reg <= 0; + delay_counter <= 0; + buffer_has_data <= 0; + end else begin + // Default: no valid output + valid_out_reg <= 0; + + // ===== WRITE SIDE ===== + if (valid_in) begin + // Store data + bram[write_ptr] <= data_in; + + // Increment write pointer (wrap at 4095) + if (write_ptr == 4095) begin + write_ptr <= 0; + end else begin + write_ptr <= write_ptr + 1; + end + + // Count how many samples we've written + if (delay_counter < LATENCY) begin + delay_counter <= delay_counter + 1; + + // When we've written LATENCY samples, buffer is "primed" + if (delay_counter == LATENCY - 1) begin + buffer_has_data <= 1'b1; + // $display("[LAT_BUF] Buffer now has %d samples (primed)", LATENCY); + end + end + end + + // ===== READ SIDE ===== + // Only start reading after we have LATENCY samples in buffer + if (buffer_has_data && valid_in) begin + // Read pointer follows write pointer with LATENCY delay + // Calculate: read_ptr = (write_ptr - LATENCY) mod 4096 + + // Handle wrap-around correctly + if (write_ptr >= LATENCY) begin + read_ptr <= write_ptr - LATENCY; + end else begin + // Wrap around: 4096 + write_ptr - LATENCY + read_ptr <= 4096 + write_ptr - LATENCY; + end + + // Output is valid + valid_out_reg <= 1'b1; + + //$display("[LAT_BUF] Reading: write_ptr=%d, read_ptr=%d, data=%h", + // write_ptr, read_ptr, bram[read_ptr]); + end + end +end + +// ========== OUTPUTS ========== +assign data_out = bram[read_ptr]; +assign valid_out = valid_out_reg; + + + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/long_chirp_seg0_i.mem b/9_Firmware/9_2_FPGA/long_chirp_seg0_i.mem new file mode 100644 index 0000000..fb6a9b5 --- /dev/null +++ b/9_Firmware/9_2_FPGA/long_chirp_seg0_i.mem @@ -0,0 +1,1024 @@ +0145 +0146 +0147 +0148 +0149 +014a +014b +014c +014d +014f +0150 +0151 +0152 +0153 +0155 +0156 +0157 +0159 +015a +015b +015c +015e +015f +0161 +0162 +0163 +0165 +0166 +0168 +0169 +016b +016c +016e +0170 +0171 +0173 +0175 +0176 +0178 +017a +017c +017d +017f +0181 +0183 +0185 +0187 +0189 +018b +018d +018f +0191 +0194 +0196 +0198 +019b +019d +01a0 +01a2 +01a5 +01a7 +01aa +01ad +01b0 +01b3 +01b6 +01b9 +01bd +01c0 +01c4 +01c8 +01cc +01d0 +01d4 +01d9 +01de +01e3 +01e9 +01f0 +01f6 +01fe +0207 +0210 +021b +0228 +0237 +0249 +025f +0279 +029a +02c5 +02fc +0345 +03a8 +0431 +04f1 +0602 +078e +09d0 +0d1d +11ec +18d5 +227c +2f59 +3f38 +5065 +5e9e +6266 +5237 +275d +e6f5 +aa59 +9ace +d40c +3848 +6a40 +23aa +adb9 +b425 +3dbd +5aa1 +c564 +b7ac +5b29 +1b80 +9bf1 +44f8 +2131 +a277 +6363 +d49d +f347 +4526 +a57e +6b86 +9c2c +672f +a31b +651f +9f55 +6c5d +9dbe +5c30 +cf3c +02b2 +44f9 +9dfc +58b8 +03d0 +ae30 +6113 +1277 +9f53 +2e31 +6240 +d1ac +aac5 +29c4 +70e4 +2278 +b799 +aa84 +f70b +4ef7 +76c9 +66c5 +3772 +04a9 +debd +c9bf +c2b3 +c47e +caa6 +d232 +d981 +dfe1 +e526 +e963 +ecc1 +ef6e +f190 +f348 +f4ae +f5d5 +f6cb +f79a +f84b +f8e3 +f968 +f9dc +fa42 +fa9d +faef +fb38 +fb7b +fbb7 +fbee +fc21 +fc4f +fc7a +fca2 +fcc7 +fcea +fd0a +fd28 +fd44 +fd5f +fd78 +fd8f +fda5 +fdba +fdce +fde1 +fdf3 +fe04 +fe15 +fe24 +fe33 +fe41 +fe4f +fe5c +fe69 +fe74 +fe80 +fe8b +fe96 +fea0 +feaa +feb3 +febd +fec5 +fece +fed6 +fede +fee6 +feee +fef5 +fefc +ff03 +ff09 +ff10 +ff16 +ff1c +ff22 +ff28 +ff2d +ff33 +ff38 +ff3d +ff42 +ff47 +ff4c +ff51 +ff55 +ff5a +ff5e +ff62 +ff66 +ff6a +ff6e +ff72 +ff76 +ff79 +ff7d +ff81 +ff84 +ff87 +ff8b +ff8e +ff91 +ff94 +ff97 +ff9a +ff9d +ffa0 +ffa3 +ffa6 +ffa8 +ffab +ffae +ffb0 +ffb3 +ffb5 +ffb8 +ffba +ffbd +ffbf +ffc1 +ffc3 +ffc6 +ffc8 +ffca +ffcc +ffce +ffd0 +ffd2 +ffd4 +ffd6 +ffd8 +ffda +ffdc +ffde +ffdf +ffe1 +ffe3 +ffe5 +ffe6 +ffe8 +ffea +ffeb +ffed +ffee +fff0 +fff2 +fff3 +fff5 +fff6 +fff8 +fff9 +fffa +fffc +fffd +ffff +0000 +0000 +0002 +0003 +0004 +0006 +0007 +0008 +0009 +000a +000c +000d +000e +000f +0010 +0012 +0013 +0014 +0015 +0016 +0017 +0018 +0019 +001a +001b +001c +001d +001e +001f +0020 +0021 +0022 +0023 +0024 +0025 +0026 +0027 +0028 +0029 +002a +002a +002b +002c +002d +002e +002f +0030 +0030 +0031 +0032 +0033 +0034 +0034 +0035 +0036 +0037 +0038 +0038 +0039 +003a +003b +003b +003c +003d +003e +003e +003f +0040 +0040 +0041 +0042 +0042 +0043 +0044 +0044 +0045 +0046 +0046 +0047 +0048 +0048 +0049 +004a +004a +004b +004b +004c +004d +004d +004e +004e +004f +0050 +0050 +0051 +0051 +0052 +0052 +0053 +0054 +0054 +0055 +0055 +0056 +0056 +0057 +0057 +0058 +0058 +0059 +005a +005a +005b +005b +005c +005c +005d +005d +005e +005e +005f +005f +0060 +0060 +0061 +0061 +0061 +0062 +0062 +0063 +0063 +0064 +0064 +0065 +0065 +0066 +0066 +0067 +0067 +0067 +0068 +0068 +0069 +0069 +006a +006a +006b +006b +006b +006c +006c +006d +006d +006e +006e +006e +006f +006f +0070 +0070 +0070 +0071 +0071 +0072 +0072 +0072 +0073 +0073 +0074 +0074 +0074 +0075 +0075 +0075 +0076 +0076 +0077 +0077 +0077 +0078 +0078 +0078 +0079 +0079 +007a +007a +007a +007b +007b +007b +007c +007c +007c +007d +007d +007e +007e +007e +007f +007f +007f +0080 +0080 +0080 +0081 +0081 +0081 +0082 +0082 +0082 +0083 +0083 +0083 +0084 +0084 +0084 +0085 +0085 +0085 +0086 +0086 +0086 +0087 +0087 +0087 +0088 +0088 +0088 +0089 +0089 +0089 +008a +008a +008a +008a +008b +008b +008b +008c +008c +008c +008d +008d +008d +008e +008e +008e +008e +008f +008f +008f +0090 +0090 +0090 +0091 +0091 +0091 +0092 +0092 +0092 +0092 +0093 +0093 +0093 +0094 +0094 +0094 +0094 +0095 +0095 +0095 +0096 +0096 +0096 +0096 +0097 +0097 +0097 +0098 +0098 +0098 +0098 +0099 +0099 +0099 +009a +009a +009a +009a +009b +009b +009b +009c +009c +009c +009c +009d +009d +009d +009e +009e +009e +009e +009f +009f +009f +009f +00a0 +00a0 +00a0 +00a1 +00a1 +00a1 +00a1 +00a2 +00a2 +00a2 +00a3 +00a3 +00a3 +00a3 +00a4 +00a4 +00a4 +00a4 +00a5 +00a5 +00a5 +00a6 +00a6 +00a6 +00a6 +00a7 +00a7 +00a7 +00a7 +00a8 +00a8 +00a8 +00a8 +00a9 +00a9 +00a9 +00aa +00aa +00aa +00aa +00ab +00ab +00ab +00ab +00ac +00ac +00ac +00ad +00ad +00ad +00ad +00ae +00ae +00ae +00ae +00af +00af +00af +00af +00b0 +00b0 +00b0 +00b1 +00b1 +00b1 +00b1 +00b2 +00b2 +00b2 +00b2 +00b3 +00b3 +00b3 +00b3 +00b4 +00b4 +00b4 +00b5 +00b5 +00b5 +00b5 +00b6 +00b6 +00b6 +00b6 +00b7 +00b7 +00b7 +00b8 +00b8 +00b8 +00b8 +00b9 +00b9 +00b9 +00b9 +00ba +00ba +00ba +00bb +00bb +00bb +00bb +00bc +00bc +00bc +00bc +00bd +00bd +00bd +00be +00be +00be +00be +00bf +00bf +00bf +00c0 +00c0 +00c0 +00c0 +00c1 +00c1 +00c1 +00c1 +00c2 +00c2 +00c2 +00c3 +00c3 +00c3 +00c3 +00c4 +00c4 +00c4 +00c5 +00c5 +00c5 +00c5 +00c6 +00c6 +00c6 +00c7 +00c7 +00c7 +00c7 +00c8 +00c8 +00c8 +00c9 +00c9 +00c9 +00c9 +00ca +00ca +00ca +00cb +00cb +00cb +00cc +00cc +00cc +00cc +00cd +00cd +00cd +00ce +00ce +00ce +00cf +00cf +00cf +00cf +00d0 +00d0 +00d0 +00d1 +00d1 +00d1 +00d2 +00d2 +00d2 +00d3 +00d3 +00d3 +00d4 +00d4 +00d4 +00d4 +00d5 +00d5 +00d5 +00d6 +00d6 +00d6 +00d7 +00d7 +00d7 +00d8 +00d8 +00d8 +00d9 +00d9 +00d9 +00da +00da +00da +00db +00db +00db +00dc +00dc +00dc +00dd +00dd +00dd +00de +00de +00de +00df +00df +00e0 +00e0 +00e0 +00e1 +00e1 +00e1 +00e2 +00e2 +00e2 +00e3 +00e3 +00e4 +00e4 +00e4 +00e5 +00e5 +00e5 +00e6 +00e6 +00e6 +00e7 +00e7 +00e8 +00e8 +00e8 +00e9 +00e9 +00ea +00ea +00ea +00eb +00eb +00ec +00ec +00ec +00ed +00ed +00ee +00ee +00ee +00ef +00ef +00f0 +00f0 +00f0 +00f1 +00f1 +00f2 +00f2 +00f3 +00f3 +00f3 +00f4 +00f4 +00f5 +00f5 +00f6 +00f6 +00f7 +00f7 +00f7 +00f8 +00f8 +00f9 +00f9 +00fa +00fa +00fb +00fb +00fc +00fc +00fd +00fd +00fe +00fe +00ff +00ff +0100 +0100 +0101 +0101 +0102 +0102 +0103 +0103 +0104 +0104 +0105 +0105 +0106 +0106 +0107 +0107 +0108 +0109 +0109 +010a +010a +010b +010b +010c +010c +010d +010e +010e +010f +010f +0110 +0111 +0111 +0112 +0112 +0113 +0114 +0114 +0115 +0116 +0116 +0117 +0118 +0118 +0119 +011a +011a +011b +011c +011c +011d +011e +011e +011f +0120 +0121 +0121 +0122 +0123 +0124 +0124 +0125 +0126 +0127 +0127 +0128 +0129 +012a +012b +012b +012c +012d +012e +012f +0130 +0130 +0131 +0132 +0133 +0134 +0135 +0136 +0137 +0138 +0139 +0139 +013a +013b +013c +013d +013e +013f +0140 +0141 +0142 +0143 diff --git a/9_Firmware/9_2_FPGA/long_chirp_seg0_q.mem b/9_Firmware/9_2_FPGA/long_chirp_seg0_q.mem new file mode 100644 index 0000000..9bb5540 --- /dev/null +++ b/9_Firmware/9_2_FPGA/long_chirp_seg0_q.mem @@ -0,0 +1,1024 @@ +fe97 +fe93 +fe8e +fe8a +fe85 +fe81 +fe7c +fe77 +fe72 +fe6d +fe68 +fe63 +fe5d +fe58 +fe52 +fe4d +fe47 +fe41 +fe3b +fe35 +fe2f +fe28 +fe22 +fe1b +fe14 +fe0d +fe06 +fdff +fdf7 +fdef +fde7 +fddf +fdd7 +fdce +fdc5 +fdbc +fdb3 +fdaa +fda0 +fd96 +fd8b +fd81 +fd76 +fd6a +fd5e +fd52 +fd46 +fd39 +fd2b +fd1e +fd0f +fd00 +fcf1 +fce1 +fcd0 +fcbf +fcad +fc9b +fc87 +fc73 +fc5e +fc47 +fc30 +fc18 +fbfe +fbe4 +fbc7 +fbaa +fb8a +fb69 +fb46 +fb21 +faf9 +facf +faa2 +fa72 +fa3f +fa07 +f9cc +f98b +f945 +f8f8 +f8a5 +f849 +f7e4 +f773 +f6f6 +f66a +f5cb +f517 +f449 +f35c +f248 +f106 +ef8a +edc9 +ebb6 +e943 +e66a +e334 +dfc9 +dc95 +da70 +dadd +e02f +ed6a +0560 +288c +51a6 +7290 +75c2 +49c7 +f6b6 +ad82 +b184 +10b9 +6c0f +45fa +c233 +b0fb +3f00 +5b00 +bce2 +cd81 +6ab4 +f247 +b34d +6851 +dbe0 +daa3 +610d +9bd6 +5452 +d4d7 +0de6 +11ce +e1da +29e4 +db41 +1e08 +f8f4 +ec68 +39ee +a6ee +695c +ae05 +12e6 +3f12 +9772 +396a +3292 +978d +11d7 +5fb7 +cbc5 +a48f +2e29 +60d3 +f455 +9789 +bc4f +24cd +623e +4c97 +0520 +bf03 +97d5 +9267 +a329 +bca2 +d588 +e983 +f7ae +00d3 +0643 +0934 +0a94 +0b09 +0afa +0aa7 +0a34 +09b6 +0939 +08c1 +0852 +07eb +078d +0737 +06e8 +06a1 +065f +0623 +05ec +05b9 +058a +055e +0536 +0510 +04ed +04cc +04ad +048f +0474 +045a +0441 +042a +0414 +03ff +03ea +03d7 +03c5 +03b4 +03a3 +0393 +0384 +0375 +0367 +0359 +034c +033f +0333 +0327 +031c +0311 +0306 +02fc +02f2 +02e8 +02df +02d6 +02cd +02c5 +02bc +02b4 +02ac +02a4 +029d +0296 +028f +0288 +0281 +027a +0274 +026d +0267 +0261 +025b +0256 +0250 +024b +0245 +0240 +023b +0236 +0231 +022c +0227 +0222 +021e +0219 +0215 +0210 +020c +0208 +0204 +0200 +01fc +01f8 +01f4 +01f0 +01ed +01e9 +01e5 +01e2 +01de +01db +01d7 +01d4 +01d1 +01ce +01ca +01c7 +01c4 +01c1 +01be +01bb +01b8 +01b5 +01b3 +01b0 +01ad +01aa +01a8 +01a5 +01a2 +01a0 +019d +019b +0198 +0196 +0193 +0191 +018f +018c +018a +0188 +0185 +0183 +0181 +017f +017d +017a +0178 +0176 +0174 +0172 +0170 +016e +016c +016a +0168 +0166 +0165 +0163 +0161 +015f +015d +015b +015a +0158 +0156 +0154 +0153 +0151 +014f +014e +014c +014a +0149 +0147 +0145 +0144 +0142 +0141 +013f +013e +013c +013b +0139 +0138 +0136 +0135 +0133 +0132 +0130 +012f +012e +012c +012b +012a +0128 +0127 +0126 +0124 +0123 +0122 +0120 +011f +011e +011d +011b +011a +0119 +0118 +0116 +0115 +0114 +0113 +0112 +0110 +010f +010e +010d +010c +010b +010a +0108 +0107 +0106 +0105 +0104 +0103 +0102 +0101 +0100 +00ff +00fe +00fd +00fc +00fb +00fa +00f8 +00f7 +00f6 +00f5 +00f4 +00f3 +00f2 +00f2 +00f1 +00f0 +00ef +00ee +00ed +00ec +00eb +00ea +00e9 +00e8 +00e7 +00e6 +00e5 +00e4 +00e3 +00e3 +00e2 +00e1 +00e0 +00df +00de +00dd +00dc +00dc +00db +00da +00d9 +00d8 +00d7 +00d6 +00d6 +00d5 +00d4 +00d3 +00d2 +00d2 +00d1 +00d0 +00cf +00ce +00cd +00cd +00cc +00cb +00ca +00ca +00c9 +00c8 +00c7 +00c6 +00c6 +00c5 +00c4 +00c3 +00c3 +00c2 +00c1 +00c0 +00c0 +00bf +00be +00bd +00bd +00bc +00bb +00bb +00ba +00b9 +00b8 +00b8 +00b7 +00b6 +00b6 +00b5 +00b4 +00b3 +00b3 +00b2 +00b1 +00b1 +00b0 +00af +00af +00ae +00ad +00ad +00ac +00ab +00ab +00aa +00a9 +00a9 +00a8 +00a7 +00a7 +00a6 +00a5 +00a5 +00a4 +00a3 +00a3 +00a2 +00a1 +00a1 +00a0 +009f +009f +009e +009e +009d +009c +009c +009b +009a +009a +0099 +0099 +0098 +0097 +0097 +0096 +0095 +0095 +0094 +0094 +0093 +0092 +0092 +0091 +0091 +0090 +008f +008f +008e +008e +008d +008c +008c +008b +008b +008a +0089 +0089 +0088 +0088 +0087 +0087 +0086 +0085 +0085 +0084 +0084 +0083 +0082 +0082 +0081 +0081 +0080 +0080 +007f +007e +007e +007d +007d +007c +007c +007b +007a +007a +0079 +0079 +0078 +0078 +0077 +0077 +0076 +0075 +0075 +0074 +0074 +0073 +0073 +0072 +0072 +0071 +0070 +0070 +006f +006f +006e +006e +006d +006d +006c +006b +006b +006a +006a +0069 +0069 +0068 +0068 +0067 +0067 +0066 +0065 +0065 +0064 +0064 +0063 +0063 +0062 +0062 +0061 +0061 +0060 +005f +005f +005e +005e +005d +005d +005c +005c +005b +005b +005a +0059 +0059 +0058 +0058 +0057 +0057 +0056 +0056 +0055 +0055 +0054 +0053 +0053 +0052 +0052 +0051 +0051 +0050 +0050 +004f +004f +004e +004e +004d +004c +004c +004b +004b +004a +004a +0049 +0049 +0048 +0048 +0047 +0046 +0046 +0045 +0045 +0044 +0044 +0043 +0043 +0042 +0041 +0041 +0040 +0040 +003f +003f +003e +003e +003d +003c +003c +003b +003b +003a +003a +0039 +0039 +0038 +0037 +0037 +0036 +0036 +0035 +0035 +0034 +0034 +0033 +0032 +0032 +0031 +0031 +0030 +0030 +002f +002e +002e +002d +002d +002c +002c +002b +002a +002a +0029 +0029 +0028 +0027 +0027 +0026 +0026 +0025 +0025 +0024 +0023 +0023 +0022 +0022 +0021 +0020 +0020 +001f +001f +001e +001d +001d +001c +001c +001b +001a +001a +0019 +0019 +0018 +0017 +0017 +0016 +0016 +0015 +0014 +0014 +0013 +0012 +0012 +0011 +0011 +0010 +000f +000f +000e +000d +000d +000c +000b +000b +000a +0009 +0009 +0008 +0008 +0007 +0006 +0006 +0005 +0004 +0004 +0003 +0002 +0002 +0001 +0000 +0000 +0000 +ffff +fffe +fffe +fffd +fffc +fffc +fffb +fffa +fffa +fff9 +fff8 +fff7 +fff7 +fff6 +fff5 +fff5 +fff4 +fff3 +fff2 +fff2 +fff1 +fff0 +fff0 +ffef +ffee +ffed +ffed +ffec +ffeb +ffea +ffea +ffe9 +ffe8 +ffe7 +ffe6 +ffe6 +ffe5 +ffe4 +ffe3 +ffe3 +ffe2 +ffe1 +ffe0 +ffdf +ffdf +ffde +ffdd +ffdc +ffdb +ffda +ffda +ffd9 +ffd8 +ffd7 +ffd6 +ffd5 +ffd5 +ffd4 +ffd3 +ffd2 +ffd1 +ffd0 +ffcf +ffcf +ffce +ffcd +ffcc +ffcb +ffca +ffc9 +ffc8 +ffc7 +ffc6 +ffc6 +ffc5 +ffc4 +ffc3 +ffc2 +ffc1 +ffc0 +ffbf +ffbe +ffbd +ffbc +ffbb +ffba +ffb9 +ffb8 +ffb7 +ffb6 +ffb5 +ffb4 +ffb3 +ffb2 +ffb1 +ffb0 +ffaf +ffae +ffad +ffac +ffaa +ffa9 +ffa8 +ffa7 +ffa6 +ffa5 +ffa4 +ffa3 +ffa2 +ffa0 +ff9f +ff9e +ff9d +ff9c +ff9b +ff99 +ff98 +ff97 +ff96 +ff95 +ff93 +ff92 +ff91 +ff90 +ff8e +ff8d +ff8c +ff8a +ff89 +ff88 +ff86 +ff85 +ff84 +ff82 +ff81 +ff80 +ff7e +ff7d +ff7b +ff7a +ff79 +ff77 +ff76 +ff74 +ff73 +ff71 +ff70 +ff6e +ff6d +ff6b +ff69 +ff68 +ff66 +ff65 +ff63 +ff61 +ff60 +ff5e +ff5c +ff5b +ff59 +ff57 +ff55 +ff54 +ff52 +ff50 +ff4e +ff4c +ff4b +ff49 +ff47 +ff45 +ff43 +ff41 +ff3f +ff3d +ff3b +ff39 +ff37 +ff35 +ff33 +ff31 +ff2f +ff2c +ff2a +ff28 +ff26 +ff23 +ff21 +ff1f +ff1c +ff1a +ff18 +ff15 +ff13 +ff10 +ff0e +ff0b +ff09 +ff06 +ff03 +ff01 +fefe +fefb +fef8 +fef6 +fef3 +fef0 +feed +feea +fee7 +fee4 +fee1 +fedd +feda +fed7 +fed4 +fed0 +fecd +fec9 +fec6 +fec2 +febf +febb +feb7 +feb4 +feb0 +feac +fea8 +fea4 +fea0 +fe9b diff --git a/9_Firmware/9_2_FPGA/long_chirp_seg1_i.mem b/9_Firmware/9_2_FPGA/long_chirp_seg1_i.mem new file mode 100644 index 0000000..12e798c --- /dev/null +++ b/9_Firmware/9_2_FPGA/long_chirp_seg1_i.mem @@ -0,0 +1,1024 @@ +ff33 +ff32 +ff30 +ff2f +ff2d +ff2c +ff2a +ff29 +ff27 +ff25 +ff24 +ff22 +ff20 +ff1f +ff1d +ff1b +ff19 +ff18 +ff16 +ff14 +ff12 +ff10 +ff0e +ff0d +ff0b +ff09 +ff07 +ff05 +ff03 +ff01 +feff +fefd +fefa +fef8 +fef6 +fef4 +fef2 +fef0 +feed +feeb +fee9 +fee6 +fee4 +fee2 +fedf +fedd +feda +fed8 +fed5 +fed2 +fed0 +fecd +feca +fec8 +fec5 +fec2 +febf +febc +feb9 +feb6 +feb3 +feb0 +fead +feaa +fea6 +fea3 +fea0 +fe9c +fe99 +fe95 +fe92 +fe8e +fe8a +fe87 +fe83 +fe7f +fe7b +fe77 +fe73 +fe6e +fe6a +fe66 +fe61 +fe5d +fe58 +fe53 +fe4e +fe4a +fe45 +fe3f +fe3a +fe35 +fe2f +fe2a +fe24 +fe1e +fe18 +fe12 +fe0c +fe05 +fdfe +fdf8 +fdf1 +fdea +fde2 +fddb +fdd3 +fdcb +fdc3 +fdbb +fdb2 +fda9 +fda0 +fd96 +fd8d +fd83 +fd78 +fd6e +fd63 +fd57 +fd4b +fd3f +fd32 +fd25 +fd17 +fd09 +fcfa +fceb +fcdb +fcca +fcb8 +fca6 +fc93 +fc7f +fc6a +fc53 +fc3c +fc24 +fc0a +fbee +fbd1 +fbb2 +fb91 +fb6e +fb49 +fb21 +faf6 +fac8 +fa95 +fa5f +fa24 +f9e3 +f99c +f94d +f8f6 +f895 +f827 +f7ab +f71e +f67b +f5be +f4df +f3d7 +f299 +f116 +ef39 +ece7 +e9fd +e653 +e1bb +dc11 +d556 +cdde +c6a9 +c1cb +c2d1 +ce96 +e9cb +1557 +48f2 +6f4e +6b6d +2dc0 +d18a +a0d0 +d8a3 +4ace +64be +ef7e +9e29 +0c94 +6af0 +e5fa +aad5 +52ca +1f21 +9e51 +5014 +05d2 +b685 +6971 +a9be +3343 +fa06 +e619 +3402 +c085 +469b +bc83 +3b7b +d78a +0bdb +1b6b +ba0d +6375 +9f54 +2c4e +25a9 +9b19 +4b1c +1a45 +975f +266c +5343 +b9ef +b050 +3cce +5749 +e205 +94b1 +c8e4 +3073 +61d7 +419b +f770 +b52b +941e +93cc +a771 +c1d2 +da63 +ed80 +fab2 +02fb +07bd +0a2c +0b30 +0b62 +0b24 +0aaf +0a24 +0994 +0909 +0887 +080f +07a1 +073e +06e4 +0692 +0647 +0603 +05c5 +058c +0557 +0527 +04fa +04d0 +04a9 +0485 +0463 +0444 +0426 +040a +03f0 +03d7 +03bf +03a9 +0393 +037f +036c +035a +0348 +0337 +0327 +0318 +0309 +02fb +02ee +02e1 +02d4 +02c8 +02bc +02b1 +02a6 +029c +0292 +0288 +027e +0275 +026c +0263 +025b +0253 +024b +0243 +023b +0234 +022d +0226 +021f +0219 +0212 +020c +0206 +0200 +01fa +01f4 +01ef +01e9 +01e4 +01df +01da +01d5 +01d0 +01cb +01c6 +01c2 +01bd +01b9 +01b5 +01b0 +01ac +01a8 +01a4 +01a0 +019c +0198 +0195 +0191 +018d +018a +0186 +0183 +0180 +017c +0179 +0176 +0173 +0170 +016d +016a +0167 +0164 +0161 +015e +015b +0158 +0156 +0153 +0150 +014e +014b +0149 +0146 +0144 +0141 +013f +013c +013a +0138 +0136 +0133 +0131 +012f +012d +012b +0128 +0126 +0124 +0122 +0120 +011e +011c +011a +0118 +0116 +0115 +0113 +0111 +010f +010d +010b +010a +0108 +0106 +0104 +0103 +0101 +00ff +00fe +00fc +00fb +00f9 +00f7 +00f6 +00f4 +00f3 +00f1 +00f0 +00ee +00ed +00eb +00ea +00e8 +00e7 +00e6 +00e4 +00e3 +00e1 +00e0 +00df +00dd +00dc +00db +00d9 +00d8 +00d7 +00d6 +00d4 +00d3 +00d2 +00d1 +00cf +00ce +00cd +00cc +00ca +00c9 +00c8 +00c7 +00c6 +00c5 +00c4 +00c2 +00c1 +00c0 +00bf +00be +00bd +00bc +00bb +00ba +00b9 +00b8 +00b7 +00b6 +00b5 +00b3 +00b2 +00b1 +00b0 +00af +00ae +00ae +00ad +00ac +00ab +00aa +00a9 +00a8 +00a7 +00a6 +00a5 +00a4 +00a3 +00a2 +00a1 +00a0 +00a0 +009f +009e +009d +009c +009b +009a +0099 +0099 +0098 +0097 +0096 +0095 +0094 +0094 +0093 +0092 +0091 +0090 +008f +008f +008e +008d +008c +008b +008b +008a +0089 +0088 +0088 +0087 +0086 +0085 +0085 +0084 +0083 +0082 +0082 +0081 +0080 +007f +007f +007e +007d +007d +007c +007b +007a +007a +0079 +0078 +0078 +0077 +0076 +0076 +0075 +0074 +0073 +0073 +0072 +0071 +0071 +0070 +006f +006f +006e +006e +006d +006c +006c +006b +006a +006a +0069 +0068 +0068 +0067 +0066 +0066 +0065 +0065 +0064 +0063 +0063 +0062 +0062 +0061 +0060 +0060 +005f +005e +005e +005d +005d +005c +005b +005b +005a +005a +0059 +0059 +0058 +0057 +0057 +0056 +0056 +0055 +0055 +0054 +0053 +0053 +0052 +0052 +0051 +0051 +0050 +004f +004f +004e +004e +004d +004d +004c +004c +004b +004a +004a +0049 +0049 +0048 +0048 +0047 +0047 +0046 +0046 +0045 +0044 +0044 +0043 +0043 +0042 +0042 +0041 +0041 +0040 +0040 +003f +003f +003e +003e +003d +003d +003c +003c +003b +003b +003a +0039 +0039 +0038 +0038 +0037 +0037 +0036 +0036 +0035 +0035 +0034 +0034 +0033 +0033 +0032 +0032 +0031 +0031 +0030 +0030 +002f +002f +002e +002e +002d +002d +002c +002c +002b +002b +002a +002a +0029 +0029 +0028 +0028 +0027 +0027 +0026 +0026 +0025 +0025 +0024 +0024 +0023 +0023 +0022 +0022 +0022 +0021 +0021 +0020 +0020 +001f +001f +001e +001e +001d +001d +001c +001c +001b +001b +001a +001a +0019 +0019 +0018 +0018 +0017 +0017 +0016 +0016 +0015 +0015 +0014 +0014 +0013 +0013 +0012 +0012 +0012 +0011 +0011 +0010 +0010 +000f +000f +000e +000e +000d +000d +000c +000c +000b +000b +000a +000a +0009 +0009 +0008 +0008 +0007 +0007 +0006 +0006 +0005 +0005 +0004 +0004 +0003 +0003 +0003 +0002 +0002 +0001 +0001 +0000 +0000 +0000 +0000 +ffff +ffff +fffe +fffe +fffd +fffd +fffc +fffc +fffb +fffb +fffa +fffa +fff9 +fff9 +fff8 +fff8 +fff7 +fff7 +fff6 +fff6 +fff5 +fff5 +fff4 +fff4 +fff3 +fff3 +fff2 +fff2 +fff1 +fff1 +fff0 +fff0 +ffef +ffef +ffee +ffee +ffed +ffed +ffec +ffec +ffeb +ffeb +ffea +ffea +ffe9 +ffe8 +ffe8 +ffe7 +ffe7 +ffe6 +ffe6 +ffe5 +ffe5 +ffe4 +ffe4 +ffe3 +ffe3 +ffe2 +ffe2 +ffe1 +ffe1 +ffe0 +ffe0 +ffdf +ffde +ffde +ffdd +ffdd +ffdc +ffdc +ffdb +ffdb +ffda +ffda +ffd9 +ffd8 +ffd8 +ffd7 +ffd7 +ffd6 +ffd6 +ffd5 +ffd5 +ffd4 +ffd3 +ffd3 +ffd2 +ffd2 +ffd1 +ffd1 +ffd0 +ffcf +ffcf +ffce +ffce +ffcd +ffcd +ffcc +ffcb +ffcb +ffca +ffca +ffc9 +ffc8 +ffc8 +ffc7 +ffc7 +ffc6 +ffc5 +ffc5 +ffc4 +ffc4 +ffc3 +ffc2 +ffc2 +ffc1 +ffc1 +ffc0 +ffbf +ffbf +ffbe +ffbd +ffbd +ffbc +ffbc +ffbb +ffba +ffba +ffb9 +ffb8 +ffb8 +ffb7 +ffb6 +ffb6 +ffb5 +ffb4 +ffb4 +ffb3 +ffb2 +ffb2 +ffb1 +ffb0 +ffb0 +ffaf +ffae +ffae +ffad +ffac +ffac +ffab +ffaa +ffa9 +ffa9 +ffa8 +ffa7 +ffa7 +ffa6 +ffa5 +ffa4 +ffa4 +ffa3 +ffa2 +ffa1 +ffa1 +ffa0 +ff9f +ff9e +ff9e +ff9d +ff9c +ff9b +ff9b +ff9a +ff99 +ff98 +ff97 +ff97 +ff96 +ff95 +ff94 +ff93 +ff93 +ff92 +ff91 +ff90 +ff8f +ff8f +ff8e +ff8d +ff8c +ff8b +ff8a +ff89 +ff89 +ff88 +ff87 +ff86 +ff85 +ff84 +ff83 +ff82 +ff81 +ff80 +ff80 +ff7f +ff7e +ff7d +ff7c +ff7b +ff7a +ff79 +ff78 +ff77 +ff76 +ff75 +ff74 +ff73 +ff72 +ff71 +ff70 +ff6f +ff6e +ff6d +ff6c +ff6b +ff6a +ff69 +ff68 +ff67 +ff65 +ff64 +ff63 +ff62 +ff61 +ff60 +ff5f +ff5e +ff5c +ff5b +ff5a +ff59 +ff58 +ff56 +ff55 +ff54 +ff53 +ff52 +ff50 +ff4f +ff4e +ff4d +ff4b +ff4a +ff49 +ff47 +ff46 +ff45 +ff43 +ff42 +ff40 +ff3f +ff3e +ff3c +ff3b +ff39 +ff38 +ff36 +ff35 diff --git a/9_Firmware/9_2_FPGA/long_chirp_seg1_q.mem b/9_Firmware/9_2_FPGA/long_chirp_seg1_q.mem new file mode 100644 index 0000000..e2be41c --- /dev/null +++ b/9_Firmware/9_2_FPGA/long_chirp_seg1_q.mem @@ -0,0 +1,1024 @@ +ff79 +ff7a +ff7a +ff7a +ff7a +ff7b +ff7b +ff7b +ff7b +ff7c +ff7c +ff7c +ff7c +ff7d +ff7d +ff7d +ff7e +ff7e +ff7e +ff7f +ff7f +ff7f +ff80 +ff80 +ff80 +ff81 +ff81 +ff81 +ff82 +ff82 +ff83 +ff83 +ff84 +ff84 +ff84 +ff85 +ff85 +ff86 +ff86 +ff87 +ff87 +ff88 +ff88 +ff89 +ff8a +ff8a +ff8b +ff8b +ff8c +ff8d +ff8d +ff8e +ff8f +ff8f +ff90 +ff91 +ff91 +ff92 +ff93 +ff94 +ff95 +ff95 +ff96 +ff97 +ff98 +ff99 +ff9a +ff9b +ff9c +ff9d +ff9e +ff9f +ffa0 +ffa1 +ffa3 +ffa4 +ffa5 +ffa6 +ffa8 +ffa9 +ffaa +ffac +ffad +ffaf +ffb0 +ffb2 +ffb4 +ffb5 +ffb7 +ffb9 +ffbb +ffbd +ffbf +ffc1 +ffc3 +ffc5 +ffc8 +ffca +ffcc +ffcf +ffd1 +ffd4 +ffd7 +ffda +ffdd +ffe0 +ffe3 +ffe7 +ffea +ffee +fff1 +fff5 +fff9 +fffd +0001 +0005 +000a +000f +0014 +001a +001f +0025 +002b +0032 +0039 +0040 +0047 +004f +0057 +0060 +0069 +0073 +007d +0088 +0093 +009f +00ac +00b9 +00c7 +00d7 +00e7 +00f8 +010b +011f +0134 +014b +0163 +017e +019b +01ba +01dc +0201 +0229 +0255 +0285 +02bb +02f5 +0336 +037d +03cc +0423 +0483 +04eb +055a +05cd +063c +069a +06cd +06a7 +05db +03ef +0023 +f96e +ee87 +de3d +c840 +ae90 +9744 +8d7e +9eee +d334 +1e2c +57ef +4e32 +f6dd +9b5a +a9da +2296 +5dad +ee53 +91aa +078f +5c5d +c440 +b6fb +5d55 +e10d +b500 +615d +b33f +ff84 +3073 +9f1e +6155 +961f +543f +a8f8 +4685 +abfe +4f12 +9ab8 +60c4 +95f0 +4642 +ddf9 +d315 +56b6 +992e +14af +3ef5 +950d +03ef +57c9 +bd98 +a96f +3ccc +48b5 +c496 +9207 +ed22 +4f48 +4ccd +f9ed +a71d +88de +a029 +d20e +03b2 +26cc +38dc +3da2 +3a62 +336e +2b8b +2427 +1dd6 +18ae +1493 +1155 +0ec6 +0cbe +0b1d +09ca +08b5 +07ce +070c +0667 +05d9 +055e +04f3 +0494 +0441 +03f6 +03b3 +0376 +033f +030d +02e0 +02b6 +0290 +026c +024b +022d +0210 +01f6 +01dd +01c6 +01b0 +019c +0189 +0177 +0166 +0156 +0146 +0138 +012a +011d +0110 +0105 +00f9 +00ef +00e4 +00da +00d1 +00c8 +00bf +00b7 +00af +00a7 +00a0 +0099 +0092 +008c +0085 +007f +007a +0074 +006e +0069 +0064 +005f +005a +0056 +0051 +004d +0049 +0045 +0041 +003d +0039 +0036 +0032 +002f +002b +0028 +0025 +0022 +001f +001c +0019 +0017 +0014 +0011 +000f +000c +000a +0007 +0005 +0003 +0001 +0000 +fffe +fffb +fffa +fff8 +fff6 +fff4 +fff2 +fff0 +ffee +ffed +ffeb +ffe9 +ffe8 +ffe6 +ffe5 +ffe3 +ffe2 +ffe0 +ffdf +ffdd +ffdc +ffdb +ffd9 +ffd8 +ffd7 +ffd6 +ffd4 +ffd3 +ffd2 +ffd1 +ffd0 +ffcf +ffce +ffcd +ffcb +ffca +ffc9 +ffc8 +ffc7 +ffc6 +ffc6 +ffc5 +ffc4 +ffc3 +ffc2 +ffc1 +ffc0 +ffbf +ffbe +ffbe +ffbd +ffbc +ffbb +ffba +ffba +ffb9 +ffb8 +ffb7 +ffb7 +ffb6 +ffb5 +ffb5 +ffb4 +ffb3 +ffb3 +ffb2 +ffb1 +ffb1 +ffb0 +ffb0 +ffaf +ffae +ffae +ffad +ffad +ffac +ffac +ffab +ffaa +ffaa +ffa9 +ffa9 +ffa8 +ffa8 +ffa7 +ffa7 +ffa6 +ffa6 +ffa5 +ffa5 +ffa4 +ffa4 +ffa4 +ffa3 +ffa3 +ffa2 +ffa2 +ffa1 +ffa1 +ffa0 +ffa0 +ffa0 +ff9f +ff9f +ff9e +ff9e +ff9e +ff9d +ff9d +ff9d +ff9c +ff9c +ff9b +ff9b +ff9b +ff9a +ff9a +ff9a +ff99 +ff99 +ff99 +ff98 +ff98 +ff98 +ff97 +ff97 +ff97 +ff97 +ff96 +ff96 +ff96 +ff95 +ff95 +ff95 +ff94 +ff94 +ff94 +ff94 +ff93 +ff93 +ff93 +ff93 +ff92 +ff92 +ff92 +ff91 +ff91 +ff91 +ff91 +ff90 +ff90 +ff90 +ff90 +ff8f +ff8f +ff8f +ff8f +ff8f +ff8e +ff8e +ff8e +ff8e +ff8d +ff8d +ff8d +ff8d +ff8d +ff8c +ff8c +ff8c +ff8c +ff8c +ff8b +ff8b +ff8b +ff8b +ff8b +ff8a +ff8a +ff8a +ff8a +ff8a +ff89 +ff89 +ff89 +ff89 +ff89 +ff88 +ff88 +ff88 +ff88 +ff88 +ff88 +ff87 +ff87 +ff87 +ff87 +ff87 +ff87 +ff86 +ff86 +ff86 +ff86 +ff86 +ff86 +ff85 +ff85 +ff85 +ff85 +ff85 +ff85 +ff85 +ff84 +ff84 +ff84 +ff84 +ff84 +ff84 +ff83 +ff83 +ff83 +ff83 +ff83 +ff83 +ff83 +ff83 +ff82 +ff82 +ff82 +ff82 +ff82 +ff82 +ff82 +ff81 +ff81 +ff81 +ff81 +ff81 +ff81 +ff81 +ff81 +ff80 +ff80 +ff80 +ff80 +ff80 +ff80 +ff80 +ff80 +ff7f +ff7f +ff7f +ff7f +ff7f +ff7f +ff7f +ff7f +ff7f +ff7e +ff7e +ff7e +ff7e +ff7e +ff7e +ff7e +ff7e +ff7e +ff7e +ff7d +ff7d +ff7d +ff7d +ff7d +ff7d +ff7d +ff7d +ff7d +ff7c +ff7c +ff7c +ff7c +ff7c +ff7c +ff7c +ff7c +ff7c +ff7c +ff7c +ff7b +ff7b +ff7b +ff7b +ff7b +ff7b +ff7b +ff7b +ff7b +ff7b +ff7b +ff7a +ff7a +ff7a +ff7a +ff7a +ff7a +ff7a +ff7a +ff7a +ff7a +ff7a +ff7a +ff79 +ff79 +ff79 +ff79 +ff79 +ff79 +ff79 +ff79 +ff79 +ff79 +ff79 +ff79 +ff79 +ff78 +ff78 +ff78 +ff78 +ff78 +ff78 +ff78 +ff78 +ff78 +ff78 +ff78 +ff78 +ff78 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff77 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff70 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff71 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff72 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff73 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff74 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff75 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff76 +ff77 +ff77 +ff77 +ff77 +ff77 +ff78 +ff78 +ff78 +ff78 +ff78 +ff79 +ff79 +ff79 +ff79 diff --git a/9_Firmware/9_2_FPGA/long_chirp_seg2_i.mem b/9_Firmware/9_2_FPGA/long_chirp_seg2_i.mem new file mode 100644 index 0000000..58cd5d9 --- /dev/null +++ b/9_Firmware/9_2_FPGA/long_chirp_seg2_i.mem @@ -0,0 +1,1024 @@ +ff8d +ffb9 +fff2 +002c +005d +007b +007f +006a +003f +0007 +ffcd +ff9b +ff7c +ff77 +ff8c +ffb7 +fff1 +002d +0062 +0084 +008c +0079 +004f +0016 +ffd9 +ffa4 +ff81 +ff78 +ff8b +ffb6 +fff0 +002f +0068 +008d +009a +008a +0061 +0027 +ffe8 +ffaf +ff88 +ff7b +ff8a +ffb4 +fff0 +0031 +006e +0098 +00a9 +009c +0074 +0039 +fff7 +ffba +ff8f +ff7e +ff8b +ffb3 +fff0 +0034 +0075 +00a4 +00b9 +00af +0089 +004d +0008 +ffc8 +ff98 +ff82 +ff8b +ffb3 +fff0 +0038 +007d +00b2 +00cb +00c5 +00a1 +0064 +001c +ffd7 +ffa2 +ff87 +ff8d +ffb3 +fff1 +003c +0086 +00c1 +00e0 +00de +00bb +007e +0033 +ffe9 +ffae +ff8e +ff90 +ffb4 +fff4 +0042 +0092 +00d3 +00f8 +00fb +00da +009d +004e +ffff +ffbd +ff97 +ff95 +ffb7 +fff7 +004a +00a0 +00e8 +0114 +011c +00fe +00c0 +006e +0018 +ffd0 +ffa3 +ff9c +ffbc +fffe +0054 +00b1 +0102 +0136 +0144 +0129 +00ea +0094 +0037 +ffe8 +ffb3 +ffa6 +ffc4 +0006 +0063 +00c8 +0122 +015f +0174 +015d +011e +00c4 +0060 +0006 +ffcb +ffb7 +ffd2 +0016 +0079 +00e7 +014c +0194 +01b2 +01a0 +0161 +0102 +0095 +0032 +ffec +ffd2 +ffe9 +0030 +009a +0114 +0186 +01dc +0204 +01f8 +01ba +0156 +00e0 +0071 +001f +fffe +0012 +005c +00d0 +0158 +01dc +0242 +0279 +0275 +0239 +01d0 +0151 +00d5 +0078 +004c +005f +00af +0131 +01cd +0268 +02e6 +0331 +033b +0305 +029a +0212 +018b +0122 +00f1 +0106 +0163 +01fc +02b9 +037a +0420 +048f +04b6 +0494 +0435 +03b2 +032d +02ca +02a7 +02d9 +0364 +043e +054b +066b +0776 +084d +08d8 +0912 +0904 +08c2 +0865 +07ff +0788 +06cb +0552 +024d +fc8c +f28e +e2e3 +cd0d +b2fb +9af1 +9070 +a18a +d5d0 +2045 +57ca +4a48 +f0ef +997c +b096 +2c34 +5e9f +e956 +9894 +1789 +5b72 +bc6a +c44d +5ffd +d16a +c1db +5f32 +a7a3 +1487 +2172 +b0d6 +6342 +9a3c +63d5 +a26b +5924 +a023 +5b80 +92da +5db6 +a137 +2df9 +ffd8 +bc7b +6786 +b5df +fd54 +6051 +b04c +e65b +63f6 +e300 +93a7 +1477 +5624 +eb3f +9284 +cadf +4098 +735b +4794 +f6bb +be7c +b4a2 +ccd4 +efff +0cd2 +1c27 +1e7c +17e3 +0d05 +01b0 +f86a +f278 +f02d +f125 +f489 +f949 +fe50 +02ac +05af +06fc +0691 +04b5 +01e8 +fec9 +fbf0 +f9df +f8e4 +f916 +fa54 +fc4e +fe98 +00be +0260 +0338 +032a +024a +00cf +ff0a +fd53 +fbfe +fb46 +fb46 +fbf4 +fd27 +fe9f +0011 +0139 +01e2 +01f3 +016e +0074 +ff3b +fe00 +fcff +fc67 +fc53 +fcc0 +fd96 +fea8 +ffc1 +00a9 +0139 +0156 +0101 +004c +ff5f +fe68 +fd97 +fd13 +fcf4 +fd3d +fddc +feb2 +ff94 +0055 +00d4 +00fa +00c1 +0037 +ff7b +feaf +fdfe +fd87 +fd62 +fd92 +fe0e +febc +ff79 +0020 +0093 +00bd +0097 +002b +ff90 +fee3 +fe48 +fddb +fdb2 +fdd2 +fe34 +fec5 +ff67 +fffb +0065 +0092 +007a +0024 +ffa1 +ff0c +fe81 +fe1c +fdef +fe03 +fe52 +fecd +ff5b +ffe0 +0043 +0072 +0065 +001f +ffb0 +ff2c +feaf +fe4f +fe21 +fe2b +fe6b +fed4 +ff52 +ffcb +0028 +0059 +0055 +001c +ffbc +ff47 +fed4 +fe7a +fe49 +fe4c +fe80 +fedb +ff4c +ffbb +0014 +0046 +0048 +001a +ffc7 +ff5d +fef3 +fe9d +fe6c +fe68 +fe92 +fee2 +ff47 +ffae +0003 +0036 +003d +0018 +ffd0 +ff71 +ff0e +febc +fe89 +fe80 +fea2 +fee8 +ff43 +ffa4 +fff5 +0028 +0035 +0017 +ffd8 +ff82 +ff26 +fed6 +fea3 +fe96 +feb0 +feed +ff41 +ff9b +ffe9 +001d +002d +0017 +ffdf +ff90 +ff3a +feee +feba +fea9 +febd +fef2 +ff3f +ff93 +ffdf +0013 +0027 +0016 +ffe6 +ff9e +ff4d +ff03 +fecf +feba +fec9 +fef7 +ff3d +ff8d +ffd6 +000a +0021 +0016 +ffec +ffa9 +ff5d +ff16 +fee2 +feca +fed3 +fefc +ff3c +ff87 +ffce +0002 +001c +0015 +fff1 +ffb4 +ff6c +ff27 +fef3 +fed8 +fede +ff01 +ff3c +ff82 +ffc6 +fffc +0017 +0015 +fff5 +ffbe +ff7a +ff37 +ff03 +fee6 +fee7 +ff05 +ff3b +ff7e +ffc0 +fff5 +0013 +0014 +fffa +ffc7 +ff87 +ff46 +ff11 +fef3 +fef0 +ff0a +ff3b +ff7a +ffba +ffef +000f +0014 +fffe +ffcf +ff93 +ff54 +ff1f +fefe +fef8 +ff0e +ff3b +ff76 +ffb5 +ffea +000b +0013 +0000 +ffd7 +ff9e +ff61 +ff2c +ff0a +ff01 +ff12 +ff3b +ff73 +ffb0 +ffe5 +0007 +0013 +0003 +ffde +ffa8 +ff6d +ff38 +ff15 +ff08 +ff16 +ff3b +ff70 +ffab +ffe0 +0004 +0012 +0006 +ffe5 +ffb2 +ff78 +ff44 +ff1f +ff10 +ff1a +ff3c +ff6e +ffa7 +ffdb +0001 +0011 +0009 +ffeb +ffbb +ff83 +ff4f +ff29 +ff18 +ff1e +ff3c +ff6c +ffa3 +ffd7 +ffff +0011 +000c +fff1 +ffc4 +ff8e +ff5a +ff33 +ff1f +ff23 +ff3d +ff6a +ff9f +ffd3 +fffc +0010 +000e +fff7 +ffcc +ff98 +ff65 +ff3c +ff26 +ff27 +ff3e +ff68 +ff9b +ffcf +fff9 +000f +0010 +fffc +ffd4 +ffa2 +ff6f +ff45 +ff2d +ff2b +ff3f +ff66 +ff98 +ffcb +fff6 +000e +0012 +0000 +ffdc +ffab +ff79 +ff4e +ff34 +ff2f +ff40 +ff65 +ff95 +ffc8 +fff3 +000e +0014 +0005 +ffe3 +ffb4 +ff82 +ff57 +ff3b +ff33 +ff42 +ff63 +ff92 +ffc4 +fff0 +000d +0016 +0009 +ffea +ffbd +ff8c +ff60 +ff42 +ff38 +ff43 +ff62 +ff8f +ffc1 +ffed +000c +0018 +000e +fff1 +ffc6 +ff95 +ff68 +ff49 +ff3c +ff45 +ff61 +ff8c +ffbd +ffeb +000b +0019 +0012 +fff8 +ffce +ff9e +ff71 +ff50 +ff40 +ff46 +ff61 +ff8a +ffba +ffe8 +000a +001b +0016 +ffff +ffd7 +ffa7 +ff7a +ff56 +ff45 +ff48 +ff60 +ff87 +ffb7 +ffe5 +0009 +001c +001a +0004 +ffdf +ffb0 +ff82 +ff5e +ff4a +ff4a +ff60 +ff85 +ffb4 +ffe3 +0008 +001d +001e +000a +ffe7 +ffb9 +ff8b +ff65 +ff4e +ff4d +ff5f +ff83 +ffb1 +ffe0 +0006 +001e +0022 +0011 +ffef +ffc2 +ff93 +ff6c +ff53 +ff4f +ff5f +ff81 +ffae +ffde +0005 +001f +0025 +0017 +fff7 +ffcb +ff9c +ff73 +ff59 +ff51 +ff5f +ff7f +ffab +ffdb +0004 +0020 +0029 +001d +ffff +ffd4 +ffa5 +ff7b +ff5e +ff54 +ff5f +ff7d +ffa9 +ffd8 +0003 +0021 +002c +0023 +0006 +ffdd +ffae +ff82 +ff63 +ff57 +ff60 +ff7c +ffa6 +ffd6 +0001 +0022 +0030 +0029 +000e +ffe6 +ffb7 +ff8a +ff69 +ff5a +ff60 +ff7a +ffa3 +ffd3 +0000 +0023 +0033 +002f +0017 +fff0 +ffc0 +ff92 +ff6f +ff5d +ff61 +ff79 +ffa1 +ffd1 +0000 +0023 +0037 +0035 +001f +fff9 +ffca +ff9b +ff75 +ff61 +ff62 +ff78 +ff9e +ffce +fffe +0024 +003a +003b +0027 +0002 +ffd3 +ffa3 +ff7c +ff65 +ff63 +ff77 +ff9c +ffcc +fffd +0025 +003e +0041 +0030 +000c +ffdd +ffac +ff83 +ff69 +ff64 +ff76 +ff9a +ffc9 +fffb +0026 +0041 +0048 +0038 +0016 +ffe8 +ffb6 +ff8a +ff6e +ff66 +ff75 +ff97 +ffc7 +fffa +0026 +0045 +004e +0041 +0020 +fff3 +ffbf +ff92 +ff73 +ff68 +ff74 +ff95 +ffc4 +fff9 +0027 +0048 +0055 +004a +002b +fffe +ffca +ff9a +ff78 +ff6a +ff74 +ff93 +ffc2 +fff7 +0028 +004c +005c +0054 +0036 +0009 +ffd5 +ffa3 +ff7e +ff6d +ff74 +ff91 +ffc0 +fff6 +0029 +0050 +0063 +005e +0042 +0015 +ffe0 +ffac +ff84 +ff70 +ff74 +ff90 +ffbd +fff5 +002a +0054 +006a +0069 +004f +0022 +ffec +ffb6 +ff8b +ff73 +ff75 +ff8e +ffbb +fff3 +002b +0058 +0072 +0074 +005c +0030 +fff9 +ffc1 +ff92 +ff77 +ff75 diff --git a/9_Firmware/9_2_FPGA/long_chirp_seg2_q.mem b/9_Firmware/9_2_FPGA/long_chirp_seg2_q.mem new file mode 100644 index 0000000..3695e1d --- /dev/null +++ b/9_Firmware/9_2_FPGA/long_chirp_seg2_q.mem @@ -0,0 +1,1024 @@ +00ed +0114 +0125 +011c +00fb +00c8 +008d +0056 +002e +001c +0025 +0047 +007b +00b7 +00f1 +011c +0131 +012b +010c +00d9 +009c +0062 +0036 +0021 +0027 +0047 +007b +00b9 +00f6 +0125 +013e +013c +011e +00eb +00ad +0070 +0040 +0027 +0029 +0047 +007b +00bc +00fc +012f +014d +014e +0132 +0100 +00c0 +0080 +004b +002d +002c +0048 +007c +00be +0102 +013b +015d +0161 +0148 +0116 +00d5 +0091 +0058 +0035 +0030 +004a +007e +00c2 +010a +0147 +016e +0178 +0161 +0130 +00ec +00a5 +0067 +003f +0036 +004d +0081 +00c7 +0113 +0156 +0183 +0191 +017d +014c +0107 +00bb +0078 +004b +003d +0051 +0085 +00ce +011e +0167 +019a +01ad +019d +016d +0126 +00d6 +008d +005a +0046 +0058 +008b +00d6 +012c +017b +01b6 +01cf +01c3 +0194 +014b +00f6 +00a6 +006c +0053 +0061 +0094 +00e2 +013d +0195 +01d7 +01f7 +01f0 +01c2 +0176 +011d +00c6 +0084 +0065 +006f +00a1 +00f3 +0155 +01b4 +0200 +0228 +0226 +01fa +01ad +014d +00ef +00a4 +007e +0083 +00b5 +010a +0174 +01de +0234 +0267 +026b +0242 +01f2 +018c +0125 +00d1 +00a2 +00a2 +00d4 +012e +01a1 +0218 +027b +02ba +02c7 +02a0 +024f +01e2 +0171 +0112 +00da +00d5 +0107 +0168 +01e7 +026d +02e2 +032f +0347 +0327 +02d4 +0261 +01e5 +017a +0138 +012f +0162 +01cd +025d +02f8 +0384 +03e7 +0410 +03f9 +03a9 +0331 +02ab +0236 +01ed +01e2 +021e +029b +0346 +0404 +04b6 +053e +0587 +0589 +0549 +04d9 +0459 +03e9 +03ab +03b8 +041a +04cf +05c5 +06de +07f8 +08f1 +09b2 +0a32 +0a79 +0aa2 +0ad7 +0b4b +0c36 +0dcb +1036 +139a +180d +1d9d +2447 +2be2 +33f9 +3b77 +4037 +3ea6 +31e9 +1561 +e86a +b3e8 +8df5 +93f6 +d46f +3173 +5f02 +22d0 +b22f +a11f +1a26 +5fec +e7b8 +956b +21eb +48e0 +a106 +ec03 +596b +a4f3 +0bfb +3c91 +9c17 +60c8 +bcfd +1bb3 +0161 +de9b +24d0 +c846 +2678 +d718 +087a +0eac +c912 +5aa8 +9c85 +52d5 +f67b +bdd3 +654b +cc0b +bbab +59b0 +f2cf +9162 +18ac +5dee +e7d2 +a050 +f9f4 +67ea +630e +035d +add9 +9cec +c55a +fd82 +2501 +31a0 +2903 +162a +028b +f3b3 +eb9f +e9f8 +ed33 +f35b +fa8c +0135 +063f +090d +0981 +07e5 +04d2 +0109 +fd52 +fa55 +f88b +f827 +f919 +fb14 +fda3 +0041 +0273 +03d9 +0441 +03ab +0246 +0063 +fe66 +fcaf +fb8d +fb2f +fb9b +fcb1 +fe35 +ffd9 +014a +0248 +02a8 +0261 +0187 +004c +fef1 +fdb8 +fcdc +fc83 +fcba +fd70 +fe7f +ffaf +00c6 +0190 +01ea +01c7 +0132 +004d +ff46 +fe50 +fd9b +fd47 +fd62 +fde3 +feb0 +ff9e +007e +0129 +017e +0170 +0105 +0053 +ff81 +feb5 +fe19 +fdc9 +fdd3 +fe32 +fed3 +ff96 +0053 +00e9 +013a +0139 +00e9 +005b +ffac +fefe +fe74 +fe26 +fe24 +fe6c +feef +ff93 +0037 +00bd +010b +0114 +00d7 +0063 +ffce +ff36 +feb9 +fe6e +fe63 +fe9a +ff06 +ff93 +0023 +009d +00e9 +00f9 +00cb +006a +ffea +ff62 +feef +fea6 +fe95 +febe +ff19 +ff94 +0015 +0085 +00cf +00e5 +00c3 +0071 +0000 +ff87 +ff1c +fed4 +febe +fedd +ff2a +ff96 +000a +0073 +00bb +00d5 +00bc +0077 +0013 +ffa5 +ff41 +fefb +fee1 +fef7 +ff38 +ff98 +0002 +0064 +00ab +00c8 +00b7 +007c +0024 +ffbf +ff61 +ff1d +feff +ff0e +ff45 +ff9a +fffd +0058 +009d +00bd +00b3 +0082 +0032 +ffd6 +ff7d +ff3a +ff19 +ff22 +ff51 +ff9d +fff8 +004e +0092 +00b5 +00b0 +0086 +003f +ffea +ff95 +ff54 +ff31 +ff34 +ff5b +ffa0 +fff4 +0046 +0088 +00ad +00ae +008a +004a +fffb +ffab +ff6b +ff46 +ff44 +ff65 +ffa2 +fff0 +003e +0080 +00a6 +00ab +008e +0055 +000a +ffbf +ff7f +ff59 +ff53 +ff6e +ffa5 +ffee +0038 +0078 +00a0 +00a9 +0091 +005e +0019 +ffd1 +ff92 +ff6a +ff60 +ff76 +ffa8 +ffec +0033 +0071 +009b +00a7 +0094 +0066 +0026 +ffe1 +ffa4 +ff7a +ff6d +ff7f +ffab +ffea +002e +006b +0096 +00a6 +0097 +006e +0032 +fff0 +ffb4 +ff8a +ff79 +ff86 +ffae +ffe8 +0029 +0066 +0092 +00a4 +009a +0075 +003d +ffff +ffc3 +ff98 +ff85 +ff8e +ffb1 +ffe7 +0025 +0061 +008e +00a3 +009c +007c +0048 +000b +ffd1 +ffa5 +ff8f +ff95 +ffb4 +ffe6 +0022 +005c +008a +00a1 +009e +0082 +0052 +0017 +ffdf +ffb2 +ff9a +ff9b +ffb7 +ffe6 +001f +0058 +0086 +00a0 +00a0 +0088 +005b +0023 +ffeb +ffbe +ffa4 +ffa2 +ffba +ffe5 +001c +0054 +0083 +009e +00a2 +008d +0064 +002e +fff8 +ffc9 +ffad +ffa9 +ffbd +ffe5 +0019 +0050 +007f +009d +00a4 +0092 +006c +0039 +0002 +ffd5 +ffb7 +ffaf +ffc0 +ffe5 +0017 +004d +007c +009c +00a5 +0097 +0074 +0043 +000e +ffdf +ffc0 +ffb6 +ffc3 +ffe5 +0014 +004a +0079 +009a +00a7 +009b +007b +004d +0018 +ffea +ffc9 +ffbc +ffc6 +ffe5 +0012 +0046 +0076 +0099 +00a8 +00a0 +0082 +0056 +0023 +fff4 +ffd1 +ffc2 +ffc9 +ffe6 +0010 +0043 +0074 +0098 +00a9 +00a4 +0089 +005f +002d +fffe +ffda +ffc8 +ffcd +ffe6 +000f +0041 +0071 +0096 +00aa +00a7 +0090 +0068 +0037 +0007 +ffe3 +ffcf +ffd0 +ffe7 +000d +003e +006e +0095 +00ab +00ab +0096 +0070 +0041 +0011 +ffeb +ffd5 +ffd4 +ffe8 +000c +003b +006c +0094 +00ac +00af +009d +0079 +004b +001b +fff4 +ffdb +ffd7 +ffe9 +000b +0039 +0069 +0092 +00ac +00b2 +00a3 +0081 +0054 +0024 +fffc +ffe2 +ffdb +ffea +000a +0037 +0067 +0091 +00ad +00b5 +00a9 +0089 +005d +002e +0004 +ffe8 +ffdf +ffeb +0009 +0034 +0064 +0090 +00ae +00b8 +00ae +0091 +0067 +0037 +000c +ffef +ffe3 +ffec +0008 +0032 +0062 +008e +00ae +00bc +00b4 +0099 +0070 +0041 +0015 +fff6 +ffe7 +ffee +0007 +0030 +0060 +008d +00af +00be +00ba +00a1 +0079 +004a +001e +fffc +ffec +fff0 +0007 +002e +005e +008b +00af +00c1 +00bf +00a9 +0083 +0054 +0026 +0003 +fff0 +fff2 +0007 +002d +005b +008a +00af +00c4 +00c5 +00b1 +008c +005e +002f +000a +fff5 +fff4 +0007 +002b +0059 +0089 +00b0 +00c7 +00ca +00b8 +0095 +0068 +0039 +0011 +fffa +fff7 +0007 +002a +0057 +0087 +00b0 +00ca +00d0 +00c0 +009f +0072 +0042 +0019 +0000 +fff9 +0007 +0028 +0055 +0086 +00b0 +00cd +00d5 +00c8 +00a8 +007c +004c +0021 +0004 +fffc +0007 +0027 +0053 +0085 +00b1 +00cf +00db +00d0 +00b2 +0087 +0056 +002a +000a +ffff +0008 +0026 +0052 +0083 +00b1 +00d2 +00e0 +00d8 +00bc +0091 +0060 +0032 +0011 +0002 +0009 +0025 +0050 +0082 +00b1 +00d5 +00e6 +00e1 +00c7 +009d +006b +003b +0017 +0006 +000a +0024 +004e +0081 +00b2 +00d8 +00ec +00e9 +00d1 +00a8 +0076 +0045 +001e +000a +000b +0023 +004d +007f +00b2 +00db +00f2 +00f2 +00dc +00b4 +0082 +004f +0026 +000e +000d +0023 +004b +007e +00b3 +00de +00f8 +00fb +00e8 +00c1 +008e +005a +002e +0013 +000f +0023 +004a +007d +00b3 +00e1 +00fe +0105 +00f4 +00ce +009b +0065 +0037 +0019 +0012 +0023 +0049 +007c +00b4 +00e5 +0105 +010f +0100 +00dc +00a9 +0072 +0040 +001f +0015 +0023 +0048 +007c +00b5 +00e8 +010c +011a +010e +00eb +00b8 +007f +004b +0026 +0018 +0024 +0047 +007b +00b6 diff --git a/9_Firmware/9_2_FPGA/lvds_to_cmos_400m.v b/9_Firmware/9_2_FPGA/lvds_to_cmos_400m.v new file mode 100644 index 0000000..1aa898b --- /dev/null +++ b/9_Firmware/9_2_FPGA/lvds_to_cmos_400m.v @@ -0,0 +1,45 @@ +`timescale 1ns / 1ps +module lvds_to_cmos_400m ( + // ADC Physical Interface (LVDS Inputs) + input wire clk_400m_p, // Data Clock Output P (400MHz LVDS, 2.5V) + input wire clk_400m_n, // Data Clock Output N (400MHz LVDS, 2.5V) + input wire reset_n, // Active-low reset + + // CMOS Output Interface (400MHz Domain) + output reg clk_400m_cmos // ADC data clock (CMOS, 3.3V) +); + +// LVDS to single-ended conversion +wire clk_400m_se; // Single-ended DCO from ADC + + +// IBUFDS for DCO clock (LVDS to CMOS conversion) +IBUFDS #( + .DIFF_TERM("FALSE"), // DISABLE internal termination (using external 100O) + .IOSTANDARD("LVDS_25") // 2.5V LVDS standard +) ibufds_dco ( + .O(clk_400m_se), // Single-ended 400MHz clock + .I(clk_400m_p), + .IB(clk_400m_n) +); + +// Optional: Global clock buffer for better clock distribution +wire clk_400m_buffered; +BUFG bufg_dco ( + .I(clk_400m_se), + .O(clk_400m_buffered) +); + + +// Main processing: Capture on rising edge only +always @(posedge clk_400m_buffered or negedge reset_n) begin + if (!reset_n) begin + // Reset state + clk_400m_cmos <= 1'b0; + end else begin + // Output buffered DCO clock + clk_400m_cmos <= clk_400m_buffered; + end +end + +endmodule diff --git a/9_Firmware/9_2_FPGA/matched_filter_multi_segment.v b/9_Firmware/9_2_FPGA/matched_filter_multi_segment.v new file mode 100644 index 0000000..0797799 --- /dev/null +++ b/9_Firmware/9_2_FPGA/matched_filter_multi_segment.v @@ -0,0 +1,410 @@ +`timescale 1ns / 1ps +// matched_filter_multi_segment.v +module matched_filter_multi_segment ( + input wire clk, // 100MHz + input wire reset_n, + + // Input from DDC (100 MSPS) + input wire signed [17:0] ddc_i, + input wire signed [17:0] ddc_q, + input wire ddc_valid, + + // Chirp control (from sequence controller) + input wire use_long_chirp, // + input wire [5:0] chirp_counter, // + + // Microcontroller sync signals + input wire mc_new_chirp, // Toggle for new chirp (32) + input wire mc_new_elevation, // Toggle for new elevation (32) + input wire mc_new_azimuth, // Toggle for new azimuth (50) + + input wire [15:0] long_chirp_real, + input wire [15:0] long_chirp_imag, + input wire [15:0] short_chirp_real, + input wire [15:0] short_chirp_imag, + + // Memory system interface + output reg [1:0] segment_request, + output wire [9:0] sample_addr_out, // Tell memory which sample we need + output reg mem_request, + input wire mem_ready, + + // Output: Pulse compressed + output wire signed [15:0] pc_i_w, + output wire signed [15:0] pc_q_w, + output wire pc_valid_w, + + // Status + output reg [3:0] status +); + +// ========== FIXED PARAMETERS ========== +parameter BUFFER_SIZE = 1024; +parameter LONG_CHIRP_SAMPLES = 3000; // Still 3000 samples total +parameter SHORT_CHIRP_SAMPLES = 50; // 0.5s @ 100MHz +parameter OVERLAP_SAMPLES = 128; // Standard for 1024-pt FFT +parameter SEGMENT_ADVANCE = BUFFER_SIZE - OVERLAP_SAMPLES; // 896 samples +parameter DEBUG = 1; // Debug output control + +// Calculate segments needed with overlap +// For 3072 samples with 128 overlap: +// Segments = ceil((3072 - 128) / 896) = ceil(2944/896) = 4 +parameter LONG_SEGMENTS = 4; // Now exactly 4 segments! +parameter SHORT_SEGMENTS = 1; // 50 samples padded to 1024 + +// ========== FIXED INTERNAL SIGNALS ========== +reg signed [31:0] pc_i, pc_q; +reg pc_valid; + +// Dual buffer for overlap-save +reg signed [15:0] input_buffer_i [0:BUFFER_SIZE-1]; +reg signed [15:0] input_buffer_q [0:BUFFER_SIZE-1]; +reg [10:0] buffer_write_ptr; +reg [10:0] buffer_read_ptr; +reg buffer_has_data; +reg buffer_processing; +reg [15:0] chirp_samples_collected; + +// State machine +reg [3:0] state; +localparam ST_IDLE = 0; +localparam ST_COLLECT_DATA = 1; +localparam ST_ZERO_PAD = 2; +localparam ST_WAIT_REF = 3; +localparam ST_PROCESSING = 4; +localparam ST_WAIT_FFT = 5; +localparam ST_OUTPUT = 6; +localparam ST_NEXT_SEGMENT = 7; + +// Segment tracking +reg [2:0] current_segment; // 0-3 +reg [2:0] total_segments; +reg segment_done; +reg chirp_complete; + +// Microcontroller sync detection +reg mc_new_chirp_prev, mc_new_elevation_prev, mc_new_azimuth_prev; +wire chirp_start_pulse = mc_new_chirp && !mc_new_chirp_prev; +wire elevation_change_pulse = mc_new_elevation && !mc_new_elevation_prev; +wire azimuth_change_pulse = mc_new_azimuth && !mc_new_azimuth_prev; + +// Processing chain signals +wire [15:0] fft_pc_i, fft_pc_q; +wire fft_pc_valid; +wire [3:0] fft_chain_state; + +// Buffer for FFT input +reg [15:0] fft_input_i, fft_input_q; +reg fft_input_valid; +reg fft_start; + +// ========== SAMPLE ADDRESS OUTPUT ========== +assign sample_addr_out = buffer_read_ptr; + +// ========== MICROCONTROLLER SYNC ========== +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + mc_new_chirp_prev <= 1'b0; + mc_new_elevation_prev <= 1'b0; + mc_new_azimuth_prev <= 1'b0; + end else begin + mc_new_chirp_prev <= mc_new_chirp; + mc_new_elevation_prev <= mc_new_elevation; + mc_new_azimuth_prev <= mc_new_azimuth; + end +end + +// ========== BUFFER INITIALIZATION ========== +integer buf_init; +initial begin + for (buf_init = 0; buf_init < BUFFER_SIZE; buf_init = buf_init + 1) begin + input_buffer_i[buf_init] = 16'd0; + input_buffer_q[buf_init] = 16'd0; + end +end + +// ========== FIXED STATE MACHINE WITH OVERLAP-SAVE ========== +integer i; +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + state <= ST_IDLE; + buffer_write_ptr <= 0; + buffer_read_ptr <= 0; + buffer_has_data <= 0; + buffer_processing <= 0; + current_segment <= 0; + segment_done <= 0; + segment_request <= 0; + mem_request <= 0; + pc_valid <= 0; + status <= 0; + chirp_samples_collected <= 0; + chirp_complete <= 0; + fft_input_valid <= 0; + fft_start <= 0; + end else begin + pc_valid <= 0; + mem_request <= 0; + fft_input_valid <= 0; + + case (state) + ST_IDLE: begin + // Reset for new chirp + buffer_write_ptr <= 0; + buffer_read_ptr <= 0; + buffer_has_data <= 0; + buffer_processing <= 0; + current_segment <= 0; + segment_done <= 0; + chirp_samples_collected <= 0; + chirp_complete <= 0; + + // Wait for chirp start from microcontroller + if (chirp_start_pulse) begin + state <= ST_COLLECT_DATA; + total_segments <= use_long_chirp ? LONG_SEGMENTS[2:0] : SHORT_SEGMENTS[2:0]; + + $display("[MULTI_SEG_FIXED] Starting %s chirp, segments: %d", + use_long_chirp ? "LONG" : "SHORT", + use_long_chirp ? LONG_SEGMENTS : SHORT_SEGMENTS); + $display("[MULTI_SEG_FIXED] Overlap: %d samples, Advance: %d samples", + OVERLAP_SAMPLES, SEGMENT_ADVANCE); + end + end + + ST_COLLECT_DATA: begin + // Collect samples for current segment with overlap-save + if (ddc_valid) begin + // Store in buffer + input_buffer_i[buffer_write_ptr] <= ddc_i[17:2] + ddc_i[1]; + input_buffer_q[buffer_write_ptr] <= ddc_q[17:2] + ddc_q[1]; + + buffer_write_ptr <= buffer_write_ptr + 1; + chirp_samples_collected <= chirp_samples_collected + 1; + + // Debug: Show first few samples + if (chirp_samples_collected < 10 && buffer_write_ptr < 10) begin + $display("[MULTI_SEG_FIXED] Store[%0d]: I=%h Q=%h", + buffer_write_ptr, + ddc_i[17:2] + ddc_i[1], + ddc_q[17:2] + ddc_q[1]); + end + + // Check conditions based on chirp type + if (use_long_chirp) begin + // LONG CHIRP: Process when we have SEGMENT_ADVANCE new samples + // (buffer contains overlap from previous segment + new data) + + // Check if we have enough NEW data to process + if (buffer_write_ptr >= SEGMENT_ADVANCE) begin + buffer_has_data <= 1; + state <= ST_WAIT_REF; + segment_request <= current_segment[1:0]; // Use lower 2 bits + mem_request <= 1; + + $display("[MULTI_SEG_FIXED] Segment %d ready: %d samples collected", + current_segment, chirp_samples_collected); + end + + // Check if end of chirp reached + if (chirp_samples_collected >= LONG_CHIRP_SAMPLES - 1) begin + chirp_complete <= 1; + $display("[MULTI_SEG_FIXED] End of long chirp reached"); + end + end else begin + // SHORT CHIRP: Only 50 samples, then zero-pad + if (chirp_samples_collected >= SHORT_CHIRP_SAMPLES - 1) begin + state <= ST_ZERO_PAD; + $display("[MULTI_SEG_FIXED] Short chirp: collected %d samples, starting zero-pad", + chirp_samples_collected + 1); + end + end + end + end + + ST_ZERO_PAD: begin + // For short chirp: zero-pad remaining buffer + input_buffer_i[buffer_write_ptr] <= 16'd0; + input_buffer_q[buffer_write_ptr] <= 16'd0; + buffer_write_ptr <= buffer_write_ptr + 1; + + if (buffer_write_ptr >= BUFFER_SIZE - 1) begin + // Done zero-padding + buffer_has_data <= 1; + buffer_write_ptr <= 0; + state <= ST_WAIT_REF; + segment_request <= 0; // Only one segment for short chirp + mem_request <= 1; + $display("[MULTI_SEG_FIXED] Zero-pad complete, buffer full"); + end + end + + ST_WAIT_REF: begin + // Wait for memory to provide reference coefficients + if (mem_ready) begin + // Start processing + buffer_processing <= 1; + buffer_read_ptr <= 0; + fft_start <= 1; + state <= ST_PROCESSING; + + $display("[MULTI_SEG_FIXED] Reference ready, starting processing segment %d", + current_segment); + end + end + + ST_PROCESSING: begin + // Feed data to FFT chain + if ((buffer_processing) && (buffer_read_ptr < BUFFER_SIZE)) begin + // 1. Feed ADC data to FFT + fft_input_i <= input_buffer_i[buffer_read_ptr]; + fft_input_q <= input_buffer_q[buffer_read_ptr]; + fft_input_valid <= 1; + + // 2. Request corresponding reference sample + mem_request <= 1'b1; + + // Debug every 100 samples + if (buffer_read_ptr % 100 == 0) begin + $display("[MULTI_SEG_FIXED] Processing[%0d]: ADC I=%h Q=%h", + buffer_read_ptr, + input_buffer_i[buffer_read_ptr], + input_buffer_q[buffer_read_ptr]); + end + + buffer_read_ptr <= buffer_read_ptr + 1; + + end else if (buffer_read_ptr >= BUFFER_SIZE) begin + // Done feeding buffer + fft_input_valid <= 0; + mem_request <= 0; + buffer_processing <= 0; + buffer_has_data <= 0; + state <= ST_WAIT_FFT; // CRITICAL: Wait for FFT completion + + $display("[MULTI_SEG_FIXED] Finished feeding %d samples to FFT, waiting...", + BUFFER_SIZE); + end + end + + ST_WAIT_FFT: begin + // Wait for the processing chain to complete (2159 cycles latency) + if (fft_pc_valid) begin + state <= ST_OUTPUT; + $display("[MULTI_SEG_FIXED] FFT processing complete for segment %d", + current_segment); + end + end + + ST_OUTPUT: begin + // Store FFT output + pc_i <= fft_pc_i; + pc_q <= fft_pc_q; + pc_valid <= 1; + segment_done <= 1; + + $display("[MULTI_SEG_FIXED] Output segment %d: I=%h Q=%h", + current_segment, fft_pc_i, fft_pc_q); + + // Check if we need more segments + if (current_segment < total_segments - 1 || !chirp_complete) begin + state <= ST_NEXT_SEGMENT; + end else begin + // All segments complete + state <= ST_IDLE; + $display("[MULTI_SEG_FIXED] All %d segments complete", + total_segments); + end + end + + ST_NEXT_SEGMENT: begin + // Prepare for next segment with OVERLAP-SAVE + current_segment <= current_segment + 1; + segment_done <= 0; + + if (use_long_chirp) begin + // OVERLAP-SAVE: Keep last OVERLAP_SAMPLES for next segment + // Shift data in buffer to preserve overlap + + for (i = 0; i < OVERLAP_SAMPLES; i = i + 1) begin + input_buffer_i[i] <= input_buffer_i[i + SEGMENT_ADVANCE]; + input_buffer_q[i] <= input_buffer_q[i + SEGMENT_ADVANCE]; + end + + // Start writing after the overlap + buffer_write_ptr <= OVERLAP_SAMPLES; + + $display("[MULTI_SEG_FIXED] Overlap-save: kept %d samples, write_ptr=%d", + OVERLAP_SAMPLES, OVERLAP_SAMPLES); + end else begin + // Short chirp: only one segment + buffer_write_ptr <= 0; + end + + // Continue collecting or finish + if (!chirp_complete) begin + state <= ST_COLLECT_DATA; + $display("[MULTI_SEG_FIXED] Starting segment %d/%d", + current_segment + 1, total_segments); + end else begin + state <= ST_IDLE; + end + end + endcase + + // Update status + status <= {state[2:0], use_long_chirp}; + end +end + +// ========== PROCESSING CHAIN INSTANTIATION ========== +matched_filter_processing_chain m_f_p_c( + .clk(clk), + .reset_n(reset_n), + + // Input ADC Data + .adc_data_i(fft_input_i), + .adc_data_q(fft_input_q), + .adc_valid(fft_input_valid),// && buffer_processing), + + // Chirp Selection + .chirp_counter(chirp_counter), + + // Reference Chirp Memory Interfaces + .long_chirp_real(long_chirp_real), + .long_chirp_imag(long_chirp_imag), + .short_chirp_real(short_chirp_real), + .short_chirp_imag(short_chirp_imag), + + // Output + .range_profile_i(fft_pc_i), + .range_profile_q(fft_pc_q), + .range_profile_valid(fft_pc_valid), + + // Status + .chain_state(fft_chain_state) +); + +// ========== DEBUG MONITOR ========== +reg [31:0] dbg_cycles; +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + dbg_cycles <= 0; + end else begin + dbg_cycles <= dbg_cycles + 1; + + // Monitor state transitions + if (dbg_cycles % 1000 == 0 && state != ST_IDLE) begin + $display("[MULTI_SEG_MONITOR @%0d] state=%0d, segment=%0d/%0d, samples=%0d", + dbg_cycles, state, current_segment, total_segments, + chirp_samples_collected); + end + end +end + +// ========== OUTPUT CONNECTIONS ========== +assign pc_i_w = fft_pc_i; +assign pc_q_w = fft_pc_q; +assign pc_valid_w = fft_pc_valid; + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/nco_400m_enhanced.v b/9_Firmware/9_2_FPGA/nco_400m_enhanced.v new file mode 100644 index 0000000..896efcf --- /dev/null +++ b/9_Firmware/9_2_FPGA/nco_400m_enhanced.v @@ -0,0 +1,117 @@ +`timescale 1ns / 1ps + +module nco_400m_enhanced ( + input wire clk_400m, + input wire reset_n, + input wire [31:0] frequency_tuning_word, + input wire phase_valid, + input wire [15:0] phase_offset, + output reg signed [15:0] sin_out, + output reg signed [15:0] cos_out, + output reg dds_ready +); + +// Phase accumulator with registered outputs for better timing +reg [31:0] phase_accumulator; +reg [31:0] phase_accumulator_reg; +reg [31:0] phase_with_offset; +reg phase_valid_delayed; + +// Use only the top 8 bits for LUT addressing (256-entry LUT equivalent) +wire [7:0] lut_address = phase_with_offset[31:24]; + +// Quarter-wave sine LUT (0-90 degrees only) +reg [15:0] sin_lut [0:63]; // 64 entries for 0-90 degrees + +// Initialize sine LUT +integer lut_init_i; +initial begin + for (lut_init_i = 0; lut_init_i < 64; lut_init_i = lut_init_i + 1) begin + sin_lut[lut_init_i] = 16'h0000; + end + + // Initialize quarter-wave sine LUT (0-90 degrees) + sin_lut[0] = 16'h0000; sin_lut[1] = 16'h0324; sin_lut[2] = 16'h0647; sin_lut[3] = 16'h096A; + sin_lut[4] = 16'h0C8B; sin_lut[5] = 16'h0FA9; sin_lut[6] = 16'h12C4; sin_lut[7] = 16'h15DB; + sin_lut[8] = 16'h18EC; sin_lut[9] = 16'h1BF8; sin_lut[10] = 16'h1EFC; sin_lut[11] = 16'h21F8; + sin_lut[12] = 16'h24EB; sin_lut[13] = 16'h27D4; sin_lut[14] = 16'h2AB1; sin_lut[15] = 16'h2D82; + sin_lut[16] = 16'h3045; sin_lut[17] = 16'h32F9; sin_lut[18] = 16'h359D; sin_lut[19] = 16'h3830; + sin_lut[20] = 16'h3AB1; sin_lut[21] = 16'h3D1E; sin_lut[22] = 16'h3F76; sin_lut[23] = 16'h41B8; + sin_lut[24] = 16'h43E3; sin_lut[25] = 16'h45F5; sin_lut[26] = 16'h47EE; sin_lut[27] = 16'h49CD; + sin_lut[28] = 16'h4B90; sin_lut[29] = 16'h4D37; sin_lut[30] = 16'h4EC1; sin_lut[31] = 16'h502D; + sin_lut[32] = 16'h517A; sin_lut[33] = 16'h52A8; sin_lut[34] = 16'h53B6; sin_lut[35] = 16'h54A4; + sin_lut[36] = 16'h5572; sin_lut[37] = 16'h561F; sin_lut[38] = 16'h56AA; sin_lut[39] = 16'h5715; + sin_lut[40] = 16'h575E; sin_lut[41] = 16'h5785; sin_lut[42] = 16'h578B; sin_lut[43] = 16'h576E; + sin_lut[44] = 16'h5730; sin_lut[45] = 16'h56D0; sin_lut[46] = 16'h564E; sin_lut[47] = 16'h55AB; + sin_lut[48] = 16'h54E7; sin_lut[49] = 16'h5403; sin_lut[50] = 16'h52FE; sin_lut[51] = 16'h51DA; + sin_lut[52] = 16'h5096; sin_lut[53] = 16'h4F34; sin_lut[54] = 16'h4DB4; sin_lut[55] = 16'h4C17; + sin_lut[56] = 16'h4A5E; sin_lut[57] = 16'h4889; sin_lut[58] = 16'h4699; sin_lut[59] = 16'h448F; + sin_lut[60] = 16'h426B; sin_lut[61] = 16'h402F; sin_lut[62] = 16'h3DDB; sin_lut[63] = 16'h3B71; +end + +// Quadrant determination +wire [1:0] quadrant = lut_address[7:6]; // 00: Q1, 01: Q2, 10: Q3, 11: Q4 +wire [5:0] lut_index = (quadrant[1] ? ~lut_address[5:0] : lut_address[5:0]); // Mirror for Q2/Q3 + +// Sine and cosine calculation with quadrant mapping +wire [15:0] sin_abs = sin_lut[lut_index]; +wire [15:0] cos_abs = sin_lut[63 - lut_index]; // Cosine is phase-shifted sine + +// Pipeline stage for better timing +always @(posedge clk_400m or negedge reset_n) begin + if (!reset_n) begin + phase_accumulator <= 32'h00000000; + phase_accumulator_reg <= 32'h00000000; + phase_with_offset <= 32'h00000000; + phase_valid_delayed <= 1'b0; + dds_ready <= 1'b0; + sin_out <= 16'h0000; + cos_out <= 16'h7FFF; + end else begin + phase_valid_delayed <= phase_valid; + + if (phase_valid) begin + // Update phase accumulator with dithered frequency tuning word + phase_accumulator <= phase_accumulator + frequency_tuning_word; + phase_accumulator_reg <= phase_accumulator; + + // Apply phase offset + phase_with_offset <= phase_accumulator + {phase_offset, 16'b0}; + dds_ready <= 1'b1; + end else begin + dds_ready <= 1'b0; + end + + // Generate outputs with one cycle delay for pipelining + if (phase_valid_delayed) begin + // Calculate sine and cosine with proper quadrant signs + case (quadrant) + 2'b00: begin // Quadrant I: sin+, cos+ + sin_out <= sin_abs; + cos_out <= cos_abs; + end + 2'b01: begin // Quadrant II: sin+, cos- + sin_out <= sin_abs; + cos_out <= -cos_abs; + end + 2'b10: begin // Quadrant III: sin-, cos- + sin_out <= -sin_abs; + cos_out <= -cos_abs; + end + 2'b11: begin // Quadrant IV: sin-, cos+ + sin_out <= -sin_abs; + cos_out <= cos_abs; + end + endcase + end + end +end + +// Add this to ensure LUT is properly loaded: +initial begin + // Wait a small amount of time for LUT initialization + #10; + $display("NCO: Sine LUT initialized with %0d entries", 64); +end + +endmodule diff --git a/9_Firmware/9_2_FPGA/plfm_chirp_controller.v b/9_Firmware/9_2_FPGA/plfm_chirp_controller.v new file mode 100644 index 0000000..29f0e96 --- /dev/null +++ b/9_Firmware/9_2_FPGA/plfm_chirp_controller.v @@ -0,0 +1,801 @@ +`timescale 1ns / 1ps + +module plfm_chirp_controller_enhanced ( + input wire clk_120m, + input wire clk_100m, + input wire reset_n, + input wire new_chirp, + input wire new_elevation, + input wire new_azimuth, + input wire mixers_enable, + output reg [7:0] chirp_data, + output reg chirp_valid, + output wire new_chirp_frame, + output reg chirp_done, + output reg rf_switch_ctrl, + output wire rx_mixer_en, + output wire tx_mixer_en, + output wire adar_tx_load_1, + output wire adar_rx_load_1, + output wire adar_tx_load_2, + output wire adar_rx_load_2, + output wire adar_tx_load_3, + output wire adar_rx_load_3, + output wire adar_tx_load_4, + output wire adar_rx_load_4, + output reg adar_tr_1, + output reg adar_tr_2, + output reg adar_tr_3, + output reg adar_tr_4, + output reg [5:0] chirp_counter, + output reg [5:0] elevation_counter, + output reg [5:0] azimuth_counter +); + +// Chirp parameters +parameter F_START = 30000000; // 30 MHz (starting frequency) +parameter F_END = 10000000; // 10 MHz (ending frequency) +parameter FS = 120000000; // 120 MHz + +// Timing parameters +parameter T1_SAMPLES = 3600; // 30us at 120MHz +parameter T1_RADAR_LISTENING = 16440; //137us at 120MHz +parameter T2_SAMPLES = 60; // 0.5us at 120MHz +parameter T2_RADAR_LISTENING = 20940; //174.5us at 120MHz +parameter GUARD_SAMPLES = 21048; // 175.4us at 120MHz + +// Chirp and beam parameters +parameter CHIRP_MAX = 32; +parameter ELEVATION_MAX = 31; +parameter AZIMUTH_MAX = 50; + +// State parameters +parameter IDLE = 3'b000; +parameter LONG_CHIRP = 3'b001; +parameter LONG_LISTEN = 3'b010; +parameter GUARD_TIME = 3'b011; +parameter SHORT_CHIRP = 3'b100; +parameter SHORT_LISTEN = 3'b101; +parameter DONE = 3'b110; + +reg [2:0] current_state; +reg [2:0] next_state; + +// Control registers +reg [15:0] sample_counter; + +// Edge detection for input signals +wire chirp__toggling, elevation__toggling, azimuth__toggling; + +// LUTs for chirp waveforms +reg [7:0] long_chirp_lut [0:3599]; // T1_SAMPLES-1 +reg [7:0] short_chirp_lut [0:59]; // T2_SAMPLES-1 + +// Edge detection +assign chirp__toggling = new_chirp; +assign elevation__toggling = new_elevation; +assign azimuth__toggling = new_azimuth; +assign new_chirp_frame = (current_state == IDLE && next_state == LONG_CHIRP); + +// Mixers Enabling +assign rx_mixer_en = mixers_enable; +assign tx_mixer_en = mixers_enable; + +// ADTR1000 pull to ground tx and rx load pins if not used +assign adar_tx_load_1 = 1'b0; +assign adar_rx_load_1 = 1'b0; +assign adar_tx_load_2 = 1'b0; +assign adar_rx_load_2 = 1'b0; +assign adar_tx_load_3 = 1'b0; +assign adar_rx_load_3 = 1'b0; +assign adar_tx_load_4 = 1'b0; +assign adar_rx_load_4 = 1'b0; + + + + +// LUT Initialization - Complete short chirp LUT +// Long PLFM chirp LUT (30us, 30MHz to 10MHz) +initial begin + long_chirp_lut[ 0] = 8'd255; long_chirp_lut[ 1] = 8'd237; long_chirp_lut[ 2] = 8'd191; long_chirp_lut[ 3] = 8'd127; long_chirp_lut[ 4] = 8'd 64; long_chirp_lut[ 5] = 8'd 17; long_chirp_lut[ 6] = 8'd 1; long_chirp_lut[ 7] = 8'd 18; + long_chirp_lut[ 8] = 8'd 65; long_chirp_lut[ 9] = 8'd129; long_chirp_lut[ 10] = 8'd193; long_chirp_lut[ 11] = 8'd239; long_chirp_lut[ 12] = 8'd254; long_chirp_lut[ 13] = 8'd236; long_chirp_lut[ 14] = 8'd188; long_chirp_lut[ 15] = 8'd123; + long_chirp_lut[ 16] = 8'd 60; long_chirp_lut[ 17] = 8'd 15; long_chirp_lut[ 18] = 8'd 1; long_chirp_lut[ 19] = 8'd 21; long_chirp_lut[ 20] = 8'd 71; long_chirp_lut[ 21] = 8'd136; long_chirp_lut[ 22] = 8'd199; long_chirp_lut[ 23] = 8'd242; + long_chirp_lut[ 24] = 8'd254; long_chirp_lut[ 25] = 8'd231; long_chirp_lut[ 26] = 8'd180; long_chirp_lut[ 27] = 8'd114; long_chirp_lut[ 28] = 8'd 52; long_chirp_lut[ 29] = 8'd 11; long_chirp_lut[ 30] = 8'd 2; long_chirp_lut[ 31] = 8'd 27; + long_chirp_lut[ 32] = 8'd 81; long_chirp_lut[ 33] = 8'd148; long_chirp_lut[ 34] = 8'd209; long_chirp_lut[ 35] = 8'd247; long_chirp_lut[ 36] = 8'd252; long_chirp_lut[ 37] = 8'd223; long_chirp_lut[ 38] = 8'd167; long_chirp_lut[ 39] = 8'd100; + long_chirp_lut[ 40] = 8'd 40; long_chirp_lut[ 41] = 8'd 5; long_chirp_lut[ 42] = 8'd 5; long_chirp_lut[ 43] = 8'd 38; long_chirp_lut[ 44] = 8'd 97; long_chirp_lut[ 45] = 8'd164; long_chirp_lut[ 46] = 8'd221; long_chirp_lut[ 47] = 8'd252; + long_chirp_lut[ 48] = 8'd247; long_chirp_lut[ 49] = 8'd209; long_chirp_lut[ 50] = 8'd148; long_chirp_lut[ 51] = 8'd 81; long_chirp_lut[ 52] = 8'd 27; long_chirp_lut[ 53] = 8'd 1; long_chirp_lut[ 54] = 8'd 12; long_chirp_lut[ 55] = 8'd 55; + long_chirp_lut[ 56] = 8'd119; long_chirp_lut[ 57] = 8'd185; long_chirp_lut[ 58] = 8'd235; long_chirp_lut[ 59] = 8'd254; long_chirp_lut[ 60] = 8'd237; long_chirp_lut[ 61] = 8'd189; long_chirp_lut[ 62] = 8'd123; long_chirp_lut[ 63] = 8'd 58; + long_chirp_lut[ 64] = 8'd 13; long_chirp_lut[ 65] = 8'd 1; long_chirp_lut[ 66] = 8'd 25; long_chirp_lut[ 67] = 8'd 79; long_chirp_lut[ 68] = 8'd146; long_chirp_lut[ 69] = 8'd209; long_chirp_lut[ 70] = 8'd247; long_chirp_lut[ 71] = 8'd252; + long_chirp_lut[ 72] = 8'd220; long_chirp_lut[ 73] = 8'd162; long_chirp_lut[ 74] = 8'd 93; long_chirp_lut[ 75] = 8'd 35; long_chirp_lut[ 76] = 8'd 3; long_chirp_lut[ 77] = 8'd 8; long_chirp_lut[ 78] = 8'd 47; long_chirp_lut[ 79] = 8'd110; + long_chirp_lut[ 80] = 8'd178; long_chirp_lut[ 81] = 8'd231; long_chirp_lut[ 82] = 8'd254; long_chirp_lut[ 83] = 8'd240; long_chirp_lut[ 84] = 8'd193; long_chirp_lut[ 85] = 8'd127; long_chirp_lut[ 86] = 8'd 61; long_chirp_lut[ 87] = 8'd 14; + long_chirp_lut[ 88] = 8'd 1; long_chirp_lut[ 89] = 8'd 25; long_chirp_lut[ 90] = 8'd 79; long_chirp_lut[ 91] = 8'd147; long_chirp_lut[ 92] = 8'd210; long_chirp_lut[ 93] = 8'd248; long_chirp_lut[ 94] = 8'd251; long_chirp_lut[ 95] = 8'd217; + long_chirp_lut[ 96] = 8'd157; long_chirp_lut[ 97] = 8'd 87; long_chirp_lut[ 98] = 8'd 30; long_chirp_lut[ 99] = 8'd 2; long_chirp_lut[ 100] = 8'd 11; long_chirp_lut[ 101] = 8'd 55; long_chirp_lut[ 102] = 8'd120; long_chirp_lut[ 103] = 8'd188; + long_chirp_lut[ 104] = 8'd238; long_chirp_lut[ 105] = 8'd254; long_chirp_lut[ 106] = 8'd233; long_chirp_lut[ 107] = 8'd180; long_chirp_lut[ 108] = 8'd112; long_chirp_lut[ 109] = 8'd 48; long_chirp_lut[ 110] = 8'd 8; long_chirp_lut[ 111] = 8'd 4; + long_chirp_lut[ 112] = 8'd 37; long_chirp_lut[ 113] = 8'd 98; long_chirp_lut[ 114] = 8'd167; long_chirp_lut[ 115] = 8'd225; long_chirp_lut[ 116] = 8'd253; long_chirp_lut[ 117] = 8'd243; long_chirp_lut[ 118] = 8'd198; long_chirp_lut[ 119] = 8'd132; + long_chirp_lut[ 120] = 8'd 64; long_chirp_lut[ 121] = 8'd 15; long_chirp_lut[ 122] = 8'd 1; long_chirp_lut[ 123] = 8'd 25; long_chirp_lut[ 124] = 8'd 80; long_chirp_lut[ 125] = 8'd150; long_chirp_lut[ 126] = 8'd213; long_chirp_lut[ 127] = 8'd250; + long_chirp_lut[ 128] = 8'd249; long_chirp_lut[ 129] = 8'd211; long_chirp_lut[ 130] = 8'd148; long_chirp_lut[ 131] = 8'd 78; long_chirp_lut[ 132] = 8'd 23; long_chirp_lut[ 133] = 8'd 1; long_chirp_lut[ 134] = 8'd 17; long_chirp_lut[ 135] = 8'd 68; + long_chirp_lut[ 136] = 8'd137; long_chirp_lut[ 137] = 8'd203; long_chirp_lut[ 138] = 8'd246; long_chirp_lut[ 139] = 8'd252; long_chirp_lut[ 140] = 8'd220; long_chirp_lut[ 141] = 8'd159; long_chirp_lut[ 142] = 8'd 88; long_chirp_lut[ 143] = 8'd 30; + long_chirp_lut[ 144] = 8'd 2; long_chirp_lut[ 145] = 8'd 13; long_chirp_lut[ 146] = 8'd 60; long_chirp_lut[ 147] = 8'd128; long_chirp_lut[ 148] = 8'd196; long_chirp_lut[ 149] = 8'd243; long_chirp_lut[ 150] = 8'd253; long_chirp_lut[ 151] = 8'd225; + long_chirp_lut[ 152] = 8'd166; long_chirp_lut[ 153] = 8'd 94; long_chirp_lut[ 154] = 8'd 34; long_chirp_lut[ 155] = 8'd 2; long_chirp_lut[ 156] = 8'd 10; long_chirp_lut[ 157] = 8'd 55; long_chirp_lut[ 158] = 8'd123; long_chirp_lut[ 159] = 8'd192; + long_chirp_lut[ 160] = 8'd241; long_chirp_lut[ 161] = 8'd254; long_chirp_lut[ 162] = 8'd227; long_chirp_lut[ 163] = 8'd168; long_chirp_lut[ 164] = 8'd 96; long_chirp_lut[ 165] = 8'd 35; long_chirp_lut[ 166] = 8'd 3; long_chirp_lut[ 167] = 8'd 10; + long_chirp_lut[ 168] = 8'd 55; long_chirp_lut[ 169] = 8'd123; long_chirp_lut[ 170] = 8'd193; long_chirp_lut[ 171] = 8'd241; long_chirp_lut[ 172] = 8'd254; long_chirp_lut[ 173] = 8'd226; long_chirp_lut[ 174] = 8'd166; long_chirp_lut[ 175] = 8'd 94; + long_chirp_lut[ 176] = 8'd 33; long_chirp_lut[ 177] = 8'd 2; long_chirp_lut[ 178] = 8'd 12; long_chirp_lut[ 179] = 8'd 58; long_chirp_lut[ 180] = 8'd128; long_chirp_lut[ 181] = 8'd197; long_chirp_lut[ 182] = 8'd244; long_chirp_lut[ 183] = 8'd253; + long_chirp_lut[ 184] = 8'd222; long_chirp_lut[ 185] = 8'd160; long_chirp_lut[ 186] = 8'd 88; long_chirp_lut[ 187] = 8'd 28; long_chirp_lut[ 188] = 8'd 1; long_chirp_lut[ 189] = 8'd 15; long_chirp_lut[ 190] = 8'd 66; long_chirp_lut[ 191] = 8'd136; + long_chirp_lut[ 192] = 8'd204; long_chirp_lut[ 193] = 8'd247; long_chirp_lut[ 194] = 8'd251; long_chirp_lut[ 195] = 8'd214; long_chirp_lut[ 196] = 8'd149; long_chirp_lut[ 197] = 8'd 77; long_chirp_lut[ 198] = 8'd 21; long_chirp_lut[ 199] = 8'd 1; + long_chirp_lut[ 200] = 8'd 21; long_chirp_lut[ 201] = 8'd 77; long_chirp_lut[ 202] = 8'd150; long_chirp_lut[ 203] = 8'd215; long_chirp_lut[ 204] = 8'd251; long_chirp_lut[ 205] = 8'd247; long_chirp_lut[ 206] = 8'd203; long_chirp_lut[ 207] = 8'd134; + long_chirp_lut[ 208] = 8'd 63; long_chirp_lut[ 209] = 8'd 13; long_chirp_lut[ 210] = 8'd 2; long_chirp_lut[ 211] = 8'd 32; long_chirp_lut[ 212] = 8'd 94; long_chirp_lut[ 213] = 8'd167; long_chirp_lut[ 214] = 8'd227; long_chirp_lut[ 215] = 8'd254; + long_chirp_lut[ 216] = 8'd239; long_chirp_lut[ 217] = 8'd186; long_chirp_lut[ 218] = 8'd114; long_chirp_lut[ 219] = 8'd 46; long_chirp_lut[ 220] = 8'd 6; long_chirp_lut[ 221] = 8'd 6; long_chirp_lut[ 222] = 8'd 47; long_chirp_lut[ 223] = 8'd115; + long_chirp_lut[ 224] = 8'd187; long_chirp_lut[ 225] = 8'd240; long_chirp_lut[ 226] = 8'd254; long_chirp_lut[ 227] = 8'd226; long_chirp_lut[ 228] = 8'd164; long_chirp_lut[ 229] = 8'd 90; long_chirp_lut[ 230] = 8'd 29; long_chirp_lut[ 231] = 8'd 1; + long_chirp_lut[ 232] = 8'd 16; long_chirp_lut[ 233] = 8'd 69; long_chirp_lut[ 234] = 8'd141; long_chirp_lut[ 235] = 8'd209; long_chirp_lut[ 236] = 8'd250; long_chirp_lut[ 237] = 8'd248; long_chirp_lut[ 238] = 8'd206; long_chirp_lut[ 239] = 8'd136; + long_chirp_lut[ 240] = 8'd 64; long_chirp_lut[ 241] = 8'd 13; long_chirp_lut[ 242] = 8'd 2; long_chirp_lut[ 243] = 8'd 33; long_chirp_lut[ 244] = 8'd 97; long_chirp_lut[ 245] = 8'd171; long_chirp_lut[ 246] = 8'd231; long_chirp_lut[ 247] = 8'd254; + long_chirp_lut[ 248] = 8'd235; long_chirp_lut[ 249] = 8'd178; long_chirp_lut[ 250] = 8'd104; long_chirp_lut[ 251] = 8'd 38; long_chirp_lut[ 252] = 8'd 3; long_chirp_lut[ 253] = 8'd 11; long_chirp_lut[ 254] = 8'd 60; long_chirp_lut[ 255] = 8'd132; + long_chirp_lut[ 256] = 8'd202; long_chirp_lut[ 257] = 8'd247; long_chirp_lut[ 258] = 8'd250; long_chirp_lut[ 259] = 8'd211; long_chirp_lut[ 260] = 8'd142; long_chirp_lut[ 261] = 8'd 69; long_chirp_lut[ 262] = 8'd 15; long_chirp_lut[ 263] = 8'd 1; + long_chirp_lut[ 264] = 8'd 31; long_chirp_lut[ 265] = 8'd 95; long_chirp_lut[ 266] = 8'd170; long_chirp_lut[ 267] = 8'd230; long_chirp_lut[ 268] = 8'd254; long_chirp_lut[ 269] = 8'd234; long_chirp_lut[ 270] = 8'd176; long_chirp_lut[ 271] = 8'd101; + long_chirp_lut[ 272] = 8'd 35; long_chirp_lut[ 273] = 8'd 2; long_chirp_lut[ 274] = 8'd 13; long_chirp_lut[ 275] = 8'd 64; long_chirp_lut[ 276] = 8'd138; long_chirp_lut[ 277] = 8'd208; long_chirp_lut[ 278] = 8'd250; long_chirp_lut[ 279] = 8'd248; + long_chirp_lut[ 280] = 8'd203; long_chirp_lut[ 281] = 8'd132; long_chirp_lut[ 282] = 8'd 59; long_chirp_lut[ 283] = 8'd 10; long_chirp_lut[ 284] = 8'd 3; long_chirp_lut[ 285] = 8'd 41; long_chirp_lut[ 286] = 8'd109; long_chirp_lut[ 287] = 8'd184; + long_chirp_lut[ 288] = 8'd239; long_chirp_lut[ 289] = 8'd254; long_chirp_lut[ 290] = 8'd224; long_chirp_lut[ 291] = 8'd159; long_chirp_lut[ 292] = 8'd 83; long_chirp_lut[ 293] = 8'd 23; long_chirp_lut[ 294] = 8'd 1; long_chirp_lut[ 295] = 8'd 24; + long_chirp_lut[ 296] = 8'd 84; long_chirp_lut[ 297] = 8'd161; long_chirp_lut[ 298] = 8'd225; long_chirp_lut[ 299] = 8'd254; long_chirp_lut[ 300] = 8'd237; long_chirp_lut[ 301] = 8'd181; long_chirp_lut[ 302] = 8'd105; long_chirp_lut[ 303] = 8'd 38; + long_chirp_lut[ 304] = 8'd 2; long_chirp_lut[ 305] = 8'd 13; long_chirp_lut[ 306] = 8'd 65; long_chirp_lut[ 307] = 8'd139; long_chirp_lut[ 308] = 8'd210; long_chirp_lut[ 309] = 8'd251; long_chirp_lut[ 310] = 8'd246; long_chirp_lut[ 311] = 8'd199; + long_chirp_lut[ 312] = 8'd125; long_chirp_lut[ 313] = 8'd 52; long_chirp_lut[ 314] = 8'd 7; long_chirp_lut[ 315] = 8'd 6; long_chirp_lut[ 316] = 8'd 50; long_chirp_lut[ 317] = 8'd122; long_chirp_lut[ 318] = 8'd196; long_chirp_lut[ 319] = 8'd245; + long_chirp_lut[ 320] = 8'd251; long_chirp_lut[ 321] = 8'd211; long_chirp_lut[ 322] = 8'd141; long_chirp_lut[ 323] = 8'd 65; long_chirp_lut[ 324] = 8'd 13; long_chirp_lut[ 325] = 8'd 3; long_chirp_lut[ 326] = 8'd 39; long_chirp_lut[ 327] = 8'd108; + long_chirp_lut[ 328] = 8'd184; long_chirp_lut[ 329] = 8'd240; long_chirp_lut[ 330] = 8'd253; long_chirp_lut[ 331] = 8'd220; long_chirp_lut[ 332] = 8'd153; long_chirp_lut[ 333] = 8'd 76; long_chirp_lut[ 334] = 8'd 18; long_chirp_lut[ 335] = 8'd 1; + long_chirp_lut[ 336] = 8'd 31; long_chirp_lut[ 337] = 8'd 98; long_chirp_lut[ 338] = 8'd175; long_chirp_lut[ 339] = 8'd235; long_chirp_lut[ 340] = 8'd254; long_chirp_lut[ 341] = 8'd226; long_chirp_lut[ 342] = 8'd161; long_chirp_lut[ 343] = 8'd 83; + long_chirp_lut[ 344] = 8'd 22; long_chirp_lut[ 345] = 8'd 1; long_chirp_lut[ 346] = 8'd 27; long_chirp_lut[ 347] = 8'd 91; long_chirp_lut[ 348] = 8'd169; long_chirp_lut[ 349] = 8'd232; long_chirp_lut[ 350] = 8'd254; long_chirp_lut[ 351] = 8'd229; + long_chirp_lut[ 352] = 8'd166; long_chirp_lut[ 353] = 8'd 87; long_chirp_lut[ 354] = 8'd 24; long_chirp_lut[ 355] = 8'd 1; long_chirp_lut[ 356] = 8'd 25; long_chirp_lut[ 357] = 8'd 88; long_chirp_lut[ 358] = 8'd167; long_chirp_lut[ 359] = 8'd230; + long_chirp_lut[ 360] = 8'd255; long_chirp_lut[ 361] = 8'd230; long_chirp_lut[ 362] = 8'd167; long_chirp_lut[ 363] = 8'd 88; long_chirp_lut[ 364] = 8'd 25; long_chirp_lut[ 365] = 8'd 1; long_chirp_lut[ 366] = 8'd 25; long_chirp_lut[ 367] = 8'd 89; + long_chirp_lut[ 368] = 8'd168; long_chirp_lut[ 369] = 8'd231; long_chirp_lut[ 370] = 8'd254; long_chirp_lut[ 371] = 8'd229; long_chirp_lut[ 372] = 8'd164; long_chirp_lut[ 373] = 8'd 85; long_chirp_lut[ 374] = 8'd 23; long_chirp_lut[ 375] = 8'd 1; + long_chirp_lut[ 376] = 8'd 28; long_chirp_lut[ 377] = 8'd 93; long_chirp_lut[ 378] = 8'd172; long_chirp_lut[ 379] = 8'd234; long_chirp_lut[ 380] = 8'd254; long_chirp_lut[ 381] = 8'd225; long_chirp_lut[ 382] = 8'd158; long_chirp_lut[ 383] = 8'd 79; + long_chirp_lut[ 384] = 8'd 19; long_chirp_lut[ 385] = 8'd 1; long_chirp_lut[ 386] = 8'd 33; long_chirp_lut[ 387] = 8'd101; long_chirp_lut[ 388] = 8'd180; long_chirp_lut[ 389] = 8'd239; long_chirp_lut[ 390] = 8'd253; long_chirp_lut[ 391] = 8'd219; + long_chirp_lut[ 392] = 8'd148; long_chirp_lut[ 393] = 8'd 70; long_chirp_lut[ 394] = 8'd 14; long_chirp_lut[ 395] = 8'd 3; long_chirp_lut[ 396] = 8'd 41; long_chirp_lut[ 397] = 8'd113; long_chirp_lut[ 398] = 8'd191; long_chirp_lut[ 399] = 8'd244; + long_chirp_lut[ 400] = 8'd251; long_chirp_lut[ 401] = 8'd209; long_chirp_lut[ 402] = 8'd135; long_chirp_lut[ 403] = 8'd 58; long_chirp_lut[ 404] = 8'd 8; long_chirp_lut[ 405] = 8'd 6; long_chirp_lut[ 406] = 8'd 52; long_chirp_lut[ 407] = 8'd128; + long_chirp_lut[ 408] = 8'd204; long_chirp_lut[ 409] = 8'd250; long_chirp_lut[ 410] = 8'd246; long_chirp_lut[ 411] = 8'd195; long_chirp_lut[ 412] = 8'd117; long_chirp_lut[ 413] = 8'd 43; long_chirp_lut[ 414] = 8'd 3; long_chirp_lut[ 415] = 8'd 13; + long_chirp_lut[ 416] = 8'd 68; long_chirp_lut[ 417] = 8'd148; long_chirp_lut[ 418] = 8'd219; long_chirp_lut[ 419] = 8'd254; long_chirp_lut[ 420] = 8'd237; long_chirp_lut[ 421] = 8'd177; long_chirp_lut[ 422] = 8'd 97; long_chirp_lut[ 423] = 8'd 29; + long_chirp_lut[ 424] = 8'd 1; long_chirp_lut[ 425] = 8'd 24; long_chirp_lut[ 426] = 8'd 89; long_chirp_lut[ 427] = 8'd170; long_chirp_lut[ 428] = 8'd233; long_chirp_lut[ 429] = 8'd254; long_chirp_lut[ 430] = 8'd224; long_chirp_lut[ 431] = 8'd154; + long_chirp_lut[ 432] = 8'd 73; long_chirp_lut[ 433] = 8'd 15; long_chirp_lut[ 434] = 8'd 2; long_chirp_lut[ 435] = 8'd 41; long_chirp_lut[ 436] = 8'd115; long_chirp_lut[ 437] = 8'd194; long_chirp_lut[ 438] = 8'd246; long_chirp_lut[ 439] = 8'd250; + long_chirp_lut[ 440] = 8'd203; long_chirp_lut[ 441] = 8'd126; long_chirp_lut[ 442] = 8'd 49; long_chirp_lut[ 443] = 8'd 5; long_chirp_lut[ 444] = 8'd 10; long_chirp_lut[ 445] = 8'd 64; long_chirp_lut[ 446] = 8'd144; long_chirp_lut[ 447] = 8'd217; + long_chirp_lut[ 448] = 8'd253; long_chirp_lut[ 449] = 8'd237; long_chirp_lut[ 450] = 8'd176; long_chirp_lut[ 451] = 8'd 95; long_chirp_lut[ 452] = 8'd 27; long_chirp_lut[ 453] = 8'd 1; long_chirp_lut[ 454] = 8'd 27; long_chirp_lut[ 455] = 8'd 95; + long_chirp_lut[ 456] = 8'd177; long_chirp_lut[ 457] = 8'd238; long_chirp_lut[ 458] = 8'd253; long_chirp_lut[ 459] = 8'd216; long_chirp_lut[ 460] = 8'd142; long_chirp_lut[ 461] = 8'd 62; long_chirp_lut[ 462] = 8'd 9; long_chirp_lut[ 463] = 8'd 6; + long_chirp_lut[ 464] = 8'd 53; long_chirp_lut[ 465] = 8'd132; long_chirp_lut[ 466] = 8'd209; long_chirp_lut[ 467] = 8'd251; long_chirp_lut[ 468] = 8'd242; long_chirp_lut[ 469] = 8'd185; long_chirp_lut[ 470] = 8'd104; long_chirp_lut[ 471] = 8'd 32; + long_chirp_lut[ 472] = 8'd 1; long_chirp_lut[ 473] = 8'd 23; long_chirp_lut[ 474] = 8'd 89; long_chirp_lut[ 475] = 8'd171; long_chirp_lut[ 476] = 8'd235; long_chirp_lut[ 477] = 8'd254; long_chirp_lut[ 478] = 8'd219; long_chirp_lut[ 479] = 8'd145; + long_chirp_lut[ 480] = 8'd 64; long_chirp_lut[ 481] = 8'd 10; long_chirp_lut[ 482] = 8'd 5; long_chirp_lut[ 483] = 8'd 53; long_chirp_lut[ 484] = 8'd132; long_chirp_lut[ 485] = 8'd209; long_chirp_lut[ 486] = 8'd252; long_chirp_lut[ 487] = 8'd241; + long_chirp_lut[ 488] = 8'd182; long_chirp_lut[ 489] = 8'd100; long_chirp_lut[ 490] = 8'd 29; long_chirp_lut[ 491] = 8'd 1; long_chirp_lut[ 492] = 8'd 26; long_chirp_lut[ 493] = 8'd 96; long_chirp_lut[ 494] = 8'd178; long_chirp_lut[ 495] = 8'd240; + long_chirp_lut[ 496] = 8'd253; long_chirp_lut[ 497] = 8'd212; long_chirp_lut[ 498] = 8'd135; long_chirp_lut[ 499] = 8'd 55; long_chirp_lut[ 500] = 8'd 6; long_chirp_lut[ 501] = 8'd 9; long_chirp_lut[ 502] = 8'd 64; long_chirp_lut[ 503] = 8'd146; + long_chirp_lut[ 504] = 8'd220; long_chirp_lut[ 505] = 8'd254; long_chirp_lut[ 506] = 8'd233; long_chirp_lut[ 507] = 8'd167; long_chirp_lut[ 508] = 8'd 83; long_chirp_lut[ 509] = 8'd 19; long_chirp_lut[ 510] = 8'd 2; long_chirp_lut[ 511] = 8'd 39; + long_chirp_lut[ 512] = 8'd115; long_chirp_lut[ 513] = 8'd197; long_chirp_lut[ 514] = 8'd248; long_chirp_lut[ 515] = 8'd247; long_chirp_lut[ 516] = 8'd193; long_chirp_lut[ 517] = 8'd111; long_chirp_lut[ 518] = 8'd 36; long_chirp_lut[ 519] = 8'd 1; + long_chirp_lut[ 520] = 8'd 21; long_chirp_lut[ 521] = 8'd 88; long_chirp_lut[ 522] = 8'd172; long_chirp_lut[ 523] = 8'd237; long_chirp_lut[ 524] = 8'd253; long_chirp_lut[ 525] = 8'd214; long_chirp_lut[ 526] = 8'd137; long_chirp_lut[ 527] = 8'd 56; + long_chirp_lut[ 528] = 8'd 6; long_chirp_lut[ 529] = 8'd 10; long_chirp_lut[ 530] = 8'd 66; long_chirp_lut[ 531] = 8'd149; long_chirp_lut[ 532] = 8'd223; long_chirp_lut[ 533] = 8'd254; long_chirp_lut[ 534] = 8'd230; long_chirp_lut[ 535] = 8'd160; + long_chirp_lut[ 536] = 8'd 76; long_chirp_lut[ 537] = 8'd 14; long_chirp_lut[ 538] = 8'd 3; long_chirp_lut[ 539] = 8'd 48; long_chirp_lut[ 540] = 8'd127; long_chirp_lut[ 541] = 8'd207; long_chirp_lut[ 542] = 8'd252; long_chirp_lut[ 543] = 8'd241; + long_chirp_lut[ 544] = 8'd179; long_chirp_lut[ 545] = 8'd 94; long_chirp_lut[ 546] = 8'd 24; long_chirp_lut[ 547] = 8'd 1; long_chirp_lut[ 548] = 8'd 34; long_chirp_lut[ 549] = 8'd109; long_chirp_lut[ 550] = 8'd193; long_chirp_lut[ 551] = 8'd247; + long_chirp_lut[ 552] = 8'd247; long_chirp_lut[ 553] = 8'd194; long_chirp_lut[ 554] = 8'd111; long_chirp_lut[ 555] = 8'd 35; long_chirp_lut[ 556] = 8'd 1; long_chirp_lut[ 557] = 8'd 24; long_chirp_lut[ 558] = 8'd 94; long_chirp_lut[ 559] = 8'd179; + long_chirp_lut[ 560] = 8'd241; long_chirp_lut[ 561] = 8'd251; long_chirp_lut[ 562] = 8'd206; long_chirp_lut[ 563] = 8'd124; long_chirp_lut[ 564] = 8'd 45; long_chirp_lut[ 565] = 8'd 2; long_chirp_lut[ 566] = 8'd 17; long_chirp_lut[ 567] = 8'd 82; + long_chirp_lut[ 568] = 8'd168; long_chirp_lut[ 569] = 8'd235; long_chirp_lut[ 570] = 8'd253; long_chirp_lut[ 571] = 8'd214; long_chirp_lut[ 572] = 8'd135; long_chirp_lut[ 573] = 8'd 53; long_chirp_lut[ 574] = 8'd 4; long_chirp_lut[ 575] = 8'd 13; + long_chirp_lut[ 576] = 8'd 73; long_chirp_lut[ 577] = 8'd159; long_chirp_lut[ 578] = 8'd230; long_chirp_lut[ 579] = 8'd254; long_chirp_lut[ 580] = 8'd220; long_chirp_lut[ 581] = 8'd143; long_chirp_lut[ 582] = 8'd 59; long_chirp_lut[ 583] = 8'd 6; + long_chirp_lut[ 584] = 8'd 10; long_chirp_lut[ 585] = 8'd 68; long_chirp_lut[ 586] = 8'd153; long_chirp_lut[ 587] = 8'd227; long_chirp_lut[ 588] = 8'd254; long_chirp_lut[ 589] = 8'd223; long_chirp_lut[ 590] = 8'd148; long_chirp_lut[ 591] = 8'd 63; + long_chirp_lut[ 592] = 8'd 8; long_chirp_lut[ 593] = 8'd 8; long_chirp_lut[ 594] = 8'd 65; long_chirp_lut[ 595] = 8'd150; long_chirp_lut[ 596] = 8'd225; long_chirp_lut[ 597] = 8'd254; long_chirp_lut[ 598] = 8'd225; long_chirp_lut[ 599] = 8'd150; + long_chirp_lut[ 600] = 8'd 64; long_chirp_lut[ 601] = 8'd 8; long_chirp_lut[ 602] = 8'd 8; long_chirp_lut[ 603] = 8'd 64; long_chirp_lut[ 604] = 8'd150; long_chirp_lut[ 605] = 8'd225; long_chirp_lut[ 606] = 8'd254; long_chirp_lut[ 607] = 8'd224; + long_chirp_lut[ 608] = 8'd148; long_chirp_lut[ 609] = 8'd 63; long_chirp_lut[ 610] = 8'd 8; long_chirp_lut[ 611] = 8'd 9; long_chirp_lut[ 612] = 8'd 66; long_chirp_lut[ 613] = 8'd153; long_chirp_lut[ 614] = 8'd227; long_chirp_lut[ 615] = 8'd254; + long_chirp_lut[ 616] = 8'd222; long_chirp_lut[ 617] = 8'd144; long_chirp_lut[ 618] = 8'd 59; long_chirp_lut[ 619] = 8'd 6; long_chirp_lut[ 620] = 8'd 11; long_chirp_lut[ 621] = 8'd 71; long_chirp_lut[ 622] = 8'd158; long_chirp_lut[ 623] = 8'd231; + long_chirp_lut[ 624] = 8'd254; long_chirp_lut[ 625] = 8'd217; long_chirp_lut[ 626] = 8'd137; long_chirp_lut[ 627] = 8'd 53; long_chirp_lut[ 628] = 8'd 4; long_chirp_lut[ 629] = 8'd 14; long_chirp_lut[ 630] = 8'd 79; long_chirp_lut[ 631] = 8'd167; + long_chirp_lut[ 632] = 8'd236; long_chirp_lut[ 633] = 8'd253; long_chirp_lut[ 634] = 8'd210; long_chirp_lut[ 635] = 8'd127; long_chirp_lut[ 636] = 8'd 45; long_chirp_lut[ 637] = 8'd 2; long_chirp_lut[ 638] = 8'd 20; long_chirp_lut[ 639] = 8'd 90; + long_chirp_lut[ 640] = 8'd178; long_chirp_lut[ 641] = 8'd242; long_chirp_lut[ 642] = 8'd250; long_chirp_lut[ 643] = 8'd200; long_chirp_lut[ 644] = 8'd114; long_chirp_lut[ 645] = 8'd 35; long_chirp_lut[ 646] = 8'd 1; long_chirp_lut[ 647] = 8'd 28; + long_chirp_lut[ 648] = 8'd104; long_chirp_lut[ 649] = 8'd191; long_chirp_lut[ 650] = 8'd247; long_chirp_lut[ 651] = 8'd246; long_chirp_lut[ 652] = 8'd186; long_chirp_lut[ 653] = 8'd 98; long_chirp_lut[ 654] = 8'd 24; long_chirp_lut[ 655] = 8'd 1; + long_chirp_lut[ 656] = 8'd 39; long_chirp_lut[ 657] = 8'd121; long_chirp_lut[ 658] = 8'd206; long_chirp_lut[ 659] = 8'd252; long_chirp_lut[ 660] = 8'd237; long_chirp_lut[ 661] = 8'd169; long_chirp_lut[ 662] = 8'd 80; long_chirp_lut[ 663] = 8'd 14; + long_chirp_lut[ 664] = 8'd 4; long_chirp_lut[ 665] = 8'd 55; long_chirp_lut[ 666] = 8'd141; long_chirp_lut[ 667] = 8'd221; long_chirp_lut[ 668] = 8'd254; long_chirp_lut[ 669] = 8'd225; long_chirp_lut[ 670] = 8'd148; long_chirp_lut[ 671] = 8'd 60; + long_chirp_lut[ 672] = 8'd 6; long_chirp_lut[ 673] = 8'd 12; long_chirp_lut[ 674] = 8'd 75; long_chirp_lut[ 675] = 8'd164; long_chirp_lut[ 676] = 8'd235; long_chirp_lut[ 677] = 8'd253; long_chirp_lut[ 678] = 8'd208; long_chirp_lut[ 679] = 8'd123; + long_chirp_lut[ 680] = 8'd 40; long_chirp_lut[ 681] = 8'd 1; long_chirp_lut[ 682] = 8'd 25; long_chirp_lut[ 683] = 8'd100; long_chirp_lut[ 684] = 8'd189; long_chirp_lut[ 685] = 8'd247; long_chirp_lut[ 686] = 8'd246; long_chirp_lut[ 687] = 8'd185; + long_chirp_lut[ 688] = 8'd 96; long_chirp_lut[ 689] = 8'd 22; long_chirp_lut[ 690] = 8'd 2; long_chirp_lut[ 691] = 8'd 44; long_chirp_lut[ 692] = 8'd129; long_chirp_lut[ 693] = 8'd213; long_chirp_lut[ 694] = 8'd254; long_chirp_lut[ 695] = 8'd231; + long_chirp_lut[ 696] = 8'd157; long_chirp_lut[ 697] = 8'd 67; long_chirp_lut[ 698] = 8'd 8; long_chirp_lut[ 699] = 8'd 9; long_chirp_lut[ 700] = 8'd 71; long_chirp_lut[ 701] = 8'd160; long_chirp_lut[ 702] = 8'd234; long_chirp_lut[ 703] = 8'd253; + long_chirp_lut[ 704] = 8'd209; long_chirp_lut[ 705] = 8'd123; long_chirp_lut[ 706] = 8'd 40; long_chirp_lut[ 707] = 8'd 1; long_chirp_lut[ 708] = 8'd 26; long_chirp_lut[ 709] = 8'd103; long_chirp_lut[ 710] = 8'd193; long_chirp_lut[ 711] = 8'd249; + long_chirp_lut[ 712] = 8'd243; long_chirp_lut[ 713] = 8'd178; long_chirp_lut[ 714] = 8'd 88; long_chirp_lut[ 715] = 8'd 17; long_chirp_lut[ 716] = 8'd 3; long_chirp_lut[ 717] = 8'd 53; long_chirp_lut[ 718] = 8'd141; long_chirp_lut[ 719] = 8'd222; + long_chirp_lut[ 720] = 8'd255; long_chirp_lut[ 721] = 8'd222; long_chirp_lut[ 722] = 8'd141; long_chirp_lut[ 723] = 8'd 53; long_chirp_lut[ 724] = 8'd 3; long_chirp_lut[ 725] = 8'd 18; long_chirp_lut[ 726] = 8'd 89; long_chirp_lut[ 727] = 8'd180; + long_chirp_lut[ 728] = 8'd244; long_chirp_lut[ 729] = 8'd248; long_chirp_lut[ 730] = 8'd189; long_chirp_lut[ 731] = 8'd 99; long_chirp_lut[ 732] = 8'd 23; long_chirp_lut[ 733] = 8'd 2; long_chirp_lut[ 734] = 8'd 45; long_chirp_lut[ 735] = 8'd132; + long_chirp_lut[ 736] = 8'd216; long_chirp_lut[ 737] = 8'd254; long_chirp_lut[ 738] = 8'd227; long_chirp_lut[ 739] = 8'd147; long_chirp_lut[ 740] = 8'd 58; long_chirp_lut[ 741] = 8'd 4; long_chirp_lut[ 742] = 8'd 15; long_chirp_lut[ 743] = 8'd 85; + long_chirp_lut[ 744] = 8'd177; long_chirp_lut[ 745] = 8'd243; long_chirp_lut[ 746] = 8'd249; long_chirp_lut[ 747] = 8'd191; long_chirp_lut[ 748] = 8'd100; long_chirp_lut[ 749] = 8'd 23; long_chirp_lut[ 750] = 8'd 2; long_chirp_lut[ 751] = 8'd 46; + long_chirp_lut[ 752] = 8'd133; long_chirp_lut[ 753] = 8'd217; long_chirp_lut[ 754] = 8'd254; long_chirp_lut[ 755] = 8'd224; long_chirp_lut[ 756] = 8'd143; long_chirp_lut[ 757] = 8'd 54; long_chirp_lut[ 758] = 8'd 3; long_chirp_lut[ 759] = 8'd 18; + long_chirp_lut[ 760] = 8'd 91; long_chirp_lut[ 761] = 8'd183; long_chirp_lut[ 762] = 8'd246; long_chirp_lut[ 763] = 8'd246; long_chirp_lut[ 764] = 8'd183; long_chirp_lut[ 765] = 8'd 91; long_chirp_lut[ 766] = 8'd 18; long_chirp_lut[ 767] = 8'd 3; + long_chirp_lut[ 768] = 8'd 55; long_chirp_lut[ 769] = 8'd145; long_chirp_lut[ 770] = 8'd226; long_chirp_lut[ 771] = 8'd254; long_chirp_lut[ 772] = 8'd215; long_chirp_lut[ 773] = 8'd129; long_chirp_lut[ 774] = 8'd 42; long_chirp_lut[ 775] = 8'd 1; + long_chirp_lut[ 776] = 8'd 28; long_chirp_lut[ 777] = 8'd108; long_chirp_lut[ 778] = 8'd199; long_chirp_lut[ 779] = 8'd251; long_chirp_lut[ 780] = 8'd237; long_chirp_lut[ 781] = 8'd165; long_chirp_lut[ 782] = 8'd 72; long_chirp_lut[ 783] = 8'd 9; + long_chirp_lut[ 784] = 8'd 10; long_chirp_lut[ 785] = 8'd 74; long_chirp_lut[ 786] = 8'd167; long_chirp_lut[ 787] = 8'd239; long_chirp_lut[ 788] = 8'd250; long_chirp_lut[ 789] = 8'd195; long_chirp_lut[ 790] = 8'd104; long_chirp_lut[ 791] = 8'd 25; + long_chirp_lut[ 792] = 8'd 2; long_chirp_lut[ 793] = 8'd 47; long_chirp_lut[ 794] = 8'd136; long_chirp_lut[ 795] = 8'd220; long_chirp_lut[ 796] = 8'd254; long_chirp_lut[ 797] = 8'd220; long_chirp_lut[ 798] = 8'd135; long_chirp_lut[ 799] = 8'd 46; + long_chirp_lut[ 800] = 8'd 1; long_chirp_lut[ 801] = 8'd 26; long_chirp_lut[ 802] = 8'd106; long_chirp_lut[ 803] = 8'd197; long_chirp_lut[ 804] = 8'd251; long_chirp_lut[ 805] = 8'd237; long_chirp_lut[ 806] = 8'd163; long_chirp_lut[ 807] = 8'd 70; + long_chirp_lut[ 808] = 8'd 8; long_chirp_lut[ 809] = 8'd 11; long_chirp_lut[ 810] = 8'd 79; long_chirp_lut[ 811] = 8'd173; long_chirp_lut[ 812] = 8'd242; long_chirp_lut[ 813] = 8'd248; long_chirp_lut[ 814] = 8'd188; long_chirp_lut[ 815] = 8'd 94; + long_chirp_lut[ 816] = 8'd 19; long_chirp_lut[ 817] = 8'd 3; long_chirp_lut[ 818] = 8'd 57; long_chirp_lut[ 819] = 8'd149; long_chirp_lut[ 820] = 8'd229; long_chirp_lut[ 821] = 8'd254; long_chirp_lut[ 822] = 8'd208; long_chirp_lut[ 823] = 8'd118; + long_chirp_lut[ 824] = 8'd 33; long_chirp_lut[ 825] = 8'd 1; long_chirp_lut[ 826] = 8'd 39; long_chirp_lut[ 827] = 8'd126; long_chirp_lut[ 828] = 8'd214; long_chirp_lut[ 829] = 8'd254; long_chirp_lut[ 830] = 8'd224; long_chirp_lut[ 831] = 8'd139; + long_chirp_lut[ 832] = 8'd 48; long_chirp_lut[ 833] = 8'd 2; long_chirp_lut[ 834] = 8'd 25; long_chirp_lut[ 835] = 8'd106; long_chirp_lut[ 836] = 8'd199; long_chirp_lut[ 837] = 8'd252; long_chirp_lut[ 838] = 8'd235; long_chirp_lut[ 839] = 8'd158; + long_chirp_lut[ 840] = 8'd 64; long_chirp_lut[ 841] = 8'd 5; long_chirp_lut[ 842] = 8'd 15; long_chirp_lut[ 843] = 8'd 88; long_chirp_lut[ 844] = 8'd183; long_chirp_lut[ 845] = 8'd247; long_chirp_lut[ 846] = 8'd243; long_chirp_lut[ 847] = 8'd174; + long_chirp_lut[ 848] = 8'd 79; long_chirp_lut[ 849] = 8'd 11; long_chirp_lut[ 850] = 8'd 9; long_chirp_lut[ 851] = 8'd 74; long_chirp_lut[ 852] = 8'd169; long_chirp_lut[ 853] = 8'd241; long_chirp_lut[ 854] = 8'd249; long_chirp_lut[ 855] = 8'd187; + long_chirp_lut[ 856] = 8'd 92; long_chirp_lut[ 857] = 8'd 17; long_chirp_lut[ 858] = 8'd 5; long_chirp_lut[ 859] = 8'd 62; long_chirp_lut[ 860] = 8'd157; long_chirp_lut[ 861] = 8'd235; long_chirp_lut[ 862] = 8'd252; long_chirp_lut[ 863] = 8'd198; + long_chirp_lut[ 864] = 8'd104; long_chirp_lut[ 865] = 8'd 23; long_chirp_lut[ 866] = 8'd 2; long_chirp_lut[ 867] = 8'd 53; long_chirp_lut[ 868] = 8'd146; long_chirp_lut[ 869] = 8'd229; long_chirp_lut[ 870] = 8'd253; long_chirp_lut[ 871] = 8'd206; + long_chirp_lut[ 872] = 8'd113; long_chirp_lut[ 873] = 8'd 29; long_chirp_lut[ 874] = 8'd 1; long_chirp_lut[ 875] = 8'd 46; long_chirp_lut[ 876] = 8'd138; long_chirp_lut[ 877] = 8'd224; long_chirp_lut[ 878] = 8'd254; long_chirp_lut[ 879] = 8'd211; + long_chirp_lut[ 880] = 8'd120; long_chirp_lut[ 881] = 8'd 33; long_chirp_lut[ 882] = 8'd 1; long_chirp_lut[ 883] = 8'd 42; long_chirp_lut[ 884] = 8'd132; long_chirp_lut[ 885] = 8'd220; long_chirp_lut[ 886] = 8'd254; long_chirp_lut[ 887] = 8'd215; + long_chirp_lut[ 888] = 8'd125; long_chirp_lut[ 889] = 8'd 36; long_chirp_lut[ 890] = 8'd 1; long_chirp_lut[ 891] = 8'd 39; long_chirp_lut[ 892] = 8'd129; long_chirp_lut[ 893] = 8'd218; long_chirp_lut[ 894] = 8'd254; long_chirp_lut[ 895] = 8'd217; + long_chirp_lut[ 896] = 8'd127; long_chirp_lut[ 897] = 8'd 38; long_chirp_lut[ 898] = 8'd 1; long_chirp_lut[ 899] = 8'd 38; long_chirp_lut[ 900] = 8'd127; long_chirp_lut[ 901] = 8'd217; long_chirp_lut[ 902] = 8'd254; long_chirp_lut[ 903] = 8'd217; + long_chirp_lut[ 904] = 8'd127; long_chirp_lut[ 905] = 8'd 37; long_chirp_lut[ 906] = 8'd 1; long_chirp_lut[ 907] = 8'd 38; long_chirp_lut[ 908] = 8'd129; long_chirp_lut[ 909] = 8'd218; long_chirp_lut[ 910] = 8'd254; long_chirp_lut[ 911] = 8'd216; + long_chirp_lut[ 912] = 8'd125; long_chirp_lut[ 913] = 8'd 36; long_chirp_lut[ 914] = 8'd 1; long_chirp_lut[ 915] = 8'd 41; long_chirp_lut[ 916] = 8'd132; long_chirp_lut[ 917] = 8'd221; long_chirp_lut[ 918] = 8'd254; long_chirp_lut[ 919] = 8'd212; + long_chirp_lut[ 920] = 8'd120; long_chirp_lut[ 921] = 8'd 32; long_chirp_lut[ 922] = 8'd 1; long_chirp_lut[ 923] = 8'd 45; long_chirp_lut[ 924] = 8'd138; long_chirp_lut[ 925] = 8'd225; long_chirp_lut[ 926] = 8'd254; long_chirp_lut[ 927] = 8'd207; + long_chirp_lut[ 928] = 8'd113; long_chirp_lut[ 929] = 8'd 27; long_chirp_lut[ 930] = 8'd 2; long_chirp_lut[ 931] = 8'd 51; long_chirp_lut[ 932] = 8'd146; long_chirp_lut[ 933] = 8'd230; long_chirp_lut[ 934] = 8'd253; long_chirp_lut[ 935] = 8'd200; + long_chirp_lut[ 936] = 8'd104; long_chirp_lut[ 937] = 8'd 22; long_chirp_lut[ 938] = 8'd 3; long_chirp_lut[ 939] = 8'd 60; long_chirp_lut[ 940] = 8'd157; long_chirp_lut[ 941] = 8'd236; long_chirp_lut[ 942] = 8'd250; long_chirp_lut[ 943] = 8'd190; + long_chirp_lut[ 944] = 8'd 92; long_chirp_lut[ 945] = 8'd 15; long_chirp_lut[ 946] = 8'd 6; long_chirp_lut[ 947] = 8'd 71; long_chirp_lut[ 948] = 8'd169; long_chirp_lut[ 949] = 8'd243; long_chirp_lut[ 950] = 8'd246; long_chirp_lut[ 951] = 8'd178; + long_chirp_lut[ 952] = 8'd 79; long_chirp_lut[ 953] = 8'd 9; long_chirp_lut[ 954] = 8'd 12; long_chirp_lut[ 955] = 8'd 84; long_chirp_lut[ 956] = 8'd183; long_chirp_lut[ 957] = 8'd248; long_chirp_lut[ 958] = 8'd240; long_chirp_lut[ 959] = 8'd162; + long_chirp_lut[ 960] = 8'd 64; long_chirp_lut[ 961] = 8'd 4; long_chirp_lut[ 962] = 8'd 20; long_chirp_lut[ 963] = 8'd101; long_chirp_lut[ 964] = 8'd199; long_chirp_lut[ 965] = 8'd253; long_chirp_lut[ 966] = 8'd230; long_chirp_lut[ 967] = 8'd144; + long_chirp_lut[ 968] = 8'd 48; long_chirp_lut[ 969] = 8'd 1; long_chirp_lut[ 970] = 8'd 31; long_chirp_lut[ 971] = 8'd121; long_chirp_lut[ 972] = 8'd214; long_chirp_lut[ 973] = 8'd254; long_chirp_lut[ 974] = 8'd216; long_chirp_lut[ 975] = 8'd123; + long_chirp_lut[ 976] = 8'd 33; long_chirp_lut[ 977] = 8'd 1; long_chirp_lut[ 978] = 8'd 47; long_chirp_lut[ 979] = 8'd143; long_chirp_lut[ 980] = 8'd229; long_chirp_lut[ 981] = 8'd253; long_chirp_lut[ 982] = 8'd198; long_chirp_lut[ 983] = 8'd100; + long_chirp_lut[ 984] = 8'd 19; long_chirp_lut[ 985] = 8'd 5; long_chirp_lut[ 986] = 8'd 67; long_chirp_lut[ 987] = 8'd167; long_chirp_lut[ 988] = 8'd242; long_chirp_lut[ 989] = 8'd246; long_chirp_lut[ 990] = 8'd176; long_chirp_lut[ 991] = 8'd 76; + long_chirp_lut[ 992] = 8'd 8; long_chirp_lut[ 993] = 8'd 14; long_chirp_lut[ 994] = 8'd 92; long_chirp_lut[ 995] = 8'd191; long_chirp_lut[ 996] = 8'd251; long_chirp_lut[ 997] = 8'd234; long_chirp_lut[ 998] = 8'd149; long_chirp_lut[ 999] = 8'd 52; + long_chirp_lut[1000] = 8'd 1; long_chirp_lut[1001] = 8'd 30; long_chirp_lut[1002] = 8'd120; long_chirp_lut[1003] = 8'd215; long_chirp_lut[1004] = 8'd254; long_chirp_lut[1005] = 8'd214; long_chirp_lut[1006] = 8'd119; long_chirp_lut[1007] = 8'd 30; + long_chirp_lut[1008] = 8'd 2; long_chirp_lut[1009] = 8'd 53; long_chirp_lut[1010] = 8'd151; long_chirp_lut[1011] = 8'd235; long_chirp_lut[1012] = 8'd250; long_chirp_lut[1013] = 8'd188; long_chirp_lut[1014] = 8'd 88; long_chirp_lut[1015] = 8'd 12; + long_chirp_lut[1016] = 8'd 10; long_chirp_lut[1017] = 8'd 82; long_chirp_lut[1018] = 8'd183; long_chirp_lut[1019] = 8'd249; long_chirp_lut[1020] = 8'd237; long_chirp_lut[1021] = 8'd156; long_chirp_lut[1022] = 8'd 56; long_chirp_lut[1023] = 8'd 2; + long_chirp_lut[1024] = 8'd 28; long_chirp_lut[1025] = 8'd117; long_chirp_lut[1026] = 8'd213; long_chirp_lut[1027] = 8'd254; long_chirp_lut[1028] = 8'd215; long_chirp_lut[1029] = 8'd119; long_chirp_lut[1030] = 8'd 29; long_chirp_lut[1031] = 8'd 2; + long_chirp_lut[1032] = 8'd 55; long_chirp_lut[1033] = 8'd155; long_chirp_lut[1034] = 8'd237; long_chirp_lut[1035] = 8'd249; long_chirp_lut[1036] = 8'd183; long_chirp_lut[1037] = 8'd 81; long_chirp_lut[1038] = 8'd 9; long_chirp_lut[1039] = 8'd 13; + long_chirp_lut[1040] = 8'd 91; long_chirp_lut[1041] = 8'd192; long_chirp_lut[1042] = 8'd252; long_chirp_lut[1043] = 8'd231; long_chirp_lut[1044] = 8'd143; long_chirp_lut[1045] = 8'd 46; long_chirp_lut[1046] = 8'd 1; long_chirp_lut[1047] = 8'd 38; + long_chirp_lut[1048] = 8'd133; long_chirp_lut[1049] = 8'd225; long_chirp_lut[1050] = 8'd253; long_chirp_lut[1051] = 8'd200; long_chirp_lut[1052] = 8'd100; long_chirp_lut[1053] = 8'd 17; long_chirp_lut[1054] = 8'd 6; long_chirp_lut[1055] = 8'd 74; + long_chirp_lut[1056] = 8'd177; long_chirp_lut[1057] = 8'd247; long_chirp_lut[1058] = 8'd240; long_chirp_lut[1059] = 8'd159; long_chirp_lut[1060] = 8'd 58; long_chirp_lut[1061] = 8'd 2; long_chirp_lut[1062] = 8'd 28; long_chirp_lut[1063] = 8'd120; + long_chirp_lut[1064] = 8'd216; long_chirp_lut[1065] = 8'd254; long_chirp_lut[1066] = 8'd210; long_chirp_lut[1067] = 8'd111; long_chirp_lut[1068] = 8'd 23; long_chirp_lut[1069] = 8'd 4; long_chirp_lut[1070] = 8'd 66; long_chirp_lut[1071] = 8'd168; + long_chirp_lut[1072] = 8'd244; long_chirp_lut[1073] = 8'd243; long_chirp_lut[1074] = 8'd166; long_chirp_lut[1075] = 8'd 64; long_chirp_lut[1076] = 8'd 3; long_chirp_lut[1077] = 8'd 25; long_chirp_lut[1078] = 8'd114; long_chirp_lut[1079] = 8'd212; + long_chirp_lut[1080] = 8'd255; long_chirp_lut[1081] = 8'd212; long_chirp_lut[1082] = 8'd114; long_chirp_lut[1083] = 8'd 25; long_chirp_lut[1084] = 8'd 3; long_chirp_lut[1085] = 8'd 64; long_chirp_lut[1086] = 8'd167; long_chirp_lut[1087] = 8'd244; + long_chirp_lut[1088] = 8'd243; long_chirp_lut[1089] = 8'd165; long_chirp_lut[1090] = 8'd 62; long_chirp_lut[1091] = 8'd 3; long_chirp_lut[1092] = 8'd 26; long_chirp_lut[1093] = 8'd117; long_chirp_lut[1094] = 8'd215; long_chirp_lut[1095] = 8'd254; + long_chirp_lut[1096] = 8'd209; long_chirp_lut[1097] = 8'd109; long_chirp_lut[1098] = 8'd 21; long_chirp_lut[1099] = 8'd 5; long_chirp_lut[1100] = 8'd 71; long_chirp_lut[1101] = 8'd174; long_chirp_lut[1102] = 8'd247; long_chirp_lut[1103] = 8'd239; + long_chirp_lut[1104] = 8'd157; long_chirp_lut[1105] = 8'd 54; long_chirp_lut[1106] = 8'd 1; long_chirp_lut[1107] = 8'd 33; long_chirp_lut[1108] = 8'd129; long_chirp_lut[1109] = 8'd223; long_chirp_lut[1110] = 8'd253; long_chirp_lut[1111] = 8'd199; + long_chirp_lut[1112] = 8'd 96; long_chirp_lut[1113] = 8'd 14; long_chirp_lut[1114] = 8'd 9; long_chirp_lut[1115] = 8'd 84; long_chirp_lut[1116] = 8'd189; long_chirp_lut[1117] = 8'd251; long_chirp_lut[1118] = 8'd230; long_chirp_lut[1119] = 8'd139; + long_chirp_lut[1120] = 8'd 40; long_chirp_lut[1121] = 8'd 1; long_chirp_lut[1122] = 8'd 47; long_chirp_lut[1123] = 8'd148; long_chirp_lut[1124] = 8'd235; long_chirp_lut[1125] = 8'd249; long_chirp_lut[1126] = 8'd180; long_chirp_lut[1127] = 8'd 75; + long_chirp_lut[1128] = 8'd 6; long_chirp_lut[1129] = 8'd 20; long_chirp_lut[1130] = 8'd107; long_chirp_lut[1131] = 8'd209; long_chirp_lut[1132] = 8'd254; long_chirp_lut[1133] = 8'd213; long_chirp_lut[1134] = 8'd114; long_chirp_lut[1135] = 8'd 23; + long_chirp_lut[1136] = 8'd 4; long_chirp_lut[1137] = 8'd 70; long_chirp_lut[1138] = 8'd175; long_chirp_lut[1139] = 8'd248; long_chirp_lut[1140] = 8'd237; long_chirp_lut[1141] = 8'd152; long_chirp_lut[1142] = 8'd 49; long_chirp_lut[1143] = 8'd 1; + long_chirp_lut[1144] = 8'd 39; long_chirp_lut[1145] = 8'd139; long_chirp_lut[1146] = 8'd231; long_chirp_lut[1147] = 8'd251; long_chirp_lut[1148] = 8'd186; long_chirp_lut[1149] = 8'd 81; long_chirp_lut[1150] = 8'd 8; long_chirp_lut[1151] = 8'd 18; + long_chirp_lut[1152] = 8'd104; long_chirp_lut[1153] = 8'd206; long_chirp_lut[1154] = 8'd254; long_chirp_lut[1155] = 8'd214; long_chirp_lut[1156] = 8'd114; long_chirp_lut[1157] = 8'd 23; long_chirp_lut[1158] = 8'd 5; long_chirp_lut[1159] = 8'd 72; + long_chirp_lut[1160] = 8'd178; long_chirp_lut[1161] = 8'd249; long_chirp_lut[1162] = 8'd235; long_chirp_lut[1163] = 8'd146; long_chirp_lut[1164] = 8'd 45; long_chirp_lut[1165] = 8'd 1; long_chirp_lut[1166] = 8'd 45; long_chirp_lut[1167] = 8'd148; + long_chirp_lut[1168] = 8'd236; long_chirp_lut[1169] = 8'd248; long_chirp_lut[1170] = 8'd176; long_chirp_lut[1171] = 8'd 70; long_chirp_lut[1172] = 8'd 4; long_chirp_lut[1173] = 8'd 25; long_chirp_lut[1174] = 8'd118; long_chirp_lut[1175] = 8'd218; + long_chirp_lut[1176] = 8'd254; long_chirp_lut[1177] = 8'd201; long_chirp_lut[1178] = 8'd 97; long_chirp_lut[1179] = 8'd 14; long_chirp_lut[1180] = 8'd 11; long_chirp_lut[1181] = 8'd 90; long_chirp_lut[1182] = 8'd196; long_chirp_lut[1183] = 8'd253; + long_chirp_lut[1184] = 8'd222; long_chirp_lut[1185] = 8'd123; long_chirp_lut[1186] = 8'd 28; long_chirp_lut[1187] = 8'd 3; long_chirp_lut[1188] = 8'd 66; long_chirp_lut[1189] = 8'd173; long_chirp_lut[1190] = 8'd247; long_chirp_lut[1191] = 8'd237; + long_chirp_lut[1192] = 8'd148; long_chirp_lut[1193] = 8'd 45; long_chirp_lut[1194] = 8'd 1; long_chirp_lut[1195] = 8'd 46; long_chirp_lut[1196] = 8'd150; long_chirp_lut[1197] = 8'd238; long_chirp_lut[1198] = 8'd247; long_chirp_lut[1199] = 8'd171; + long_chirp_lut[1200] = 8'd 64; long_chirp_lut[1201] = 8'd 2; long_chirp_lut[1202] = 8'd 30; long_chirp_lut[1203] = 8'd128; long_chirp_lut[1204] = 8'd225; long_chirp_lut[1205] = 8'd252; long_chirp_lut[1206] = 8'd190; long_chirp_lut[1207] = 8'd 83; + long_chirp_lut[1208] = 8'd 8; long_chirp_lut[1209] = 8'd 18; long_chirp_lut[1210] = 8'd107; long_chirp_lut[1211] = 8'd211; long_chirp_lut[1212] = 8'd254; long_chirp_lut[1213] = 8'd207; long_chirp_lut[1214] = 8'd102; long_chirp_lut[1215] = 8'd 15; + long_chirp_lut[1216] = 8'd 10; long_chirp_lut[1217] = 8'd 89; long_chirp_lut[1218] = 8'd196; long_chirp_lut[1219] = 8'd254; long_chirp_lut[1220] = 8'd220; long_chirp_lut[1221] = 8'd119; long_chirp_lut[1222] = 8'd 25; long_chirp_lut[1223] = 8'd 4; + long_chirp_lut[1224] = 8'd 73; long_chirp_lut[1225] = 8'd182; long_chirp_lut[1226] = 8'd251; long_chirp_lut[1227] = 8'd230; long_chirp_lut[1228] = 8'd135; long_chirp_lut[1229] = 8'd 35; long_chirp_lut[1230] = 8'd 2; long_chirp_lut[1231] = 8'd 60; + long_chirp_lut[1232] = 8'd168; long_chirp_lut[1233] = 8'd246; long_chirp_lut[1234] = 8'd238; long_chirp_lut[1235] = 8'd149; long_chirp_lut[1236] = 8'd 45; long_chirp_lut[1237] = 8'd 1; long_chirp_lut[1238] = 8'd 49; long_chirp_lut[1239] = 8'd155; + long_chirp_lut[1240] = 8'd241; long_chirp_lut[1241] = 8'd244; long_chirp_lut[1242] = 8'd161; long_chirp_lut[1243] = 8'd 54; long_chirp_lut[1244] = 8'd 1; long_chirp_lut[1245] = 8'd 41; long_chirp_lut[1246] = 8'd144; long_chirp_lut[1247] = 8'd236; + long_chirp_lut[1248] = 8'd247; long_chirp_lut[1249] = 8'd171; long_chirp_lut[1250] = 8'd 62; long_chirp_lut[1251] = 8'd 2; long_chirp_lut[1252] = 8'd 34; long_chirp_lut[1253] = 8'd135; long_chirp_lut[1254] = 8'd231; long_chirp_lut[1255] = 8'd250; + long_chirp_lut[1256] = 8'd179; long_chirp_lut[1257] = 8'd 70; long_chirp_lut[1258] = 8'd 3; long_chirp_lut[1259] = 8'd 29; long_chirp_lut[1260] = 8'd127; long_chirp_lut[1261] = 8'd226; long_chirp_lut[1262] = 8'd252; long_chirp_lut[1263] = 8'd185; + long_chirp_lut[1264] = 8'd 76; long_chirp_lut[1265] = 8'd 5; long_chirp_lut[1266] = 8'd 25; long_chirp_lut[1267] = 8'd122; long_chirp_lut[1268] = 8'd223; long_chirp_lut[1269] = 8'd253; long_chirp_lut[1270] = 8'd189; long_chirp_lut[1271] = 8'd 80; + long_chirp_lut[1272] = 8'd 6; long_chirp_lut[1273] = 8'd 23; long_chirp_lut[1274] = 8'd118; long_chirp_lut[1275] = 8'd220; long_chirp_lut[1276] = 8'd253; long_chirp_lut[1277] = 8'd192; long_chirp_lut[1278] = 8'd 83; long_chirp_lut[1279] = 8'd 7; + long_chirp_lut[1280] = 8'd 21; long_chirp_lut[1281] = 8'd116; long_chirp_lut[1282] = 8'd219; long_chirp_lut[1283] = 8'd253; long_chirp_lut[1284] = 8'd193; long_chirp_lut[1285] = 8'd 84; long_chirp_lut[1286] = 8'd 7; long_chirp_lut[1287] = 8'd 21; + long_chirp_lut[1288] = 8'd115; long_chirp_lut[1289] = 8'd219; long_chirp_lut[1290] = 8'd253; long_chirp_lut[1291] = 8'd193; long_chirp_lut[1292] = 8'd 83; long_chirp_lut[1293] = 8'd 7; long_chirp_lut[1294] = 8'd 22; long_chirp_lut[1295] = 8'd117; + long_chirp_lut[1296] = 8'd220; long_chirp_lut[1297] = 8'd253; long_chirp_lut[1298] = 8'd191; long_chirp_lut[1299] = 8'd 81; long_chirp_lut[1300] = 8'd 6; long_chirp_lut[1301] = 8'd 23; long_chirp_lut[1302] = 8'd120; long_chirp_lut[1303] = 8'd222; + long_chirp_lut[1304] = 8'd253; long_chirp_lut[1305] = 8'd187; long_chirp_lut[1306] = 8'd 77; long_chirp_lut[1307] = 8'd 5; long_chirp_lut[1308] = 8'd 26; long_chirp_lut[1309] = 8'd125; long_chirp_lut[1310] = 8'd226; long_chirp_lut[1311] = 8'd251; + long_chirp_lut[1312] = 8'd182; long_chirp_lut[1313] = 8'd 71; long_chirp_lut[1314] = 8'd 3; long_chirp_lut[1315] = 8'd 31; long_chirp_lut[1316] = 8'd132; long_chirp_lut[1317] = 8'd230; long_chirp_lut[1318] = 8'd250; long_chirp_lut[1319] = 8'd175; + long_chirp_lut[1320] = 8'd 64; long_chirp_lut[1321] = 8'd 2; long_chirp_lut[1322] = 8'd 36; long_chirp_lut[1323] = 8'd141; long_chirp_lut[1324] = 8'd235; long_chirp_lut[1325] = 8'd247; long_chirp_lut[1326] = 8'd166; long_chirp_lut[1327] = 8'd 56; + long_chirp_lut[1328] = 8'd 1; long_chirp_lut[1329] = 8'd 44; long_chirp_lut[1330] = 8'd151; long_chirp_lut[1331] = 8'd241; long_chirp_lut[1332] = 8'd242; long_chirp_lut[1333] = 8'd155; long_chirp_lut[1334] = 8'd 46; long_chirp_lut[1335] = 8'd 1; + long_chirp_lut[1336] = 8'd 53; long_chirp_lut[1337] = 8'd163; long_chirp_lut[1338] = 8'd246; long_chirp_lut[1339] = 8'd236; long_chirp_lut[1340] = 8'd142; long_chirp_lut[1341] = 8'd 37; long_chirp_lut[1342] = 8'd 2; long_chirp_lut[1343] = 8'd 65; + long_chirp_lut[1344] = 8'd177; long_chirp_lut[1345] = 8'd250; long_chirp_lut[1346] = 8'd228; long_chirp_lut[1347] = 8'd127; long_chirp_lut[1348] = 8'd 27; long_chirp_lut[1349] = 8'd 5; long_chirp_lut[1350] = 8'd 79; long_chirp_lut[1351] = 8'd191; + long_chirp_lut[1352] = 8'd253; long_chirp_lut[1353] = 8'd217; long_chirp_lut[1354] = 8'd111; long_chirp_lut[1355] = 8'd 17; long_chirp_lut[1356] = 8'd 10; long_chirp_lut[1357] = 8'd 96; long_chirp_lut[1358] = 8'd206; long_chirp_lut[1359] = 8'd254; + long_chirp_lut[1360] = 8'd203; long_chirp_lut[1361] = 8'd 92; long_chirp_lut[1362] = 8'd 9; long_chirp_lut[1363] = 8'd 19; long_chirp_lut[1364] = 8'd115; long_chirp_lut[1365] = 8'd220; long_chirp_lut[1366] = 8'd253; long_chirp_lut[1367] = 8'd186; + long_chirp_lut[1368] = 8'd 73; long_chirp_lut[1369] = 8'd 3; long_chirp_lut[1370] = 8'd 31; long_chirp_lut[1371] = 8'd136; long_chirp_lut[1372] = 8'd233; long_chirp_lut[1373] = 8'd247; long_chirp_lut[1374] = 8'd166; long_chirp_lut[1375] = 8'd 54; + long_chirp_lut[1376] = 8'd 1; long_chirp_lut[1377] = 8'd 48; long_chirp_lut[1378] = 8'd158; long_chirp_lut[1379] = 8'd244; long_chirp_lut[1380] = 8'd237; long_chirp_lut[1381] = 8'd143; long_chirp_lut[1382] = 8'd 36; long_chirp_lut[1383] = 8'd 2; + long_chirp_lut[1384] = 8'd 68; long_chirp_lut[1385] = 8'd182; long_chirp_lut[1386] = 8'd252; long_chirp_lut[1387] = 8'd223; long_chirp_lut[1388] = 8'd117; long_chirp_lut[1389] = 8'd 20; long_chirp_lut[1390] = 8'd 9; long_chirp_lut[1391] = 8'd 93; + long_chirp_lut[1392] = 8'd204; long_chirp_lut[1393] = 8'd254; long_chirp_lut[1394] = 8'd203; long_chirp_lut[1395] = 8'd 91; long_chirp_lut[1396] = 8'd 8; long_chirp_lut[1397] = 8'd 21; long_chirp_lut[1398] = 8'd120; long_chirp_lut[1399] = 8'd225; + long_chirp_lut[1400] = 8'd251; long_chirp_lut[1401] = 8'd178; long_chirp_lut[1402] = 8'd 64; long_chirp_lut[1403] = 8'd 1; long_chirp_lut[1404] = 8'd 41; long_chirp_lut[1405] = 8'd150; long_chirp_lut[1406] = 8'd241; long_chirp_lut[1407] = 8'd241; + long_chirp_lut[1408] = 8'd148; long_chirp_lut[1409] = 8'd 39; long_chirp_lut[1410] = 8'd 2; long_chirp_lut[1411] = 8'd 66; long_chirp_lut[1412] = 8'd180; long_chirp_lut[1413] = 8'd252; long_chirp_lut[1414] = 8'd222; long_chirp_lut[1415] = 8'd116; + long_chirp_lut[1416] = 8'd 19; long_chirp_lut[1417] = 8'd 10; long_chirp_lut[1418] = 8'd 97; long_chirp_lut[1419] = 8'd209; long_chirp_lut[1420] = 8'd254; long_chirp_lut[1421] = 8'd197; long_chirp_lut[1422] = 8'd 83; long_chirp_lut[1423] = 8'd 5; + long_chirp_lut[1424] = 8'd 28; long_chirp_lut[1425] = 8'd132; long_chirp_lut[1426] = 8'd232; long_chirp_lut[1427] = 8'd247; long_chirp_lut[1428] = 8'd164; long_chirp_lut[1429] = 8'd 51; long_chirp_lut[1430] = 8'd 1; long_chirp_lut[1431] = 8'd 54; + long_chirp_lut[1432] = 8'd168; long_chirp_lut[1433] = 8'd249; long_chirp_lut[1434] = 8'd230; long_chirp_lut[1435] = 8'd127; long_chirp_lut[1436] = 8'd 25; long_chirp_lut[1437] = 8'd 7; long_chirp_lut[1438] = 8'd 88; long_chirp_lut[1439] = 8'd202; + long_chirp_lut[1440] = 8'd255; long_chirp_lut[1441] = 8'd202; long_chirp_lut[1442] = 8'd 88; long_chirp_lut[1443] = 8'd 7; long_chirp_lut[1444] = 8'd 25; long_chirp_lut[1445] = 8'd128; long_chirp_lut[1446] = 8'd231; long_chirp_lut[1447] = 8'd248; + long_chirp_lut[1448] = 8'd166; long_chirp_lut[1449] = 8'd 52; long_chirp_lut[1450] = 8'd 1; long_chirp_lut[1451] = 8'd 55; long_chirp_lut[1452] = 8'd169; long_chirp_lut[1453] = 8'd249; long_chirp_lut[1454] = 8'd228; long_chirp_lut[1455] = 8'd123; + long_chirp_lut[1456] = 8'd 22; long_chirp_lut[1457] = 8'd 8; long_chirp_lut[1458] = 8'd 94; long_chirp_lut[1459] = 8'd207; long_chirp_lut[1460] = 8'd254; long_chirp_lut[1461] = 8'd195; long_chirp_lut[1462] = 8'd 80; long_chirp_lut[1463] = 8'd 4; + long_chirp_lut[1464] = 8'd 31; long_chirp_lut[1465] = 8'd139; long_chirp_lut[1466] = 8'd237; long_chirp_lut[1467] = 8'd243; long_chirp_lut[1468] = 8'd153; long_chirp_lut[1469] = 8'd 41; long_chirp_lut[1470] = 8'd 2; long_chirp_lut[1471] = 8'd 68; + long_chirp_lut[1472] = 8'd184; long_chirp_lut[1473] = 8'd253; long_chirp_lut[1474] = 8'd216; long_chirp_lut[1475] = 8'd105; long_chirp_lut[1476] = 8'd 13; long_chirp_lut[1477] = 8'd 17; long_chirp_lut[1478] = 8'd114; long_chirp_lut[1479] = 8'd223; + long_chirp_lut[1480] = 8'd251; long_chirp_lut[1481] = 8'd175; long_chirp_lut[1482] = 8'd 59; long_chirp_lut[1483] = 8'd 1; long_chirp_lut[1484] = 8'd 50; long_chirp_lut[1485] = 8'd164; long_chirp_lut[1486] = 8'd248; long_chirp_lut[1487] = 8'd230; + long_chirp_lut[1488] = 8'd125; long_chirp_lut[1489] = 8'd 22; long_chirp_lut[1490] = 8'd 9; long_chirp_lut[1491] = 8'd 96; long_chirp_lut[1492] = 8'd210; long_chirp_lut[1493] = 8'd254; long_chirp_lut[1494] = 8'd190; long_chirp_lut[1495] = 8'd 73; + long_chirp_lut[1496] = 8'd 2; long_chirp_lut[1497] = 8'd 38; long_chirp_lut[1498] = 8'd150; long_chirp_lut[1499] = 8'd243; long_chirp_lut[1500] = 8'd237; long_chirp_lut[1501] = 8'd139; long_chirp_lut[1502] = 8'd 30; long_chirp_lut[1503] = 8'd 5; + long_chirp_lut[1504] = 8'd 84; long_chirp_lut[1505] = 8'd201; long_chirp_lut[1506] = 8'd254; long_chirp_lut[1507] = 8'd200; long_chirp_lut[1508] = 8'd 83; long_chirp_lut[1509] = 8'd 4; long_chirp_lut[1510] = 8'd 31; long_chirp_lut[1511] = 8'd141; + long_chirp_lut[1512] = 8'd239; long_chirp_lut[1513] = 8'd241; long_chirp_lut[1514] = 8'd146; long_chirp_lut[1515] = 8'd 35; long_chirp_lut[1516] = 8'd 3; long_chirp_lut[1517] = 8'd 79; long_chirp_lut[1518] = 8'd196; long_chirp_lut[1519] = 8'd254; + long_chirp_lut[1520] = 8'd203; long_chirp_lut[1521] = 8'd 87; long_chirp_lut[1522] = 8'd 5; long_chirp_lut[1523] = 8'd 29; long_chirp_lut[1524] = 8'd138; long_chirp_lut[1525] = 8'd238; long_chirp_lut[1526] = 8'd242; long_chirp_lut[1527] = 8'd147; + long_chirp_lut[1528] = 8'd 35; long_chirp_lut[1529] = 8'd 3; long_chirp_lut[1530] = 8'd 79; long_chirp_lut[1531] = 8'd197; long_chirp_lut[1532] = 8'd254; long_chirp_lut[1533] = 8'd202; long_chirp_lut[1534] = 8'd 85; long_chirp_lut[1535] = 8'd 5; + long_chirp_lut[1536] = 8'd 31; long_chirp_lut[1537] = 8'd142; long_chirp_lut[1538] = 8'd240; long_chirp_lut[1539] = 8'd240; long_chirp_lut[1540] = 8'd142; long_chirp_lut[1541] = 8'd 32; long_chirp_lut[1542] = 8'd 5; long_chirp_lut[1543] = 8'd 85; + long_chirp_lut[1544] = 8'd202; long_chirp_lut[1545] = 8'd254; long_chirp_lut[1546] = 8'd195; long_chirp_lut[1547] = 8'd 77; long_chirp_lut[1548] = 8'd 3; long_chirp_lut[1549] = 8'd 38; long_chirp_lut[1550] = 8'd151; long_chirp_lut[1551] = 8'd244; + long_chirp_lut[1552] = 8'd235; long_chirp_lut[1553] = 8'd131; long_chirp_lut[1554] = 8'd 24; long_chirp_lut[1555] = 8'd 8; long_chirp_lut[1556] = 8'd 97; long_chirp_lut[1557] = 8'd213; long_chirp_lut[1558] = 8'd253; long_chirp_lut[1559] = 8'd183; + long_chirp_lut[1560] = 8'd 64; long_chirp_lut[1561] = 8'd 1; long_chirp_lut[1562] = 8'd 49; long_chirp_lut[1563] = 8'd167; long_chirp_lut[1564] = 8'd250; long_chirp_lut[1565] = 8'd224; long_chirp_lut[1566] = 8'd114; long_chirp_lut[1567] = 8'd 15; + long_chirp_lut[1568] = 8'd 16; long_chirp_lut[1569] = 8'd116; long_chirp_lut[1570] = 8'd226; long_chirp_lut[1571] = 8'd249; long_chirp_lut[1572] = 8'd164; long_chirp_lut[1573] = 8'd 47; long_chirp_lut[1574] = 8'd 1; long_chirp_lut[1575] = 8'd 68; + long_chirp_lut[1576] = 8'd187; long_chirp_lut[1577] = 8'd254; long_chirp_lut[1578] = 8'd208; long_chirp_lut[1579] = 8'd 90; long_chirp_lut[1580] = 8'd 6; long_chirp_lut[1581] = 8'd 30; long_chirp_lut[1582] = 8'd141; long_chirp_lut[1583] = 8'd240; + long_chirp_lut[1584] = 8'd239; long_chirp_lut[1585] = 8'd138; long_chirp_lut[1586] = 8'd 28; long_chirp_lut[1587] = 8'd 7; long_chirp_lut[1588] = 8'd 94; long_chirp_lut[1589] = 8'd211; long_chirp_lut[1590] = 8'd253; long_chirp_lut[1591] = 8'd183; + long_chirp_lut[1592] = 8'd 63; long_chirp_lut[1593] = 8'd 1; long_chirp_lut[1594] = 8'd 52; long_chirp_lut[1595] = 8'd171; long_chirp_lut[1596] = 8'd251; long_chirp_lut[1597] = 8'd220; long_chirp_lut[1598] = 8'd105; long_chirp_lut[1599] = 8'd 11; + long_chirp_lut[1600] = 8'd 21; long_chirp_lut[1601] = 8'd128; long_chirp_lut[1602] = 8'd234; long_chirp_lut[1603] = 8'd244; long_chirp_lut[1604] = 8'd149; long_chirp_lut[1605] = 8'd 35; long_chirp_lut[1606] = 8'd 4; long_chirp_lut[1607] = 8'd 85; + long_chirp_lut[1608] = 8'd204; long_chirp_lut[1609] = 8'd254; long_chirp_lut[1610] = 8'd189; long_chirp_lut[1611] = 8'd 69; long_chirp_lut[1612] = 8'd 1; long_chirp_lut[1613] = 8'd 48; long_chirp_lut[1614] = 8'd167; long_chirp_lut[1615] = 8'd250; + long_chirp_lut[1616] = 8'd222; long_chirp_lut[1617] = 8'd107; long_chirp_lut[1618] = 8'd 11; long_chirp_lut[1619] = 8'd 21; long_chirp_lut[1620] = 8'd127; long_chirp_lut[1621] = 8'd234; long_chirp_lut[1622] = 8'd243; long_chirp_lut[1623] = 8'd147; + long_chirp_lut[1624] = 8'd 33; long_chirp_lut[1625] = 8'd 5; long_chirp_lut[1626] = 8'd 89; long_chirp_lut[1627] = 8'd208; long_chirp_lut[1628] = 8'd254; long_chirp_lut[1629] = 8'd184; long_chirp_lut[1630] = 8'd 62; long_chirp_lut[1631] = 8'd 1; + long_chirp_lut[1632] = 8'd 55; long_chirp_lut[1633] = 8'd176; long_chirp_lut[1634] = 8'd252; long_chirp_lut[1635] = 8'd214; long_chirp_lut[1636] = 8'd 96; long_chirp_lut[1637] = 8'd 7; long_chirp_lut[1638] = 8'd 28; long_chirp_lut[1639] = 8'd141; + long_chirp_lut[1640] = 8'd241; long_chirp_lut[1641] = 8'd237; long_chirp_lut[1642] = 8'd132; long_chirp_lut[1643] = 8'd 23; long_chirp_lut[1644] = 8'd 10; long_chirp_lut[1645] = 8'd106; long_chirp_lut[1646] = 8'd221; long_chirp_lut[1647] = 8'd250; + long_chirp_lut[1648] = 8'd166; long_chirp_lut[1649] = 8'd 46; long_chirp_lut[1650] = 8'd 2; long_chirp_lut[1651] = 8'd 74; long_chirp_lut[1652] = 8'd196; long_chirp_lut[1653] = 8'd254; long_chirp_lut[1654] = 8'd195; long_chirp_lut[1655] = 8'd 73; + long_chirp_lut[1656] = 8'd 2; long_chirp_lut[1657] = 8'd 47; long_chirp_lut[1658] = 8'd167; long_chirp_lut[1659] = 8'd251; long_chirp_lut[1660] = 8'd220; long_chirp_lut[1661] = 8'd103; long_chirp_lut[1662] = 8'd 9; long_chirp_lut[1663] = 8'd 25; + long_chirp_lut[1664] = 8'd137; long_chirp_lut[1665] = 8'd240; long_chirp_lut[1666] = 8'd238; long_chirp_lut[1667] = 8'd133; long_chirp_lut[1668] = 8'd 23; long_chirp_lut[1669] = 8'd 11; long_chirp_lut[1670] = 8'd107; long_chirp_lut[1671] = 8'd223; + long_chirp_lut[1672] = 8'd249; long_chirp_lut[1673] = 8'd162; long_chirp_lut[1674] = 8'd 42; long_chirp_lut[1675] = 8'd 3; long_chirp_lut[1676] = 8'd 80; long_chirp_lut[1677] = 8'd202; long_chirp_lut[1678] = 8'd254; long_chirp_lut[1679] = 8'd187; + long_chirp_lut[1680] = 8'd 64; long_chirp_lut[1681] = 8'd 1; long_chirp_lut[1682] = 8'd 57; long_chirp_lut[1683] = 8'd179; long_chirp_lut[1684] = 8'd253; long_chirp_lut[1685] = 8'd209; long_chirp_lut[1686] = 8'd 88; long_chirp_lut[1687] = 8'd 4; + long_chirp_lut[1688] = 8'd 37; long_chirp_lut[1689] = 8'd155; long_chirp_lut[1690] = 8'd247; long_chirp_lut[1691] = 8'd226; long_chirp_lut[1692] = 8'd112; long_chirp_lut[1693] = 8'd 12; long_chirp_lut[1694] = 8'd 22; long_chirp_lut[1695] = 8'd132; + long_chirp_lut[1696] = 8'd238; long_chirp_lut[1697] = 8'd239; long_chirp_lut[1698] = 8'd135; long_chirp_lut[1699] = 8'd 23; long_chirp_lut[1700] = 8'd 11; long_chirp_lut[1701] = 8'd109; long_chirp_lut[1702] = 8'd225; long_chirp_lut[1703] = 8'd248; + long_chirp_lut[1704] = 8'd157; long_chirp_lut[1705] = 8'd 37; long_chirp_lut[1706] = 8'd 4; long_chirp_lut[1707] = 8'd 88; long_chirp_lut[1708] = 8'd210; long_chirp_lut[1709] = 8'd253; long_chirp_lut[1710] = 8'd176; long_chirp_lut[1711] = 8'd 53; + long_chirp_lut[1712] = 8'd 1; long_chirp_lut[1713] = 8'd 70; long_chirp_lut[1714] = 8'd194; long_chirp_lut[1715] = 8'd254; long_chirp_lut[1716] = 8'd193; long_chirp_lut[1717] = 8'd 69; long_chirp_lut[1718] = 8'd 1; long_chirp_lut[1719] = 8'd 54; + long_chirp_lut[1720] = 8'd178; long_chirp_lut[1721] = 8'd253; long_chirp_lut[1722] = 8'd208; long_chirp_lut[1723] = 8'd 85; long_chirp_lut[1724] = 8'd 3; long_chirp_lut[1725] = 8'd 41; long_chirp_lut[1726] = 8'd162; long_chirp_lut[1727] = 8'd250; + long_chirp_lut[1728] = 8'd220; long_chirp_lut[1729] = 8'd101; long_chirp_lut[1730] = 8'd 8; long_chirp_lut[1731] = 8'd 30; long_chirp_lut[1732] = 8'd146; long_chirp_lut[1733] = 8'd245; long_chirp_lut[1734] = 8'd230; long_chirp_lut[1735] = 8'd116; + long_chirp_lut[1736] = 8'd 13; long_chirp_lut[1737] = 8'd 21; long_chirp_lut[1738] = 8'd132; long_chirp_lut[1739] = 8'd239; long_chirp_lut[1740] = 8'd237; long_chirp_lut[1741] = 8'd130; long_chirp_lut[1742] = 8'd 20; long_chirp_lut[1743] = 8'd 14; + long_chirp_lut[1744] = 8'd119; long_chirp_lut[1745] = 8'd232; long_chirp_lut[1746] = 8'd243; long_chirp_lut[1747] = 8'd142; long_chirp_lut[1748] = 8'd 27; long_chirp_lut[1749] = 8'd 9; long_chirp_lut[1750] = 8'd107; long_chirp_lut[1751] = 8'd225; + long_chirp_lut[1752] = 8'd247; long_chirp_lut[1753] = 8'd153; long_chirp_lut[1754] = 8'd 34; long_chirp_lut[1755] = 8'd 6; long_chirp_lut[1756] = 8'd 97; long_chirp_lut[1757] = 8'd218; long_chirp_lut[1758] = 8'd250; long_chirp_lut[1759] = 8'd162; + long_chirp_lut[1760] = 8'd 40; long_chirp_lut[1761] = 8'd 4; long_chirp_lut[1762] = 8'd 88; long_chirp_lut[1763] = 8'd212; long_chirp_lut[1764] = 8'd252; long_chirp_lut[1765] = 8'd171; long_chirp_lut[1766] = 8'd 46; long_chirp_lut[1767] = 8'd 2; + long_chirp_lut[1768] = 8'd 81; long_chirp_lut[1769] = 8'd206; long_chirp_lut[1770] = 8'd253; long_chirp_lut[1771] = 8'd177; long_chirp_lut[1772] = 8'd 52; long_chirp_lut[1773] = 8'd 1; long_chirp_lut[1774] = 8'd 75; long_chirp_lut[1775] = 8'd201; + long_chirp_lut[1776] = 8'd254; long_chirp_lut[1777] = 8'd182; long_chirp_lut[1778] = 8'd 56; long_chirp_lut[1779] = 8'd 1; long_chirp_lut[1780] = 8'd 71; long_chirp_lut[1781] = 8'd197; long_chirp_lut[1782] = 8'd254; long_chirp_lut[1783] = 8'd186; + long_chirp_lut[1784] = 8'd 60; long_chirp_lut[1785] = 8'd 1; long_chirp_lut[1786] = 8'd 67; long_chirp_lut[1787] = 8'd194; long_chirp_lut[1788] = 8'd254; long_chirp_lut[1789] = 8'd189; long_chirp_lut[1790] = 8'd 62; long_chirp_lut[1791] = 8'd 1; + long_chirp_lut[1792] = 8'd 65; long_chirp_lut[1793] = 8'd192; long_chirp_lut[1794] = 8'd254; long_chirp_lut[1795] = 8'd191; long_chirp_lut[1796] = 8'd 64; long_chirp_lut[1797] = 8'd 1; long_chirp_lut[1798] = 8'd 64; long_chirp_lut[1799] = 8'd191; + long_chirp_lut[1800] = 8'd255; long_chirp_lut[1801] = 8'd191; long_chirp_lut[1802] = 8'd 64; long_chirp_lut[1803] = 8'd 1; long_chirp_lut[1804] = 8'd 64; long_chirp_lut[1805] = 8'd191; long_chirp_lut[1806] = 8'd254; long_chirp_lut[1807] = 8'd190; + long_chirp_lut[1808] = 8'd 63; long_chirp_lut[1809] = 8'd 1; long_chirp_lut[1810] = 8'd 66; long_chirp_lut[1811] = 8'd193; long_chirp_lut[1812] = 8'd254; long_chirp_lut[1813] = 8'd188; long_chirp_lut[1814] = 8'd 61; long_chirp_lut[1815] = 8'd 1; + long_chirp_lut[1816] = 8'd 68; long_chirp_lut[1817] = 8'd196; long_chirp_lut[1818] = 8'd254; long_chirp_lut[1819] = 8'd185; long_chirp_lut[1820] = 8'd 58; long_chirp_lut[1821] = 8'd 1; long_chirp_lut[1822] = 8'd 72; long_chirp_lut[1823] = 8'd199; + long_chirp_lut[1824] = 8'd254; long_chirp_lut[1825] = 8'd181; long_chirp_lut[1826] = 8'd 54; long_chirp_lut[1827] = 8'd 1; long_chirp_lut[1828] = 8'd 77; long_chirp_lut[1829] = 8'd204; long_chirp_lut[1830] = 8'd253; long_chirp_lut[1831] = 8'd175; + long_chirp_lut[1832] = 8'd 48; long_chirp_lut[1833] = 8'd 2; long_chirp_lut[1834] = 8'd 83; long_chirp_lut[1835] = 8'd209; long_chirp_lut[1836] = 8'd252; long_chirp_lut[1837] = 8'd168; long_chirp_lut[1838] = 8'd 42; long_chirp_lut[1839] = 8'd 4; + long_chirp_lut[1840] = 8'd 91; long_chirp_lut[1841] = 8'd216; long_chirp_lut[1842] = 8'd250; long_chirp_lut[1843] = 8'd159; long_chirp_lut[1844] = 8'd 36; long_chirp_lut[1845] = 8'd 6; long_chirp_lut[1846] = 8'd100; long_chirp_lut[1847] = 8'd222; + long_chirp_lut[1848] = 8'd247; long_chirp_lut[1849] = 8'd150; long_chirp_lut[1850] = 8'd 29; long_chirp_lut[1851] = 8'd 9; long_chirp_lut[1852] = 8'd111; long_chirp_lut[1853] = 8'd229; long_chirp_lut[1854] = 8'd243; long_chirp_lut[1855] = 8'd138; + long_chirp_lut[1856] = 8'd 22; long_chirp_lut[1857] = 8'd 14; long_chirp_lut[1858] = 8'd123; long_chirp_lut[1859] = 8'd236; long_chirp_lut[1860] = 8'd237; long_chirp_lut[1861] = 8'd125; long_chirp_lut[1862] = 8'd 15; long_chirp_lut[1863] = 8'd 21; + long_chirp_lut[1864] = 8'd137; long_chirp_lut[1865] = 8'd243; long_chirp_lut[1866] = 8'd230; long_chirp_lut[1867] = 8'd111; long_chirp_lut[1868] = 8'd 9; long_chirp_lut[1869] = 8'd 30; long_chirp_lut[1870] = 8'd151; long_chirp_lut[1871] = 8'd248; + long_chirp_lut[1872] = 8'd220; long_chirp_lut[1873] = 8'd 96; long_chirp_lut[1874] = 8'd 4; long_chirp_lut[1875] = 8'd 41; long_chirp_lut[1876] = 8'd167; long_chirp_lut[1877] = 8'd252; long_chirp_lut[1878] = 8'd208; long_chirp_lut[1879] = 8'd 80; + long_chirp_lut[1880] = 8'd 1; long_chirp_lut[1881] = 8'd 54; long_chirp_lut[1882] = 8'd183; long_chirp_lut[1883] = 8'd254; long_chirp_lut[1884] = 8'd193; long_chirp_lut[1885] = 8'd 64; long_chirp_lut[1886] = 8'd 1; long_chirp_lut[1887] = 8'd 70; + long_chirp_lut[1888] = 8'd199; long_chirp_lut[1889] = 8'd254; long_chirp_lut[1890] = 8'd176; long_chirp_lut[1891] = 8'd 48; long_chirp_lut[1892] = 8'd 3; long_chirp_lut[1893] = 8'd 88; long_chirp_lut[1894] = 8'd215; long_chirp_lut[1895] = 8'd250; + long_chirp_lut[1896] = 8'd157; long_chirp_lut[1897] = 8'd 33; long_chirp_lut[1898] = 8'd 8; long_chirp_lut[1899] = 8'd109; long_chirp_lut[1900] = 8'd229; long_chirp_lut[1901] = 8'd243; long_chirp_lut[1902] = 8'd135; long_chirp_lut[1903] = 8'd 19; + long_chirp_lut[1904] = 8'd 18; long_chirp_lut[1905] = 8'd132; long_chirp_lut[1906] = 8'd241; long_chirp_lut[1907] = 8'd231; long_chirp_lut[1908] = 8'd112; long_chirp_lut[1909] = 8'd 9; long_chirp_lut[1910] = 8'd 31; long_chirp_lut[1911] = 8'd155; + long_chirp_lut[1912] = 8'd250; long_chirp_lut[1913] = 8'd215; long_chirp_lut[1914] = 8'd 88; long_chirp_lut[1915] = 8'd 2; long_chirp_lut[1916] = 8'd 50; long_chirp_lut[1917] = 8'd179; long_chirp_lut[1918] = 8'd254; long_chirp_lut[1919] = 8'd195; + long_chirp_lut[1920] = 8'd 64; long_chirp_lut[1921] = 8'd 1; long_chirp_lut[1922] = 8'd 72; long_chirp_lut[1923] = 8'd202; long_chirp_lut[1924] = 8'd253; long_chirp_lut[1925] = 8'd171; long_chirp_lut[1926] = 8'd 42; long_chirp_lut[1927] = 8'd 4; + long_chirp_lut[1928] = 8'd 98; long_chirp_lut[1929] = 8'd223; long_chirp_lut[1930] = 8'd246; long_chirp_lut[1931] = 8'd143; long_chirp_lut[1932] = 8'd 23; long_chirp_lut[1933] = 8'd 15; long_chirp_lut[1934] = 8'd127; long_chirp_lut[1935] = 8'd240; + long_chirp_lut[1936] = 8'd233; long_chirp_lut[1937] = 8'd113; long_chirp_lut[1938] = 8'd 9; long_chirp_lut[1939] = 8'd 32; long_chirp_lut[1940] = 8'd157; long_chirp_lut[1941] = 8'd251; long_chirp_lut[1942] = 8'd212; long_chirp_lut[1943] = 8'd 83; + long_chirp_lut[1944] = 8'd 2; long_chirp_lut[1945] = 8'd 55; long_chirp_lut[1946] = 8'd186; long_chirp_lut[1947] = 8'd254; long_chirp_lut[1948] = 8'd186; long_chirp_lut[1949] = 8'd 55; long_chirp_lut[1950] = 8'd 2; long_chirp_lut[1951] = 8'd 84; + long_chirp_lut[1952] = 8'd213; long_chirp_lut[1953] = 8'd250; long_chirp_lut[1954] = 8'd155; long_chirp_lut[1955] = 8'd 30; long_chirp_lut[1956] = 8'd 10; long_chirp_lut[1957] = 8'd117; long_chirp_lut[1958] = 8'd235; long_chirp_lut[1959] = 8'd237; + long_chirp_lut[1960] = 8'd120; long_chirp_lut[1961] = 8'd 11; long_chirp_lut[1962] = 8'd 28; long_chirp_lut[1963] = 8'd153; long_chirp_lut[1964] = 8'd250; long_chirp_lut[1965] = 8'd214; long_chirp_lut[1966] = 8'd 85; long_chirp_lut[1967] = 8'd 2; + long_chirp_lut[1968] = 8'd 55; long_chirp_lut[1969] = 8'd187; long_chirp_lut[1970] = 8'd254; long_chirp_lut[1971] = 8'd184; long_chirp_lut[1972] = 8'd 52; long_chirp_lut[1973] = 8'd 2; long_chirp_lut[1974] = 8'd 89; long_chirp_lut[1975] = 8'd218; + long_chirp_lut[1976] = 8'd248; long_chirp_lut[1977] = 8'd147; long_chirp_lut[1978] = 8'd 25; long_chirp_lut[1979] = 8'd 14; long_chirp_lut[1980] = 8'd127; long_chirp_lut[1981] = 8'd241; long_chirp_lut[1982] = 8'd230; long_chirp_lut[1983] = 8'd107; + long_chirp_lut[1984] = 8'd 7; long_chirp_lut[1985] = 8'd 38; long_chirp_lut[1986] = 8'd167; long_chirp_lut[1987] = 8'd253; long_chirp_lut[1988] = 8'd201; long_chirp_lut[1989] = 8'd 69; long_chirp_lut[1990] = 8'd 1; long_chirp_lut[1991] = 8'd 72; + long_chirp_lut[1992] = 8'd204; long_chirp_lut[1993] = 8'd252; long_chirp_lut[1994] = 8'd163; long_chirp_lut[1995] = 8'd 35; long_chirp_lut[1996] = 8'd 8; long_chirp_lut[1997] = 8'd113; long_chirp_lut[1998] = 8'd234; long_chirp_lut[1999] = 8'd237; + long_chirp_lut[2000] = 8'd120; long_chirp_lut[2001] = 8'd 11; long_chirp_lut[2002] = 8'd 30; long_chirp_lut[2003] = 8'd157; long_chirp_lut[2004] = 8'd251; long_chirp_lut[2005] = 8'd209; long_chirp_lut[2006] = 8'd 77; long_chirp_lut[2007] = 8'd 1; + long_chirp_lut[2008] = 8'd 65; long_chirp_lut[2009] = 8'd199; long_chirp_lut[2010] = 8'd253; long_chirp_lut[2011] = 8'd169; long_chirp_lut[2012] = 8'd 38; long_chirp_lut[2013] = 8'd 7; long_chirp_lut[2014] = 8'd109; long_chirp_lut[2015] = 8'd232; + long_chirp_lut[2016] = 8'd239; long_chirp_lut[2017] = 8'd122; long_chirp_lut[2018] = 8'd 11; long_chirp_lut[2019] = 8'd 30; long_chirp_lut[2020] = 8'd157; long_chirp_lut[2021] = 8'd251; long_chirp_lut[2022] = 8'd208; long_chirp_lut[2023] = 8'd 75; + long_chirp_lut[2024] = 8'd 1; long_chirp_lut[2025] = 8'd 68; long_chirp_lut[2026] = 8'd201; long_chirp_lut[2027] = 8'd253; long_chirp_lut[2028] = 8'd164; long_chirp_lut[2029] = 8'd 35; long_chirp_lut[2030] = 8'd 9; long_chirp_lut[2031] = 8'd116; + long_chirp_lut[2032] = 8'd236; long_chirp_lut[2033] = 8'd235; long_chirp_lut[2034] = 8'd114; long_chirp_lut[2035] = 8'd 8; long_chirp_lut[2036] = 8'd 36; long_chirp_lut[2037] = 8'd167; long_chirp_lut[2038] = 8'd253; long_chirp_lut[2039] = 8'd199; + long_chirp_lut[2040] = 8'd 64; long_chirp_lut[2041] = 8'd 1; long_chirp_lut[2042] = 8'd 80; long_chirp_lut[2043] = 8'd213; long_chirp_lut[2044] = 8'd249; long_chirp_lut[2045] = 8'd149; long_chirp_lut[2046] = 8'd 24; long_chirp_lut[2047] = 8'd 16; + long_chirp_lut[2048] = 8'd133; long_chirp_lut[2049] = 8'd244; long_chirp_lut[2050] = 8'd224; long_chirp_lut[2051] = 8'd 95; long_chirp_lut[2052] = 8'd 3; long_chirp_lut[2053] = 8'd 52; long_chirp_lut[2054] = 8'd186; long_chirp_lut[2055] = 8'd254; + long_chirp_lut[2056] = 8'd179; long_chirp_lut[2057] = 8'd 45; long_chirp_lut[2058] = 8'd 5; long_chirp_lut[2059] = 8'd103; long_chirp_lut[2060] = 8'd229; long_chirp_lut[2061] = 8'd240; long_chirp_lut[2062] = 8'd123; long_chirp_lut[2063] = 8'd 11; + long_chirp_lut[2064] = 8'd 31; long_chirp_lut[2065] = 8'd161; long_chirp_lut[2066] = 8'd252; long_chirp_lut[2067] = 8'd202; long_chirp_lut[2068] = 8'd 67; long_chirp_lut[2069] = 8'd 1; long_chirp_lut[2070] = 8'd 79; long_chirp_lut[2071] = 8'd212; + long_chirp_lut[2072] = 8'd249; long_chirp_lut[2073] = 8'd147; long_chirp_lut[2074] = 8'd 23; long_chirp_lut[2075] = 8'd 18; long_chirp_lut[2076] = 8'd138; long_chirp_lut[2077] = 8'd246; long_chirp_lut[2078] = 8'd219; long_chirp_lut[2079] = 8'd 87; + long_chirp_lut[2080] = 8'd 1; long_chirp_lut[2081] = 8'd 60; long_chirp_lut[2082] = 8'd196; long_chirp_lut[2083] = 8'd253; long_chirp_lut[2084] = 8'd166; long_chirp_lut[2085] = 8'd 35; long_chirp_lut[2086] = 8'd 9; long_chirp_lut[2087] = 8'd120; + long_chirp_lut[2088] = 8'd239; long_chirp_lut[2089] = 8'd230; long_chirp_lut[2090] = 8'd104; long_chirp_lut[2091] = 8'd 4; long_chirp_lut[2092] = 8'd 47; long_chirp_lut[2093] = 8'd182; long_chirp_lut[2094] = 8'd254; long_chirp_lut[2095] = 8'd181; + long_chirp_lut[2096] = 8'd 46; long_chirp_lut[2097] = 8'd 5; long_chirp_lut[2098] = 8'd106; long_chirp_lut[2099] = 8'd232; long_chirp_lut[2100] = 8'd237; long_chirp_lut[2101] = 8'd116; long_chirp_lut[2102] = 8'd 8; long_chirp_lut[2103] = 8'd 38; + long_chirp_lut[2104] = 8'd171; long_chirp_lut[2105] = 8'd254; long_chirp_lut[2106] = 8'd190; long_chirp_lut[2107] = 8'd 54; long_chirp_lut[2108] = 8'd 3; long_chirp_lut[2109] = 8'd 96; long_chirp_lut[2110] = 8'd226; long_chirp_lut[2111] = 8'd242; + long_chirp_lut[2112] = 8'd125; long_chirp_lut[2113] = 8'd 11; long_chirp_lut[2114] = 8'd 33; long_chirp_lut[2115] = 8'd164; long_chirp_lut[2116] = 8'd253; long_chirp_lut[2117] = 8'd196; long_chirp_lut[2118] = 8'd 59; long_chirp_lut[2119] = 8'd 2; + long_chirp_lut[2120] = 8'd 91; long_chirp_lut[2121] = 8'd223; long_chirp_lut[2122] = 8'd243; long_chirp_lut[2123] = 8'd129; long_chirp_lut[2124] = 8'd 13; long_chirp_lut[2125] = 8'd 31; long_chirp_lut[2126] = 8'd162; long_chirp_lut[2127] = 8'd253; + long_chirp_lut[2128] = 8'd198; long_chirp_lut[2129] = 8'd 60; long_chirp_lut[2130] = 8'd 2; long_chirp_lut[2131] = 8'd 90; long_chirp_lut[2132] = 8'd223; long_chirp_lut[2133] = 8'd243; long_chirp_lut[2134] = 8'd128; long_chirp_lut[2135] = 8'd 12; + long_chirp_lut[2136] = 8'd 31; long_chirp_lut[2137] = 8'd163; long_chirp_lut[2138] = 8'd253; long_chirp_lut[2139] = 8'd195; long_chirp_lut[2140] = 8'd 58; long_chirp_lut[2141] = 8'd 2; long_chirp_lut[2142] = 8'd 94; long_chirp_lut[2143] = 8'd225; + long_chirp_lut[2144] = 8'd242; long_chirp_lut[2145] = 8'd123; long_chirp_lut[2146] = 8'd 10; long_chirp_lut[2147] = 8'd 35; long_chirp_lut[2148] = 8'd169; long_chirp_lut[2149] = 8'd254; long_chirp_lut[2150] = 8'd189; long_chirp_lut[2151] = 8'd 52; + long_chirp_lut[2152] = 8'd 4; long_chirp_lut[2153] = 8'd102; long_chirp_lut[2154] = 8'd231; long_chirp_lut[2155] = 8'd237; long_chirp_lut[2156] = 8'd114; long_chirp_lut[2157] = 8'd 7; long_chirp_lut[2158] = 8'd 43; long_chirp_lut[2159] = 8'd179; + long_chirp_lut[2160] = 8'd255; long_chirp_lut[2161] = 8'd179; long_chirp_lut[2162] = 8'd 42; long_chirp_lut[2163] = 8'd 7; long_chirp_lut[2164] = 8'd115; long_chirp_lut[2165] = 8'd238; long_chirp_lut[2166] = 8'd230; long_chirp_lut[2167] = 8'd100; + long_chirp_lut[2168] = 8'd 3; long_chirp_lut[2169] = 8'd 54; long_chirp_lut[2170] = 8'd193; long_chirp_lut[2171] = 8'd254; long_chirp_lut[2172] = 8'd164; long_chirp_lut[2173] = 8'd 31; long_chirp_lut[2174] = 8'd 13; long_chirp_lut[2175] = 8'd132; + long_chirp_lut[2176] = 8'd245; long_chirp_lut[2177] = 8'd218; long_chirp_lut[2178] = 8'd 83; long_chirp_lut[2179] = 8'd 1; long_chirp_lut[2180] = 8'd 71; long_chirp_lut[2181] = 8'd209; long_chirp_lut[2182] = 8'd250; long_chirp_lut[2183] = 8'd144; + long_chirp_lut[2184] = 8'd 19; long_chirp_lut[2185] = 8'd 24; long_chirp_lut[2186] = 8'd153; long_chirp_lut[2187] = 8'd252; long_chirp_lut[2188] = 8'd201; long_chirp_lut[2189] = 8'd 62; long_chirp_lut[2190] = 8'd 2; long_chirp_lut[2191] = 8'd 93; + long_chirp_lut[2192] = 8'd226; long_chirp_lut[2193] = 8'd241; long_chirp_lut[2194] = 8'd119; long_chirp_lut[2195] = 8'd 8; long_chirp_lut[2196] = 8'd 41; long_chirp_lut[2197] = 8'd178; long_chirp_lut[2198] = 8'd254; long_chirp_lut[2199] = 8'd178; + long_chirp_lut[2200] = 8'd 40; long_chirp_lut[2201] = 8'd 8; long_chirp_lut[2202] = 8'd120; long_chirp_lut[2203] = 8'd241; long_chirp_lut[2204] = 8'd225; long_chirp_lut[2205] = 8'd 91; long_chirp_lut[2206] = 8'd 1; long_chirp_lut[2207] = 8'd 65; + long_chirp_lut[2208] = 8'd204; long_chirp_lut[2209] = 8'd251; long_chirp_lut[2210] = 8'd148; long_chirp_lut[2211] = 8'd 20; long_chirp_lut[2212] = 8'd 23; long_chirp_lut[2213] = 8'd153; long_chirp_lut[2214] = 8'd252; long_chirp_lut[2215] = 8'd200; + long_chirp_lut[2216] = 8'd 60; long_chirp_lut[2217] = 8'd 2; long_chirp_lut[2218] = 8'd 97; long_chirp_lut[2219] = 8'd229; long_chirp_lut[2220] = 8'd237; long_chirp_lut[2221] = 8'd112; long_chirp_lut[2222] = 8'd 5; long_chirp_lut[2223] = 8'd 48; + long_chirp_lut[2224] = 8'd187; long_chirp_lut[2225] = 8'd254; long_chirp_lut[2226] = 8'd166; long_chirp_lut[2227] = 8'd 31; long_chirp_lut[2228] = 8'd 14; long_chirp_lut[2229] = 8'd136; long_chirp_lut[2230] = 8'd247; long_chirp_lut[2231] = 8'd212; + long_chirp_lut[2232] = 8'd 73; long_chirp_lut[2233] = 8'd 1; long_chirp_lut[2234] = 8'd 83; long_chirp_lut[2235] = 8'd220; long_chirp_lut[2236] = 8'd243; long_chirp_lut[2237] = 8'd124; long_chirp_lut[2238] = 8'd 9; long_chirp_lut[2239] = 8'd 39; + long_chirp_lut[2240] = 8'd178; long_chirp_lut[2241] = 8'd254; long_chirp_lut[2242] = 8'd175; long_chirp_lut[2243] = 8'd 37; long_chirp_lut[2244] = 8'd 10; long_chirp_lut[2245] = 8'd128; long_chirp_lut[2246] = 8'd245; long_chirp_lut[2247] = 8'd217; + long_chirp_lut[2248] = 8'd 79; long_chirp_lut[2249] = 8'd 1; long_chirp_lut[2250] = 8'd 79; long_chirp_lut[2251] = 8'd217; long_chirp_lut[2252] = 8'd245; long_chirp_lut[2253] = 8'd127; long_chirp_lut[2254] = 8'd 10; long_chirp_lut[2255] = 8'd 38; + long_chirp_lut[2256] = 8'd177; long_chirp_lut[2257] = 8'd254; long_chirp_lut[2258] = 8'd175; long_chirp_lut[2259] = 8'd 37; long_chirp_lut[2260] = 8'd 11; long_chirp_lut[2261] = 8'd130; long_chirp_lut[2262] = 8'd246; long_chirp_lut[2263] = 8'd215; + long_chirp_lut[2264] = 8'd 76; long_chirp_lut[2265] = 8'd 1; long_chirp_lut[2266] = 8'd 83; long_chirp_lut[2267] = 8'd221; long_chirp_lut[2268] = 8'd242; long_chirp_lut[2269] = 8'd121; long_chirp_lut[2270] = 8'd 8; long_chirp_lut[2271] = 8'd 44; + long_chirp_lut[2272] = 8'd184; long_chirp_lut[2273] = 8'd254; long_chirp_lut[2274] = 8'd166; long_chirp_lut[2275] = 8'd 30; long_chirp_lut[2276] = 8'd 16; long_chirp_lut[2277] = 8'd141; long_chirp_lut[2278] = 8'd250; long_chirp_lut[2279] = 8'd206; + long_chirp_lut[2280] = 8'd 64; long_chirp_lut[2281] = 8'd 2; long_chirp_lut[2282] = 8'd 97; long_chirp_lut[2283] = 8'd230; long_chirp_lut[2284] = 8'd235; long_chirp_lut[2285] = 8'd105; long_chirp_lut[2286] = 8'd 3; long_chirp_lut[2287] = 8'd 57; + long_chirp_lut[2288] = 8'd199; long_chirp_lut[2289] = 8'd251; long_chirp_lut[2290] = 8'd148; long_chirp_lut[2291] = 8'd 19; long_chirp_lut[2292] = 8'd 26; long_chirp_lut[2293] = 8'd161; long_chirp_lut[2294] = 8'd254; long_chirp_lut[2295] = 8'd187; + long_chirp_lut[2296] = 8'd 46; long_chirp_lut[2297] = 8'd 7; long_chirp_lut[2298] = 8'd120; long_chirp_lut[2299] = 8'd243; long_chirp_lut[2300] = 8'd220; long_chirp_lut[2301] = 8'd 81; long_chirp_lut[2302] = 8'd 1; long_chirp_lut[2303] = 8'd 81; + long_chirp_lut[2304] = 8'd220; long_chirp_lut[2305] = 8'd242; long_chirp_lut[2306] = 8'd119; long_chirp_lut[2307] = 8'd 7; long_chirp_lut[2308] = 8'd 47; long_chirp_lut[2309] = 8'd189; long_chirp_lut[2310] = 8'd253; long_chirp_lut[2311] = 8'd158; + long_chirp_lut[2312] = 8'd 24; long_chirp_lut[2313] = 8'd 21; long_chirp_lut[2314] = 8'd153; long_chirp_lut[2315] = 8'd253; long_chirp_lut[2316] = 8'd193; long_chirp_lut[2317] = 8'd 50; long_chirp_lut[2318] = 8'd 5; long_chirp_lut[2319] = 8'd116; + long_chirp_lut[2320] = 8'd241; long_chirp_lut[2321] = 8'd222; long_chirp_lut[2322] = 8'd 83; long_chirp_lut[2323] = 8'd 1; long_chirp_lut[2324] = 8'd 80; long_chirp_lut[2325] = 8'd220; long_chirp_lut[2326] = 8'd242; long_chirp_lut[2327] = 8'd118; + long_chirp_lut[2328] = 8'd 6; long_chirp_lut[2329] = 8'd 49; long_chirp_lut[2330] = 8'd193; long_chirp_lut[2331] = 8'd253; long_chirp_lut[2332] = 8'd153; long_chirp_lut[2333] = 8'd 20; long_chirp_lut[2334] = 8'd 25; long_chirp_lut[2335] = 8'd161; + long_chirp_lut[2336] = 8'd254; long_chirp_lut[2337] = 8'd185; long_chirp_lut[2338] = 8'd 42; long_chirp_lut[2339] = 8'd 9; long_chirp_lut[2340] = 8'd127; long_chirp_lut[2341] = 8'd246; long_chirp_lut[2342] = 8'd212; long_chirp_lut[2343] = 8'd 70; + long_chirp_lut[2344] = 8'd 1; long_chirp_lut[2345] = 8'd 95; long_chirp_lut[2346] = 8'd231; long_chirp_lut[2347] = 8'd234; long_chirp_lut[2348] = 8'd100; long_chirp_lut[2349] = 8'd 2; long_chirp_lut[2350] = 8'd 66; long_chirp_lut[2351] = 8'd209; + long_chirp_lut[2352] = 8'd247; long_chirp_lut[2353] = 8'd131; long_chirp_lut[2354] = 8'd 10; long_chirp_lut[2355] = 8'd 41; long_chirp_lut[2356] = 8'd183; long_chirp_lut[2357] = 8'd254; long_chirp_lut[2358] = 8'd161; long_chirp_lut[2359] = 8'd 25; + long_chirp_lut[2360] = 8'd 21; long_chirp_lut[2361] = 8'd155; long_chirp_lut[2362] = 8'd253; long_chirp_lut[2363] = 8'd188; long_chirp_lut[2364] = 8'd 45; long_chirp_lut[2365] = 8'd 8; long_chirp_lut[2366] = 8'd127; long_chirp_lut[2367] = 8'd246; + long_chirp_lut[2368] = 8'd212; long_chirp_lut[2369] = 8'd 68; long_chirp_lut[2370] = 8'd 2; long_chirp_lut[2371] = 8'd 99; long_chirp_lut[2372] = 8'd233; long_chirp_lut[2373] = 8'd230; long_chirp_lut[2374] = 8'd 93; long_chirp_lut[2375] = 8'd 1; + long_chirp_lut[2376] = 8'd 73; long_chirp_lut[2377] = 8'd216; long_chirp_lut[2378] = 8'd243; long_chirp_lut[2379] = 8'd119; long_chirp_lut[2380] = 8'd 6; long_chirp_lut[2381] = 8'd 51; long_chirp_lut[2382] = 8'd196; long_chirp_lut[2383] = 8'd252; + long_chirp_lut[2384] = 8'd145; long_chirp_lut[2385] = 8'd 15; long_chirp_lut[2386] = 8'd 33; long_chirp_lut[2387] = 8'd174; long_chirp_lut[2388] = 8'd254; long_chirp_lut[2389] = 8'd169; long_chirp_lut[2390] = 8'd 29; long_chirp_lut[2391] = 8'd 18; + long_chirp_lut[2392] = 8'd151; long_chirp_lut[2393] = 8'd253; long_chirp_lut[2394] = 8'd190; long_chirp_lut[2395] = 8'd 46; long_chirp_lut[2396] = 8'd 8; long_chirp_lut[2397] = 8'd128; long_chirp_lut[2398] = 8'd247; long_chirp_lut[2399] = 8'd209; + long_chirp_lut[2400] = 8'd 64; long_chirp_lut[2401] = 8'd 2; long_chirp_lut[2402] = 8'd106; long_chirp_lut[2403] = 8'd238; long_chirp_lut[2404] = 8'd225; long_chirp_lut[2405] = 8'd 84; long_chirp_lut[2406] = 8'd 1; long_chirp_lut[2407] = 8'd 85; + long_chirp_lut[2408] = 8'd226; long_chirp_lut[2409] = 8'd237; long_chirp_lut[2410] = 8'd104; long_chirp_lut[2411] = 8'd 2; long_chirp_lut[2412] = 8'd 66; long_chirp_lut[2413] = 8'd212; long_chirp_lut[2414] = 8'd246; long_chirp_lut[2415] = 8'd123; + long_chirp_lut[2416] = 8'd 7; long_chirp_lut[2417] = 8'd 50; long_chirp_lut[2418] = 8'd196; long_chirp_lut[2419] = 8'd251; long_chirp_lut[2420] = 8'd142; long_chirp_lut[2421] = 8'd 14; long_chirp_lut[2422] = 8'd 36; long_chirp_lut[2423] = 8'd180; + long_chirp_lut[2424] = 8'd254; long_chirp_lut[2425] = 8'd160; long_chirp_lut[2426] = 8'd 23; long_chirp_lut[2427] = 8'd 25; long_chirp_lut[2428] = 8'd164; long_chirp_lut[2429] = 8'd254; long_chirp_lut[2430] = 8'd176; long_chirp_lut[2431] = 8'd 33; + long_chirp_lut[2432] = 8'd 16; long_chirp_lut[2433] = 8'd148; long_chirp_lut[2434] = 8'd252; long_chirp_lut[2435] = 8'd191; long_chirp_lut[2436] = 8'd 45; long_chirp_lut[2437] = 8'd 9; long_chirp_lut[2438] = 8'd132; long_chirp_lut[2439] = 8'd249; + long_chirp_lut[2440] = 8'd203; long_chirp_lut[2441] = 8'd 56; long_chirp_lut[2442] = 8'd 5; long_chirp_lut[2443] = 8'd117; long_chirp_lut[2444] = 8'd244; long_chirp_lut[2445] = 8'd214; long_chirp_lut[2446] = 8'd 69; long_chirp_lut[2447] = 8'd 2; + long_chirp_lut[2448] = 8'd104; long_chirp_lut[2449] = 8'd237; long_chirp_lut[2450] = 8'd224; long_chirp_lut[2451] = 8'd 81; long_chirp_lut[2452] = 8'd 1; long_chirp_lut[2453] = 8'd 91; long_chirp_lut[2454] = 8'd231; long_chirp_lut[2455] = 8'd231; + long_chirp_lut[2456] = 8'd 92; long_chirp_lut[2457] = 8'd 1; long_chirp_lut[2458] = 8'd 80; long_chirp_lut[2459] = 8'd223; long_chirp_lut[2460] = 8'd237; long_chirp_lut[2461] = 8'd103; long_chirp_lut[2462] = 8'd 2; long_chirp_lut[2463] = 8'd 70; + long_chirp_lut[2464] = 8'd216; long_chirp_lut[2465] = 8'd242; long_chirp_lut[2466] = 8'd114; long_chirp_lut[2467] = 8'd 4; long_chirp_lut[2468] = 8'd 61; long_chirp_lut[2469] = 8'd209; long_chirp_lut[2470] = 8'd246; long_chirp_lut[2471] = 8'd123; + long_chirp_lut[2472] = 8'd 6; long_chirp_lut[2473] = 8'd 54; long_chirp_lut[2474] = 8'd201; long_chirp_lut[2475] = 8'd249; long_chirp_lut[2476] = 8'd132; long_chirp_lut[2477] = 8'd 9; long_chirp_lut[2478] = 8'd 47; long_chirp_lut[2479] = 8'd195; + long_chirp_lut[2480] = 8'd251; long_chirp_lut[2481] = 8'd139; long_chirp_lut[2482] = 8'd 11; long_chirp_lut[2483] = 8'd 42; long_chirp_lut[2484] = 8'd189; long_chirp_lut[2485] = 8'd252; long_chirp_lut[2486] = 8'd146; long_chirp_lut[2487] = 8'd 14; + long_chirp_lut[2488] = 8'd 37; long_chirp_lut[2489] = 8'd183; long_chirp_lut[2490] = 8'd253; long_chirp_lut[2491] = 8'd152; long_chirp_lut[2492] = 8'd 17; long_chirp_lut[2493] = 8'd 33; long_chirp_lut[2494] = 8'd178; long_chirp_lut[2495] = 8'd254; + long_chirp_lut[2496] = 8'd157; long_chirp_lut[2497] = 8'd 19; long_chirp_lut[2498] = 8'd 30; long_chirp_lut[2499] = 8'd174; long_chirp_lut[2500] = 8'd254; long_chirp_lut[2501] = 8'd160; long_chirp_lut[2502] = 8'd 21; long_chirp_lut[2503] = 8'd 28; + long_chirp_lut[2504] = 8'd171; long_chirp_lut[2505] = 8'd254; long_chirp_lut[2506] = 8'd163; long_chirp_lut[2507] = 8'd 23; long_chirp_lut[2508] = 8'd 26; long_chirp_lut[2509] = 8'd169; long_chirp_lut[2510] = 8'd254; long_chirp_lut[2511] = 8'd165; + long_chirp_lut[2512] = 8'd 24; long_chirp_lut[2513] = 8'd 25; long_chirp_lut[2514] = 8'd167; long_chirp_lut[2515] = 8'd254; long_chirp_lut[2516] = 8'd166; long_chirp_lut[2517] = 8'd 25; long_chirp_lut[2518] = 8'd 25; long_chirp_lut[2519] = 8'd167; + long_chirp_lut[2520] = 8'd255; long_chirp_lut[2521] = 8'd167; long_chirp_lut[2522] = 8'd 25; long_chirp_lut[2523] = 8'd 25; long_chirp_lut[2524] = 8'd167; long_chirp_lut[2525] = 8'd254; long_chirp_lut[2526] = 8'd166; long_chirp_lut[2527] = 8'd 24; + long_chirp_lut[2528] = 8'd 25; long_chirp_lut[2529] = 8'd168; long_chirp_lut[2530] = 8'd254; long_chirp_lut[2531] = 8'd165; long_chirp_lut[2532] = 8'd 23; long_chirp_lut[2533] = 8'd 27; long_chirp_lut[2534] = 8'd170; long_chirp_lut[2535] = 8'd254; + long_chirp_lut[2536] = 8'd162; long_chirp_lut[2537] = 8'd 22; long_chirp_lut[2538] = 8'd 28; long_chirp_lut[2539] = 8'd173; long_chirp_lut[2540] = 8'd254; long_chirp_lut[2541] = 8'd159; long_chirp_lut[2542] = 8'd 20; long_chirp_lut[2543] = 8'd 31; + long_chirp_lut[2544] = 8'd177; long_chirp_lut[2545] = 8'd254; long_chirp_lut[2546] = 8'd155; long_chirp_lut[2547] = 8'd 17; long_chirp_lut[2548] = 8'd 34; long_chirp_lut[2549] = 8'd181; long_chirp_lut[2550] = 8'd253; long_chirp_lut[2551] = 8'd150; + long_chirp_lut[2552] = 8'd 15; long_chirp_lut[2553] = 8'd 38; long_chirp_lut[2554] = 8'd186; long_chirp_lut[2555] = 8'd252; long_chirp_lut[2556] = 8'd143; long_chirp_lut[2557] = 8'd 12; long_chirp_lut[2558] = 8'd 43; long_chirp_lut[2559] = 8'd192; + long_chirp_lut[2560] = 8'd251; long_chirp_lut[2561] = 8'd136; long_chirp_lut[2562] = 8'd 9; long_chirp_lut[2563] = 8'd 48; long_chirp_lut[2564] = 8'd199; long_chirp_lut[2565] = 8'd249; long_chirp_lut[2566] = 8'd128; long_chirp_lut[2567] = 8'd 6; + long_chirp_lut[2568] = 8'd 55; long_chirp_lut[2569] = 8'd206; long_chirp_lut[2570] = 8'd246; long_chirp_lut[2571] = 8'd119; long_chirp_lut[2572] = 8'd 4; long_chirp_lut[2573] = 8'd 63; long_chirp_lut[2574] = 8'd213; long_chirp_lut[2575] = 8'd242; + long_chirp_lut[2576] = 8'd110; long_chirp_lut[2577] = 8'd 2; long_chirp_lut[2578] = 8'd 72; long_chirp_lut[2579] = 8'd220; long_chirp_lut[2580] = 8'd237; long_chirp_lut[2581] = 8'd 99; long_chirp_lut[2582] = 8'd 1; long_chirp_lut[2583] = 8'd 82; + long_chirp_lut[2584] = 8'd228; long_chirp_lut[2585] = 8'd231; long_chirp_lut[2586] = 8'd 88; long_chirp_lut[2587] = 8'd 1; long_chirp_lut[2588] = 8'd 94; long_chirp_lut[2589] = 8'd235; long_chirp_lut[2590] = 8'd224; long_chirp_lut[2591] = 8'd 76; + long_chirp_lut[2592] = 8'd 2; long_chirp_lut[2593] = 8'd106; long_chirp_lut[2594] = 8'd241; long_chirp_lut[2595] = 8'd214; long_chirp_lut[2596] = 8'd 64; long_chirp_lut[2597] = 8'd 4; long_chirp_lut[2598] = 8'd120; long_chirp_lut[2599] = 8'd247; + long_chirp_lut[2600] = 8'd203; long_chirp_lut[2601] = 8'd 52; long_chirp_lut[2602] = 8'd 8; long_chirp_lut[2603] = 8'd135; long_chirp_lut[2604] = 8'd251; long_chirp_lut[2605] = 8'd191; long_chirp_lut[2606] = 8'd 40; long_chirp_lut[2607] = 8'd 14; + long_chirp_lut[2608] = 8'd151; long_chirp_lut[2609] = 8'd254; long_chirp_lut[2610] = 8'd176; long_chirp_lut[2611] = 8'd 29; long_chirp_lut[2612] = 8'd 23; long_chirp_lut[2613] = 8'd167; long_chirp_lut[2614] = 8'd254; long_chirp_lut[2615] = 8'd160; + long_chirp_lut[2616] = 8'd 19; long_chirp_lut[2617] = 8'd 34; long_chirp_lut[2618] = 8'd183; long_chirp_lut[2619] = 8'd253; long_chirp_lut[2620] = 8'd142; long_chirp_lut[2621] = 8'd 11; long_chirp_lut[2622] = 8'd 47; long_chirp_lut[2623] = 8'd199; + long_chirp_lut[2624] = 8'd248; long_chirp_lut[2625] = 8'd123; long_chirp_lut[2626] = 8'd 4; long_chirp_lut[2627] = 8'd 63; long_chirp_lut[2628] = 8'd214; long_chirp_lut[2629] = 8'd241; long_chirp_lut[2630] = 8'd104; long_chirp_lut[2631] = 8'd 1; + long_chirp_lut[2632] = 8'd 81; long_chirp_lut[2633] = 8'd228; long_chirp_lut[2634] = 8'd230; long_chirp_lut[2635] = 8'd 84; long_chirp_lut[2636] = 8'd 1; long_chirp_lut[2637] = 8'd101; long_chirp_lut[2638] = 8'd240; long_chirp_lut[2639] = 8'd216; + long_chirp_lut[2640] = 8'd 64; long_chirp_lut[2641] = 8'd 4; long_chirp_lut[2642] = 8'd123; long_chirp_lut[2643] = 8'd248; long_chirp_lut[2644] = 8'd198; long_chirp_lut[2645] = 8'd 46; long_chirp_lut[2646] = 8'd 12; long_chirp_lut[2647] = 8'd146; + long_chirp_lut[2648] = 8'd253; long_chirp_lut[2649] = 8'd178; long_chirp_lut[2650] = 8'd 29; long_chirp_lut[2651] = 8'd 23; long_chirp_lut[2652] = 8'd169; long_chirp_lut[2653] = 8'd254; long_chirp_lut[2654] = 8'd155; long_chirp_lut[2655] = 8'd 15; + long_chirp_lut[2656] = 8'd 39; long_chirp_lut[2657] = 8'd192; long_chirp_lut[2658] = 8'd250; long_chirp_lut[2659] = 8'd130; long_chirp_lut[2660] = 8'd 6; long_chirp_lut[2661] = 8'd 60; long_chirp_lut[2662] = 8'd213; long_chirp_lut[2663] = 8'd241; + long_chirp_lut[2664] = 8'd104; long_chirp_lut[2665] = 8'd 1; long_chirp_lut[2666] = 8'd 83; long_chirp_lut[2667] = 8'd230; long_chirp_lut[2668] = 8'd227; long_chirp_lut[2669] = 8'd 78; long_chirp_lut[2670] = 8'd 2; long_chirp_lut[2671] = 8'd110; + long_chirp_lut[2672] = 8'd244; long_chirp_lut[2673] = 8'd207; long_chirp_lut[2674] = 8'd 54; long_chirp_lut[2675] = 8'd 8; long_chirp_lut[2676] = 8'd138; long_chirp_lut[2677] = 8'd252; long_chirp_lut[2678] = 8'd183; long_chirp_lut[2679] = 8'd 32; + long_chirp_lut[2680] = 8'd 21; long_chirp_lut[2681] = 8'd167; long_chirp_lut[2682] = 8'd254; long_chirp_lut[2683] = 8'd155; long_chirp_lut[2684] = 8'd 15; long_chirp_lut[2685] = 8'd 41; long_chirp_lut[2686] = 8'd194; long_chirp_lut[2687] = 8'd249; + long_chirp_lut[2688] = 8'd125; long_chirp_lut[2689] = 8'd 4; long_chirp_lut[2690] = 8'd 66; long_chirp_lut[2691] = 8'd218; long_chirp_lut[2692] = 8'd237; long_chirp_lut[2693] = 8'd 94; long_chirp_lut[2694] = 8'd 1; long_chirp_lut[2695] = 8'd 95; + long_chirp_lut[2696] = 8'd238; long_chirp_lut[2697] = 8'd217; long_chirp_lut[2698] = 8'd 64; long_chirp_lut[2699] = 8'd 5; long_chirp_lut[2700] = 8'd127; long_chirp_lut[2701] = 8'd250; long_chirp_lut[2702] = 8'd191; long_chirp_lut[2703] = 8'd 38; + long_chirp_lut[2704] = 8'd 18; long_chirp_lut[2705] = 8'd161; long_chirp_lut[2706] = 8'd254; long_chirp_lut[2707] = 8'd159; long_chirp_lut[2708] = 8'd 17; long_chirp_lut[2709] = 8'd 39; long_chirp_lut[2710] = 8'd193; long_chirp_lut[2711] = 8'd250; + long_chirp_lut[2712] = 8'd125; long_chirp_lut[2713] = 8'd 4; long_chirp_lut[2714] = 8'd 67; long_chirp_lut[2715] = 8'd220; long_chirp_lut[2716] = 8'd235; long_chirp_lut[2717] = 8'd 90; long_chirp_lut[2718] = 8'd 1; long_chirp_lut[2719] = 8'd101; + long_chirp_lut[2720] = 8'd241; long_chirp_lut[2721] = 8'd211; long_chirp_lut[2722] = 8'd 56; long_chirp_lut[2723] = 8'd 8; long_chirp_lut[2724] = 8'd138; long_chirp_lut[2725] = 8'd253; long_chirp_lut[2726] = 8'd180; long_chirp_lut[2727] = 8'd 29; + long_chirp_lut[2728] = 8'd 25; long_chirp_lut[2729] = 8'd175; long_chirp_lut[2730] = 8'd253; long_chirp_lut[2731] = 8'd143; long_chirp_lut[2732] = 8'd 9; long_chirp_lut[2733] = 8'd 53; long_chirp_lut[2734] = 8'd209; long_chirp_lut[2735] = 8'd242; + long_chirp_lut[2736] = 8'd104; long_chirp_lut[2737] = 8'd 1; long_chirp_lut[2738] = 8'd 88; long_chirp_lut[2739] = 8'd235; long_chirp_lut[2740] = 8'd220; long_chirp_lut[2741] = 8'd 66; long_chirp_lut[2742] = 8'd 5; long_chirp_lut[2743] = 8'd128; + long_chirp_lut[2744] = 8'd251; long_chirp_lut[2745] = 8'd187; long_chirp_lut[2746] = 8'd 34; long_chirp_lut[2747] = 8'd 21; long_chirp_lut[2748] = 8'd169; long_chirp_lut[2749] = 8'd254; long_chirp_lut[2750] = 8'd148; long_chirp_lut[2751] = 8'd 11; + long_chirp_lut[2752] = 8'd 50; long_chirp_lut[2753] = 8'd206; long_chirp_lut[2754] = 8'd243; long_chirp_lut[2755] = 8'd105; long_chirp_lut[2756] = 8'd 1; long_chirp_lut[2757] = 8'd 88; long_chirp_lut[2758] = 8'd235; long_chirp_lut[2759] = 8'd219; + long_chirp_lut[2760] = 8'd 64; long_chirp_lut[2761] = 8'd 5; long_chirp_lut[2762] = 8'd132; long_chirp_lut[2763] = 8'd252; long_chirp_lut[2764] = 8'd183; long_chirp_lut[2765] = 8'd 30; long_chirp_lut[2766] = 8'd 25; long_chirp_lut[2767] = 8'd176; + long_chirp_lut[2768] = 8'd253; long_chirp_lut[2769] = 8'd139; long_chirp_lut[2770] = 8'd 8; long_chirp_lut[2771] = 8'd 58; long_chirp_lut[2772] = 8'd214; long_chirp_lut[2773] = 8'd238; long_chirp_lut[2774] = 8'd 93; long_chirp_lut[2775] = 8'd 1; + long_chirp_lut[2776] = 8'd101; long_chirp_lut[2777] = 8'd242; long_chirp_lut[2778] = 8'd208; long_chirp_lut[2779] = 8'd 51; long_chirp_lut[2780] = 8'd 11; long_chirp_lut[2781] = 8'd149; long_chirp_lut[2782] = 8'd254; long_chirp_lut[2783] = 8'd166; + long_chirp_lut[2784] = 8'd 19; long_chirp_lut[2785] = 8'd 38; long_chirp_lut[2786] = 8'd194; long_chirp_lut[2787] = 8'd248; long_chirp_lut[2788] = 8'd117; long_chirp_lut[2789] = 8'd 2; long_chirp_lut[2790] = 8'd 79; long_chirp_lut[2791] = 8'd230; + long_chirp_lut[2792] = 8'd224; long_chirp_lut[2793] = 8'd 70; long_chirp_lut[2794] = 8'd 4; long_chirp_lut[2795] = 8'd128; long_chirp_lut[2796] = 8'd251; long_chirp_lut[2797] = 8'd184; long_chirp_lut[2798] = 8'd 30; long_chirp_lut[2799] = 8'd 26; + long_chirp_lut[2800] = 8'd178; long_chirp_lut[2801] = 8'd253; long_chirp_lut[2802] = 8'd135; long_chirp_lut[2803] = 8'd 6; long_chirp_lut[2804] = 8'd 64; long_chirp_lut[2805] = 8'd220; long_chirp_lut[2806] = 8'd233; long_chirp_lut[2807] = 8'd 83; + long_chirp_lut[2808] = 8'd 2; long_chirp_lut[2809] = 8'd114; long_chirp_lut[2810] = 8'd247; long_chirp_lut[2811] = 8'd195; long_chirp_lut[2812] = 8'd 38; long_chirp_lut[2813] = 8'd 19; long_chirp_lut[2814] = 8'd167; long_chirp_lut[2815] = 8'd254; + long_chirp_lut[2816] = 8'd145; long_chirp_lut[2817] = 8'd 9; long_chirp_lut[2818] = 8'd 57; long_chirp_lut[2819] = 8'd214; long_chirp_lut[2820] = 8'd237; long_chirp_lut[2821] = 8'd 90; long_chirp_lut[2822] = 8'd 1; long_chirp_lut[2823] = 8'd108; + long_chirp_lut[2824] = 8'd245; long_chirp_lut[2825] = 8'd200; long_chirp_lut[2826] = 8'd 42; long_chirp_lut[2827] = 8'd 17; long_chirp_lut[2828] = 8'd164; long_chirp_lut[2829] = 8'd254; long_chirp_lut[2830] = 8'd148; long_chirp_lut[2831] = 8'd 10; + long_chirp_lut[2832] = 8'd 55; long_chirp_lut[2833] = 8'd213; long_chirp_lut[2834] = 8'd238; long_chirp_lut[2835] = 8'd 91; long_chirp_lut[2836] = 8'd 1; long_chirp_lut[2837] = 8'd109; long_chirp_lut[2838] = 8'd246; long_chirp_lut[2839] = 8'd199; + long_chirp_lut[2840] = 8'd 40; long_chirp_lut[2841] = 8'd 18; long_chirp_lut[2842] = 8'd167; long_chirp_lut[2843] = 8'd254; long_chirp_lut[2844] = 8'd143; long_chirp_lut[2845] = 8'd 8; long_chirp_lut[2846] = 8'd 60; long_chirp_lut[2847] = 8'd217; + long_chirp_lut[2848] = 8'd235; long_chirp_lut[2849] = 8'd 84; long_chirp_lut[2850] = 8'd 2; long_chirp_lut[2851] = 8'd116; long_chirp_lut[2852] = 8'd249; long_chirp_lut[2853] = 8'd191; long_chirp_lut[2854] = 8'd 34; long_chirp_lut[2855] = 8'd 24; + long_chirp_lut[2856] = 8'd177; long_chirp_lut[2857] = 8'd252; long_chirp_lut[2858] = 8'd132; long_chirp_lut[2859] = 8'd 4; long_chirp_lut[2860] = 8'd 71; long_chirp_lut[2861] = 8'd226; long_chirp_lut[2862] = 8'd227; long_chirp_lut[2863] = 8'd 71; + long_chirp_lut[2864] = 8'd 4; long_chirp_lut[2865] = 8'd132; long_chirp_lut[2866] = 8'd252; long_chirp_lut[2867] = 8'd176; long_chirp_lut[2868] = 8'd 23; long_chirp_lut[2869] = 8'd 35; long_chirp_lut[2870] = 8'd193; long_chirp_lut[2871] = 8'd248; + long_chirp_lut[2872] = 8'd113; long_chirp_lut[2873] = 8'd 1; long_chirp_lut[2874] = 8'd 89; long_chirp_lut[2875] = 8'd238; long_chirp_lut[2876] = 8'd212; long_chirp_lut[2877] = 8'd 53; long_chirp_lut[2878] = 8'd 12; long_chirp_lut[2879] = 8'd154; + long_chirp_lut[2880] = 8'd255; long_chirp_lut[2881] = 8'd154; long_chirp_lut[2882] = 8'd 11; long_chirp_lut[2883] = 8'd 53; long_chirp_lut[2884] = 8'd213; long_chirp_lut[2885] = 8'd237; long_chirp_lut[2886] = 8'd 88; long_chirp_lut[2887] = 8'd 1; + long_chirp_lut[2888] = 8'd115; long_chirp_lut[2889] = 8'd249; long_chirp_lut[2890] = 8'd189; long_chirp_lut[2891] = 8'd 32; long_chirp_lut[2892] = 8'd 26; long_chirp_lut[2893] = 8'd182; long_chirp_lut[2894] = 8'd251; long_chirp_lut[2895] = 8'd123; + long_chirp_lut[2896] = 8'd 2; long_chirp_lut[2897] = 8'd 81; long_chirp_lut[2898] = 8'd234; long_chirp_lut[2899] = 8'd217; long_chirp_lut[2900] = 8'd 58; long_chirp_lut[2901] = 8'd 9; long_chirp_lut[2902] = 8'd150; long_chirp_lut[2903] = 8'd254; + long_chirp_lut[2904] = 8'd157; long_chirp_lut[2905] = 8'd 12; long_chirp_lut[2906] = 8'd 52; long_chirp_lut[2907] = 8'd213; long_chirp_lut[2908] = 8'd237; long_chirp_lut[2909] = 8'd 86; long_chirp_lut[2910] = 8'd 2; long_chirp_lut[2911] = 8'd119; + long_chirp_lut[2912] = 8'd250; long_chirp_lut[2913] = 8'd185; long_chirp_lut[2914] = 8'd 28; long_chirp_lut[2915] = 8'd 31; long_chirp_lut[2916] = 8'd189; long_chirp_lut[2917] = 8'd249; long_chirp_lut[2918] = 8'd114; long_chirp_lut[2919] = 8'd 1; + long_chirp_lut[2920] = 8'd 91; long_chirp_lut[2921] = 8'd240; long_chirp_lut[2922] = 8'd208; long_chirp_lut[2923] = 8'd 47; long_chirp_lut[2924] = 8'd 16; long_chirp_lut[2925] = 8'd164; long_chirp_lut[2926] = 8'd254; long_chirp_lut[2927] = 8'd140; + long_chirp_lut[2928] = 8'd 6; long_chirp_lut[2929] = 8'd 68; long_chirp_lut[2930] = 8'd226; long_chirp_lut[2931] = 8'd225; long_chirp_lut[2932] = 8'd 67; long_chirp_lut[2933] = 8'd 6; long_chirp_lut[2934] = 8'd141; long_chirp_lut[2935] = 8'd254; + long_chirp_lut[2936] = 8'd162; long_chirp_lut[2937] = 8'd 14; long_chirp_lut[2938] = 8'd 49; long_chirp_lut[2939] = 8'd211; long_chirp_lut[2940] = 8'd237; long_chirp_lut[2941] = 8'd 86; long_chirp_lut[2942] = 8'd 2; long_chirp_lut[2943] = 8'd121; + long_chirp_lut[2944] = 8'd251; long_chirp_lut[2945] = 8'd181; long_chirp_lut[2946] = 8'd 24; long_chirp_lut[2947] = 8'd 35; long_chirp_lut[2948] = 8'd196; long_chirp_lut[2949] = 8'd246; long_chirp_lut[2950] = 8'd104; long_chirp_lut[2951] = 8'd 1; + long_chirp_lut[2952] = 8'd104; long_chirp_lut[2953] = 8'd246; long_chirp_lut[2954] = 8'd195; long_chirp_lut[2955] = 8'd 35; long_chirp_lut[2956] = 8'd 25; long_chirp_lut[2957] = 8'd182; long_chirp_lut[2958] = 8'd250; long_chirp_lut[2959] = 8'd119; + long_chirp_lut[2960] = 8'd 1; long_chirp_lut[2961] = 8'd 90; long_chirp_lut[2962] = 8'd240; long_chirp_lut[2963] = 8'd207; long_chirp_lut[2964] = 8'd 45; long_chirp_lut[2965] = 8'd 18; long_chirp_lut[2966] = 8'd170; long_chirp_lut[2967] = 8'd253; + long_chirp_lut[2968] = 8'd131; long_chirp_lut[2969] = 8'd 3; long_chirp_lut[2970] = 8'd 79; long_chirp_lut[2971] = 8'd234; long_chirp_lut[2972] = 8'd215; long_chirp_lut[2973] = 8'd 53; long_chirp_lut[2974] = 8'd 13; long_chirp_lut[2975] = 8'd161; + long_chirp_lut[2976] = 8'd254; long_chirp_lut[2977] = 8'd140; long_chirp_lut[2978] = 8'd 5; long_chirp_lut[2979] = 8'd 71; long_chirp_lut[2980] = 8'd229; long_chirp_lut[2981] = 8'd220; long_chirp_lut[2982] = 8'd 59; long_chirp_lut[2983] = 8'd 10; + long_chirp_lut[2984] = 8'd154; long_chirp_lut[2985] = 8'd254; long_chirp_lut[2986] = 8'd146; long_chirp_lut[2987] = 8'd 7; long_chirp_lut[2988] = 8'd 66; long_chirp_lut[2989] = 8'd226; long_chirp_lut[2990] = 8'd224; long_chirp_lut[2991] = 8'd 63; + long_chirp_lut[2992] = 8'd 9; long_chirp_lut[2993] = 8'd150; long_chirp_lut[2994] = 8'd254; long_chirp_lut[2995] = 8'd149; long_chirp_lut[2996] = 8'd 8; long_chirp_lut[2997] = 8'd 64; long_chirp_lut[2998] = 8'd225; long_chirp_lut[2999] = 8'd225; + long_chirp_lut[3000] = 8'd 64; long_chirp_lut[3001] = 8'd 8; long_chirp_lut[3002] = 8'd150; long_chirp_lut[3003] = 8'd254; long_chirp_lut[3004] = 8'd149; long_chirp_lut[3005] = 8'd 8; long_chirp_lut[3006] = 8'd 65; long_chirp_lut[3007] = 8'd225; + long_chirp_lut[3008] = 8'd224; long_chirp_lut[3009] = 8'd 63; long_chirp_lut[3010] = 8'd 9; long_chirp_lut[3011] = 8'd152; long_chirp_lut[3012] = 8'd254; long_chirp_lut[3013] = 8'd146; long_chirp_lut[3014] = 8'd 7; long_chirp_lut[3015] = 8'd 68; + long_chirp_lut[3016] = 8'd228; long_chirp_lut[3017] = 8'd221; long_chirp_lut[3018] = 8'd 59; long_chirp_lut[3019] = 8'd 11; long_chirp_lut[3020] = 8'd157; long_chirp_lut[3021] = 8'd254; long_chirp_lut[3022] = 8'd141; long_chirp_lut[3023] = 8'd 5; + long_chirp_lut[3024] = 8'd 73; long_chirp_lut[3025] = 8'd232; long_chirp_lut[3026] = 8'd216; long_chirp_lut[3027] = 8'd 53; long_chirp_lut[3028] = 8'd 14; long_chirp_lut[3029] = 8'd165; long_chirp_lut[3030] = 8'd253; long_chirp_lut[3031] = 8'd132; + long_chirp_lut[3032] = 8'd 3; long_chirp_lut[3033] = 8'd 82; long_chirp_lut[3034] = 8'd237; long_chirp_lut[3035] = 8'd209; long_chirp_lut[3036] = 8'd 45; long_chirp_lut[3037] = 8'd 19; long_chirp_lut[3038] = 8'd175; long_chirp_lut[3039] = 8'd251; + long_chirp_lut[3040] = 8'd120; long_chirp_lut[3041] = 8'd 1; long_chirp_lut[3042] = 8'd 94; long_chirp_lut[3043] = 8'd243; long_chirp_lut[3044] = 8'd198; long_chirp_lut[3045] = 8'd 35; long_chirp_lut[3046] = 8'd 27; long_chirp_lut[3047] = 8'd188; + long_chirp_lut[3048] = 8'd247; long_chirp_lut[3049] = 8'd105; long_chirp_lut[3050] = 8'd 1; long_chirp_lut[3051] = 8'd109; long_chirp_lut[3052] = 8'd249; long_chirp_lut[3053] = 8'd184; long_chirp_lut[3054] = 8'd 24; long_chirp_lut[3055] = 8'd 38; + long_chirp_lut[3056] = 8'd202; long_chirp_lut[3057] = 8'd241; long_chirp_lut[3058] = 8'd 88; long_chirp_lut[3059] = 8'd 2; long_chirp_lut[3060] = 8'd127; long_chirp_lut[3061] = 8'd253; long_chirp_lut[3062] = 8'd167; long_chirp_lut[3063] = 8'd 14; + long_chirp_lut[3064] = 8'd 53; long_chirp_lut[3065] = 8'd218; long_chirp_lut[3066] = 8'd230; long_chirp_lut[3067] = 8'd 69; long_chirp_lut[3068] = 8'd 7; long_chirp_lut[3069] = 8'd149; long_chirp_lut[3070] = 8'd254; long_chirp_lut[3071] = 8'd145; + long_chirp_lut[3072] = 8'd 6; long_chirp_lut[3073] = 8'd 73; long_chirp_lut[3074] = 8'd232; long_chirp_lut[3075] = 8'd214; long_chirp_lut[3076] = 8'd 49; long_chirp_lut[3077] = 8'd 17; long_chirp_lut[3078] = 8'd172; long_chirp_lut[3079] = 8'd252; + long_chirp_lut[3080] = 8'd120; long_chirp_lut[3081] = 8'd 1; long_chirp_lut[3082] = 8'd 97; long_chirp_lut[3083] = 8'd245; long_chirp_lut[3084] = 8'd193; long_chirp_lut[3085] = 8'd 30; long_chirp_lut[3086] = 8'd 33; long_chirp_lut[3087] = 8'd197; + long_chirp_lut[3088] = 8'd243; long_chirp_lut[3089] = 8'd 92; long_chirp_lut[3090] = 8'd 2; long_chirp_lut[3091] = 8'd125; long_chirp_lut[3092] = 8'd253; long_chirp_lut[3093] = 8'd167; long_chirp_lut[3094] = 8'd 14; long_chirp_lut[3095] = 8'd 55; + long_chirp_lut[3096] = 8'd220; long_chirp_lut[3097] = 8'd227; long_chirp_lut[3098] = 8'd 64; long_chirp_lut[3099] = 8'd 9; long_chirp_lut[3100] = 8'd157; long_chirp_lut[3101] = 8'd254; long_chirp_lut[3102] = 8'd135; long_chirp_lut[3103] = 8'd 3; + long_chirp_lut[3104] = 8'd 84; long_chirp_lut[3105] = 8'd240; long_chirp_lut[3106] = 8'd203; long_chirp_lut[3107] = 8'd 37; long_chirp_lut[3108] = 8'd 26; long_chirp_lut[3109] = 8'd189; long_chirp_lut[3110] = 8'd246; long_chirp_lut[3111] = 8'd100; + long_chirp_lut[3112] = 8'd 1; long_chirp_lut[3113] = 8'd120; long_chirp_lut[3114] = 8'd252; long_chirp_lut[3115] = 8'd171; long_chirp_lut[3116] = 8'd 15; long_chirp_lut[3117] = 8'd 53; long_chirp_lut[3118] = 8'd219; long_chirp_lut[3119] = 8'd228; + long_chirp_lut[3120] = 8'd 64; long_chirp_lut[3121] = 8'd 10; long_chirp_lut[3122] = 8'd158; long_chirp_lut[3123] = 8'd254; long_chirp_lut[3124] = 8'd132; long_chirp_lut[3125] = 8'd 2; long_chirp_lut[3126] = 8'd 89; long_chirp_lut[3127] = 8'd242; + long_chirp_lut[3128] = 8'd198; long_chirp_lut[3129] = 8'd 32; long_chirp_lut[3130] = 8'd 31; long_chirp_lut[3131] = 8'd197; long_chirp_lut[3132] = 8'd242; long_chirp_lut[3133] = 8'd 90; long_chirp_lut[3134] = 8'd 2; long_chirp_lut[3135] = 8'd132; + long_chirp_lut[3136] = 8'd254; long_chirp_lut[3137] = 8'd157; long_chirp_lut[3138] = 8'd 9; long_chirp_lut[3139] = 8'd 66; long_chirp_lut[3140] = 8'd229; long_chirp_lut[3141] = 8'd216; long_chirp_lut[3142] = 8'd 49; long_chirp_lut[3143] = 8'd 18; + long_chirp_lut[3144] = 8'd177; long_chirp_lut[3145] = 8'd250; long_chirp_lut[3146] = 8'd111; long_chirp_lut[3147] = 8'd 1; long_chirp_lut[3148] = 8'd111; long_chirp_lut[3149] = 8'd250; long_chirp_lut[3150] = 8'd176; long_chirp_lut[3151] = 8'd 18; + long_chirp_lut[3152] = 8'd 50; long_chirp_lut[3153] = 8'd217; long_chirp_lut[3154] = 8'd228; long_chirp_lut[3155] = 8'd 64; long_chirp_lut[3156] = 8'd 10; long_chirp_lut[3157] = 8'd161; long_chirp_lut[3158] = 8'd253; long_chirp_lut[3159] = 8'd126; + long_chirp_lut[3160] = 8'd 1; long_chirp_lut[3161] = 8'd 97; long_chirp_lut[3162] = 8'd246; long_chirp_lut[3163] = 8'd188; long_chirp_lut[3164] = 8'd 25; long_chirp_lut[3165] = 8'd 41; long_chirp_lut[3166] = 8'd209; long_chirp_lut[3167] = 8'd235; + long_chirp_lut[3168] = 8'd 73; long_chirp_lut[3169] = 8'd 7; long_chirp_lut[3170] = 8'd151; long_chirp_lut[3171] = 8'd254; long_chirp_lut[3172] = 8'd135; long_chirp_lut[3173] = 8'd 3; long_chirp_lut[3174] = 8'd 89; long_chirp_lut[3175] = 8'd243; + long_chirp_lut[3176] = 8'd195; long_chirp_lut[3177] = 8'd 29; long_chirp_lut[3178] = 8'd 36; long_chirp_lut[3179] = 8'd204; long_chirp_lut[3180] = 8'd237; long_chirp_lut[3181] = 8'd 78; long_chirp_lut[3182] = 8'd 5; long_chirp_lut[3183] = 8'd148; + long_chirp_lut[3184] = 8'd254; long_chirp_lut[3185] = 8'd138; long_chirp_lut[3186] = 8'd 3; long_chirp_lut[3187] = 8'd 87; long_chirp_lut[3188] = 8'd242; long_chirp_lut[3189] = 8'd195; long_chirp_lut[3190] = 8'd 29; long_chirp_lut[3191] = 8'd 36; + long_chirp_lut[3192] = 8'd204; long_chirp_lut[3193] = 8'd237; long_chirp_lut[3194] = 8'd 77; long_chirp_lut[3195] = 8'd 6; long_chirp_lut[3196] = 8'd150; long_chirp_lut[3197] = 8'd254; long_chirp_lut[3198] = 8'd135; long_chirp_lut[3199] = 8'd 2; + long_chirp_lut[3200] = 8'd 91; long_chirp_lut[3201] = 8'd244; long_chirp_lut[3202] = 8'd191; long_chirp_lut[3203] = 8'd 26; long_chirp_lut[3204] = 8'd 41; long_chirp_lut[3205] = 8'd209; long_chirp_lut[3206] = 8'd233; long_chirp_lut[3207] = 8'd 70; + long_chirp_lut[3208] = 8'd 9; long_chirp_lut[3209] = 8'd158; long_chirp_lut[3210] = 8'd253; long_chirp_lut[3211] = 8'd125; long_chirp_lut[3212] = 8'd 1; long_chirp_lut[3213] = 8'd101; long_chirp_lut[3214] = 8'd248; long_chirp_lut[3215] = 8'd181; + long_chirp_lut[3216] = 8'd 19; long_chirp_lut[3217] = 8'd 50; long_chirp_lut[3218] = 8'd219; long_chirp_lut[3219] = 8'd225; long_chirp_lut[3220] = 8'd 58; long_chirp_lut[3221] = 8'd 14; long_chirp_lut[3222] = 8'd172; long_chirp_lut[3223] = 8'd251; + long_chirp_lut[3224] = 8'd110; long_chirp_lut[3225] = 8'd 1; long_chirp_lut[3226] = 8'd118; long_chirp_lut[3227] = 8'd252; long_chirp_lut[3228] = 8'd164; long_chirp_lut[3229] = 8'd 11; long_chirp_lut[3230] = 8'd 66; long_chirp_lut[3231] = 8'd231; + long_chirp_lut[3232] = 8'd212; long_chirp_lut[3233] = 8'd 42; long_chirp_lut[3234] = 8'd 25; long_chirp_lut[3235] = 8'd191; long_chirp_lut[3236] = 8'd243; long_chirp_lut[3237] = 8'd 88; long_chirp_lut[3238] = 8'd 3; long_chirp_lut[3239] = 8'd141; + long_chirp_lut[3240] = 8'd255; long_chirp_lut[3241] = 8'd141; long_chirp_lut[3242] = 8'd 3; long_chirp_lut[3243] = 8'd 88; long_chirp_lut[3244] = 8'd244; long_chirp_lut[3245] = 8'd191; long_chirp_lut[3246] = 8'd 24; long_chirp_lut[3247] = 8'd 43; + long_chirp_lut[3248] = 8'd213; long_chirp_lut[3249] = 8'd229; long_chirp_lut[3250] = 8'd 62; long_chirp_lut[3251] = 8'd 12; long_chirp_lut[3252] = 8'd169; long_chirp_lut[3253] = 8'd251; long_chirp_lut[3254] = 8'd111; long_chirp_lut[3255] = 8'd 1; + long_chirp_lut[3256] = 8'd119; long_chirp_lut[3257] = 8'd253; long_chirp_lut[3258] = 8'd161; long_chirp_lut[3259] = 8'd 9; long_chirp_lut[3260] = 8'd 71; long_chirp_lut[3261] = 8'd235; long_chirp_lut[3262] = 8'd206; long_chirp_lut[3263] = 8'd 36; + long_chirp_lut[3264] = 8'd 31; long_chirp_lut[3265] = 8'd201; long_chirp_lut[3266] = 8'd238; long_chirp_lut[3267] = 8'd 76; long_chirp_lut[3268] = 8'd 7; long_chirp_lut[3269] = 8'd156; long_chirp_lut[3270] = 8'd253; long_chirp_lut[3271] = 8'd123; + long_chirp_lut[3272] = 8'd 1; long_chirp_lut[3273] = 8'd108; long_chirp_lut[3274] = 8'd251; long_chirp_lut[3275] = 8'd171; long_chirp_lut[3276] = 8'd 13; long_chirp_lut[3277] = 8'd 63; long_chirp_lut[3278] = 8'd230; long_chirp_lut[3279] = 8'd211; + long_chirp_lut[3280] = 8'd 40; long_chirp_lut[3281] = 8'd 27; long_chirp_lut[3282] = 8'd196; long_chirp_lut[3283] = 8'd240; long_chirp_lut[3284] = 8'd 80; long_chirp_lut[3285] = 8'd 6; long_chirp_lut[3286] = 8'd153; long_chirp_lut[3287] = 8'd254; + long_chirp_lut[3288] = 8'd125; long_chirp_lut[3289] = 8'd 1; long_chirp_lut[3290] = 8'd107; long_chirp_lut[3291] = 8'd251; long_chirp_lut[3292] = 8'd170; long_chirp_lut[3293] = 8'd 12; long_chirp_lut[3294] = 8'd 65; long_chirp_lut[3295] = 8'd232; + long_chirp_lut[3296] = 8'd209; long_chirp_lut[3297] = 8'd 38; long_chirp_lut[3298] = 8'd 30; long_chirp_lut[3299] = 8'd200; long_chirp_lut[3300] = 8'd237; long_chirp_lut[3301] = 8'd 74; long_chirp_lut[3302] = 8'd 8; long_chirp_lut[3303] = 8'd161; + long_chirp_lut[3304] = 8'd253; long_chirp_lut[3305] = 8'd116; long_chirp_lut[3306] = 8'd 1; long_chirp_lut[3307] = 8'd117; long_chirp_lut[3308] = 8'd253; long_chirp_lut[3309] = 8'd159; long_chirp_lut[3310] = 8'd 8; long_chirp_lut[3311] = 8'd 76; + long_chirp_lut[3312] = 8'd239; long_chirp_lut[3313] = 8'd198; long_chirp_lut[3314] = 8'd 28; long_chirp_lut[3315] = 8'd 41; long_chirp_lut[3316] = 8'd213; long_chirp_lut[3317] = 8'd228; long_chirp_lut[3318] = 8'd 59; long_chirp_lut[3319] = 8'd 15; + long_chirp_lut[3320] = 8'd178; long_chirp_lut[3321] = 8'd248; long_chirp_lut[3322] = 8'd 97; long_chirp_lut[3323] = 8'd 2; long_chirp_lut[3324] = 8'd138; long_chirp_lut[3325] = 8'd254; long_chirp_lut[3326] = 8'd137; long_chirp_lut[3327] = 8'd 2; + long_chirp_lut[3328] = 8'd 98; long_chirp_lut[3329] = 8'd248; long_chirp_lut[3330] = 8'd176; long_chirp_lut[3331] = 8'd 14; long_chirp_lut[3332] = 8'd 61; long_chirp_lut[3333] = 8'd230; long_chirp_lut[3334] = 8'd210; long_chirp_lut[3335] = 8'd 37; + long_chirp_lut[3336] = 8'd 31; long_chirp_lut[3337] = 8'd203; long_chirp_lut[3338] = 8'd235; long_chirp_lut[3339] = 8'd 69; long_chirp_lut[3340] = 8'd 11; long_chirp_lut[3341] = 8'd169; long_chirp_lut[3342] = 8'd250; long_chirp_lut[3343] = 8'd105; + long_chirp_lut[3344] = 8'd 1; long_chirp_lut[3345] = 8'd132; long_chirp_lut[3346] = 8'd254; long_chirp_lut[3347] = 8'd142; long_chirp_lut[3348] = 8'd 3; long_chirp_lut[3349] = 8'd 95; long_chirp_lut[3350] = 8'd247; long_chirp_lut[3351] = 8'd178; + long_chirp_lut[3352] = 8'd 15; long_chirp_lut[3353] = 8'd 61; long_chirp_lut[3354] = 8'd231; long_chirp_lut[3355] = 8'd209; long_chirp_lut[3356] = 8'd 36; long_chirp_lut[3357] = 8'd 33; long_chirp_lut[3358] = 8'd206; long_chirp_lut[3359] = 8'd233; + long_chirp_lut[3360] = 8'd 64; long_chirp_lut[3361] = 8'd 13; long_chirp_lut[3362] = 8'd175; long_chirp_lut[3363] = 8'd248; long_chirp_lut[3364] = 8'd 96; long_chirp_lut[3365] = 8'd 3; long_chirp_lut[3366] = 8'd141; long_chirp_lut[3367] = 8'd254; + long_chirp_lut[3368] = 8'd131; long_chirp_lut[3369] = 8'd 1; long_chirp_lut[3370] = 8'd107; long_chirp_lut[3371] = 8'd251; long_chirp_lut[3372] = 8'd164; long_chirp_lut[3373] = 8'd 9; long_chirp_lut[3374] = 8'd 75; long_chirp_lut[3375] = 8'd240; + long_chirp_lut[3376] = 8'd195; long_chirp_lut[3377] = 8'd 24; long_chirp_lut[3378] = 8'd 47; long_chirp_lut[3379] = 8'd220; long_chirp_lut[3380] = 8'd220; long_chirp_lut[3381] = 8'd 46; long_chirp_lut[3382] = 8'd 25; long_chirp_lut[3383] = 8'd196; + long_chirp_lut[3384] = 8'd239; long_chirp_lut[3385] = 8'd 73; long_chirp_lut[3386] = 8'd 9; long_chirp_lut[3387] = 8'd167; long_chirp_lut[3388] = 8'd250; long_chirp_lut[3389] = 8'd103; long_chirp_lut[3390] = 8'd 2; long_chirp_lut[3391] = 8'd136; + long_chirp_lut[3392] = 8'd254; long_chirp_lut[3393] = 8'd134; long_chirp_lut[3394] = 8'd 1; long_chirp_lut[3395] = 8'd106; long_chirp_lut[3396] = 8'd251; long_chirp_lut[3397] = 8'd164; long_chirp_lut[3398] = 8'd 8; long_chirp_lut[3399] = 8'd 77; + long_chirp_lut[3400] = 8'd241; long_chirp_lut[3401] = 8'd191; long_chirp_lut[3402] = 8'd 21; long_chirp_lut[3403] = 8'd 52; long_chirp_lut[3404] = 8'd225; long_chirp_lut[3405] = 8'd214; long_chirp_lut[3406] = 8'd 40; long_chirp_lut[3407] = 8'd 31; + long_chirp_lut[3408] = 8'd204; long_chirp_lut[3409] = 8'd233; long_chirp_lut[3410] = 8'd 62; long_chirp_lut[3411] = 8'd 15; long_chirp_lut[3412] = 8'd180; long_chirp_lut[3413] = 8'd246; long_chirp_lut[3414] = 8'd 88; long_chirp_lut[3415] = 8'd 5; + long_chirp_lut[3416] = 8'd154; long_chirp_lut[3417] = 8'd253; long_chirp_lut[3418] = 8'd114; long_chirp_lut[3419] = 8'd 1; long_chirp_lut[3420] = 8'd127; long_chirp_lut[3421] = 8'd254; long_chirp_lut[3422] = 8'd141; long_chirp_lut[3423] = 8'd 2; + long_chirp_lut[3424] = 8'd101; long_chirp_lut[3425] = 8'd250; long_chirp_lut[3426] = 8'd166; long_chirp_lut[3427] = 8'd 9; long_chirp_lut[3428] = 8'd 77; long_chirp_lut[3429] = 8'd241; long_chirp_lut[3430] = 8'd189; long_chirp_lut[3431] = 8'd 20; + long_chirp_lut[3432] = 8'd 55; long_chirp_lut[3433] = 8'd228; long_chirp_lut[3434] = 8'd210; long_chirp_lut[3435] = 8'd 35; long_chirp_lut[3436] = 8'd 36; long_chirp_lut[3437] = 8'd212; long_chirp_lut[3438] = 8'd227; long_chirp_lut[3439] = 8'd 53; + long_chirp_lut[3440] = 8'd 21; long_chirp_lut[3441] = 8'd192; long_chirp_lut[3442] = 8'd240; long_chirp_lut[3443] = 8'd 73; long_chirp_lut[3444] = 8'd 10; long_chirp_lut[3445] = 8'd171; long_chirp_lut[3446] = 8'd249; long_chirp_lut[3447] = 8'd 94; + long_chirp_lut[3448] = 8'd 4; long_chirp_lut[3449] = 8'd150; long_chirp_lut[3450] = 8'd253; long_chirp_lut[3451] = 8'd116; long_chirp_lut[3452] = 8'd 1; long_chirp_lut[3453] = 8'd128; long_chirp_lut[3454] = 8'd254; long_chirp_lut[3455] = 8'd138; + long_chirp_lut[3456] = 8'd 2; long_chirp_lut[3457] = 8'd106; long_chirp_lut[3458] = 8'd252; long_chirp_lut[3459] = 8'd159; long_chirp_lut[3460] = 8'd 6; long_chirp_lut[3461] = 8'd 86; long_chirp_lut[3462] = 8'd246; long_chirp_lut[3463] = 8'd178; + long_chirp_lut[3464] = 8'd 13; long_chirp_lut[3465] = 8'd 68; long_chirp_lut[3466] = 8'd237; long_chirp_lut[3467] = 8'd196; long_chirp_lut[3468] = 8'd 23; long_chirp_lut[3469] = 8'd 51; long_chirp_lut[3470] = 8'd226; long_chirp_lut[3471] = 8'd211; + long_chirp_lut[3472] = 8'd 35; long_chirp_lut[3473] = 8'd 37; long_chirp_lut[3474] = 8'd213; long_chirp_lut[3475] = 8'd224; long_chirp_lut[3476] = 8'd 49; long_chirp_lut[3477] = 8'd 25; long_chirp_lut[3478] = 8'd199; long_chirp_lut[3479] = 8'd235; + long_chirp_lut[3480] = 8'd 64; long_chirp_lut[3481] = 8'd 15; long_chirp_lut[3482] = 8'd183; long_chirp_lut[3483] = 8'd243; long_chirp_lut[3484] = 8'd 80; long_chirp_lut[3485] = 8'd 8; long_chirp_lut[3486] = 8'd167; long_chirp_lut[3487] = 8'd249; + long_chirp_lut[3488] = 8'd 96; long_chirp_lut[3489] = 8'd 4; long_chirp_lut[3490] = 8'd151; long_chirp_lut[3491] = 8'd253; long_chirp_lut[3492] = 8'd112; long_chirp_lut[3493] = 8'd 1; long_chirp_lut[3494] = 8'd136; long_chirp_lut[3495] = 8'd254; + long_chirp_lut[3496] = 8'd127; long_chirp_lut[3497] = 8'd 1; long_chirp_lut[3498] = 8'd120; long_chirp_lut[3499] = 8'd254; long_chirp_lut[3500] = 8'd142; long_chirp_lut[3501] = 8'd 2; long_chirp_lut[3502] = 8'd106; long_chirp_lut[3503] = 8'd252; + long_chirp_lut[3504] = 8'd157; long_chirp_lut[3505] = 8'd 5; long_chirp_lut[3506] = 8'd 92; long_chirp_lut[3507] = 8'd248; long_chirp_lut[3508] = 8'd170; long_chirp_lut[3509] = 8'd 9; long_chirp_lut[3510] = 8'd 79; long_chirp_lut[3511] = 8'd244; + long_chirp_lut[3512] = 8'd182; long_chirp_lut[3513] = 8'd 14; long_chirp_lut[3514] = 8'd 67; long_chirp_lut[3515] = 8'd238; long_chirp_lut[3516] = 8'd193; long_chirp_lut[3517] = 8'd 20; long_chirp_lut[3518] = 8'd 57; long_chirp_lut[3519] = 8'd231; + long_chirp_lut[3520] = 8'd203; long_chirp_lut[3521] = 8'd 27; long_chirp_lut[3522] = 8'd 47; long_chirp_lut[3523] = 8'd224; long_chirp_lut[3524] = 8'd212; long_chirp_lut[3525] = 8'd 35; long_chirp_lut[3526] = 8'd 39; long_chirp_lut[3527] = 8'd216; + long_chirp_lut[3528] = 8'd220; long_chirp_lut[3529] = 8'd 43; long_chirp_lut[3530] = 8'd 31; long_chirp_lut[3531] = 8'd209; long_chirp_lut[3532] = 8'd227; long_chirp_lut[3533] = 8'd 50; long_chirp_lut[3534] = 8'd 25; long_chirp_lut[3535] = 8'd201; + long_chirp_lut[3536] = 8'd233; long_chirp_lut[3537] = 8'd 58; long_chirp_lut[3538] = 8'd 20; long_chirp_lut[3539] = 8'd193; long_chirp_lut[3540] = 8'd237; long_chirp_lut[3541] = 8'd 66; long_chirp_lut[3542] = 8'd 15; long_chirp_lut[3543] = 8'd185; + long_chirp_lut[3544] = 8'd242; long_chirp_lut[3545] = 8'd 73; long_chirp_lut[3546] = 8'd 12; long_chirp_lut[3547] = 8'd178; long_chirp_lut[3548] = 8'd245; long_chirp_lut[3549] = 8'd 81; long_chirp_lut[3550] = 8'd 9; long_chirp_lut[3551] = 8'd171; + long_chirp_lut[3552] = 8'd247; long_chirp_lut[3553] = 8'd 87; long_chirp_lut[3554] = 8'd 6; long_chirp_lut[3555] = 8'd164; long_chirp_lut[3556] = 8'd249; long_chirp_lut[3557] = 8'd 94; long_chirp_lut[3558] = 8'd 5; long_chirp_lut[3559] = 8'd158; + long_chirp_lut[3560] = 8'd251; long_chirp_lut[3561] = 8'd100; long_chirp_lut[3562] = 8'd 3; long_chirp_lut[3563] = 8'd153; long_chirp_lut[3564] = 8'd252; long_chirp_lut[3565] = 8'd105; long_chirp_lut[3566] = 8'd 2; long_chirp_lut[3567] = 8'd148; + long_chirp_lut[3568] = 8'd253; long_chirp_lut[3569] = 8'd110; long_chirp_lut[3570] = 8'd 2; long_chirp_lut[3571] = 8'd143; long_chirp_lut[3572] = 8'd254; long_chirp_lut[3573] = 8'd114; long_chirp_lut[3574] = 8'd 1; long_chirp_lut[3575] = 8'd139; + long_chirp_lut[3576] = 8'd254; long_chirp_lut[3577] = 8'd118; long_chirp_lut[3578] = 8'd 1; long_chirp_lut[3579] = 8'd136; long_chirp_lut[3580] = 8'd254; long_chirp_lut[3581] = 8'd121; long_chirp_lut[3582] = 8'd 1; long_chirp_lut[3583] = 8'd133; + long_chirp_lut[3584] = 8'd254; long_chirp_lut[3585] = 8'd123; long_chirp_lut[3586] = 8'd 1; long_chirp_lut[3587] = 8'd131; long_chirp_lut[3588] = 8'd254; long_chirp_lut[3589] = 8'd125; long_chirp_lut[3590] = 8'd 1; long_chirp_lut[3591] = 8'd129; + long_chirp_lut[3592] = 8'd254; long_chirp_lut[3593] = 8'd127; long_chirp_lut[3594] = 8'd 1; long_chirp_lut[3595] = 8'd128; long_chirp_lut[3596] = 8'd254; long_chirp_lut[3597] = 8'd127; long_chirp_lut[3598] = 8'd 1; long_chirp_lut[3599] = 8'd128; + + // Complete Short PLFM chirp LUT (0.5us, 30MHz to 10MHz) + short_chirp_lut[ 0] = 8'd255; short_chirp_lut[ 1] = 8'd237; short_chirp_lut[ 2] = 8'd187; short_chirp_lut[ 3] = 8'd118; short_chirp_lut[ 4] = 8'd 49; short_chirp_lut[ 5] = 8'd 6; short_chirp_lut[ 6] = 8'd 7; short_chirp_lut[ 7] = 8'd 54; + short_chirp_lut[ 8] = 8'd132; short_chirp_lut[ 9] = 8'd210; short_chirp_lut[10] = 8'd253; short_chirp_lut[11] = 8'd237; short_chirp_lut[12] = 8'd167; short_chirp_lut[13] = 8'd 75; short_chirp_lut[14] = 8'd 10; short_chirp_lut[15] = 8'd 10; + short_chirp_lut[16] = 8'd 80; short_chirp_lut[17] = 8'd180; short_chirp_lut[18] = 8'd248; short_chirp_lut[19] = 8'd237; short_chirp_lut[20] = 8'd150; short_chirp_lut[21] = 8'd 45; short_chirp_lut[22] = 8'd 1; short_chirp_lut[23] = 8'd 54; + short_chirp_lut[24] = 8'd167; short_chirp_lut[25] = 8'd249; short_chirp_lut[26] = 8'd228; short_chirp_lut[27] = 8'd118; short_chirp_lut[28] = 8'd 15; short_chirp_lut[29] = 8'd 18; short_chirp_lut[30] = 8'd127; short_chirp_lut[31] = 8'd238; + short_chirp_lut[32] = 8'd235; short_chirp_lut[33] = 8'd118; short_chirp_lut[34] = 8'd 10; short_chirp_lut[35] = 8'd 34; short_chirp_lut[36] = 8'd167; short_chirp_lut[37] = 8'd254; short_chirp_lut[38] = 8'd187; short_chirp_lut[39] = 8'd 45; + short_chirp_lut[40] = 8'd 8; short_chirp_lut[41] = 8'd129; short_chirp_lut[42] = 8'd248; short_chirp_lut[43] = 8'd201; short_chirp_lut[44] = 8'd 49; short_chirp_lut[45] = 8'd 10; short_chirp_lut[46] = 8'd145; short_chirp_lut[47] = 8'd254; + short_chirp_lut[48] = 8'd167; short_chirp_lut[49] = 8'd 17; short_chirp_lut[50] = 8'd 46; short_chirp_lut[51] = 8'd210; short_chirp_lut[52] = 8'd235; short_chirp_lut[53] = 8'd 75; short_chirp_lut[54] = 8'd 7; short_chirp_lut[55] = 8'd155; + short_chirp_lut[56] = 8'd253; short_chirp_lut[57] = 8'd118; short_chirp_lut[58] = 8'd 1; short_chirp_lut[59] = 8'd129; +end + +//chirp counter + +always @(posedge clk_100m or negedge reset_n) begin + if (!reset_n) begin + chirp_counter <= 6'd1; + end else begin + if (chirp__toggling) begin + if (chirp_counter == CHIRP_MAX) begin + chirp_counter <= 6'd1; + end else begin + chirp_counter <= chirp_counter + 6'd1; + end + end +end +end + +// Elevation counter + +always @(posedge clk_100m or negedge reset_n) begin + if (!reset_n) begin + elevation_counter <= 6'b1; + end else begin + if (elevation__toggling) begin + if (elevation_counter == ELEVATION_MAX) begin + elevation_counter <= 6'b1; + end else begin + elevation_counter <= elevation_counter + 6'b1; + end + end +end +end + + +// Azimuth counter + +always @(posedge clk_100m or negedge reset_n) begin + if (!reset_n) begin + azimuth_counter <= 6'd1; + end else begin + if (azimuth__toggling) begin + if (azimuth_counter == AZIMUTH_MAX) begin + azimuth_counter <= 6'd1; + end else begin + azimuth_counter <= azimuth_counter + 6'd1; + end + end +end +end + +// State register +always @(posedge clk_120m or negedge reset_n) begin + if (!reset_n) begin + current_state <= IDLE; + end else begin + current_state <= next_state; + end +end + +// Next state logic +always @(*) begin + case (current_state) + IDLE: begin + if (chirp__toggling && mixers_enable) + next_state = LONG_CHIRP; + else + next_state = IDLE; + end + + LONG_CHIRP: begin + if (sample_counter == T1_SAMPLES-1) + next_state = LONG_LISTEN; + else + next_state = LONG_CHIRP; + end + + LONG_LISTEN: begin + if (sample_counter == T1_RADAR_LISTENING-1) begin + if (chirp_counter == (CHIRP_MAX/2)-1) + next_state = GUARD_TIME; + else + next_state = LONG_CHIRP; + end else begin + next_state = LONG_LISTEN; + end + end + + GUARD_TIME: begin + if (sample_counter == GUARD_SAMPLES-1) + next_state = SHORT_CHIRP; + else + next_state = GUARD_TIME; + end + + SHORT_CHIRP: begin + if (sample_counter == T2_SAMPLES-1) + next_state = SHORT_LISTEN; + else + next_state = SHORT_CHIRP; + end + + SHORT_LISTEN: begin + if (sample_counter == T2_RADAR_LISTENING-1) begin + if (chirp_counter == CHIRP_MAX-1) + next_state = DONE; + else + next_state = SHORT_CHIRP; + end else begin + next_state = SHORT_LISTEN; + end + end + + DONE: begin + next_state = IDLE; + end + + default: begin + next_state = IDLE; + end + endcase +end + +always @(posedge clk_120m or negedge reset_n) begin + if (!reset_n) begin + sample_counter <= 0; + chirp_counter <= 0; + chirp_valid <= 0; + chirp_done <= 0; + chirp_data <= 8'd128; + rf_switch_ctrl <= 1'b0; + adar_tr_1 <= 1'b0; + adar_tr_2 <= 1'b0; + adar_tr_3 <= 1'b0; + adar_tr_4 <= 1'b0; + end else if (mixers_enable) begin + // Default outputs + chirp_valid <= 0; + chirp_done <= 0; + rf_switch_ctrl <= 0; + {adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4} <= 4'b0000; + + // Sample counter increment logic + if (current_state == LONG_CHIRP || current_state == LONG_LISTEN || + current_state == GUARD_TIME || current_state == SHORT_CHIRP || + current_state == SHORT_LISTEN) begin + if (sample_counter == get_max_counter(current_state) - 1) begin + sample_counter <= 0; + // Increment chirp counter at end of listen states + if (current_state == LONG_LISTEN || current_state == SHORT_LISTEN) begin + chirp_counter <= chirp_counter + 1; + end + end else begin + sample_counter <= sample_counter + 1; + end + end else begin + sample_counter <= 0; + end + + // State-specific outputs + case (current_state) + IDLE: begin + chirp_data <= 8'd128; + end + + LONG_CHIRP: begin + rf_switch_ctrl <= 1'b1; + {adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4} <= 4'b1111; + + // CRITICAL FIX: Generate valid signal + if (sample_counter < T1_SAMPLES) begin + chirp_data <= long_chirp_lut[sample_counter]; + chirp_valid <= 1'b1; // Valid during entire chirp + end else begin + chirp_data <= 8'd128; + end + end + + LONG_LISTEN: begin + chirp_data <= 8'd128; + rf_switch_ctrl <= 1'b0; + end + + GUARD_TIME: begin + chirp_data <= 8'd128; + rf_switch_ctrl <= 1'b0; + end + + SHORT_CHIRP: begin + rf_switch_ctrl <= 1'b1; + {adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4} <= 4'b1111; + + // CRITICAL FIX: Generate valid signal for short chirp + if (sample_counter < T2_SAMPLES) begin + chirp_data <= short_chirp_lut[sample_counter]; + chirp_valid <= 1'b1; // Valid during entire chirp + end else begin + chirp_data <= 8'd128; + end + end + + SHORT_LISTEN: begin + chirp_data <= 8'd128; + rf_switch_ctrl <= 1'b0; + end + + DONE: begin + chirp_done <= 1'b1; + chirp_data <= 8'd128; + end + + default: begin + chirp_data <= 8'd128; + end + endcase + end else begin + // Mixers disabled + chirp_data <= 8'd128; + chirp_valid <= 0; + chirp_done <= 0; + rf_switch_ctrl <= 0; + {adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4} <= 4'b0000; + sample_counter <= 0; + end +end + +// Helper function to get max counter for each state +function [15:0] get_max_counter; + input [2:0] state; + begin + case (state) + LONG_CHIRP: get_max_counter = T1_SAMPLES; + LONG_LISTEN: get_max_counter = T1_RADAR_LISTENING; + GUARD_TIME: get_max_counter = GUARD_SAMPLES; + SHORT_CHIRP: get_max_counter = T2_SAMPLES; + SHORT_LISTEN: get_max_counter = T2_RADAR_LISTENING; + default: get_max_counter = 0; + endcase + end +endfunction + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/radar_receiver_final.v b/9_Firmware/9_2_FPGA/radar_receiver_final.v new file mode 100644 index 0000000..e768634 --- /dev/null +++ b/9_Firmware/9_2_FPGA/radar_receiver_final.v @@ -0,0 +1,353 @@ +`timescale 1ns / 1ps + +module radar_receiver_final ( + input wire clk, // 100MHz + input wire reset_n, + + // ADC Physical Interface (LVDS Inputs) + input wire [7:0] adc_d_p, // ADC Data P (LVDS) + input wire [7:0] adc_d_n, // ADC Data N (LVDS) + input wire adc_dco_p, // Data Clock Output P (400MHz LVDS) + input wire adc_dco_n, // Data Clock Output N (400MHz LVDS) + output wire adc_pwdn, + + output reg [31:0] doppler_output, + output reg doppler_valid, + output reg [4:0] doppler_bin, + output reg [5:0] range_bin +); + +// ========== INTERNAL SIGNALS ========== +wire use_long_chirp; +wire [5:0] chirp_counter; +wire chirp_start; +wire azimuth_change; +wire elevation_change; + +wire [1:0] segment_request; +wire mem_request; +wire [15:0] ref_i, ref_q; +wire mem_ready; + +wire [15:0] adc_i_scaled, adc_q_scaled; +wire adc_valid_sync; + +// Reference signals for the processing chain +wire [15:0] long_chirp_real, long_chirp_imag; +wire [15:0] short_chirp_real, short_chirp_imag; + +// ========== DOPPLER PROCESSING SIGNALS ========== +wire [31:0] range_data_32bit; +wire range_data_valid; +wire new_chirp_frame; + +// Doppler processor outputs +wire [31:0] doppler_spectrum; +wire doppler_spectrum_valid; +wire [4:0] doppler_bin_out; +wire [5:0] doppler_range_bin_out; +wire doppler_processing; +wire doppler_frame_done; + +// ========== RANGE BIN DECIMATOR SIGNALS ========== +wire signed [15:0] decimated_range_i; +wire signed [15:0] decimated_range_q; +wire decimated_range_valid; +wire [5:0] decimated_range_bin; + +// ========== MODULE INSTANTIATIONS ========== +reg clk_400m; + +lvds_to_cmos_400m clk_400m_inst( + // ADC Physical Interface (LVDS Inputs) + .clk_400m_p(adc_dco_p), // Data Clock Output P (400MHz LVDS, 2.5V) + .clk_400m_n(adc_dco_n), // Data Clock Output N (400MHz LVDS, 2.5V) + .reset_n(reset_n), // Active-low reset + + // CMOS Output Interface (400MHz Domain) + .clk_400m_cmos(clk_400m) // ADC data clock (CMOS, 3.3V) +); + +// 1. ADC + CDC + AGC + +// CMOS Output Interface (400MHz Domain) +wire [7:0] adc_data_cmos; // 8-bit ADC data (CMOS) +wire adc_dco_cmos; // ADC data clock (CMOS, 400MHz) +wire adc_valid; // Data valid signal + +wire [7:0] cdc_data_cmos; // 8-bit ADC data (CMOS) +wire cdc_valid; // Data valid signal + + +ad9484_lvds_to_cmos_400m adc ( + .adc_d_p(adc_d_p), + .adc_d_n(adc_d_n), + .adc_dco_p(adc_dco_p), + .adc_dco_n(adc_dco_n), + .reset_n(reset_n), + .adc_data_cmos(adc_data_cmos), + .adc_dco_cmos(adc_dco_cmos), + .adc_valid(adc_valid), + .adc_pwdn(adc_pwdn) +); + +cdc_adc_to_processing #( + .WIDTH(8), + .STAGES(3) +)cdc( + .src_clk(adc_dco_cmos), + .dst_clk(clk_400m), + .reset_n(reset_n), + .src_data(adc_data_cmos), + .src_valid(adc_valid), + .dst_data(cdc_data_cmos), + .dst_valid(cdc_valid) +); + +// 2. DDC Input Interface +wire signed [17:0] ddc_out_i; +wire signed [17:0] ddc_out_q; + +wire ddc_valid_i; +wire ddc_valid_q; + +ddc_400m_enhanced ddc( + .clk_400m(clk_400m), // 400MHz clock from ADC DCO + .clk_100m(clk), // 100MHz system clock //used by the 2 FIR + .reset_n(reset_n), + .adc_data(cdc_data_cmos), // ADC data at 400MHz (unsigned 0-255) + .adc_data_valid_i(cdc_valid), // Valid at 400MHz + .adc_data_valid_q(cdc_valid), // Valid at 400MHz + .baseband_i(ddc_out_i), // I output at 100MHz + .baseband_q(ddc_out_q), // Q output at 100MHz + .baseband_valid_i(ddc_valid_i), // Valid at 100MHz + .baseband_valid_q(ddc_valid_q), + .mixers_enable(1'b1), + .bypass_mode(1'b1) +); + +ddc_input_interface ddc_if ( + .clk(clk), + .reset_n(reset_n), + .ddc_i(ddc_out_i), + .ddc_q(ddc_out_q), + .valid_i(ddc_valid_i), + .valid_q(ddc_valid_q), + .adc_i(adc_i_scaled), + .adc_q(adc_q_scaled), + .adc_valid(adc_valid_sync), + .data_sync_error() +); + +// 3. Dual Chirp Memory Loader + +chirp_memory_loader_param chirp_mem ( + .clk(clk), + .reset_n(reset_n), + .segment_select(segment_request), + .mem_request(mem_request), + .use_long_chirp(use_long_chirp), + .sample_addr(sample_addr_from_chain), + .ref_i(ref_i), + .ref_q(ref_q), + .mem_ready(mem_ready) +); + +// Sample address generator +reg [9:0] sample_addr_reg; +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + sample_addr_reg <= 0; + end else if (mem_request) begin + sample_addr_reg <= sample_addr_reg + 1; + if (sample_addr_reg == 1023) sample_addr_reg <= 0; + end +end +assign sample_addr_wire = sample_addr_reg; + +// 4. CRITICAL: Reference Chirp Latency Buffer +// This aligns reference data with FFT output (2159 cycle delay) +wire [15:0] delayed_ref_i, delayed_ref_q; +wire mem_ready_delayed; + +latency_buffer_2159 #( + .DATA_WIDTH(32), // 16-bit I + 16-bit Q + .LATENCY(3187) +) ref_latency_buffer ( + .clk(clk), + .reset_n(reset_n), + .data_in({ref_i, ref_q}), + .valid_in(mem_request), + .data_out({delayed_ref_i, delayed_ref_q}), + .valid_out(mem_ready_delayed) +); + +// Assign delayed reference signals +assign long_chirp_real = delayed_ref_i; +assign long_chirp_imag = delayed_ref_q; +assign short_chirp_real = delayed_ref_i; +assign short_chirp_imag = delayed_ref_q; + +// 5. Dual Chirp Matched Filter +wire [9:0] sample_addr_from_chain; + +wire signed [15:0] range_profile_i; +wire signed [15:0] range_profile_q; +wire range_valid; + +matched_filter_multi_segment mf_dual ( + .clk(clk), + .reset_n(reset_n), + .ddc_i({{2{adc_i_scaled[15]}}, adc_i_scaled}), + .ddc_q({{2{adc_q_scaled[15]}}, adc_q_scaled}), + .ddc_valid(adc_valid_sync), + .use_long_chirp(use_long_chirp), + .chirp_counter(chirp_counter), + .mc_new_chirp(mc_new_chirp), + .mc_new_elevation(mc_new_elevation), + .mc_new_azimuth(mc_new_azimuth), + .long_chirp_real(delayed_ref_i), // From latency buffer + .long_chirp_imag(delayed_ref_q), + .short_chirp_real(delayed_ref_i), // Same for short chirp + .short_chirp_imag(delayed_ref_q), + .segment_request(segment_request), + .mem_request(mem_request), + .sample_addr_out(sample_addr_from_chain), + .ref_i(16'd0), // Direct ref to multi_seg + .ref_q(16'd0), + .mem_ready(mem_ready), + .pc_i_w(range_profile_i), + .pc_q_w(range_profile_q), + .pc_valid_w(range_valid) +); + +// ========== CRITICAL: RANGE BIN DECIMATOR ========== +// Convert 1024 range bins to 64 bins for Doppler +range_bin_decimator #( + .INPUT_BINS(1024), + .OUTPUT_BINS(64), + .DECIMATION_FACTOR(16) +) range_decim ( + .clk(clk), + .reset_n(reset_n), + .range_i_in(range_profile_i), + .range_q_in(range_profile_q), + .range_valid_in(range_valid), + .range_i_out(decimated_range_i), + .range_q_out(decimated_range_q), + .range_valid_out(decimated_range_valid), + .range_bin_index(decimated_range_bin), + .decimation_mode(2'b01), // Peak detection mode + .start_bin(10'd0) +); + +// ========== FRAME SYNC USING chirp_counter ========== +reg [5:0] chirp_counter_prev; +reg new_frame_pulse; + +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + chirp_counter_prev <= 6'd0; + new_frame_pulse <= 1'b0; + end else begin + // Default: no pulse + new_frame_pulse <= 1'b0; + + // ===== CHOOSE ONE FRAME DETECTION METHOD ===== + + // METHOD A: Detect frame start at chirp_counter = 0 + // (Assumes frames are 64 chirps: 0-63) + //if (chirp_counter == 6'd0 && chirp_counter_prev != 6'd0) begin + // new_frame_pulse <= 1'b1; + //end + + // METHOD B: Detect frame start at chirp_counter = 0 AND 32 + // (For 32-chirp frames in a 64-chirp sequence) + if ((chirp_counter == 6'd0 || chirp_counter == 6'd32) && + (chirp_counter_prev != chirp_counter)) begin + new_frame_pulse <= 1'b1; + end + + // METHOD C: Programmable frame start + // localparam FRAME_START_CHIRP = 6'd0; // Set based on your sequence + // if (chirp_counter == FRAME_START_CHIRP && + // chirp_counter_prev != FRAME_START_CHIRP) begin + // new_frame_pulse <= 1'b1; + // end + + // Store previous value + chirp_counter_prev <= chirp_counter; + end +end + +assign new_chirp_frame = new_frame_pulse; + +// ========== DATA PACKING FOR DOPPLER ========== +assign range_data_32bit = {decimated_range_q, decimated_range_i}; +assign range_data_valid = decimated_range_valid; + +// ========== DOPPLER PROCESSOR ========== +doppler_processor_optimized #( + .DOPPLER_FFT_SIZE(32), + .RANGE_BINS(64), + .CHIRPS_PER_FRAME(32) // MUST MATCH YOUR ACTUAL FRAME SIZE! +) doppler_proc ( + .clk(clk), + .reset_n(reset_n), + .range_data(range_data_32bit), + .data_valid(range_data_valid), + .new_chirp_frame(new_chirp_frame), + + // Outputs + .doppler_output(doppler_output), + .doppler_valid(doppler_valid), + .doppler_bin(doppler_bin), + .range_bin(doppler_range_bin_out), + + // Status + .processing_active(doppler_processing), + .frame_complete(doppler_frame_done), + .status() +); + +// ========== OUTPUT CONNECTIONS ========== +assign doppler_range_bin = doppler_range_bin_out; +assign doppler_processing_active = doppler_processing; +assign doppler_frame_complete = doppler_frame_done; + +// ========== STATUS ========== + +// ========== DEBUG AND VERIFICATION ========== +reg [31:0] frame_counter; +reg [5:0] chirps_in_current_frame; + +always @(posedge clk or negedge reset_n) begin + if (!reset_n) begin + frame_counter <= 0; + chirps_in_current_frame <= 0; + end else begin + // Count chirps in current frame + if (range_data_valid && decimated_range_bin == 0) begin + // First range bin of a chirp + chirps_in_current_frame <= chirps_in_current_frame + 1; + end + + // Detect frame completion + if (new_chirp_frame) begin + frame_counter <= frame_counter + 1; + $display("[TOP] Frame %0d started. Previous frame had %0d chirps", + frame_counter, chirps_in_current_frame); + chirps_in_current_frame <= 0; + end + + // Monitor chirp counter pattern + if (chirp_counter != chirp_counter_prev) begin + $display("[TOP] chirp_counter: %0d ? %0d", + chirp_counter_prev, chirp_counter); + end + end +end + + + +endmodule \ No newline at end of file diff --git a/9_Firmware/9_2_FPGA/radar_transmitter.v b/9_Firmware/9_2_FPGA/radar_transmitter.v new file mode 100644 index 0000000..2f1f9c3 --- /dev/null +++ b/9_Firmware/9_2_FPGA/radar_transmitter.v @@ -0,0 +1,157 @@ +`timescale 1ns / 1ps +////////////////////////////////////////////////////////////////////////////////// +// Company: +// Engineer: +// +// Create Date: 19:04:35 12/14/2025 +// Design Name: +// Module Name: radar_transmitter +// Project Name: +// Target Devices: +// Tool versions: +// Description: +// +// Dependencies: +// +// Revision: +// Revision 0.01 - File Created +// Additional Comments: +// +////////////////////////////////////////////////////////////////////////////////// +module radar_transmitter( + // System Clocks + input wire clk_100m, // System clock + input wire clk_120m_dac, // 120MHz DAC clock + input wire reset_n, + + // DAC Interface + output wire [7:0] dac_data, + output wire dac_clk, + output wire dac_sleep, + output wire rx_mixer_en, + output wire tx_mixer_en, + + // STM32 Control Interface + input wire stm32_new_chirp, + input wire stm32_new_elevation, + input wire stm32_new_azimuth, + input wire stm32_mixers_enable, + + output wire fpga_rf_switch, + + // ADAR1000 Control Interface + output wire adar_tx_load_1, + output wire adar_rx_load_1, + output wire adar_tx_load_2, + output wire adar_rx_load_2, + output wire adar_tx_load_3, + output wire adar_rx_load_3, + output wire adar_tx_load_4, + output wire adar_rx_load_4, + output wire adar_tr_1, + output wire adar_tr_2, + output wire adar_tr_3, + output wire adar_tr_4, + + // Level Shifter SPI Interface (STM32F7 to ADAR1000) + input wire stm32_sclk_3v3, + input wire stm32_mosi_3v3, + output wire stm32_miso_3v3, + input wire stm32_cs_adar1_3v3, + input wire stm32_cs_adar2_3v3, + input wire stm32_cs_adar3_3v3, + input wire stm32_cs_adar4_3v3, + + output wire stm32_sclk_1v8, + output wire stm32_mosi_1v8, + input wire stm32_miso_1v8, + output wire stm32_cs_adar1_1v8, + output wire stm32_cs_adar2_1v8, + output wire stm32_cs_adar3_1v8, + output wire stm32_cs_adar4_1v8, + + // Beam Position Tracking + output wire [5:0] current_elevation, + output wire [5:0] current_azimuth, + output wire [5:0] current_chirp, + output wire new_chirp_frame + + + ); + +// Edge Detection Signals +wire new_chirp_pulse; +wire new_elevation_pulse; +wire new_azimuth_pulse; + +// Chirp Control Signals +wire [7:0] chirp_data; +wire chirp_valid; +wire chirp_sequence_done; + +// Enhanced STM32 Input Edge Detection with Debouncing +edge_detector_enhanced chirp_edge ( + .clk(clk_100m), + .reset_n(reset_n), + .signal_in(stm32_new_chirp), + .rising_falling_edge(new_chirp_pulse) +); + +edge_detector_enhanced elevation_edge ( + .clk(clk_100m), + .reset_n(reset_n), + .signal_in(stm32_new_elevation), + .rising_falling_edge(new_elevation_pulse) +); + +edge_detector_enhanced azimuth_edge ( + .clk(clk_100m), + .reset_n(reset_n), + .signal_in(stm32_new_azimuth), + .rising_falling_edge(new_azimuth_pulse) +); + +// Enhanced PLFM Chirp Generation +plfm_chirp_controller_enhanced plfm_chirp_inst ( + .clk_120m(clk_120m_dac), + .clk_100m(clk_100m), + .reset_n(reset_n), + .new_chirp(new_chirp_pulse), + .new_elevation(new_elevation_pulse), + .new_azimuth(new_azimuth_pulse), + .new_chirp_frame(new_chirp_frame), + .mixers_enable(stm32_mixers_enable), + .chirp_data(chirp_data), + .chirp_valid(chirp_valid), + .chirp_done(chirp_sequence_done), + .rf_switch_ctrl(fpga_rf_switch), + .rx_mixer_en(rx_mixer_en), + .tx_mixer_en(tx_mixer_en), + .adar_tx_load_1(adar_tx_load_1), + .adar_rx_load_1(adar_rx_load_1), + .adar_tx_load_2(adar_tx_load_2), + .adar_rx_load_2(adar_rx_load_2), + .adar_tx_load_3(adar_tx_load_3), + .adar_rx_load_3(adar_rx_load_3), + .adar_tx_load_4(adar_tx_load_4), + .adar_rx_load_4(adar_rx_load_4), + .adar_tr_1(adar_tr_1), + .adar_tr_2(adar_tr_2), + .adar_tr_3(adar_tr_3), + .adar_tr_4(adar_tr_4), + .elevation_counter(current_elevation), + .azimuth_counter(current_azimuth), + .chirp_counter(current_chirp) +); + +// Enhanced DAC Interface +dac_interface_enhanced dac_interface_inst ( + .clk_120m(clk_120m_dac), + .reset_n(reset_n), + .chirp_data(chirp_data), + .chirp_valid(chirp_valid), + .dac_data(dac_data), + .dac_clk(dac_clk), + .dac_sleep(dac_sleep) +); +endmodule diff --git a/9_Firmware/9_2_FPGA/short_chirp_i.mem b/9_Firmware/9_2_FPGA/short_chirp_i.mem new file mode 100644 index 0000000..64fa298 --- /dev/null +++ b/9_Firmware/9_2_FPGA/short_chirp_i.mem @@ -0,0 +1,50 @@ +0095 +000d +ffdd +0007 +008c +015e +026b +039c +04d4 +05f9 +06ef +07a1 +07fd +07fd +07a0 +06ef +05fa +04d8 +03a5 +027d +017c +00bc +004d +003d +008f +013b +0234 +0364 +04b2 +05ff +072e +0825 +08ce +091a +0904 +088d +07c3 +06b9 +0589 +0450 +032d +023c +0197 +014e +016c +01f1 +02d3 +0402 +0563 +06db diff --git a/9_Firmware/9_2_FPGA/short_chirp_q.mem b/9_Firmware/9_2_FPGA/short_chirp_q.mem new file mode 100644 index 0000000..16bfcbc --- /dev/null +++ b/9_Firmware/9_2_FPGA/short_chirp_q.mem @@ -0,0 +1,50 @@ +f8b6 +f791 +f64d +f505 +f3d6 +f2d8 +f221 +f1c0 +f1bb +f210 +f2b6 +f39b +f4a8 +f5c1 +f6c9 +f7a6 +f840 +f886 +f86d +f7f5 +f724 +f60b +f4bf +f35b +f1fc +f0bf +efbe +ef0d +eeb8 +eec5 +ef2e +efe7 +f0db +f1f0 +f308 +f405 +f4cc +f545 +f560 +f516 +f467 +f35f +f210 +f094 +ef07 +ed88 +ec36 +eb2a +ea78 +ea29 diff --git a/9_Firmware/9_3_GUI/GUI_V1.py b/9_Firmware/9_3_GUI/GUI_V1.py new file mode 100644 index 0000000..9df2966 --- /dev/null +++ b/9_Firmware/9_3_GUI/GUI_V1.py @@ -0,0 +1,41 @@ + + def update_gps_display(self): + """Step 18: Update GPS display and center map""" + try: + while not self.gps_data_queue.empty(): + gps_data = self.gps_data_queue.get_nowait() + self.current_gps = gps_data + + # Update GPS label + self.gps_label.config( + text=f"GPS: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m") + + # Update map + self.update_map_display(gps_data) + + except queue.Empty: + pass + + def update_map_display(self, gps_data): + """Step 18: Update map display with current GPS position""" + try: + self.map_label.config(text=f"Radar Position: {gps_data.latitude:.6f}, {gps_data.longitude:.6f}\n" + f"Altitude: {gps_data.altitude:.1f}m\n" + f"Coverage: 50km radius\n" + f"Map centered on GPS coordinates") + + except Exception as e: + logging.error(f"Error updating map display: {e}") + +def main(): + """Main application entry point""" + try: + root = tk.Tk() + app = RadarGUI(root) + root.mainloop() + except Exception as e: + logging.error(f"Application error: {e}") + messagebox.showerror("Fatal Error", f"Application failed to start: {e}") + +if __name__ == "__main__": + main() diff --git a/9_Firmware/9_3_GUI/GUI_V2.py b/9_Firmware/9_3_GUI/GUI_V2.py new file mode 100644 index 0000000..8f7a16a --- /dev/null +++ b/9_Firmware/9_3_GUI/GUI_V2.py @@ -0,0 +1,1059 @@ +import tkinter as tk +from tkinter import ttk, messagebox +import threading +import queue +import time +import struct +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.figure import Figure +import logging +from dataclasses import dataclass +from typing import Dict, List, Tuple, Optional +from scipy import signal +from sklearn.cluster import DBSCAN +from filterpy.kalman import KalmanFilter +import crcmod +import math + +try: + import usb.core + import usb.util + USB_AVAILABLE = True +except ImportError: + USB_AVAILABLE = False + logging.warning("pyusb not available. USB CDC functionality will be disabled.") + +try: + from pyftdi.ftdi import Ftdi + from pyftdi.usbtools import UsbTools + FTDI_AVAILABLE = True +except ImportError: + FTDI_AVAILABLE = False + logging.warning("pyftdi not available. FTDI functionality will be disabled.") + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +@dataclass +class RadarTarget: + id: int + range: float + velocity: float + azimuth: int + elevation: int + snr: float + timestamp: float + track_id: int = -1 + +@dataclass +class RadarSettings: + system_frequency: float = 10e9 + chirp_duration: float = 30e-6 + chirps_per_position: int = 32 + freq_min: float = 10e6 + freq_max: float = 30e6 + prf1: float = 1000 + prf2: float = 2000 + max_distance: float = 50000 + +@dataclass +class GPSData: + latitude: float + longitude: float + altitude: float + timestamp: float + +class STM32USBInterface: + def __init__(self): + self.device = None + self.is_open = False + self.ep_in = None + self.ep_out = None + + def list_devices(self): + """List available STM32 USB CDC devices""" + if not USB_AVAILABLE: + logging.warning("USB not available - please install pyusb") + return [] + + try: + devices = [] + # STM32 USB CDC devices typically use these vendor/product IDs + stm32_vid_pids = [ + (0x0483, 0x5740), # STM32 Virtual COM Port + (0x0483, 0x3748), # STM32 Discovery + (0x0483, 0x374B), # STM32 CDC + (0x0483, 0x374D), # STM32 CDC + (0x0483, 0x374E), # STM32 CDC + (0x0483, 0x3752), # STM32 CDC + ] + + for vid, pid in stm32_vid_pids: + found_devices = usb.core.find(find_all=True, idVendor=vid, idProduct=pid) + for dev in found_devices: + try: + product = usb.util.get_string(dev, dev.iProduct) if dev.iProduct else "STM32 CDC" + serial = usb.util.get_string(dev, dev.iSerialNumber) if dev.iSerialNumber else "Unknown" + devices.append({ + 'description': f"{product} ({serial})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + except: + devices.append({ + 'description': f"STM32 CDC (VID:{vid:04X}, PID:{pid:04X})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + + return devices + except Exception as e: + logging.error(f"Error listing USB devices: {e}") + # Return mock devices for testing + return [{'description': 'STM32 Virtual COM Port', 'vendor_id': 0x0483, 'product_id': 0x5740}] + + def open_device(self, device_info): + """Open STM32 USB CDC device""" + if not USB_AVAILABLE: + logging.error("USB not available - cannot open device") + return False + + try: + self.device = device_info['device'] + + # Detach kernel driver if active + if self.device.is_kernel_driver_active(0): + self.device.detach_kernel_driver(0) + + # Set configuration + self.device.set_configuration() + + # Get CDC endpoints + cfg = self.device.get_active_configuration() + intf = cfg[(0,0)] + + # Find bulk endpoints (CDC data interface) + self.ep_out = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT + ) + + self.ep_in = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN + ) + + if self.ep_out is None or self.ep_in is None: + logging.error("Could not find CDC endpoints") + return False + + self.is_open = True + logging.info(f"STM32 USB device opened: {device_info['description']}") + return True + + except Exception as e: + logging.error(f"Error opening USB device: {e}") + return False + + def send_start_flag(self): + """Step 12: Send start flag to STM32 via USB""" + start_packet = bytes([23, 46, 158, 237]) + logging.info("Sending start flag to STM32 via USB...") + return self._send_data(start_packet) + + def send_settings(self, settings): + """Step 13: Send radar settings to STM32 via USB""" + try: + packet = self._create_settings_packet(settings) + logging.info("Sending radar settings to STM32 via USB...") + return self._send_data(packet) + except Exception as e: + logging.error(f"Error sending settings via USB: {e}") + return False + + def read_data(self, size=64, timeout=1000): + """Read data from STM32 via USB""" + if not self.is_open or self.ep_in is None: + return None + + try: + data = self.ep_in.read(size, timeout=timeout) + return bytes(data) + except usb.core.USBError as e: + if e.errno == 110: # Timeout + return None + logging.error(f"USB read error: {e}") + return None + except Exception as e: + logging.error(f"Error reading from USB: {e}") + return None + + def _send_data(self, data): + """Send data to STM32 via USB""" + if not self.is_open or self.ep_out is None: + return False + + try: + # USB CDC typically uses 64-byte packets + packet_size = 64 + for i in range(0, len(data), packet_size): + chunk = data[i:i + packet_size] + # Pad to packet size if needed + if len(chunk) < packet_size: + chunk += b'\x00' * (packet_size - len(chunk)) + self.ep_out.write(chunk) + + return True + except Exception as e: + logging.error(f"Error sending data via USB: {e}") + return False + + def _create_settings_packet(self, settings): + """Create binary settings packet for USB transmission""" + packet = b'SET' + packet += struct.pack('>d', settings.system_frequency) + packet += struct.pack('>d', settings.chirp_duration) + packet += struct.pack('>I', settings.chirps_per_position) + packet += struct.pack('>d', settings.freq_min) + packet += struct.pack('>d', settings.freq_max) + packet += struct.pack('>d', settings.prf1) + packet += struct.pack('>d', settings.prf2) + packet += struct.pack('>d', settings.max_distance) + packet += b'END' + return packet + + def close(self): + """Close USB device""" + if self.device and self.is_open: + try: + usb.util.dispose_resources(self.device) + self.is_open = False + except Exception as e: + logging.error(f"Error closing USB device: {e}") + +class FTDIInterface: + def __init__(self): + self.ftdi = None + self.is_open = False + + def list_devices(self): + """List available FTDI devices using pyftdi""" + if not FTDI_AVAILABLE: + logging.warning("FTDI not available - please install pyftdi") + return [] + + try: + devices = [] + # Get list of all FTDI devices + for device in UsbTools.find_all([(0x0403, 0x6010)]): # FT2232H vendor/product ID + devices.append({ + 'description': f"FTDI Device {device}", + 'url': f"ftdi://{device}/1" + }) + return devices + except Exception as e: + logging.error(f"Error listing FTDI devices: {e}") + # Return mock devices for testing + return [{'description': 'FT2232H Device A', 'url': 'ftdi://device/1'}] + + def open_device(self, device_url): + """Open FTDI device using pyftdi""" + if not FTDI_AVAILABLE: + logging.error("FTDI not available - cannot open device") + return False + + try: + self.ftdi = Ftdi() + self.ftdi.open_from_url(device_url) + + # Configure for synchronous FIFO mode + self.ftdi.set_bitmode(0xFF, Ftdi.BitMode.SYNCFF) + + # Set latency timer + self.ftdi.set_latency_timer(2) + + # Purge buffers + self.ftdi.purge_buffers() + + self.is_open = True + logging.info(f"FTDI device opened: {device_url}") + return True + + except Exception as e: + logging.error(f"Error opening FTDI device: {e}") + return False + + def read_data(self, bytes_to_read): + """Read data from FTDI""" + if not self.is_open or self.ftdi is None: + return None + + try: + data = self.ftdi.read_data(bytes_to_read) + if data: + return bytes(data) + return None + except Exception as e: + logging.error(f"Error reading from FTDI: {e}") + return None + + def close(self): + """Close FTDI device""" + if self.ftdi and self.is_open: + self.ftdi.close() + self.is_open = False + +class RadarProcessor: + def __init__(self): + self.range_doppler_map = np.zeros((1024, 32)) + self.detected_targets = [] + self.track_id_counter = 0 + self.tracks = {} + self.frame_count = 0 + + def dual_cpi_fusion(self, range_profiles_1, range_profiles_2): + """Dual-CPI fusion for better detection""" + fused_profile = np.mean(range_profiles_1, axis=0) + np.mean(range_profiles_2, axis=0) + return fused_profile + + def multi_prf_unwrap(self, doppler_measurements, prf1, prf2): + """Multi-PRF velocity unwrapping""" + lambda_wavelength = 3e8 / 10e9 + v_max1 = prf1 * lambda_wavelength / 2 + v_max2 = prf2 * lambda_wavelength / 2 + + unwrapped_velocities = [] + for doppler in doppler_measurements: + v1 = doppler * lambda_wavelength / 2 + v2 = doppler * lambda_wavelength / 2 + + velocity = self._solve_chinese_remainder(v1, v2, v_max1, v_max2) + unwrapped_velocities.append(velocity) + + return unwrapped_velocities + + def _solve_chinese_remainder(self, v1, v2, max1, max2): + for k in range(-5, 6): + candidate = v1 + k * max1 + if abs(candidate - v2) < max2 / 2: + return candidate + return v1 + + def clustering(self, detections, eps=100, min_samples=2): + """DBSCAN clustering of detections""" + if len(detections) == 0: + return [] + + points = np.array([[d.range, d.velocity] for d in detections]) + clustering = DBSCAN(eps=eps, min_samples=min_samples).fit(points) + + clusters = [] + for label in set(clustering.labels_): + if label != -1: + cluster_points = points[clustering.labels_ == label] + clusters.append({ + 'center': np.mean(cluster_points, axis=0), + 'points': cluster_points, + 'size': len(cluster_points) + }) + + return clusters + + def association(self, detections, clusters): + """Association of detections to tracks""" + associated_detections = [] + + for detection in detections: + best_track = None + min_distance = float('inf') + + for track_id, track in self.tracks.items(): + distance = np.sqrt( + (detection.range - track['state'][0])**2 + + (detection.velocity - track['state'][2])**2 + ) + + if distance < min_distance and distance < 500: + min_distance = distance + best_track = track_id + + if best_track is not None: + detection.track_id = best_track + associated_detections.append(detection) + else: + detection.track_id = self.track_id_counter + self.track_id_counter += 1 + associated_detections.append(detection) + + return associated_detections + + def tracking(self, associated_detections): + """Kalman filter tracking""" + current_time = time.time() + + for detection in associated_detections: + if detection.track_id not in self.tracks: + kf = KalmanFilter(dim_x=4, dim_z=2) + kf.x = np.array([detection.range, 0, detection.velocity, 0]) + kf.F = np.array([[1, 1, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 1], + [0, 0, 0, 1]]) + kf.H = np.array([[1, 0, 0, 0], + [0, 0, 1, 0]]) + kf.P *= 1000 + kf.R = np.diag([10, 1]) + kf.Q = np.eye(4) * 0.1 + + self.tracks[detection.track_id] = { + 'filter': kf, + 'state': kf.x, + 'last_update': current_time, + 'hits': 1 + } + else: + track = self.tracks[detection.track_id] + track['filter'].predict() + track['filter'].update([detection.range, detection.velocity]) + track['state'] = track['filter'].x + track['last_update'] = current_time + track['hits'] += 1 + + stale_tracks = [tid for tid, track in self.tracks.items() + if current_time - track['last_update'] > 5.0] + for tid in stale_tracks: + del self.tracks[tid] + +class USBPacketParser: + def __init__(self): + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_gps_data(self, data): + """Parse GPS data from STM32 USB CDC""" + if not data: + return None + + try: + # Try text format first: "GPS:lat,lon,alt\r\n" + text_data = data.decode('utf-8', errors='ignore').strip() + if text_data.startswith('GPS:'): + parts = text_data.split(':')[1].split(',') + if len(parts) == 3: + lat = float(parts[0]) + lon = float(parts[1]) + alt = float(parts[2]) + return GPSData(latitude=lat, longitude=lon, altitude=alt, timestamp=time.time()) + + # Try binary format + if len(data) >= 26 and data[0:4] == b'GPSB': + return self._parse_binary_gps(data) + + except Exception as e: + logging.error(f"Error parsing GPS data: {e}") + + return None + + def _parse_binary_gps(self, data): + """Parse binary GPS format""" + try: + # Binary format: [Header 4][Latitude 8][Longitude 8][Altitude 4][CRC 2] + if len(data) < 26: + return None + + # Verify CRC (simple checksum) + crc_received = (data[24] << 8) | data[25] + crc_calculated = sum(data[0:24]) & 0xFFFF + + if crc_received != crc_calculated: + logging.warning("GPS CRC mismatch") + return None + + # Parse latitude (double, big-endian) + lat_bits = 0 + for i in range(8): + lat_bits = (lat_bits << 8) | data[4 + i] + latitude = struct.unpack('>d', struct.pack('>Q', lat_bits))[0] + + # Parse longitude (double, big-endian) + lon_bits = 0 + for i in range(8): + lon_bits = (lon_bits << 8) | data[12 + i] + longitude = struct.unpack('>d', struct.pack('>Q', lon_bits))[0] + + # Parse altitude (float, big-endian) + alt_bits = 0 + for i in range(4): + alt_bits = (alt_bits << 8) | data[20 + i] + altitude = struct.unpack('>f', struct.pack('>I', alt_bits))[0] + + return GPSData(latitude=latitude, longitude=longitude, altitude=altitude, timestamp=time.time()) + + except Exception as e: + logging.error(f"Error parsing binary GPS: {e}") + return None + +class RadarPacketParser: + def __init__(self): + self.sync_pattern = b'\xA5\xC3' + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_packet(self, data): + if len(data) < 6: + return None + + sync_index = data.find(self.sync_pattern) + if sync_index == -1: + return None + + packet = data[sync_index:] + + if len(packet) < 6: + return None + + sync = packet[0:2] + packet_type = packet[2] + length = packet[3] + + if len(packet) < (4 + length + 2): + return None + + payload = packet[4:4+length] + crc_received = struct.unpack('I', payload[0:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'range', + 'range': range_value, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing range packet: {e}") + return None + + def parse_doppler_packet(self, payload): + if len(payload) < 12: + return None + + try: + doppler_real = struct.unpack('>h', payload[0:2])[0] + doppler_imag = struct.unpack('>h', payload[2:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'doppler', + 'doppler_real': doppler_real, + 'doppler_imag': doppler_imag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing Doppler packet: {e}") + return None + + def parse_detection_packet(self, payload): + if len(payload) < 8: + return None + + try: + detection_flag = (payload[0] & 0x01) != 0 + elevation = payload[1] & 0x1F + azimuth = payload[2] & 0x3F + chirp_counter = payload[3] & 0x1F + + return { + 'type': 'detection', + 'detected': detection_flag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing detection packet: {e}") + return None + +class RadarGUI: + def __init__(self, root): + self.root = root + self.root.title("Advanced Radar System GUI - USB CDC") + self.root.geometry("1400x900") + + # Initialize interfaces + self.stm32_usb_interface = STM32USBInterface() + self.ftdi_interface = FTDIInterface() + self.radar_processor = RadarProcessor() + self.usb_packet_parser = USBPacketParser() + self.radar_packet_parser = RadarPacketParser() + self.settings = RadarSettings() + + # Data queues + self.radar_data_queue = queue.Queue() + self.gps_data_queue = queue.Queue() + + # Thread control + self.running = False + self.radar_thread = None + self.gps_thread = None + + # Counters + self.received_packets = 0 + self.current_gps = GPSData(latitude=41.9028, longitude=12.4964, altitude=0, timestamp=0) + + self.create_gui() + self.start_background_threads() + + def create_gui(self): + """Create the main GUI with tabs""" + self.notebook = ttk.Notebook(self.root) + self.notebook.pack(fill='both', expand=True, padx=10, pady=10) + + self.tab_main = ttk.Frame(self.notebook) + self.tab_map = ttk.Frame(self.notebook) + self.tab_diagnostics = ttk.Frame(self.notebook) + self.tab_settings = ttk.Frame(self.notebook) + + self.notebook.add(self.tab_main, text='Main View') + self.notebook.add(self.tab_map, text='Map View') + self.notebook.add(self.tab_diagnostics, text='Diagnostics') + self.notebook.add(self.tab_settings, text='Settings') + + self.setup_main_tab() + self.setup_map_tab() + self.setup_settings_tab() + + def setup_main_tab(self): + """Setup the main radar display tab""" + # Control frame + control_frame = ttk.Frame(self.tab_main) + control_frame.pack(fill='x', padx=10, pady=5) + + # USB Device selection + ttk.Label(control_frame, text="STM32 USB Device:").grid(row=0, column=0, padx=5) + self.stm32_usb_combo = ttk.Combobox(control_frame, state="readonly", width=40) + self.stm32_usb_combo.grid(row=0, column=1, padx=5) + + ttk.Label(control_frame, text="FTDI Device:").grid(row=0, column=2, padx=5) + self.ftdi_combo = ttk.Combobox(control_frame, state="readonly", width=30) + self.ftdi_combo.grid(row=0, column=3, padx=5) + + ttk.Button(control_frame, text="Refresh Devices", + command=self.refresh_devices).grid(row=0, column=4, padx=5) + + self.start_button = ttk.Button(control_frame, text="Start Radar", + command=self.start_radar) + self.start_button.grid(row=0, column=5, padx=5) + + self.stop_button = ttk.Button(control_frame, text="Stop Radar", + command=self.stop_radar, state="disabled") + self.stop_button.grid(row=0, column=6, padx=5) + + # GPS info + self.gps_label = ttk.Label(control_frame, text="GPS: Waiting for data...") + self.gps_label.grid(row=1, column=0, columnspan=4, sticky='w', padx=5, pady=2) + + # Status info + self.status_label = ttk.Label(control_frame, text="Status: Ready") + self.status_label.grid(row=1, column=4, columnspan=3, sticky='e', padx=5, pady=2) + + # Main display area + display_frame = ttk.Frame(self.tab_main) + display_frame.pack(fill='both', expand=True, padx=10, pady=5) + + # Range-Doppler Map + fig = Figure(figsize=(10, 6)) + self.range_doppler_ax = fig.add_subplot(111) + self.range_doppler_plot = self.range_doppler_ax.imshow( + np.random.rand(1024, 32), aspect='auto', cmap='hot', + extent=[0, 32, 0, 1024]) + self.range_doppler_ax.set_title('Range-Doppler Map') + self.range_doppler_ax.set_xlabel('Doppler Bin') + self.range_doppler_ax.set_ylabel('Range Bin') + + self.canvas = FigureCanvasTkAgg(fig, display_frame) + self.canvas.draw() + self.canvas.get_tk_widget().pack(side='left', fill='both', expand=True) + + # Targets list + targets_frame = ttk.LabelFrame(display_frame, text="Detected Targets") + targets_frame.pack(side='right', fill='y', padx=5) + + self.targets_tree = ttk.Treeview(targets_frame, + columns=('ID', 'Range', 'Velocity', 'Azimuth', 'Elevation', 'SNR'), + show='headings', height=20) + self.targets_tree.heading('ID', text='Track ID') + self.targets_tree.heading('Range', text='Range (m)') + self.targets_tree.heading('Velocity', text='Velocity (m/s)') + self.targets_tree.heading('Azimuth', text='Azimuth') + self.targets_tree.heading('Elevation', text='Elevation') + self.targets_tree.heading('SNR', text='SNR (dB)') + + self.targets_tree.column('ID', width=80) + self.targets_tree.column('Range', width=100) + self.targets_tree.column('Velocity', width=100) + self.targets_tree.column('Azimuth', width=80) + self.targets_tree.column('Elevation', width=80) + self.targets_tree.column('SNR', width=80) + + self.targets_tree.pack(fill='both', expand=True, padx=5, pady=5) + + def setup_map_tab(self): + """Setup the map display tab""" + self.map_frame = ttk.Frame(self.tab_map) + self.map_frame.pack(fill='both', expand=True, padx=10, pady=10) + + # Map placeholder + self.map_label = ttk.Label(self.map_frame, text="Map will be displayed here after GPS data is received", + font=('Arial', 12)) + self.map_label.pack(expand=True) + + def setup_settings_tab(self): + """Setup the settings tab""" + settings_frame = ttk.Frame(self.tab_settings) + settings_frame.pack(fill='both', expand=True, padx=10, pady=10) + + entries = [ + ('System Frequency (Hz):', 'system_frequency', 10e9), + ('Chirp Duration (s):', 'chirp_duration', 30e-6), + ('Chirps per Position:', 'chirps_per_position', 32), + ('Frequency Min (Hz):', 'freq_min', 10e6), + ('Frequency Max (Hz):', 'freq_max', 30e6), + ('PRF1 (Hz):', 'prf1', 1000), + ('PRF2 (Hz):', 'prf2', 2000), + ('Max Distance (m):', 'max_distance', 50000) + ] + + self.settings_vars = {} + + for i, (label, attr, default) in enumerate(entries): + ttk.Label(settings_frame, text=label).grid(row=i, column=0, sticky='w', padx=5, pady=5) + var = tk.StringVar(value=str(default)) + entry = ttk.Entry(settings_frame, textvariable=var, width=20) + entry.grid(row=i, column=1, padx=5, pady=5) + self.settings_vars[attr] = var + + ttk.Button(settings_frame, text="Apply Settings", + command=self.apply_settings).grid(row=len(entries), column=0, columnspan=2, pady=10) + + def refresh_devices(self): + """Refresh available USB devices""" + # STM32 USB devices + stm32_devices = self.stm32_usb_interface.list_devices() + stm32_names = [dev['description'] for dev in stm32_devices] + self.stm32_usb_combo['values'] = stm32_names + + # FTDI devices + ftdi_devices = self.ftdi_interface.list_devices() + ftdi_names = [dev['description'] for dev in ftdi_devices] + self.ftdi_combo['values'] = ftdi_names + + if stm32_names: + self.stm32_usb_combo.current(0) + if ftdi_names: + self.ftdi_combo.current(0) + + def start_radar(self): + """Step 11: Start button pressed - Begin radar operation""" + try: + # Open STM32 USB device + stm32_index = self.stm32_usb_combo.current() + if stm32_index == -1: + messagebox.showerror("Error", "Please select an STM32 USB device") + return + + stm32_devices = self.stm32_usb_interface.list_devices() + if stm32_index >= len(stm32_devices): + messagebox.showerror("Error", "Invalid STM32 device selection") + return + + if not self.stm32_usb_interface.open_device(stm32_devices[stm32_index]): + messagebox.showerror("Error", "Failed to open STM32 USB device") + return + + # Open FTDI device + if FTDI_AVAILABLE: + ftdi_index = self.ftdi_combo.current() + if ftdi_index != -1: + ftdi_devices = self.ftdi_interface.list_devices() + if ftdi_index < len(ftdi_devices): + device_url = ftdi_devices[ftdi_index]['url'] + if not self.ftdi_interface.open_device(device_url): + logging.warning("Failed to open FTDI device, continuing without radar data") + else: + logging.warning("No FTDI device selected, continuing without radar data") + else: + logging.warning("FTDI not available, continuing without radar data") + + # Step 12: Send start flag to STM32 via USB + if not self.stm32_usb_interface.send_start_flag(): + messagebox.showerror("Error", "Failed to send start flag to STM32") + return + + # Step 13: Send settings to STM32 via USB + self.apply_settings() + + # Start radar operation + self.running = True + self.start_button.config(state="disabled") + self.stop_button.config(state="normal") + self.status_label.config(text="Status: Radar running - Waiting for GPS data...") + + logging.info("Radar system started successfully via USB CDC") + + except Exception as e: + messagebox.showerror("Error", f"Failed to start radar: {e}") + logging.error(f"Start radar error: {e}") + + def stop_radar(self): + """Stop radar operation""" + self.running = False + self.start_button.config(state="normal") + self.stop_button.config(state="disabled") + self.status_label.config(text="Status: Radar stopped") + + self.stm32_usb_interface.close() + self.ftdi_interface.close() + + logging.info("Radar system stopped") + + def apply_settings(self): + """Step 13: Apply and send radar settings via USB""" + try: + self.settings.system_frequency = float(self.settings_vars['system_frequency'].get()) + self.settings.chirp_duration = float(self.settings_vars['chirp_duration'].get()) + self.settings.chirps_per_position = int(self.settings_vars['chirps_per_position'].get()) + self.settings.freq_min = float(self.settings_vars['freq_min'].get()) + self.settings.freq_max = float(self.settings_vars['freq_max'].get()) + self.settings.prf1 = float(self.settings_vars['prf1'].get()) + self.settings.prf2 = float(self.settings_vars['prf2'].get()) + self.settings.max_distance = float(self.settings_vars['max_distance'].get()) + + if self.stm32_usb_interface.is_open: + self.stm32_usb_interface.send_settings(self.settings) + + messagebox.showinfo("Success", "Settings applied and sent to STM32 via USB") + logging.info("Radar settings applied via USB") + + except ValueError as e: + messagebox.showerror("Error", f"Invalid setting value: {e}") + + def start_background_threads(self): + """Start background data processing threads""" + self.radar_thread = threading.Thread(target=self.process_radar_data, daemon=True) + self.radar_thread.start() + + self.gps_thread = threading.Thread(target=self.process_gps_data, daemon=True) + self.gps_thread.start() + + self.root.after(100, self.update_gui) + + def process_radar_data(self): + """Step 39: Process incoming radar data from FTDI""" + buffer = b'' + while True: + if self.running and self.ftdi_interface.is_open: + try: + data = self.ftdi_interface.read_data(4096) + if data: + buffer += data + + while len(buffer) >= 6: + packet = self.radar_packet_parser.parse_packet(buffer) + if packet: + self.process_radar_packet(packet) + packet_length = 4 + len(packet.get('payload', b'')) + 2 + buffer = buffer[packet_length:] + self.received_packets += 1 + else: + break + + except Exception as e: + logging.error(f"Error processing radar data: {e}") + time.sleep(0.1) + else: + time.sleep(0.1) + + def process_gps_data(self): + """Step 16/17: Process GPS data from STM32 via USB CDC""" + while True: + if self.running and self.stm32_usb_interface.is_open: + try: + # Read data from STM32 USB + data = self.stm32_usb_interface.read_data(64, timeout=100) + if data: + gps_data = self.usb_packet_parser.parse_gps_data(data) + if gps_data: + self.gps_data_queue.put(gps_data) + logging.info(f"GPS Data received via USB: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m") + except Exception as e: + logging.error(f"Error processing GPS data via USB: {e}") + time.sleep(0.1) + + def process_radar_packet(self, packet): + """Step 40: Process radar data and update displays""" + try: + if packet['type'] == 'range': + range_meters = packet['range'] * 0.1 + + target = RadarTarget( + id=packet['chirp'], + range=range_meters, + velocity=0, + azimuth=packet['azimuth'], + elevation=packet['elevation'], + snr=20.0, + timestamp=packet['timestamp'] + ) + + self.update_range_doppler_map(target) + + elif packet['type'] == 'doppler': + lambda_wavelength = 3e8 / self.settings.system_frequency + velocity = (packet['doppler_real'] / 32767.0) * (self.settings.prf1 * lambda_wavelength / 2) + self.update_target_velocity(packet, velocity) + + elif packet['type'] == 'detection': + if packet['detected']: + logging.info(f"CFAR Detection: Elevation {packet['elevation']}, Azimuth {packet['azimuth']}") + + except Exception as e: + logging.error(f"Error processing radar packet: {e}") + + def update_range_doppler_map(self, target): + """Update range-Doppler map with new target""" + range_bin = min(int(target.range / 50), 1023) + doppler_bin = min(abs(int(target.velocity)), 31) + + self.radar_processor.range_doppler_map[range_bin, doppler_bin] += 1 + + self.radar_processor.detected_targets.append(target) + + if len(self.radar_processor.detected_targets) > 100: + self.radar_processor.detected_targets = self.radar_processor.detected_targets[-100:] + + def update_target_velocity(self, packet, velocity): + """Update target velocity information""" + for target in self.radar_processor.detected_targets: + if (target.azimuth == packet['azimuth'] and + target.elevation == packet['elevation'] and + target.id == packet['chirp']): + target.velocity = velocity + break + + def update_gui(self): + """Step 40: Update all GUI displays""" + try: + # Update status + if self.running: + self.status_label.config( + text=f"Status: Running - Packets: {self.received_packets} - GPS: {self.current_gps.latitude:.4f}, {self.current_gps.longitude:.4f}") + + # Update range-Doppler map + if hasattr(self, 'range_doppler_plot'): + display_data = np.log10(self.radar_processor.range_doppler_map + 1) + self.range_doppler_plot.set_array(display_data) + self.canvas.draw_idle() + + # Update targets list + self.update_targets_list() + + # Update GPS display + self.update_gps_display() + + except Exception as e: + logging.error(f"Error updating GUI: {e}") + + self.root.after(100, self.update_gui) + + def update_targets_list(self): + """Update the targets list display""" + for item in self.targets_tree.get_children(): + self.targets_tree.delete(item) + + for target in self.radar_processor.detected_targets[-20:]: + self.targets_tree.insert('', 'end', values=( + target.track_id, + f"{target.range:.1f}", + f"{target.velocity:.1f}", + target.azimuth, + target.elevation, + f"{target.snr:.1f}" + )) + + def update_gps_display(self): + """Step 18: Update GPS display and center map""" + try: + while not self.gps_data_queue.empty(): + gps_data = self.gps_data_queue.get_nowait() + self.current_gps = gps_data + + # Update GPS label + self.gps_label.config( + text=f"GPS: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m") + + # Update map + self.update_map_display(gps_data) + + except queue.Empty: + pass + + def update_map_display(self, gps_data): + """Step 18: Update map display with current GPS position""" + try: + self.map_label.config(text=f"Radar Position: {gps_data.latitude:.6f}, {gps_data.longitude:.6f}\n" + f"Altitude: {gps_data.altitude:.1f}m\n" + f"Coverage: 50km radius\n" + f"Map centered on GPS coordinates") + + except Exception as e: + logging.error(f"Error updating map display: {e}") + +def main(): + """Main application entry point""" + try: + root = tk.Tk() + app = RadarGUI(root) + root.mainloop() + except Exception as e: + logging.error(f"Application error: {e}") + messagebox.showerror("Fatal Error", f"Application failed to start: {e}") + +if __name__ == "__main__": + main() diff --git a/9_Firmware/9_3_GUI/GUI_V3.py b/9_Firmware/9_3_GUI/GUI_V3.py new file mode 100644 index 0000000..f519804 --- /dev/null +++ b/9_Firmware/9_3_GUI/GUI_V3.py @@ -0,0 +1,1146 @@ +import tkinter as tk +from tkinter import ttk, messagebox +import threading +import queue +import time +import struct +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.figure import Figure +import logging +from dataclasses import dataclass +from typing import Dict, List, Tuple, Optional +from scipy import signal +from sklearn.cluster import DBSCAN +from filterpy.kalman import KalmanFilter +import crcmod +import math + +try: + import usb.core + import usb.util + USB_AVAILABLE = True +except ImportError: + USB_AVAILABLE = False + logging.warning("pyusb not available. USB CDC functionality will be disabled.") + +try: + from pyftdi.ftdi import Ftdi + from pyftdi.usbtools import UsbTools + FTDI_AVAILABLE = True +except ImportError: + FTDI_AVAILABLE = False + logging.warning("pyftdi not available. FTDI functionality will be disabled.") + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +@dataclass +class RadarTarget: + id: int + range: float + velocity: float + azimuth: int + elevation: int + snr: float + timestamp: float + track_id: int = -1 + +@dataclass +class RadarSettings: + system_frequency: float = 10e9 + chirp_duration: float = 30e-6 + chirps_per_position: int = 32 + freq_min: float = 10e6 + freq_max: float = 30e6 + prf1: float = 1000 + prf2: float = 2000 + max_distance: float = 50000 + +@dataclass +class GPSData: + latitude: float + longitude: float + altitude: float + pitch: float # Pitch angle in degrees + timestamp: float + +class STM32USBInterface: + def __init__(self): + self.device = None + self.is_open = False + self.ep_in = None + self.ep_out = None + + def list_devices(self): + """List available STM32 USB CDC devices""" + if not USB_AVAILABLE: + logging.warning("USB not available - please install pyusb") + return [] + + try: + devices = [] + # STM32 USB CDC devices typically use these vendor/product IDs + stm32_vid_pids = [ + (0x0483, 0x5740), # STM32 Virtual COM Port + (0x0483, 0x3748), # STM32 Discovery + (0x0483, 0x374B), # STM32 CDC + (0x0483, 0x374D), # STM32 CDC + (0x0483, 0x374E), # STM32 CDC + (0x0483, 0x3752), # STM32 CDC + ] + + for vid, pid in stm32_vid_pids: + found_devices = usb.core.find(find_all=True, idVendor=vid, idProduct=pid) + for dev in found_devices: + try: + product = usb.util.get_string(dev, dev.iProduct) if dev.iProduct else "STM32 CDC" + serial = usb.util.get_string(dev, dev.iSerialNumber) if dev.iSerialNumber else "Unknown" + devices.append({ + 'description': f"{product} ({serial})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + except: + devices.append({ + 'description': f"STM32 CDC (VID:{vid:04X}, PID:{pid:04X})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + + return devices + except Exception as e: + logging.error(f"Error listing USB devices: {e}") + # Return mock devices for testing + return [{'description': 'STM32 Virtual COM Port', 'vendor_id': 0x0483, 'product_id': 0x5740}] + + def open_device(self, device_info): + """Open STM32 USB CDC device""" + if not USB_AVAILABLE: + logging.error("USB not available - cannot open device") + return False + + try: + self.device = device_info['device'] + + # Detach kernel driver if active + if self.device.is_kernel_driver_active(0): + self.device.detach_kernel_driver(0) + + # Set configuration + self.device.set_configuration() + + # Get CDC endpoints + cfg = self.device.get_active_configuration() + intf = cfg[(0,0)] + + # Find bulk endpoints (CDC data interface) + self.ep_out = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT + ) + + self.ep_in = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN + ) + + if self.ep_out is None or self.ep_in is None: + logging.error("Could not find CDC endpoints") + return False + + self.is_open = True + logging.info(f"STM32 USB device opened: {device_info['description']}") + return True + + except Exception as e: + logging.error(f"Error opening USB device: {e}") + return False + + def send_start_flag(self): + """Step 12: Send start flag to STM32 via USB""" + start_packet = bytes([23, 46, 158, 237]) + logging.info("Sending start flag to STM32 via USB...") + return self._send_data(start_packet) + + def send_settings(self, settings): + """Step 13: Send radar settings to STM32 via USB""" + try: + packet = self._create_settings_packet(settings) + logging.info("Sending radar settings to STM32 via USB...") + return self._send_data(packet) + except Exception as e: + logging.error(f"Error sending settings via USB: {e}") + return False + + def read_data(self, size=64, timeout=1000): + """Read data from STM32 via USB""" + if not self.is_open or self.ep_in is None: + return None + + try: + data = self.ep_in.read(size, timeout=timeout) + return bytes(data) + except usb.core.USBError as e: + if e.errno == 110: # Timeout + return None + logging.error(f"USB read error: {e}") + return None + except Exception as e: + logging.error(f"Error reading from USB: {e}") + return None + + def _send_data(self, data): + """Send data to STM32 via USB""" + if not self.is_open or self.ep_out is None: + return False + + try: + # USB CDC typically uses 64-byte packets + packet_size = 64 + for i in range(0, len(data), packet_size): + chunk = data[i:i + packet_size] + # Pad to packet size if needed + if len(chunk) < packet_size: + chunk += b'\x00' * (packet_size - len(chunk)) + self.ep_out.write(chunk) + + return True + except Exception as e: + logging.error(f"Error sending data via USB: {e}") + return False + + def _create_settings_packet(self, settings): + """Create binary settings packet for USB transmission""" + packet = b'SET' + packet += struct.pack('>d', settings.system_frequency) + packet += struct.pack('>d', settings.chirp_duration) + packet += struct.pack('>I', settings.chirps_per_position) + packet += struct.pack('>d', settings.freq_min) + packet += struct.pack('>d', settings.freq_max) + packet += struct.pack('>d', settings.prf1) + packet += struct.pack('>d', settings.prf2) + packet += struct.pack('>d', settings.max_distance) + packet += b'END' + return packet + + def close(self): + """Close USB device""" + if self.device and self.is_open: + try: + usb.util.dispose_resources(self.device) + self.is_open = False + except Exception as e: + logging.error(f"Error closing USB device: {e}") + +class FTDIInterface: + def __init__(self): + self.ftdi = None + self.is_open = False + + def list_devices(self): + """List available FTDI devices using pyftdi""" + if not FTDI_AVAILABLE: + logging.warning("FTDI not available - please install pyftdi") + return [] + + try: + devices = [] + # Get list of all FTDI devices + for device in UsbTools.find_all([(0x0403, 0x6010)]): # FT2232H vendor/product ID + devices.append({ + 'description': f"FTDI Device {device}", + 'url': f"ftdi://{device}/1" + }) + return devices + except Exception as e: + logging.error(f"Error listing FTDI devices: {e}") + # Return mock devices for testing + return [{'description': 'FT2232H Device A', 'url': 'ftdi://device/1'}] + + def open_device(self, device_url): + """Open FTDI device using pyftdi""" + if not FTDI_AVAILABLE: + logging.error("FTDI not available - cannot open device") + return False + + try: + self.ftdi = Ftdi() + self.ftdi.open_from_url(device_url) + + # Configure for synchronous FIFO mode + self.ftdi.set_bitmode(0xFF, Ftdi.BitMode.SYNCFF) + + # Set latency timer + self.ftdi.set_latency_timer(2) + + # Purge buffers + self.ftdi.purge_buffers() + + self.is_open = True + logging.info(f"FTDI device opened: {device_url}") + return True + + except Exception as e: + logging.error(f"Error opening FTDI device: {e}") + return False + + def read_data(self, bytes_to_read): + """Read data from FTDI""" + if not self.is_open or self.ftdi is None: + return None + + try: + data = self.ftdi.read_data(bytes_to_read) + if data: + return bytes(data) + return None + except Exception as e: + logging.error(f"Error reading from FTDI: {e}") + return None + + def close(self): + """Close FTDI device""" + if self.ftdi and self.is_open: + self.ftdi.close() + self.is_open = False + +class RadarProcessor: + def __init__(self): + self.range_doppler_map = np.zeros((1024, 32)) + self.detected_targets = [] + self.track_id_counter = 0 + self.tracks = {} + self.frame_count = 0 + + def dual_cpi_fusion(self, range_profiles_1, range_profiles_2): + """Dual-CPI fusion for better detection""" + fused_profile = np.mean(range_profiles_1, axis=0) + np.mean(range_profiles_2, axis=0) + return fused_profile + + def multi_prf_unwrap(self, doppler_measurements, prf1, prf2): + """Multi-PRF velocity unwrapping""" + lambda_wavelength = 3e8 / 10e9 + v_max1 = prf1 * lambda_wavelength / 2 + v_max2 = prf2 * lambda_wavelength / 2 + + unwrapped_velocities = [] + for doppler in doppler_measurements: + v1 = doppler * lambda_wavelength / 2 + v2 = doppler * lambda_wavelength / 2 + + velocity = self._solve_chinese_remainder(v1, v2, v_max1, v_max2) + unwrapped_velocities.append(velocity) + + return unwrapped_velocities + + def _solve_chinese_remainder(self, v1, v2, max1, max2): + for k in range(-5, 6): + candidate = v1 + k * max1 + if abs(candidate - v2) < max2 / 2: + return candidate + return v1 + + def clustering(self, detections, eps=100, min_samples=2): + """DBSCAN clustering of detections""" + if len(detections) == 0: + return [] + + points = np.array([[d.range, d.velocity] for d in detections]) + clustering = DBSCAN(eps=eps, min_samples=min_samples).fit(points) + + clusters = [] + for label in set(clustering.labels_): + if label != -1: + cluster_points = points[clustering.labels_ == label] + clusters.append({ + 'center': np.mean(cluster_points, axis=0), + 'points': cluster_points, + 'size': len(cluster_points) + }) + + return clusters + + def association(self, detections, clusters): + """Association of detections to tracks""" + associated_detections = [] + + for detection in detections: + best_track = None + min_distance = float('inf') + + for track_id, track in self.tracks.items(): + distance = np.sqrt( + (detection.range - track['state'][0])**2 + + (detection.velocity - track['state'][2])**2 + ) + + if distance < min_distance and distance < 500: + min_distance = distance + best_track = track_id + + if best_track is not None: + detection.track_id = best_track + associated_detections.append(detection) + else: + detection.track_id = self.track_id_counter + self.track_id_counter += 1 + associated_detections.append(detection) + + return associated_detections + + def tracking(self, associated_detections): + """Kalman filter tracking""" + current_time = time.time() + + for detection in associated_detections: + if detection.track_id not in self.tracks: + kf = KalmanFilter(dim_x=4, dim_z=2) + kf.x = np.array([detection.range, 0, detection.velocity, 0]) + kf.F = np.array([[1, 1, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 1], + [0, 0, 0, 1]]) + kf.H = np.array([[1, 0, 0, 0], + [0, 0, 1, 0]]) + kf.P *= 1000 + kf.R = np.diag([10, 1]) + kf.Q = np.eye(4) * 0.1 + + self.tracks[detection.track_id] = { + 'filter': kf, + 'state': kf.x, + 'last_update': current_time, + 'hits': 1 + } + else: + track = self.tracks[detection.track_id] + track['filter'].predict() + track['filter'].update([detection.range, detection.velocity]) + track['state'] = track['filter'].x + track['last_update'] = current_time + track['hits'] += 1 + + stale_tracks = [tid for tid, track in self.tracks.items() + if current_time - track['last_update'] > 5.0] + for tid in stale_tracks: + del self.tracks[tid] + +class USBPacketParser: + def __init__(self): + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_gps_data(self, data): + """Parse GPS data from STM32 USB CDC with pitch angle""" + if not data: + return None + + try: + # Try text format first: "GPS:lat,lon,alt,pitch\r\n" + text_data = data.decode('utf-8', errors='ignore').strip() + if text_data.startswith('GPS:'): + parts = text_data.split(':')[1].split(',') + if len(parts) == 4: # Now expecting 4 values + lat = float(parts[0]) + lon = float(parts[1]) + alt = float(parts[2]) + pitch = float(parts[3]) # Pitch angle in degrees + return GPSData(latitude=lat, longitude=lon, altitude=alt, pitch=pitch, timestamp=time.time()) + + # Try binary format (30 bytes with pitch) + if len(data) >= 30 and data[0:4] == b'GPSB': + return self._parse_binary_gps_with_pitch(data) + + except Exception as e: + logging.error(f"Error parsing GPS data: {e}") + + return None + + def _parse_binary_gps_with_pitch(self, data): + """Parse binary GPS format with pitch angle (30 bytes)""" + try: + # Binary format: [Header 4][Latitude 8][Longitude 8][Altitude 4][Pitch 4][CRC 2] + if len(data) < 30: + return None + + # Verify CRC (simple checksum) + crc_received = (data[28] << 8) | data[29] + crc_calculated = sum(data[0:28]) & 0xFFFF + + if crc_received != crc_calculated: + logging.warning("GPS CRC mismatch") + return None + + # Parse latitude (double, big-endian) + lat_bits = 0 + for i in range(8): + lat_bits = (lat_bits << 8) | data[4 + i] + latitude = struct.unpack('>d', struct.pack('>Q', lat_bits))[0] + + # Parse longitude (double, big-endian) + lon_bits = 0 + for i in range(8): + lon_bits = (lon_bits << 8) | data[12 + i] + longitude = struct.unpack('>d', struct.pack('>Q', lon_bits))[0] + + # Parse altitude (float, big-endian) + alt_bits = 0 + for i in range(4): + alt_bits = (alt_bits << 8) | data[20 + i] + altitude = struct.unpack('>f', struct.pack('>I', alt_bits))[0] + + # Parse pitch angle (float, big-endian) + pitch_bits = 0 + for i in range(4): + pitch_bits = (pitch_bits << 8) | data[24 + i] + pitch = struct.unpack('>f', struct.pack('>I', pitch_bits))[0] + + return GPSData( + latitude=latitude, + longitude=longitude, + altitude=altitude, + pitch=pitch, + timestamp=time.time() + ) + + except Exception as e: + logging.error(f"Error parsing binary GPS with pitch: {e}") + return None + +class RadarPacketParser: + def __init__(self): + self.sync_pattern = b'\xA5\xC3' + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_packet(self, data): + if len(data) < 6: + return None + + sync_index = data.find(self.sync_pattern) + if sync_index == -1: + return None + + packet = data[sync_index:] + + if len(packet) < 6: + return None + + sync = packet[0:2] + packet_type = packet[2] + length = packet[3] + + if len(packet) < (4 + length + 2): + return None + + payload = packet[4:4+length] + crc_received = struct.unpack('I', payload[0:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'range', + 'range': range_value, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing range packet: {e}") + return None + + def parse_doppler_packet(self, payload): + if len(payload) < 12: + return None + + try: + doppler_real = struct.unpack('>h', payload[0:2])[0] + doppler_imag = struct.unpack('>h', payload[2:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'doppler', + 'doppler_real': doppler_real, + 'doppler_imag': doppler_imag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing Doppler packet: {e}") + return None + + def parse_detection_packet(self, payload): + if len(payload) < 8: + return None + + try: + detection_flag = (payload[0] & 0x01) != 0 + elevation = payload[1] & 0x1F + azimuth = payload[2] & 0x3F + chirp_counter = payload[3] & 0x1F + + return { + 'type': 'detection', + 'detected': detection_flag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing detection packet: {e}") + return None + +class RadarGUI: + def __init__(self, root): + self.root = root + self.root.title("Advanced Radar System GUI - USB CDC with Pitch Correction") + self.root.geometry("1400x900") + + # Initialize interfaces + self.stm32_usb_interface = STM32USBInterface() + self.ftdi_interface = FTDIInterface() + self.radar_processor = RadarProcessor() + self.usb_packet_parser = USBPacketParser() + self.radar_packet_parser = RadarPacketParser() + self.settings = RadarSettings() + + # Data queues + self.radar_data_queue = queue.Queue() + self.gps_data_queue = queue.Queue() + + # Thread control + self.running = False + self.radar_thread = None + self.gps_thread = None + + # Counters + self.received_packets = 0 + self.current_gps = GPSData(latitude=41.9028, longitude=12.4964, altitude=0, pitch=0.0, timestamp=0) + self.corrected_elevations = [] # Store corrected elevation values + + self.create_gui() + self.start_background_threads() + + def create_gui(self): + """Create the main GUI with tabs""" + self.notebook = ttk.Notebook(self.root) + self.notebook.pack(fill='both', expand=True, padx=10, pady=10) + + self.tab_main = ttk.Frame(self.notebook) + self.tab_map = ttk.Frame(self.notebook) + self.tab_diagnostics = ttk.Frame(self.notebook) + self.tab_settings = ttk.Frame(self.notebook) + + self.notebook.add(self.tab_main, text='Main View') + self.notebook.add(self.tab_map, text='Map View') + self.notebook.add(self.tab_diagnostics, text='Diagnostics') + self.notebook.add(self.tab_settings, text='Settings') + + self.setup_main_tab() + self.setup_map_tab() + self.setup_settings_tab() + + def setup_main_tab(self): + """Setup the main radar display tab""" + # Control frame + control_frame = ttk.Frame(self.tab_main) + control_frame.pack(fill='x', padx=10, pady=5) + + # USB Device selection + ttk.Label(control_frame, text="STM32 USB Device:").grid(row=0, column=0, padx=5) + self.stm32_usb_combo = ttk.Combobox(control_frame, state="readonly", width=40) + self.stm32_usb_combo.grid(row=0, column=1, padx=5) + + ttk.Label(control_frame, text="FTDI Device:").grid(row=0, column=2, padx=5) + self.ftdi_combo = ttk.Combobox(control_frame, state="readonly", width=30) + self.ftdi_combo.grid(row=0, column=3, padx=5) + + ttk.Button(control_frame, text="Refresh Devices", + command=self.refresh_devices).grid(row=0, column=4, padx=5) + + self.start_button = ttk.Button(control_frame, text="Start Radar", + command=self.start_radar) + self.start_button.grid(row=0, column=5, padx=5) + + self.stop_button = ttk.Button(control_frame, text="Stop Radar", + command=self.stop_radar, state="disabled") + self.stop_button.grid(row=0, column=6, padx=5) + + # GPS and Pitch info + self.gps_label = ttk.Label(control_frame, text="GPS: Waiting for data...") + self.gps_label.grid(row=1, column=0, columnspan=4, sticky='w', padx=5, pady=2) + + # Pitch display + self.pitch_label = ttk.Label(control_frame, text="Pitch: --.--°") + self.pitch_label.grid(row=1, column=4, columnspan=2, padx=5, pady=2) + + # Status info + self.status_label = ttk.Label(control_frame, text="Status: Ready") + self.status_label.grid(row=1, column=6, sticky='e', padx=5, pady=2) + + # Main display area + display_frame = ttk.Frame(self.tab_main) + display_frame.pack(fill='both', expand=True, padx=10, pady=5) + + # Range-Doppler Map + fig = Figure(figsize=(10, 6)) + self.range_doppler_ax = fig.add_subplot(111) + self.range_doppler_plot = self.range_doppler_ax.imshow( + np.random.rand(1024, 32), aspect='auto', cmap='hot', + extent=[0, 32, 0, 1024]) + self.range_doppler_ax.set_title('Range-Doppler Map (Pitch Corrected)') + self.range_doppler_ax.set_xlabel('Doppler Bin') + self.range_doppler_ax.set_ylabel('Range Bin') + + self.canvas = FigureCanvasTkAgg(fig, display_frame) + self.canvas.draw() + self.canvas.get_tk_widget().pack(side='left', fill='both', expand=True) + + # Targets list with corrected elevation + targets_frame = ttk.LabelFrame(display_frame, text="Detected Targets (Pitch Corrected)") + targets_frame.pack(side='right', fill='y', padx=5) + + self.targets_tree = ttk.Treeview(targets_frame, + columns=('ID', 'Range', 'Velocity', 'Azimuth', 'Elevation', 'Corrected Elev', 'SNR'), + show='headings', height=20) + self.targets_tree.heading('ID', text='Track ID') + self.targets_tree.heading('Range', text='Range (m)') + self.targets_tree.heading('Velocity', text='Velocity (m/s)') + self.targets_tree.heading('Azimuth', text='Azimuth') + self.targets_tree.heading('Elevation', text='Raw Elev') + self.targets_tree.heading('Corrected Elev', text='Corr Elev') + self.targets_tree.heading('SNR', text='SNR (dB)') + + self.targets_tree.column('ID', width=70) + self.targets_tree.column('Range', width=90) + self.targets_tree.column('Velocity', width=90) + self.targets_tree.column('Azimuth', width=70) + self.targets_tree.column('Elevation', width=70) + self.targets_tree.column('Corrected Elev', width=70) + self.targets_tree.column('SNR', width=70) + + self.targets_tree.pack(fill='both', expand=True, padx=5, pady=5) + + def setup_map_tab(self): + """Setup the map display tab""" + self.map_frame = ttk.Frame(self.tab_map) + self.map_frame.pack(fill='both', expand=True, padx=10, pady=10) + + # Map placeholder + self.map_label = ttk.Label(self.map_frame, text="Map will be displayed here after GPS data is received", + font=('Arial', 12)) + self.map_label.pack(expand=True) + + def setup_settings_tab(self): + """Setup the settings tab""" + settings_frame = ttk.Frame(self.tab_settings) + settings_frame.pack(fill='both', expand=True, padx=10, pady=10) + + entries = [ + ('System Frequency (Hz):', 'system_frequency', 10e9), + ('Chirp Duration (s):', 'chirp_duration', 30e-6), + ('Chirps per Position:', 'chirps_per_position', 32), + ('Frequency Min (Hz):', 'freq_min', 10e6), + ('Frequency Max (Hz):', 'freq_max', 30e6), + ('PRF1 (Hz):', 'prf1', 1000), + ('PRF2 (Hz):', 'prf2', 2000), + ('Max Distance (m):', 'max_distance', 50000) + ] + + self.settings_vars = {} + + for i, (label, attr, default) in enumerate(entries): + ttk.Label(settings_frame, text=label).grid(row=i, column=0, sticky='w', padx=5, pady=5) + var = tk.StringVar(value=str(default)) + entry = ttk.Entry(settings_frame, textvariable=var, width=20) + entry.grid(row=i, column=1, padx=5, pady=5) + self.settings_vars[attr] = var + + ttk.Button(settings_frame, text="Apply Settings", + command=self.apply_settings).grid(row=len(entries), column=0, columnspan=2, pady=10) + + def apply_pitch_correction(self, raw_elevation, pitch_angle): + """ + Apply pitch correction to elevation angle + raw_elevation: measured elevation from radar (degrees) + pitch_angle: antenna pitch angle from IMU (degrees) + Returns: corrected elevation angle (degrees) + """ + # Convert to radians for trigonometric functions + raw_elev_rad = math.radians(raw_elevation) + pitch_rad = math.radians(pitch_angle) + + # Apply pitch correction: corrected_elev = raw_elev - pitch + # This assumes the pitch angle is positive when antenna is tilted up + corrected_elev_rad = raw_elev_rad - pitch_rad + + # Convert back to degrees and ensure it's within valid range + corrected_elev_deg = math.degrees(corrected_elev_rad) + + # Normalize to 0-180 degree range + corrected_elev_deg = corrected_elev_deg % 180 + if corrected_elev_deg < 0: + corrected_elev_deg += 180 + + return corrected_elev_deg + + def refresh_devices(self): + """Refresh available USB devices""" + # STM32 USB devices + stm32_devices = self.stm32_usb_interface.list_devices() + stm32_names = [dev['description'] for dev in stm32_devices] + self.stm32_usb_combo['values'] = stm32_names + + # FTDI devices + ftdi_devices = self.ftdi_interface.list_devices() + ftdi_names = [dev['description'] for dev in ftdi_devices] + self.ftdi_combo['values'] = ftdi_names + + if stm32_names: + self.stm32_usb_combo.current(0) + if ftdi_names: + self.ftdi_combo.current(0) + + def start_radar(self): + """Step 11: Start button pressed - Begin radar operation""" + try: + # Open STM32 USB device + stm32_index = self.stm32_usb_combo.current() + if stm32_index == -1: + messagebox.showerror("Error", "Please select an STM32 USB device") + return + + stm32_devices = self.stm32_usb_interface.list_devices() + if stm32_index >= len(stm32_devices): + messagebox.showerror("Error", "Invalid STM32 device selection") + return + + if not self.stm32_usb_interface.open_device(stm32_devices[stm32_index]): + messagebox.showerror("Error", "Failed to open STM32 USB device") + return + + # Open FTDI device + if FTDI_AVAILABLE: + ftdi_index = self.ftdi_combo.current() + if ftdi_index != -1: + ftdi_devices = self.ftdi_interface.list_devices() + if ftdi_index < len(ftdi_devices): + device_url = ftdi_devices[ftdi_index]['url'] + if not self.ftdi_interface.open_device(device_url): + logging.warning("Failed to open FTDI device, continuing without radar data") + else: + logging.warning("No FTDI device selected, continuing without radar data") + else: + logging.warning("FTDI not available, continuing without radar data") + + # Step 12: Send start flag to STM32 via USB + if not self.stm32_usb_interface.send_start_flag(): + messagebox.showerror("Error", "Failed to send start flag to STM32") + return + + # Step 13: Send settings to STM32 via USB + self.apply_settings() + + # Start radar operation + self.running = True + self.start_button.config(state="disabled") + self.stop_button.config(state="normal") + self.status_label.config(text="Status: Radar running - Waiting for GPS data...") + + logging.info("Radar system started successfully via USB CDC") + + except Exception as e: + messagebox.showerror("Error", f"Failed to start radar: {e}") + logging.error(f"Start radar error: {e}") + + def stop_radar(self): + """Stop radar operation""" + self.running = False + self.start_button.config(state="normal") + self.stop_button.config(state="disabled") + self.status_label.config(text="Status: Radar stopped") + + self.stm32_usb_interface.close() + self.ftdi_interface.close() + + logging.info("Radar system stopped") + + def apply_settings(self): + """Step 13: Apply and send radar settings via USB""" + try: + self.settings.system_frequency = float(self.settings_vars['system_frequency'].get()) + self.settings.chirp_duration = float(self.settings_vars['chirp_duration'].get()) + self.settings.chirps_per_position = int(self.settings_vars['chirps_per_position'].get()) + self.settings.freq_min = float(self.settings_vars['freq_min'].get()) + self.settings.freq_max = float(self.settings_vars['freq_max'].get()) + self.settings.prf1 = float(self.settings_vars['prf1'].get()) + self.settings.prf2 = float(self.settings_vars['prf2'].get()) + self.settings.max_distance = float(self.settings_vars['max_distance'].get()) + + if self.stm32_usb_interface.is_open: + self.stm32_usb_interface.send_settings(self.settings) + + messagebox.showinfo("Success", "Settings applied and sent to STM32 via USB") + logging.info("Radar settings applied via USB") + + except ValueError as e: + messagebox.showerror("Error", f"Invalid setting value: {e}") + + def start_background_threads(self): + """Start background data processing threads""" + self.radar_thread = threading.Thread(target=self.process_radar_data, daemon=True) + self.radar_thread.start() + + self.gps_thread = threading.Thread(target=self.process_gps_data, daemon=True) + self.gps_thread.start() + + self.root.after(100, self.update_gui) + + def process_radar_data(self): + """Step 39: Process incoming radar data from FTDI""" + buffer = b'' + while True: + if self.running and self.ftdi_interface.is_open: + try: + data = self.ftdi_interface.read_data(4096) + if data: + buffer += data + + while len(buffer) >= 6: + packet = self.radar_packet_parser.parse_packet(buffer) + if packet: + self.process_radar_packet(packet) + packet_length = 4 + len(packet.get('payload', b'')) + 2 + buffer = buffer[packet_length:] + self.received_packets += 1 + else: + break + + except Exception as e: + logging.error(f"Error processing radar data: {e}") + time.sleep(0.1) + else: + time.sleep(0.1) + + def process_gps_data(self): + """Step 16/17: Process GPS data from STM32 via USB CDC""" + while True: + if self.running and self.stm32_usb_interface.is_open: + try: + # Read data from STM32 USB + data = self.stm32_usb_interface.read_data(64, timeout=100) + if data: + gps_data = self.usb_packet_parser.parse_gps_data(data) + if gps_data: + self.gps_data_queue.put(gps_data) + logging.info(f"GPS Data received via USB: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m, Pitch {gps_data.pitch:.1f}°") + except Exception as e: + logging.error(f"Error processing GPS data via USB: {e}") + time.sleep(0.1) + + def process_radar_packet(self, packet): + """Step 40: Process radar data and apply pitch correction""" + try: + if packet['type'] == 'range': + range_meters = packet['range'] * 0.1 + + # Apply pitch correction to elevation + raw_elevation = packet['elevation'] + corrected_elevation = self.apply_pitch_correction(raw_elevation, self.current_gps.pitch) + + # Store correction for display + self.corrected_elevations.append({ + 'raw': raw_elevation, + 'corrected': corrected_elevation, + 'pitch': self.current_gps.pitch, + 'timestamp': packet['timestamp'] + }) + + # Keep only recent corrections + if len(self.corrected_elevations) > 100: + self.corrected_elevations = self.corrected_elevations[-100:] + + target = RadarTarget( + id=packet['chirp'], + range=range_meters, + velocity=0, + azimuth=packet['azimuth'], + elevation=corrected_elevation, # Use corrected elevation + snr=20.0, + timestamp=packet['timestamp'] + ) + + self.update_range_doppler_map(target) + + elif packet['type'] == 'doppler': + lambda_wavelength = 3e8 / self.settings.system_frequency + velocity = (packet['doppler_real'] / 32767.0) * (self.settings.prf1 * lambda_wavelength / 2) + self.update_target_velocity(packet, velocity) + + elif packet['type'] == 'detection': + if packet['detected']: + # Apply pitch correction to detection elevation + raw_elevation = packet['elevation'] + corrected_elevation = self.apply_pitch_correction(raw_elevation, self.current_gps.pitch) + + logging.info(f"CFAR Detection: Raw Elev {raw_elevation}°, Corrected Elev {corrected_elevation:.1f}°, Pitch {self.current_gps.pitch:.1f}°") + + except Exception as e: + logging.error(f"Error processing radar packet: {e}") + + def update_range_doppler_map(self, target): + """Update range-Doppler map with new target""" + range_bin = min(int(target.range / 50), 1023) + doppler_bin = min(abs(int(target.velocity)), 31) + + self.radar_processor.range_doppler_map[range_bin, doppler_bin] += 1 + + self.radar_processor.detected_targets.append(target) + + if len(self.radar_processor.detected_targets) > 100: + self.radar_processor.detected_targets = self.radar_processor.detected_targets[-100:] + + def update_target_velocity(self, packet, velocity): + """Update target velocity information""" + for target in self.radar_processor.detected_targets: + if (target.azimuth == packet['azimuth'] and + target.elevation == packet['elevation'] and + target.id == packet['chirp']): + target.velocity = velocity + break + + def update_gps_display(self): + """Step 18: Update GPS and pitch display""" + try: + while not self.gps_data_queue.empty(): + gps_data = self.gps_data_queue.get_nowait() + self.current_gps = gps_data + + # Update GPS label + self.gps_label.config( + text=f"GPS: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m") + + # Update pitch label with color coding + pitch_text = f"Pitch: {gps_data.pitch:+.1f}°" + self.pitch_label.config(text=pitch_text) + + # Color code based on pitch magnitude + if abs(gps_data.pitch) > 10: + self.pitch_label.config(foreground='red') # High pitch warning + elif abs(gps_data.pitch) > 5: + self.pitch_label.config(foreground='orange') # Medium pitch + else: + self.pitch_label.config(foreground='green') # Normal pitch + + # Update map + self.update_map_display(gps_data) + + except queue.Empty: + pass + + def update_targets_list(self): + """Update the targets list display with corrected elevations""" + for item in self.targets_tree.get_children(): + self.targets_tree.delete(item) + + for target in self.radar_processor.detected_targets[-20:]: + # Find the corresponding raw elevation if available + raw_elevation = "N/A" + for correction in self.corrected_elevations[-20:]: + if abs(correction['corrected'] - target.elevation) < 0.1: # Fuzzy match + raw_elevation = f"{correction['raw']}" + break + + self.targets_tree.insert('', 'end', values=( + target.track_id, + f"{target.range:.1f}", + f"{target.velocity:.1f}", + target.azimuth, + raw_elevation, # Show raw elevation + f"{target.elevation:.1f}", # Show corrected elevation + f"{target.snr:.1f}" + )) + + def update_gui(self): + """Step 40: Update all GUI displays""" + try: + # Update status with pitch information + if self.running: + self.status_label.config( + text=f"Status: Running - Packets: {self.received_packets} - Pitch: {self.current_gps.pitch:+.1f}°") + + # Update range-Doppler map + if hasattr(self, 'range_doppler_plot'): + display_data = np.log10(self.radar_processor.range_doppler_map + 1) + self.range_doppler_plot.set_array(display_data) + self.canvas.draw_idle() + + # Update targets list + self.update_targets_list() + + # Update GPS and pitch display + self.update_gps_display() + + except Exception as e: + logging.error(f"Error updating GUI: {e}") + + self.root.after(100, self.update_gui) + + def update_map_display(self, gps_data): + """Step 18: Update map display with current GPS position""" + try: + self.map_label.config(text=f"Radar Position: {gps_data.latitude:.6f}, {gps_data.longitude:.6f}\n" + f"Altitude: {gps_data.altitude:.1f}m\n" + f"Pitch: {gps_data.pitch:+.1f}°\n" + f"Coverage: 50km radius\n" + f"Map centered on GPS coordinates") + + except Exception as e: + logging.error(f"Error updating map display: {e}") + +def main(): + """Main application entry point""" + try: + root = tk.Tk() + app = RadarGUI(root) + root.mainloop() + except Exception as e: + logging.error(f"Application error: {e}") + messagebox.showerror("Fatal Error", f"Application failed to start: {e}") + +if __name__ == "__main__": + main() diff --git a/9_Firmware/9_3_GUI/GUI_V4.py b/9_Firmware/9_3_GUI/GUI_V4.py new file mode 100644 index 0000000..430323c --- /dev/null +++ b/9_Firmware/9_3_GUI/GUI_V4.py @@ -0,0 +1,1427 @@ +import tkinter as tk +from tkinter import ttk, messagebox +import threading +import queue +import time +import struct +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.figure import Figure +import matplotlib.patches as patches +import logging +from dataclasses import dataclass +from typing import Dict, List, Tuple, Optional +from scipy import signal +from sklearn.cluster import DBSCAN +from filterpy.kalman import KalmanFilter +import crcmod +import math +import webbrowser +import tempfile +import os + +try: + import usb.core + import usb.util + USB_AVAILABLE = True +except ImportError: + USB_AVAILABLE = False + logging.warning("pyusb not available. USB CDC functionality will be disabled.") + +try: + from pyftdi.ftdi import Ftdi + from pyftdi.usbtools import UsbTools + FTDI_AVAILABLE = True +except ImportError: + FTDI_AVAILABLE = False + logging.warning("pyftdi not available. FTDI functionality will be disabled.") + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +@dataclass +class RadarTarget: + id: int + range: float + velocity: float + azimuth: int + elevation: int + latitude: float = 0.0 + longitude: float = 0.0 + snr: float = 0.0 + timestamp: float = 0.0 + track_id: int = -1 + +@dataclass +class RadarSettings: + system_frequency: float = 10e9 + chirp_duration_1: float = 30e-6 # Long chirp duration + chirp_duration_2: float = 0.5e-6 # Short chirp duration + chirps_per_position: int = 32 + freq_min: float = 10e6 + freq_max: float = 30e6 + prf1: float = 1000 + prf2: float = 2000 + max_distance: float = 50000 + map_size: float = 50000 # Map size in meters + +@dataclass +class GPSData: + latitude: float + longitude: float + altitude: float + pitch: float # Pitch angle in degrees + timestamp: float + +class MapGenerator: + def __init__(self): + self.map_html_template = """ + + + + Radar Map + + + + + +
+ + + + + + + """ + + def generate_map(self, gps_data, targets, coverage_radius, api_key="YOUR_GOOGLE_MAPS_API_KEY"): + """Generate HTML map with radar and targets""" + # Convert targets to map coordinates + map_targets = [] + for target in targets: + # Convert polar coordinates (range, azimuth) to geographic coordinates + target_lat, target_lon = self.polar_to_geographic( + gps_data.latitude, gps_data.longitude, + target.range, target.azimuth + ) + map_targets.append({ + 'id': target.track_id, + 'lat': target_lat, + 'lng': target_lon, + 'range': target.range, + 'velocity': target.velocity, + 'azimuth': target.azimuth, + 'elevation': target.elevation, + 'snr': target.snr + }) + + # Generate targets script + targets_script = "" + if map_targets: + targets_json = str(map_targets).replace("'", '"') + targets_script = f"updateTargets({targets_json});" + + # Fill template + map_html = self.map_html_template.format( + lat=gps_data.latitude, + lon=gps_data.longitude, + alt=gps_data.altitude, + pitch=gps_data.pitch, + coverage_radius=coverage_radius, + targets_script=targets_script, + api_key=api_key + ) + + return map_html + + def polar_to_geographic(self, radar_lat, radar_lon, range_m, azimuth_deg): + """ + Convert polar coordinates (range, azimuth) to geographic coordinates + using simple flat-earth approximation (good for small distances) + """ + # Earth radius in meters + earth_radius = 6371000 + + # Convert azimuth to radians (0° = North, 90° = East) + azimuth_rad = math.radians(90 - azimuth_deg) # Convert to math convention + + # Convert range to angular distance + angular_distance = range_m / earth_radius + + # Convert to geographic coordinates + target_lat = radar_lat + math.cos(azimuth_rad) * angular_distance * (180 / math.pi) + target_lon = radar_lon + math.sin(azimuth_rad) * angular_distance * (180 / math.pi) / math.cos(math.radians(radar_lat)) + + return target_lat, target_lon + +class STM32USBInterface: + def __init__(self): + self.device = None + self.is_open = False + self.ep_in = None + self.ep_out = None + + def list_devices(self): + """List available STM32 USB CDC devices""" + if not USB_AVAILABLE: + logging.warning("USB not available - please install pyusb") + return [] + + try: + devices = [] + # STM32 USB CDC devices typically use these vendor/product IDs + stm32_vid_pids = [ + (0x0483, 0x5740), # STM32 Virtual COM Port + (0x0483, 0x3748), # STM32 Discovery + (0x0483, 0x374B), # STM32 CDC + (0x0483, 0x374D), # STM32 CDC + (0x0483, 0x374E), # STM32 CDC + (0x0483, 0x3752), # STM32 CDC + ] + + for vid, pid in stm32_vid_pids: + found_devices = usb.core.find(find_all=True, idVendor=vid, idProduct=pid) + for dev in found_devices: + try: + product = usb.util.get_string(dev, dev.iProduct) if dev.iProduct else "STM32 CDC" + serial = usb.util.get_string(dev, dev.iSerialNumber) if dev.iSerialNumber else "Unknown" + devices.append({ + 'description': f"{product} ({serial})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + except: + devices.append({ + 'description': f"STM32 CDC (VID:{vid:04X}, PID:{pid:04X})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + + return devices + except Exception as e: + logging.error(f"Error listing USB devices: {e}") + # Return mock devices for testing + return [{'description': 'STM32 Virtual COM Port', 'vendor_id': 0x0483, 'product_id': 0x5740}] + + def open_device(self, device_info): + """Open STM32 USB CDC device""" + if not USB_AVAILABLE: + logging.error("USB not available - cannot open device") + return False + + try: + self.device = device_info['device'] + + # Detach kernel driver if active + if self.device.is_kernel_driver_active(0): + self.device.detach_kernel_driver(0) + + # Set configuration + self.device.set_configuration() + + # Get CDC endpoints + cfg = self.device.get_active_configuration() + intf = cfg[(0,0)] + + # Find bulk endpoints (CDC data interface) + self.ep_out = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT + ) + + self.ep_in = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN + ) + + if self.ep_out is None or self.ep_in is None: + logging.error("Could not find CDC endpoints") + return False + + self.is_open = True + logging.info(f"STM32 USB device opened: {device_info['description']}") + return True + + except Exception as e: + logging.error(f"Error opening USB device: {e}") + return False + + def send_start_flag(self): + """Step 12: Send start flag to STM32 via USB""" + start_packet = bytes([23, 46, 158, 237]) + logging.info("Sending start flag to STM32 via USB...") + return self._send_data(start_packet) + + def send_settings(self, settings): + """Step 13: Send radar settings to STM32 via USB""" + try: + packet = self._create_settings_packet(settings) + logging.info("Sending radar settings to STM32 via USB...") + return self._send_data(packet) + except Exception as e: + logging.error(f"Error sending settings via USB: {e}") + return False + + def read_data(self, size=64, timeout=1000): + """Read data from STM32 via USB""" + if not self.is_open or self.ep_in is None: + return None + + try: + data = self.ep_in.read(size, timeout=timeout) + return bytes(data) + except usb.core.USBError as e: + if e.errno == 110: # Timeout + return None + logging.error(f"USB read error: {e}") + return None + except Exception as e: + logging.error(f"Error reading from USB: {e}") + return None + + def _send_data(self, data): + """Send data to STM32 via USB""" + if not self.is_open or self.ep_out is None: + return False + + try: + # USB CDC typically uses 64-byte packets + packet_size = 64 + for i in range(0, len(data), packet_size): + chunk = data[i:i + packet_size] + # Pad to packet size if needed + if len(chunk) < packet_size: + chunk += b'\x00' * (packet_size - len(chunk)) + self.ep_out.write(chunk) + + return True + except Exception as e: + logging.error(f"Error sending data via USB: {e}") + return False + + def _create_settings_packet(self, settings): + """Create binary settings packet for USB transmission""" + packet = b'SET' + packet += struct.pack('>d', settings.system_frequency) + packet += struct.pack('>d', settings.chirp_duration_1) + packet += struct.pack('>d', settings.chirp_duration_2) + packet += struct.pack('>I', settings.chirps_per_position) + packet += struct.pack('>d', settings.freq_min) + packet += struct.pack('>d', settings.freq_max) + packet += struct.pack('>d', settings.prf1) + packet += struct.pack('>d', settings.prf2) + packet += struct.pack('>d', settings.max_distance) + packet += struct.pack('>d', settings.map_size) + packet += b'END' + return packet + + def close(self): + """Close USB device""" + if self.device and self.is_open: + try: + usb.util.dispose_resources(self.device) + self.is_open = False + except Exception as e: + logging.error(f"Error closing USB device: {e}") + +class FTDIInterface: + def __init__(self): + self.ftdi = None + self.is_open = False + + def list_devices(self): + """List available FTDI devices using pyftdi""" + if not FTDI_AVAILABLE: + logging.warning("FTDI not available - please install pyftdi") + return [] + + try: + devices = [] + # Get list of all FTDI devices + for device in UsbTools.find_all([(0x0403, 0x6010)]): # FT2232H vendor/product ID + devices.append({ + 'description': f"FTDI Device {device}", + 'url': f"ftdi://{device}/1" + }) + return devices + except Exception as e: + logging.error(f"Error listing FTDI devices: {e}") + # Return mock devices for testing + return [{'description': 'FT2232H Device A', 'url': 'ftdi://device/1'}] + + def open_device(self, device_url): + """Open FTDI device using pyftdi""" + if not FTDI_AVAILABLE: + logging.error("FTDI not available - cannot open device") + return False + + try: + self.ftdi = Ftdi() + self.ftdi.open_from_url(device_url) + + # Configure for synchronous FIFO mode + self.ftdi.set_bitmode(0xFF, Ftdi.BitMode.SYNCFF) + + # Set latency timer + self.ftdi.set_latency_timer(2) + + # Purge buffers + self.ftdi.purge_buffers() + + self.is_open = True + logging.info(f"FTDI device opened: {device_url}") + return True + + except Exception as e: + logging.error(f"Error opening FTDI device: {e}") + return False + + def read_data(self, bytes_to_read): + """Read data from FTDI""" + if not self.is_open or self.ftdi is None: + return None + + try: + data = self.ftdi.read_data(bytes_to_read) + if data: + return bytes(data) + return None + except Exception as e: + logging.error(f"Error reading from FTDI: {e}") + return None + + def close(self): + """Close FTDI device""" + if self.ftdi and self.is_open: + self.ftdi.close() + self.is_open = False + +class RadarProcessor: + def __init__(self): + self.range_doppler_map = np.zeros((1024, 32)) + self.detected_targets = [] + self.track_id_counter = 0 + self.tracks = {} + self.frame_count = 0 + + def dual_cpi_fusion(self, range_profiles_1, range_profiles_2): + """Dual-CPI fusion for better detection""" + fused_profile = np.mean(range_profiles_1, axis=0) + np.mean(range_profiles_2, axis=0) + return fused_profile + + def multi_prf_unwrap(self, doppler_measurements, prf1, prf2): + """Multi-PRF velocity unwrapping""" + lambda_wavelength = 3e8 / 10e9 + v_max1 = prf1 * lambda_wavelength / 2 + v_max2 = prf2 * lambda_wavelength / 2 + + unwrapped_velocities = [] + for doppler in doppler_measurements: + v1 = doppler * lambda_wavelength / 2 + v2 = doppler * lambda_wavelength / 2 + + velocity = self._solve_chinese_remainder(v1, v2, v_max1, v_max2) + unwrapped_velocities.append(velocity) + + return unwrapped_velocities + + def _solve_chinese_remainder(self, v1, v2, max1, max2): + for k in range(-5, 6): + candidate = v1 + k * max1 + if abs(candidate - v2) < max2 / 2: + return candidate + return v1 + + def clustering(self, detections, eps=100, min_samples=2): + """DBSCAN clustering of detections""" + if len(detections) == 0: + return [] + + points = np.array([[d.range, d.velocity] for d in detections]) + clustering = DBSCAN(eps=eps, min_samples=min_samples).fit(points) + + clusters = [] + for label in set(clustering.labels_): + if label != -1: + cluster_points = points[clustering.labels_ == label] + clusters.append({ + 'center': np.mean(cluster_points, axis=0), + 'points': cluster_points, + 'size': len(cluster_points) + }) + + return clusters + + def association(self, detections, clusters): + """Association of detections to tracks""" + associated_detections = [] + + for detection in detections: + best_track = None + min_distance = float('inf') + + for track_id, track in self.tracks.items(): + distance = np.sqrt( + (detection.range - track['state'][0])**2 + + (detection.velocity - track['state'][2])**2 + ) + + if distance < min_distance and distance < 500: + min_distance = distance + best_track = track_id + + if best_track is not None: + detection.track_id = best_track + associated_detections.append(detection) + else: + detection.track_id = self.track_id_counter + self.track_id_counter += 1 + associated_detections.append(detection) + + return associated_detections + + def tracking(self, associated_detections): + """Kalman filter tracking""" + current_time = time.time() + + for detection in associated_detections: + if detection.track_id not in self.tracks: + kf = KalmanFilter(dim_x=4, dim_z=2) + kf.x = np.array([detection.range, 0, detection.velocity, 0]) + kf.F = np.array([[1, 1, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 1], + [0, 0, 0, 1]]) + kf.H = np.array([[1, 0, 0, 0], + [0, 0, 1, 0]]) + kf.P *= 1000 + kf.R = np.diag([10, 1]) + kf.Q = np.eye(4) * 0.1 + + self.tracks[detection.track_id] = { + 'filter': kf, + 'state': kf.x, + 'last_update': current_time, + 'hits': 1 + } + else: + track = self.tracks[detection.track_id] + track['filter'].predict() + track['filter'].update([detection.range, detection.velocity]) + track['state'] = track['filter'].x + track['last_update'] = current_time + track['hits'] += 1 + + stale_tracks = [tid for tid, track in self.tracks.items() + if current_time - track['last_update'] > 5.0] + for tid in stale_tracks: + del self.tracks[tid] + +class USBPacketParser: + def __init__(self): + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_gps_data(self, data): + """Parse GPS data from STM32 USB CDC with pitch angle""" + if not data: + return None + + try: + # Try text format first: "GPS:lat,lon,alt,pitch\r\n" + text_data = data.decode('utf-8', errors='ignore').strip() + if text_data.startswith('GPS:'): + parts = text_data.split(':')[1].split(',') + if len(parts) == 4: # Now expecting 4 values + lat = float(parts[0]) + lon = float(parts[1]) + alt = float(parts[2]) + pitch = float(parts[3]) # Pitch angle in degrees + return GPSData(latitude=lat, longitude=lon, altitude=alt, pitch=pitch, timestamp=time.time()) + + # Try binary format (30 bytes with pitch) + if len(data) >= 30 and data[0:4] == b'GPSB': + return self._parse_binary_gps_with_pitch(data) + + except Exception as e: + logging.error(f"Error parsing GPS data: {e}") + + return None + + def _parse_binary_gps_with_pitch(self, data): + """Parse binary GPS format with pitch angle (30 bytes)""" + try: + # Binary format: [Header 4][Latitude 8][Longitude 8][Altitude 4][Pitch 4][CRC 2] + if len(data) < 30: + return None + + # Verify CRC (simple checksum) + crc_received = (data[28] << 8) | data[29] + crc_calculated = sum(data[0:28]) & 0xFFFF + + if crc_received != crc_calculated: + logging.warning("GPS CRC mismatch") + return None + + # Parse latitude (double, big-endian) + lat_bits = 0 + for i in range(8): + lat_bits = (lat_bits << 8) | data[4 + i] + latitude = struct.unpack('>d', struct.pack('>Q', lat_bits))[0] + + # Parse longitude (double, big-endian) + lon_bits = 0 + for i in range(8): + lon_bits = (lon_bits << 8) | data[12 + i] + longitude = struct.unpack('>d', struct.pack('>Q', lon_bits))[0] + + # Parse altitude (float, big-endian) + alt_bits = 0 + for i in range(4): + alt_bits = (alt_bits << 8) | data[20 + i] + altitude = struct.unpack('>f', struct.pack('>I', alt_bits))[0] + + # Parse pitch angle (float, big-endian) + pitch_bits = 0 + for i in range(4): + pitch_bits = (pitch_bits << 8) | data[24 + i] + pitch = struct.unpack('>f', struct.pack('>I', pitch_bits))[0] + + return GPSData( + latitude=latitude, + longitude=longitude, + altitude=altitude, + pitch=pitch, + timestamp=time.time() + ) + + except Exception as e: + logging.error(f"Error parsing binary GPS with pitch: {e}") + return None + +class RadarPacketParser: + def __init__(self): + self.sync_pattern = b'\xA5\xC3' + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_packet(self, data): + if len(data) < 6: + return None + + sync_index = data.find(self.sync_pattern) + if sync_index == -1: + return None + + packet = data[sync_index:] + + if len(packet) < 6: + return None + + sync = packet[0:2] + packet_type = packet[2] + length = packet[3] + + if len(packet) < (4 + length + 2): + return None + + payload = packet[4:4+length] + crc_received = struct.unpack('I', payload[0:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'range', + 'range': range_value, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing range packet: {e}") + return None + + def parse_doppler_packet(self, payload): + if len(payload) < 12: + return None + + try: + doppler_real = struct.unpack('>h', payload[0:2])[0] + doppler_imag = struct.unpack('>h', payload[2:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'doppler', + 'doppler_real': doppler_real, + 'doppler_imag': doppler_imag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing Doppler packet: {e}") + return None + + def parse_detection_packet(self, payload): + if len(payload) < 8: + return None + + try: + detection_flag = (payload[0] & 0x01) != 0 + elevation = payload[1] & 0x1F + azimuth = payload[2] & 0x3F + chirp_counter = payload[3] & 0x1F + + return { + 'type': 'detection', + 'detected': detection_flag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing detection packet: {e}") + return None + +class RadarGUI: + def __init__(self, root): + self.root = root + self.root.title("Advanced Radar System GUI - USB CDC with Google Maps") + self.root.geometry("1400x900") + + # Initialize interfaces + self.stm32_usb_interface = STM32USBInterface() + self.ftdi_interface = FTDIInterface() + self.radar_processor = RadarProcessor() + self.usb_packet_parser = USBPacketParser() + self.radar_packet_parser = RadarPacketParser() + self.map_generator = MapGenerator() + self.settings = RadarSettings() + + # Data queues + self.radar_data_queue = queue.Queue() + self.gps_data_queue = queue.Queue() + + # Thread control + self.running = False + self.radar_thread = None + self.gps_thread = None + + # Counters + self.received_packets = 0 + self.current_gps = GPSData(latitude=41.9028, longitude=12.4964, altitude=0, pitch=0.0, timestamp=0) + self.corrected_elevations = [] # Store corrected elevation values + self.map_file_path = None + self.google_maps_api_key = "YOUR_GOOGLE_MAPS_API_KEY" # Replace with your API key + + self.create_gui() + self.start_background_threads() + + def create_gui(self): + """Create the main GUI with tabs""" + self.notebook = ttk.Notebook(self.root) + self.notebook.pack(fill='both', expand=True, padx=10, pady=10) + + self.tab_main = ttk.Frame(self.notebook) + self.tab_map = ttk.Frame(self.notebook) + self.tab_diagnostics = ttk.Frame(self.notebook) + self.tab_settings = ttk.Frame(self.notebook) + + self.notebook.add(self.tab_main, text='Main View') + self.notebook.add(self.tab_map, text='Map View') + self.notebook.add(self.tab_diagnostics, text='Diagnostics') + self.notebook.add(self.tab_settings, text='Settings') + + self.setup_main_tab() + self.setup_map_tab() + self.setup_settings_tab() + + def setup_main_tab(self): + """Setup the main radar display tab""" + # Control frame + control_frame = ttk.Frame(self.tab_main) + control_frame.pack(fill='x', padx=10, pady=5) + + # USB Device selection + ttk.Label(control_frame, text="STM32 USB Device:").grid(row=0, column=0, padx=5) + self.stm32_usb_combo = ttk.Combobox(control_frame, state="readonly", width=40) + self.stm32_usb_combo.grid(row=0, column=1, padx=5) + + ttk.Label(control_frame, text="FTDI Device:").grid(row=0, column=2, padx=5) + self.ftdi_combo = ttk.Combobox(control_frame, state="readonly", width=30) + self.ftdi_combo.grid(row=0, column=3, padx=5) + + ttk.Button(control_frame, text="Refresh Devices", + command=self.refresh_devices).grid(row=0, column=4, padx=5) + + self.start_button = ttk.Button(control_frame, text="Start Radar", + command=self.start_radar) + self.start_button.grid(row=0, column=5, padx=5) + + self.stop_button = ttk.Button(control_frame, text="Stop Radar", + command=self.stop_radar, state="disabled") + self.stop_button.grid(row=0, column=6, padx=5) + + # GPS and Pitch info + self.gps_label = ttk.Label(control_frame, text="GPS: Waiting for data...") + self.gps_label.grid(row=1, column=0, columnspan=4, sticky='w', padx=5, pady=2) + + # Pitch display + self.pitch_label = ttk.Label(control_frame, text="Pitch: --.--°") + self.pitch_label.grid(row=1, column=4, columnspan=2, padx=5, pady=2) + + # Status info + self.status_label = ttk.Label(control_frame, text="Status: Ready") + self.status_label.grid(row=1, column=6, sticky='e', padx=5, pady=2) + + # Main display area + display_frame = ttk.Frame(self.tab_main) + display_frame.pack(fill='both', expand=True, padx=10, pady=5) + + # Range-Doppler Map + fig = Figure(figsize=(10, 6)) + self.range_doppler_ax = fig.add_subplot(111) + self.range_doppler_plot = self.range_doppler_ax.imshow( + np.random.rand(1024, 32), aspect='auto', cmap='hot', + extent=[0, 32, 0, 1024]) + self.range_doppler_ax.set_title('Range-Doppler Map (Pitch Corrected)') + self.range_doppler_ax.set_xlabel('Doppler Bin') + self.range_doppler_ax.set_ylabel('Range Bin') + + self.canvas = FigureCanvasTkAgg(fig, display_frame) + self.canvas.draw() + self.canvas.get_tk_widget().pack(side='left', fill='both', expand=True) + + # Targets list with corrected elevation + targets_frame = ttk.LabelFrame(display_frame, text="Detected Targets (Pitch Corrected)") + targets_frame.pack(side='right', fill='y', padx=5) + + self.targets_tree = ttk.Treeview(targets_frame, + columns=('ID', 'Range', 'Velocity', 'Azimuth', 'Elevation', 'Corrected Elev', 'SNR'), + show='headings', height=20) + self.targets_tree.heading('ID', text='Track ID') + self.targets_tree.heading('Range', text='Range (m)') + self.targets_tree.heading('Velocity', text='Velocity (m/s)') + self.targets_tree.heading('Azimuth', text='Azimuth') + self.targets_tree.heading('Elevation', text='Raw Elev') + self.targets_tree.heading('Corrected Elev', text='Corr Elev') + self.targets_tree.heading('SNR', text='SNR (dB)') + + self.targets_tree.column('ID', width=70) + self.targets_tree.column('Range', width=90) + self.targets_tree.column('Velocity', width=90) + self.targets_tree.column('Azimuth', width=70) + self.targets_tree.column('Elevation', width=70) + self.targets_tree.column('Corrected Elev', width=70) + self.targets_tree.column('SNR', width=70) + + self.targets_tree.pack(fill='both', expand=True, padx=5, pady=5) + + def setup_map_tab(self): + """Setup the map display tab with Google Maps""" + map_frame = ttk.Frame(self.tab_map) + map_frame.pack(fill='both', expand=True, padx=10, pady=10) + + # Map controls + controls_frame = ttk.Frame(map_frame) + controls_frame.pack(fill='x', pady=5) + + ttk.Button(controls_frame, text="Open Map in Browser", + command=self.open_map_in_browser).pack(side='left', padx=5) + + ttk.Button(controls_frame, text="Refresh Map", + command=self.refresh_map).pack(side='left', padx=5) + + self.map_status_label = ttk.Label(controls_frame, text="Map: Ready to generate") + self.map_status_label.pack(side='left', padx=20) + + # Map info display + info_frame = ttk.Frame(map_frame) + info_frame.pack(fill='x', pady=5) + + self.map_info_label = ttk.Label(info_frame, text="No GPS data received yet", font=('Arial', 10)) + self.map_info_label.pack() + + def setup_settings_tab(self): + """Setup the settings tab with additional chirp durations and map size""" + settings_frame = ttk.Frame(self.tab_settings) + settings_frame.pack(fill='both', expand=True, padx=10, pady=10) + + entries = [ + ('System Frequency (Hz):', 'system_frequency', 10e9), + ('Chirp Duration 1 - Long (s):', 'chirp_duration_1', 30e-6), + ('Chirp Duration 2 - Short (s):', 'chirp_duration_2', 0.5e-6), + ('Chirps per Position:', 'chirps_per_position', 32), + ('Frequency Min (Hz):', 'freq_min', 10e6), + ('Frequency Max (Hz):', 'freq_max', 30e6), + ('PRF1 (Hz):', 'prf1', 1000), + ('PRF2 (Hz):', 'prf2', 2000), + ('Max Distance (m):', 'max_distance', 50000), + ('Map Size (m):', 'map_size', 50000), + ('Google Maps API Key:', 'google_maps_api_key', 'YOUR_GOOGLE_MAPS_API_KEY') + ] + + self.settings_vars = {} + + for i, (label, attr, default) in enumerate(entries): + ttk.Label(settings_frame, text=label).grid(row=i, column=0, sticky='w', padx=5, pady=5) + var = tk.StringVar(value=str(default)) + entry = ttk.Entry(settings_frame, textvariable=var, width=25) + entry.grid(row=i, column=1, padx=5, pady=5) + self.settings_vars[attr] = var + + ttk.Button(settings_frame, text="Apply Settings", + command=self.apply_settings).grid(row=len(entries), column=0, columnspan=2, pady=10) + + def apply_pitch_correction(self, raw_elevation, pitch_angle): + """ + Apply pitch correction to elevation angle + raw_elevation: measured elevation from radar (degrees) + pitch_angle: antenna pitch angle from IMU (degrees) + Returns: corrected elevation angle (degrees) + """ + # Convert to radians for trigonometric functions + raw_elev_rad = math.radians(raw_elevation) + pitch_rad = math.radians(pitch_angle) + + # Apply pitch correction: corrected_elev = raw_elev - pitch + # This assumes the pitch angle is positive when antenna is tilted up + corrected_elev_rad = raw_elev_rad - pitch_rad + + # Convert back to degrees and ensure it's within valid range + corrected_elev_deg = math.degrees(corrected_elev_rad) + + # Normalize to 0-180 degree range + corrected_elev_deg = corrected_elev_deg % 180 + if corrected_elev_deg < 0: + corrected_elev_deg += 180 + + return corrected_elev_deg + + def refresh_devices(self): + """Refresh available USB devices""" + # STM32 USB devices + stm32_devices = self.stm32_usb_interface.list_devices() + stm32_names = [dev['description'] for dev in stm32_devices] + self.stm32_usb_combo['values'] = stm32_names + + # FTDI devices + ftdi_devices = self.ftdi_interface.list_devices() + ftdi_names = [dev['description'] for dev in ftdi_devices] + self.ftdi_combo['values'] = ftdi_names + + if stm32_names: + self.stm32_usb_combo.current(0) + if ftdi_names: + self.ftdi_combo.current(0) + + def start_radar(self): + """Step 11: Start button pressed - Begin radar operation""" + try: + # Open STM32 USB device + stm32_index = self.stm32_usb_combo.current() + if stm32_index == -1: + messagebox.showerror("Error", "Please select an STM32 USB device") + return + + stm32_devices = self.stm32_usb_interface.list_devices() + if stm32_index >= len(stm32_devices): + messagebox.showerror("Error", "Invalid STM32 device selection") + return + + if not self.stm32_usb_interface.open_device(stm32_devices[stm32_index]): + messagebox.showerror("Error", "Failed to open STM32 USB device") + return + + # Open FTDI device + if FTDI_AVAILABLE: + ftdi_index = self.ftdi_combo.current() + if ftdi_index != -1: + ftdi_devices = self.ftdi_interface.list_devices() + if ftdi_index < len(ftdi_devices): + device_url = ftdi_devices[ftdi_index]['url'] + if not self.ftdi_interface.open_device(device_url): + logging.warning("Failed to open FTDI device, continuing without radar data") + else: + logging.warning("No FTDI device selected, continuing without radar data") + else: + logging.warning("FTDI not available, continuing without radar data") + + # Step 12: Send start flag to STM32 via USB + if not self.stm32_usb_interface.send_start_flag(): + messagebox.showerror("Error", "Failed to send start flag to STM32") + return + + # Step 13: Send settings to STM32 via USB + self.apply_settings() + + # Start radar operation + self.running = True + self.start_button.config(state="disabled") + self.stop_button.config(state="normal") + self.status_label.config(text="Status: Radar running - Waiting for GPS data...") + + logging.info("Radar system started successfully via USB CDC") + + except Exception as e: + messagebox.showerror("Error", f"Failed to start radar: {e}") + logging.error(f"Start radar error: {e}") + + def stop_radar(self): + """Stop radar operation""" + self.running = False + self.start_button.config(state="normal") + self.stop_button.config(state="disabled") + self.status_label.config(text="Status: Radar stopped") + + self.stm32_usb_interface.close() + self.ftdi_interface.close() + + logging.info("Radar system stopped") + + def apply_settings(self): + """Step 13: Apply and send radar settings via USB""" + try: + self.settings.system_frequency = float(self.settings_vars['system_frequency'].get()) + self.settings.chirp_duration_1 = float(self.settings_vars['chirp_duration_1'].get()) + self.settings.chirp_duration_2 = float(self.settings_vars['chirp_duration_2'].get()) + self.settings.chirps_per_position = int(self.settings_vars['chirps_per_position'].get()) + self.settings.freq_min = float(self.settings_vars['freq_min'].get()) + self.settings.freq_max = float(self.settings_vars['freq_max'].get()) + self.settings.prf1 = float(self.settings_vars['prf1'].get()) + self.settings.prf2 = float(self.settings_vars['prf2'].get()) + self.settings.max_distance = float(self.settings_vars['max_distance'].get()) + self.settings.map_size = float(self.settings_vars['map_size'].get()) + self.google_maps_api_key = self.settings_vars['google_maps_api_key'].get() + + if self.stm32_usb_interface.is_open: + self.stm32_usb_interface.send_settings(self.settings) + + messagebox.showinfo("Success", "Settings applied and sent to STM32 via USB") + logging.info("Radar settings applied via USB") + + except ValueError as e: + messagebox.showerror("Error", f"Invalid setting value: {e}") + + def start_background_threads(self): + """Start background data processing threads""" + self.radar_thread = threading.Thread(target=self.process_radar_data, daemon=True) + self.radar_thread.start() + + self.gps_thread = threading.Thread(target=self.process_gps_data, daemon=True) + self.gps_thread.start() + + self.root.after(100, self.update_gui) + + def process_radar_data(self): + """Step 39: Process incoming radar data from FTDI""" + buffer = b'' + while True: + if self.running and self.ftdi_interface.is_open: + try: + data = self.ftdi_interface.read_data(4096) + if data: + buffer += data + + while len(buffer) >= 6: + packet = self.radar_packet_parser.parse_packet(buffer) + if packet: + self.process_radar_packet(packet) + packet_length = 4 + len(packet.get('payload', b'')) + 2 + buffer = buffer[packet_length:] + self.received_packets += 1 + else: + break + + except Exception as e: + logging.error(f"Error processing radar data: {e}") + time.sleep(0.1) + else: + time.sleep(0.1) + + def process_gps_data(self): + """Step 16/17: Process GPS data from STM32 via USB CDC""" + while True: + if self.running and self.stm32_usb_interface.is_open: + try: + # Read data from STM32 USB + data = self.stm32_usb_interface.read_data(64, timeout=100) + if data: + gps_data = self.usb_packet_parser.parse_gps_data(data) + if gps_data: + self.gps_data_queue.put(gps_data) + logging.info(f"GPS Data received via USB: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m, Pitch {gps_data.pitch:.1f}°") + except Exception as e: + logging.error(f"Error processing GPS data via USB: {e}") + time.sleep(0.1) + + def process_radar_packet(self, packet): + """Step 40: Process radar data and apply pitch correction""" + try: + if packet['type'] == 'range': + range_meters = packet['range'] * 0.1 + + # Apply pitch correction to elevation + raw_elevation = packet['elevation'] + corrected_elevation = self.apply_pitch_correction(raw_elevation, self.current_gps.pitch) + + # Store correction for display + self.corrected_elevations.append({ + 'raw': raw_elevation, + 'corrected': corrected_elevation, + 'pitch': self.current_gps.pitch, + 'timestamp': packet['timestamp'] + }) + + # Keep only recent corrections + if len(self.corrected_elevations) > 100: + self.corrected_elevations = self.corrected_elevations[-100:] + + target = RadarTarget( + id=packet['chirp'], + range=range_meters, + velocity=0, + azimuth=packet['azimuth'], + elevation=corrected_elevation, # Use corrected elevation + snr=20.0, + timestamp=packet['timestamp'] + ) + + self.update_range_doppler_map(target) + + elif packet['type'] == 'doppler': + lambda_wavelength = 3e8 / self.settings.system_frequency + velocity = (packet['doppler_real'] / 32767.0) * (self.settings.prf1 * lambda_wavelength / 2) + self.update_target_velocity(packet, velocity) + + elif packet['type'] == 'detection': + if packet['detected']: + # Apply pitch correction to detection elevation + raw_elevation = packet['elevation'] + corrected_elevation = self.apply_pitch_correction(raw_elevation, self.current_gps.pitch) + + logging.info(f"CFAR Detection: Raw Elev {raw_elevation}°, Corrected Elev {corrected_elevation:.1f}°, Pitch {self.current_gps.pitch:.1f}°") + + except Exception as e: + logging.error(f"Error processing radar packet: {e}") + + def update_range_doppler_map(self, target): + """Update range-Doppler map with new target""" + range_bin = min(int(target.range / 50), 1023) + doppler_bin = min(abs(int(target.velocity)), 31) + + self.radar_processor.range_doppler_map[range_bin, doppler_bin] += 1 + + self.radar_processor.detected_targets.append(target) + + if len(self.radar_processor.detected_targets) > 100: + self.radar_processor.detected_targets = self.radar_processor.detected_targets[-100:] + + def update_target_velocity(self, packet, velocity): + """Update target velocity information""" + for target in self.radar_processor.detected_targets: + if (target.azimuth == packet['azimuth'] and + target.elevation == packet['elevation'] and + target.id == packet['chirp']): + target.velocity = velocity + break + + def open_map_in_browser(self): + """Open the generated map in the default web browser""" + if self.map_file_path and os.path.exists(self.map_file_path): + webbrowser.open('file://' + os.path.abspath(self.map_file_path)) + else: + messagebox.showwarning("Warning", "No map file available. Generate map first by receiving GPS data.") + + def refresh_map(self): + """Refresh the map with current data""" + self.generate_map() + + def generate_map(self): + """Generate Google Maps HTML file with current targets""" + if self.current_gps.latitude == 0 and self.current_gps.longitude == 0: + self.map_status_label.config(text="Map: Waiting for GPS data") + return + + try: + # Create temporary HTML file + with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, encoding='utf-8') as f: + map_html = self.map_generator.generate_map( + self.current_gps, + self.radar_processor.detected_targets, + self.settings.map_size, + self.google_maps_api_key + ) + f.write(map_html) + self.map_file_path = f.name + + self.map_status_label.config(text=f"Map: Generated at {self.map_file_path}") + self.map_info_label.config( + text=f"Radar: {self.current_gps.latitude:.6f}, {self.current_gps.longitude:.6f} | " + f"Targets: {len(self.radar_processor.detected_targets)} | " + f"Coverage: {self.settings.map_size/1000:.1f}km" + ) + logging.info(f"Map generated: {self.map_file_path}") + + except Exception as e: + logging.error(f"Error generating map: {e}") + self.map_status_label.config(text=f"Map: Error - {str(e)}") + + def update_gps_display(self): + """Step 18: Update GPS and pitch display""" + try: + while not self.gps_data_queue.empty(): + gps_data = self.gps_data_queue.get_nowait() + self.current_gps = gps_data + + # Update GPS label + self.gps_label.config( + text=f"GPS: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m") + + # Update pitch label with color coding + pitch_text = f"Pitch: {gps_data.pitch:+.1f}°" + self.pitch_label.config(text=pitch_text) + + # Color code based on pitch magnitude + if abs(gps_data.pitch) > 10: + self.pitch_label.config(foreground='red') # High pitch warning + elif abs(gps_data.pitch) > 5: + self.pitch_label.config(foreground='orange') # Medium pitch + else: + self.pitch_label.config(foreground='green') # Normal pitch + + # Generate/update map when new GPS data arrives + self.generate_map() + + except queue.Empty: + pass + + def update_targets_list(self): + """Update the targets list display with corrected elevations""" + for item in self.targets_tree.get_children(): + self.targets_tree.delete(item) + + for target in self.radar_processor.detected_targets[-20:]: + # Find the corresponding raw elevation if available + raw_elevation = "N/A" + for correction in self.corrected_elevations[-20:]: + if abs(correction['corrected'] - target.elevation) < 0.1: # Fuzzy match + raw_elevation = f"{correction['raw']}" + break + + self.targets_tree.insert('', 'end', values=( + target.track_id, + f"{target.range:.1f}", + f"{target.velocity:.1f}", + target.azimuth, + raw_elevation, # Show raw elevation + f"{target.elevation:.1f}", # Show corrected elevation + f"{target.snr:.1f}" + )) + + def update_gui(self): + """Step 40: Update all GUI displays""" + try: + # Update status with pitch information + if self.running: + self.status_label.config( + text=f"Status: Running - Packets: {self.received_packets} - Pitch: {self.current_gps.pitch:+.1f}°") + + # Update range-Doppler map + if hasattr(self, 'range_doppler_plot'): + display_data = np.log10(self.radar_processor.range_doppler_map + 1) + self.range_doppler_plot.set_array(display_data) + self.canvas.draw_idle() + + # Update targets list + self.update_targets_list() + + # Update GPS and pitch display + self.update_gps_display() + + except Exception as e: + logging.error(f"Error updating GUI: {e}") + + self.root.after(100, self.update_gui) + +def main(): + """Main application entry point""" + try: + root = tk.Tk() + app = RadarGUI(root) + root.mainloop() + except Exception as e: + logging.error(f"Application error: {e}") + messagebox.showerror("Fatal Error", f"Application failed to start: {e}") + +if __name__ == "__main__": + main() diff --git a/9_Firmware/9_3_GUI/GUI_V4_2_CSV.py b/9_Firmware/9_3_GUI/GUI_V4_2_CSV.py new file mode 100644 index 0000000..71da913 --- /dev/null +++ b/9_Firmware/9_3_GUI/GUI_V4_2_CSV.py @@ -0,0 +1,678 @@ +import tkinter as tk +from tkinter import ttk, filedialog, messagebox +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.figure import Figure +import matplotlib.patches as patches +from scipy import signal +from scipy.fft import fft, fftshift +from scipy.signal import butter, filtfilt +import logging +from dataclasses import dataclass +from typing import List, Dict, Tuple +import threading +import queue +import time + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +@dataclass +class RadarTarget: + range: float + velocity: float + azimuth: int + elevation: int + snr: float + chirp_type: str + timestamp: float + +class SignalProcessor: + def __init__(self): + self.range_resolution = 1.0 # meters + self.velocity_resolution = 0.1 # m/s + self.cfar_threshold = 15.0 # dB + + def doppler_fft(self, iq_data: np.ndarray, fs: float = 100e6) -> Tuple[np.ndarray, np.ndarray]: + """ + Perform Doppler FFT on IQ data + Returns Doppler frequencies and spectrum + """ + # Window function for FFT + window = np.hanning(len(iq_data)) + windowed_data = (iq_data['I_value'].values + 1j * iq_data['Q_value'].values) * window + + # Perform FFT + doppler_fft = fft(windowed_data) + doppler_fft = fftshift(doppler_fft) + + # Frequency axis + N = len(iq_data) + freq_axis = np.linspace(-fs/2, fs/2, N) + + # Convert to velocity (assuming radar frequency = 10 GHz) + radar_freq = 10e9 + wavelength = 3e8 / radar_freq + velocity_axis = freq_axis * wavelength / 2 + + return velocity_axis, np.abs(doppler_fft) + + def mti_filter(self, iq_data: np.ndarray, filter_type: str = 'single_canceler') -> np.ndarray: + """ + Moving Target Indicator filter + Removes stationary clutter with better shape handling + """ + if iq_data is None or len(iq_data) < 2: + return np.array([], dtype=complex) + + try: + # Ensure we're working with complex data + complex_data = iq_data.astype(complex) + + if filter_type == 'single_canceler': + # Single delay line canceler + if len(complex_data) < 2: + return np.array([], dtype=complex) + filtered = np.zeros(len(complex_data) - 1, dtype=complex) + for i in range(1, len(complex_data)): + filtered[i-1] = complex_data[i] - complex_data[i-1] + return filtered + + elif filter_type == 'double_canceler': + # Double delay line canceler + if len(complex_data) < 3: + return np.array([], dtype=complex) + filtered = np.zeros(len(complex_data) - 2, dtype=complex) + for i in range(2, len(complex_data)): + filtered[i-2] = complex_data[i] - 2*complex_data[i-1] + complex_data[i-2] + return filtered + + else: + return complex_data + except Exception as e: + logging.error(f"MTI filter error: {e}") + return np.array([], dtype=complex) + + + def cfar_detection(self, range_profile: np.ndarray, guard_cells: int = 2, + training_cells: int = 10, threshold_factor: float = 3.0) -> List[Tuple[int, float]]: + detections = [] + N = len(range_profile) + + # Ensure guard_cells and training_cells are integers + guard_cells = int(guard_cells) + training_cells = int(training_cells) + + for i in range(N): + # Convert to integer indices + i_int = int(i) + if i_int < guard_cells + training_cells or i_int >= N - guard_cells - training_cells: + continue + + # Leading window - ensure integer indices + lead_start = i_int - guard_cells - training_cells + lead_end = i_int - guard_cells + lead_cells = range_profile[lead_start:lead_end] + + # Lagging window - ensure integer indices + lag_start = i_int + guard_cells + 1 + lag_end = i_int + guard_cells + training_cells + 1 + lag_cells = range_profile[lag_start:lag_end] + + # Combine training cells + training_cells_combined = np.concatenate([lead_cells, lag_cells]) + + # Calculate noise floor (mean of training cells) + if len(training_cells_combined) > 0: + noise_floor = np.mean(training_cells_combined) + + # Apply threshold + threshold = noise_floor * threshold_factor + + if range_profile[i_int] > threshold: + detections.append((i_int, float(range_profile[i_int]))) # Ensure float magnitude + + return detections + + def range_fft(self, iq_data: np.ndarray, fs: float = 100e6, bw: float = 20e6) -> Tuple[np.ndarray, np.ndarray]: + """ + Perform range FFT on IQ data + Returns range profile + """ + # Window function + window = np.hanning(len(iq_data)) + windowed_data = np.abs(iq_data) * window + + # Perform FFT + range_fft = fft(windowed_data) + + # Range calculation + N = len(iq_data) + range_max = (3e8 * N) / (2 * bw) + range_axis = np.linspace(0, range_max, N) + + return range_axis, np.abs(range_fft) + + def process_chirp_sequence(self, df: pd.DataFrame, chirp_type: str = 'LONG') -> Dict: + try: + # Filter data by chirp type + chirp_data = df[df['chirp_type'] == chirp_type] + + if len(chirp_data) == 0: + return {} + + # Group by chirp number + chirp_numbers = chirp_data['chirp_number'].unique() + num_chirps = len(chirp_numbers) + + if num_chirps == 0: + return {} + + # Get samples per chirp and ensure consistency + samples_per_chirp_list = [len(chirp_data[chirp_data['chirp_number'] == num]) + for num in chirp_numbers] + + # Use minimum samples to ensure consistent shape + samples_per_chirp = min(samples_per_chirp_list) + + # Create range-Doppler matrix with consistent shape + range_doppler_matrix = np.zeros((samples_per_chirp, num_chirps), dtype=complex) + + for i, chirp_num in enumerate(chirp_numbers): + chirp_samples = chirp_data[chirp_data['chirp_number'] == chirp_num] + # Take only the first samples_per_chirp samples to ensure consistent shape + chirp_samples = chirp_samples.head(samples_per_chirp) + + # Create complex IQ data + iq_data = chirp_samples['I_value'].values + 1j * chirp_samples['Q_value'].values + + # Ensure the shape matches + if len(iq_data) == samples_per_chirp: + range_doppler_matrix[:, i] = iq_data + + # Apply MTI filter along slow-time (chirp-to-chirp) + mti_filtered = np.zeros_like(range_doppler_matrix) + for i in range(samples_per_chirp): + slow_time_data = range_doppler_matrix[i, :] + filtered = self.mti_filter(slow_time_data) + # Ensure filtered data matches expected shape + if len(filtered) == num_chirps: + mti_filtered[i, :] = filtered + else: + # Handle shape mismatch by padding or truncating + if len(filtered) < num_chirps: + padded = np.zeros(num_chirps, dtype=complex) + padded[:len(filtered)] = filtered + mti_filtered[i, :] = padded + else: + mti_filtered[i, :] = filtered[:num_chirps] + + # Perform Doppler FFT along slow-time dimension + doppler_fft_result = np.zeros((samples_per_chirp, num_chirps), dtype=complex) + for i in range(samples_per_chirp): + doppler_fft_result[i, :] = fft(mti_filtered[i, :]) + + return { + 'range_doppler_matrix': np.abs(doppler_fft_result), + 'chirp_type': chirp_type, + 'num_chirps': num_chirps, + 'samples_per_chirp': samples_per_chirp + } + + except Exception as e: + logging.error(f"Error in process_chirp_sequence: {e}") + return {} + +class RadarGUI: + def __init__(self, root): + self.root = root + self.root.title("Radar Signal Processor - CSV Analysis") + self.root.geometry("1400x900") + + # Initialize processor + self.processor = SignalProcessor() + + # Data storage + self.df = None + self.processed_data = {} + self.detected_targets = [] + + # Create GUI + self.create_gui() + + # Start background processing + self.processing_queue = queue.Queue() + self.processing_thread = threading.Thread(target=self.background_processing, daemon=True) + self.processing_thread.start() + + # Update GUI periodically + self.root.after(100, self.update_gui) + + def create_gui(self): + """Create the main GUI layout""" + # Main frame + main_frame = ttk.Frame(self.root) + main_frame.pack(fill='both', expand=True, padx=10, pady=10) + + # Control panel + control_frame = ttk.LabelFrame(main_frame, text="File Controls") + control_frame.pack(fill='x', pady=5) + + # File selection + ttk.Button(control_frame, text="Load CSV File", + command=self.load_csv_file).pack(side='left', padx=5, pady=5) + + self.file_label = ttk.Label(control_frame, text="No file loaded") + self.file_label.pack(side='left', padx=10, pady=5) + + # Processing controls + ttk.Button(control_frame, text="Process Data", + command=self.process_data).pack(side='left', padx=5, pady=5) + + ttk.Button(control_frame, text="Run CFAR Detection", + command=self.run_cfar_detection).pack(side='left', padx=5, pady=5) + + # Status + self.status_label = ttk.Label(control_frame, text="Status: Ready") + self.status_label.pack(side='right', padx=10, pady=5) + + # Display area + display_frame = ttk.Frame(main_frame) + display_frame.pack(fill='both', expand=True, pady=5) + + # Create matplotlib figures + self.create_plots(display_frame) + + # Targets list + targets_frame = ttk.LabelFrame(main_frame, text="Detected Targets") + targets_frame.pack(fill='x', pady=5) + + self.targets_tree = ttk.Treeview(targets_frame, + columns=('Range', 'Velocity', 'Azimuth', 'Elevation', 'SNR', 'Chirp Type'), + show='headings', height=8) + + self.targets_tree.heading('Range', text='Range (m)') + self.targets_tree.heading('Velocity', text='Velocity (m/s)') + self.targets_tree.heading('Azimuth', text='Azimuth (°)') + self.targets_tree.heading('Elevation', text='Elevation (°)') + self.targets_tree.heading('SNR', text='SNR (dB)') + self.targets_tree.heading('Chirp Type', text='Chirp Type') + + self.targets_tree.column('Range', width=100) + self.targets_tree.column('Velocity', width=100) + self.targets_tree.column('Azimuth', width=80) + self.targets_tree.column('Elevation', width=80) + self.targets_tree.column('SNR', width=80) + self.targets_tree.column('Chirp Type', width=100) + + self.targets_tree.pack(fill='x', padx=5, pady=5) + + def create_plots(self, parent): + """Create matplotlib plots""" + # Create figure with subplots + self.fig = Figure(figsize=(12, 8)) + self.canvas = FigureCanvasTkAgg(self.fig, parent) + self.canvas.get_tk_widget().pack(fill='both', expand=True) + + # Create subplots + self.ax1 = self.fig.add_subplot(221) # Range profile + self.ax2 = self.fig.add_subplot(222) # Doppler spectrum + self.ax3 = self.fig.add_subplot(223) # Range-Doppler map + self.ax4 = self.fig.add_subplot(224) # MTI filtered data + + # Set titles + self.ax1.set_title('Range Profile') + self.ax1.set_xlabel('Range (m)') + self.ax1.set_ylabel('Magnitude') + self.ax1.grid(True) + + self.ax2.set_title('Doppler Spectrum') + self.ax2.set_xlabel('Velocity (m/s)') + self.ax2.set_ylabel('Magnitude') + self.ax2.grid(True) + + self.ax3.set_title('Range-Doppler Map') + self.ax3.set_xlabel('Doppler Bin') + self.ax3.set_ylabel('Range Bin') + + self.ax4.set_title('MTI Filtered Data') + self.ax4.set_xlabel('Sample') + self.ax4.set_ylabel('Magnitude') + self.ax4.grid(True) + + self.fig.tight_layout() + + def load_csv_file(self): + """Load CSV file generated by testbench""" + filename = filedialog.askopenfilename( + title="Select CSV file", + filetypes=[("CSV files", "*.csv"), ("All files", "*.*")] + ) + + # Add magnitude and phase calculations after loading CSV + if self.df is not None: + # Calculate magnitude from I/Q values + self.df['magnitude'] = np.sqrt(self.df['I_value']**2 + self.df['Q_value']**2) + + # Calculate phase from I/Q values + self.df['phase_rad'] = np.arctan2(self.df['Q_value'], self.df['I_value']) + + # If you used magnitude_squared in CSV, calculate actual magnitude + if 'magnitude_squared' in self.df.columns: + self.df['magnitude'] = np.sqrt(self.df['magnitude_squared']) + if filename: + try: + self.status_label.config(text="Status: Loading CSV file...") + self.df = pd.read_csv(filename) + self.file_label.config(text=f"Loaded: {filename.split('/')[-1]}") + self.status_label.config(text=f"Status: Loaded {len(self.df)} samples") + + # Show basic info + self.show_file_info() + + except Exception as e: + messagebox.showerror("Error", f"Failed to load CSV file: {e}") + self.status_label.config(text="Status: Error loading file") + + def show_file_info(self): + """Display basic information about loaded data""" + if self.df is not None: + info_text = f"Samples: {len(self.df)} | " + info_text += f"Chirps: {self.df['chirp_number'].nunique()} | " + info_text += f"Long: {len(self.df[self.df['chirp_type'] == 'LONG'])} | " + info_text += f"Short: {len(self.df[self.df['chirp_type'] == 'SHORT'])}" + + self.file_label.config(text=info_text) + + def process_data(self): + """Process loaded CSV data""" + if self.df is None: + messagebox.showwarning("Warning", "Please load a CSV file first") + return + + self.status_label.config(text="Status: Processing data...") + + # Add to processing queue + self.processing_queue.put(('process', self.df)) + + def run_cfar_detection(self): + """Run CFAR detection on processed data""" + if self.df is None: + messagebox.showwarning("Warning", "Please load and process data first") + return + + self.status_label.config(text="Status: Running CFAR detection...") + self.processing_queue.put(('cfar', self.df)) + + def background_processing(self): + + while True: + try: + task_type, data = self.processing_queue.get(timeout=1.0) + + if task_type == 'process': + self._process_data_background(data) + elif task_type == 'cfar': + self._run_cfar_background(data) + else: + logging.warning(f"Unknown task type: {task_type}") + + self.processing_queue.task_done() + + except queue.Empty: + continue + except Exception as e: + logging.error(f"Background processing error: {e}") + # Update GUI to show error state + self.root.after(0, lambda: self.status_label.config( + text=f"Status: Processing error - {e}" + )) + + def _process_data_background(self, df): + try: + # Process long chirps + long_chirp_data = self.processor.process_chirp_sequence(df, 'LONG') + + # Process short chirps + short_chirp_data = self.processor.process_chirp_sequence(df, 'SHORT') + + # Store results + self.processed_data = { + 'long': long_chirp_data, + 'short': short_chirp_data + } + + # Update GUI in main thread + self.root.after(0, self._update_plots_after_processing) + + except Exception as e: + logging.error(f"Processing error: {e}") + error_msg = str(e) + self.root.after(0, lambda msg=error_msg: self.status_label.config( + text=f"Status: Processing error - {msg}" + )) + + def _run_cfar_background(self, df): + try: + # Get first chirp for CFAR demonstration + first_chirp = df[df['chirp_number'] == df['chirp_number'].min()] + + if len(first_chirp) == 0: + return + + # Create IQ data - FIXED TYPO: first_chirp not first_chip + iq_data = first_chirp['I_value'].values + 1j * first_chirp['Q_value'].values + + # Perform range FFT + range_axis, range_profile = self.processor.range_fft(iq_data) + + # Run CFAR detection + detections = self.processor.cfar_detection(range_profile) + + # Convert to target objects + self.detected_targets = [] + for range_bin, magnitude in detections: + target = RadarTarget( + range=range_axis[range_bin], + velocity=0, # Would need Doppler processing for velocity + azimuth=0, # From actual data + elevation=0, # From actual data + snr=20 * np.log10(magnitude + 1e-9), # Convert to dB + chirp_type='LONG', + timestamp=time.time() + ) + self.detected_targets.append(target) + + # Update GUI in main thread + self.root.after(0, lambda: self._update_cfar_results(range_axis, range_profile, detections)) + + except Exception as e: + logging.error(f"CFAR detection error: {e}") + error_msg = str(e) + self.root.after(0, lambda msg=error_msg: self.status_label.config( + text=f"Status: CFAR error - {msg}" + )) + + def _update_plots_after_processing(self): + try: + # Clear all plots + for ax in [self.ax1, self.ax2, self.ax3, self.ax4]: + ax.clear() + + # Plot 1: Range profile from first chirp + if self.df is not None and len(self.df) > 0: + try: + first_chirp_num = self.df['chirp_number'].min() + first_chirp = self.df[self.df['chirp_number'] == first_chirp_num] + + if len(first_chirp) > 0: + iq_data = first_chirp['I_value'].values + 1j * first_chirp['Q_value'].values + range_axis, range_profile = self.processor.range_fft(iq_data) + + if len(range_axis) > 0 and len(range_profile) > 0: + self.ax1.plot(range_axis, range_profile, 'b-') + self.ax1.set_title('Range Profile - First Chirp') + self.ax1.set_xlabel('Range (m)') + self.ax1.set_ylabel('Magnitude') + self.ax1.grid(True) + except Exception as e: + logging.warning(f"Range profile plot error: {e}") + self.ax1.set_title('Range Profile - Error') + + # Plot 2: Doppler spectrum + if self.df is not None and len(self.df) > 0: + try: + sample_data = self.df.head(1024) + if len(sample_data) > 10: + iq_data = sample_data['I_value'].values + 1j * sample_data['Q_value'].values + velocity_axis, doppler_spectrum = self.processor.doppler_fft(iq_data) + + if len(velocity_axis) > 0 and len(doppler_spectrum) > 0: + self.ax2.plot(velocity_axis, doppler_spectrum, 'g-') + self.ax2.set_title('Doppler Spectrum') + self.ax2.set_xlabel('Velocity (m/s)') + self.ax2.set_ylabel('Magnitude') + self.ax2.grid(True) + except Exception as e: + logging.warning(f"Doppler spectrum plot error: {e}") + self.ax2.set_title('Doppler Spectrum - Error') + + # Plot 3: Range-Doppler map + if (self.processed_data.get('long') and + 'range_doppler_matrix' in self.processed_data['long'] and + self.processed_data['long']['range_doppler_matrix'].size > 0): + + try: + rd_matrix = self.processed_data['long']['range_doppler_matrix'] + # Use integer indices for extent + extent = [0, int(rd_matrix.shape[1]), 0, int(rd_matrix.shape[0])] + + im = self.ax3.imshow(10 * np.log10(rd_matrix + 1e-9), + aspect='auto', cmap='hot', + extent=extent) + self.ax3.set_title('Range-Doppler Map (Long Chirps)') + self.ax3.set_xlabel('Doppler Bin') + self.ax3.set_ylabel('Range Bin') + self.fig.colorbar(im, ax=self.ax3, label='dB') + except Exception as e: + logging.warning(f"Range-Doppler map plot error: {e}") + self.ax3.set_title('Range-Doppler Map - Error') + + # Plot 4: MTI filtered data + if self.df is not None and len(self.df) > 0: + try: + sample_data = self.df.head(100) + if len(sample_data) > 10: + iq_data = sample_data['I_value'].values + 1j * sample_data['Q_value'].values + + # Original data + original_mag = np.abs(iq_data) + + # MTI filtered + mti_filtered = self.processor.mti_filter(iq_data) + + if mti_filtered is not None and len(mti_filtered) > 0: + mti_mag = np.abs(mti_filtered) + + # Use integer indices for plotting + x_original = np.arange(len(original_mag)) + x_mti = np.arange(len(mti_mag)) + + self.ax4.plot(x_original, original_mag, 'b-', label='Original', alpha=0.7) + self.ax4.plot(x_mti, mti_mag, 'r-', label='MTI Filtered', alpha=0.7) + self.ax4.set_title('MTI Filter Comparison') + self.ax4.set_xlabel('Sample Index') + self.ax4.set_ylabel('Magnitude') + self.ax4.legend() + self.ax4.grid(True) + except Exception as e: + logging.warning(f"MTI filter plot error: {e}") + self.ax4.set_title('MTI Filter - Error') + + # Adjust layout and draw + self.fig.tight_layout() + self.canvas.draw() + self.status_label.config(text="Status: Processing complete") + + except Exception as e: + logging.error(f"Plot update error: {e}") + error_msg = str(e) + self.status_label.config(text=f"Status: Plot error - {error_msg}") + + def _update_cfar_results(self, range_axis, range_profile, detections): + try: + # Clear the plot + self.ax1.clear() + + # Plot range profile + self.ax1.plot(range_axis, range_profile, 'b-', label='Range Profile') + + # Plot detections - ensure we use integer indices + if detections and len(range_axis) > 0: + detection_ranges = [] + detection_mags = [] + + for bin_idx, mag in detections: + # Convert bin_idx to integer and ensure it's within bounds + bin_idx_int = int(bin_idx) + if 0 <= bin_idx_int < len(range_axis): + detection_ranges.append(range_axis[bin_idx_int]) + detection_mags.append(mag) + + if detection_ranges: # Only plot if we have valid detections + self.ax1.plot(detection_ranges, detection_mags, 'ro', + markersize=8, label='CFAR Detections') + + self.ax1.set_title('Range Profile with CFAR Detections') + self.ax1.set_xlabel('Range (m)') + self.ax1.set_ylabel('Magnitude') + self.ax1.legend() + self.ax1.grid(True) + + # Update targets list + self.update_targets_list() + + self.canvas.draw() + self.status_label.config(text=f"Status: CFAR complete - {len(detections)} targets detected") + + except Exception as e: + logging.error(f"CFAR results update error: {e}") + error_msg = str(e) + self.status_label.config(text=f"Status: CFAR results error - {error_msg}") + + def update_targets_list(self): + """Update the targets list display""" + # Clear current list + for item in self.targets_tree.get_children(): + self.targets_tree.delete(item) + + # Add detected targets + for i, target in enumerate(self.detected_targets): + self.targets_tree.insert('', 'end', values=( + f"{target.range:.1f}", + f"{target.velocity:.1f}", + f"{target.azimuth}", + f"{target.elevation}", + f"{target.snr:.1f}", + target.chirp_type + )) + + def update_gui(self): + """Periodic GUI update""" + # You can add any periodic updates here + self.root.after(100, self.update_gui) + +def main(): + """Main application entry point""" + try: + root = tk.Tk() + app = RadarGUI(root) + root.mainloop() + except Exception as e: + logging.error(f"Application error: {e}") + messagebox.showerror("Fatal Error", f"Application failed to start: {e}") + +if __name__ == "__main__": + main() diff --git a/9_Firmware/9_3_GUI/GUI_V5.py b/9_Firmware/9_3_GUI/GUI_V5.py new file mode 100644 index 0000000..336a143 --- /dev/null +++ b/9_Firmware/9_3_GUI/GUI_V5.py @@ -0,0 +1,1542 @@ +import tkinter as tk +from tkinter import ttk, messagebox +import threading +import queue +import time +import struct +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.figure import Figure +import matplotlib.patches as patches +import logging +from dataclasses import dataclass +from typing import Dict, List, Tuple, Optional +from scipy import signal +from sklearn.cluster import DBSCAN +from filterpy.kalman import KalmanFilter +import crcmod +import math +import webbrowser +import tempfile +import os + +try: + import usb.core + import usb.util + USB_AVAILABLE = True +except ImportError: + USB_AVAILABLE = False + logging.warning("pyusb not available. USB CDC functionality will be disabled.") + +try: + from pyftdi.ftdi import Ftdi + from pyftdi.usbtools import UsbTools + FTDI_AVAILABLE = True +except ImportError: + FTDI_AVAILABLE = False + logging.warning("pyftdi not available. FTDI functionality will be disabled.") + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +# Dark theme colors +DARK_BG = "#2b2b2b" +DARK_FG = "#e0e0e0" +DARK_ACCENT = "#3c3f41" +DARK_HIGHLIGHT = "#4e5254" +DARK_BORDER = "#555555" +DARK_TEXT = "#cccccc" +DARK_BUTTON = "#3c3f41" +DARK_BUTTON_HOVER = "#4e5254" +DARK_TREEVIEW = "#3c3f41" +DARK_TREEVIEW_ALT = "#404040" + +@dataclass +class RadarTarget: + id: int + range: float + velocity: float + azimuth: int + elevation: int + latitude: float = 0.0 + longitude: float = 0.0 + snr: float = 0.0 + timestamp: float = 0.0 + track_id: int = -1 + +@dataclass +class RadarSettings: + system_frequency: float = 10e9 + chirp_duration_1: float = 30e-6 # Long chirp duration + chirp_duration_2: float = 0.5e-6 # Short chirp duration + chirps_per_position: int = 32 + freq_min: float = 10e6 + freq_max: float = 30e6 + prf1: float = 1000 + prf2: float = 2000 + max_distance: float = 50000 + map_size: float = 50000 # Map size in meters + +@dataclass +class GPSData: + latitude: float + longitude: float + altitude: float + pitch: float # Pitch angle in degrees + timestamp: float + +class MapGenerator: + def __init__(self): + self.map_html_template = """ + + + + Radar Map + + + + + +
+ + + + + + + """ + + def generate_map(self, gps_data, targets, coverage_radius, api_key="YOUR_GOOGLE_MAPS_API_KEY"): + """Generate HTML map with radar and targets""" + # Convert targets to map coordinates + map_targets = [] + for target in targets: + # Convert polar coordinates (range, azimuth) to geographic coordinates + target_lat, target_lon = self.polar_to_geographic( + gps_data.latitude, gps_data.longitude, + target.range, target.azimuth + ) + map_targets.append({ + 'id': target.track_id, + 'lat': target_lat, + 'lng': target_lon, + 'range': target.range, + 'velocity': target.velocity, + 'azimuth': target.azimuth, + 'elevation': target.elevation, + 'snr': target.snr + }) + + # Generate targets script + targets_script = "" + if map_targets: + targets_json = str(map_targets).replace("'", '"') + targets_script = f"updateTargets({targets_json});" + + # Fill template + map_html = self.map_html_template.format( + lat=gps_data.latitude, + lon=gps_data.longitude, + alt=gps_data.altitude, + pitch=gps_data.pitch, + coverage_radius=coverage_radius, + targets_script=targets_script, + api_key=api_key + ) + + return map_html + + def polar_to_geographic(self, radar_lat, radar_lon, range_m, azimuth_deg): + """ + Convert polar coordinates (range, azimuth) to geographic coordinates + using simple flat-earth approximation (good for small distances) + """ + # Earth radius in meters + earth_radius = 6371000 + + # Convert azimuth to radians (0° = North, 90° = East) + azimuth_rad = math.radians(90 - azimuth_deg) # Convert to math convention + + # Convert range to angular distance + angular_distance = range_m / earth_radius + + # Convert to geographic coordinates + target_lat = radar_lat + math.cos(azimuth_rad) * angular_distance * (180 / math.pi) + target_lon = radar_lon + math.sin(azimuth_rad) * angular_distance * (180 / math.pi) / math.cos(math.radians(radar_lat)) + + return target_lat, target_lon + +class STM32USBInterface: + def __init__(self): + self.device = None + self.is_open = False + self.ep_in = None + self.ep_out = None + + def list_devices(self): + """List available STM32 USB CDC devices""" + if not USB_AVAILABLE: + logging.warning("USB not available - please install pyusb") + return [] + + try: + devices = [] + # STM32 USB CDC devices typically use these vendor/product IDs + stm32_vid_pids = [ + (0x0483, 0x5740), # STM32 Virtual COM Port + (0x0483, 0x3748), # STM32 Discovery + (0x0483, 0x374B), # STM32 CDC + (0x0483, 0x374D), # STM32 CDC + (0x0483, 0x374E), # STM32 CDC + (0x0483, 0x3752), # STM32 CDC + ] + + for vid, pid in stm32_vid_pids: + found_devices = usb.core.find(find_all=True, idVendor=vid, idProduct=pid) + for dev in found_devices: + try: + product = usb.util.get_string(dev, dev.iProduct) if dev.iProduct else "STM32 CDC" + serial = usb.util.get_string(dev, dev.iSerialNumber) if dev.iSerialNumber else "Unknown" + devices.append({ + 'description': f"{product} ({serial})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + except: + devices.append({ + 'description': f"STM32 CDC (VID:{vid:04X}, PID:{pid:04X})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + + return devices + except Exception as e: + logging.error(f"Error listing USB devices: {e}") + # Return mock devices for testing + return [{'description': 'STM32 Virtual COM Port', 'vendor_id': 0x0483, 'product_id': 0x5740}] + + def open_device(self, device_info): + """Open STM32 USB CDC device""" + if not USB_AVAILABLE: + logging.error("USB not available - cannot open device") + return False + + try: + self.device = device_info['device'] + + # Detach kernel driver if active + if self.device.is_kernel_driver_active(0): + self.device.detach_kernel_driver(0) + + # Set configuration + self.device.set_configuration() + + # Get CDC endpoints + cfg = self.device.get_active_configuration() + intf = cfg[(0,0)] + + # Find bulk endpoints (CDC data interface) + self.ep_out = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT + ) + + self.ep_in = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN + ) + + if self.ep_out is None or self.ep_in is None: + logging.error("Could not find CDC endpoints") + return False + + self.is_open = True + logging.info(f"STM32 USB device opened: {device_info['description']}") + return True + + except Exception as e: + logging.error(f"Error opening USB device: {e}") + return False + + def send_start_flag(self): + """Step 12: Send start flag to STM32 via USB""" + start_packet = bytes([23, 46, 158, 237]) + logging.info("Sending start flag to STM32 via USB...") + return self._send_data(start_packet) + + def send_settings(self, settings): + """Step 13: Send radar settings to STM32 via USB""" + try: + packet = self._create_settings_packet(settings) + logging.info("Sending radar settings to STM32 via USB...") + return self._send_data(packet) + except Exception as e: + logging.error(f"Error sending settings via USB: {e}") + return False + + def read_data(self, size=64, timeout=1000): + """Read data from STM32 via USB""" + if not self.is_open or self.ep_in is None: + return None + + try: + data = self.ep_in.read(size, timeout=timeout) + return bytes(data) + except usb.core.USBError as e: + if e.errno == 110: # Timeout + return None + logging.error(f"USB read error: {e}") + return None + except Exception as e: + logging.error(f"Error reading from USB: {e}") + return None + + def _send_data(self, data): + """Send data to STM32 via USB""" + if not self.is_open or self.ep_out is None: + return False + + try: + # USB CDC typically uses 64-byte packets + packet_size = 64 + for i in range(0, len(data), packet_size): + chunk = data[i:i + packet_size] + # Pad to packet size if needed + if len(chunk) < packet_size: + chunk += b'\x00' * (packet_size - len(chunk)) + self.ep_out.write(chunk) + + return True + except Exception as e: + logging.error(f"Error sending data via USB: {e}") + return False + + def _create_settings_packet(self, settings): + """Create binary settings packet for USB transmission""" + packet = b'SET' + packet += struct.pack('>d', settings.system_frequency) + packet += struct.pack('>d', settings.chirp_duration_1) + packet += struct.pack('>d', settings.chirp_duration_2) + packet += struct.pack('>I', settings.chirps_per_position) + packet += struct.pack('>d', settings.freq_min) + packet += struct.pack('>d', settings.freq_max) + packet += struct.pack('>d', settings.prf1) + packet += struct.pack('>d', settings.prf2) + packet += struct.pack('>d', settings.max_distance) + packet += struct.pack('>d', settings.map_size) + packet += b'END' + return packet + + def close(self): + """Close USB device""" + if self.device and self.is_open: + try: + usb.util.dispose_resources(self.device) + self.is_open = False + except Exception as e: + logging.error(f"Error closing USB device: {e}") + +class FTDIInterface: + def __init__(self): + self.ftdi = None + self.is_open = False + + def list_devices(self): + """List available FTDI devices using pyftdi""" + if not FTDI_AVAILABLE: + logging.warning("FTDI not available - please install pyftdi") + return [] + + try: + devices = [] + # Get list of all FTDI devices + for device in UsbTools.find_all([(0x0403, 0x6010)]): # FT2232H vendor/product ID + devices.append({ + 'description': f"FTDI Device {device}", + 'url': f"ftdi://{device}/1" + }) + return devices + except Exception as e: + logging.error(f"Error listing FTDI devices: {e}") + # Return mock devices for testing + return [{'description': 'FT2232H Device A', 'url': 'ftdi://device/1'}] + + def open_device(self, device_url): + """Open FTDI device using pyftdi""" + if not FTDI_AVAILABLE: + logging.error("FTDI not available - cannot open device") + return False + + try: + self.ftdi = Ftdi() + self.ftdi.open_from_url(device_url) + + # Configure for synchronous FIFO mode + self.ftdi.set_bitmode(0xFF, Ftdi.BitMode.SYNCFF) + + # Set latency timer + self.ftdi.set_latency_timer(2) + + # Purge buffers + self.ftdi.purge_buffers() + + self.is_open = True + logging.info(f"FTDI device opened: {device_url}") + return True + + except Exception as e: + logging.error(f"Error opening FTDI device: {e}") + return False + + def read_data(self, bytes_to_read): + """Read data from FTDI""" + if not self.is_open or self.ftdi is None: + return None + + try: + data = self.ftdi.read_data(bytes_to_read) + if data: + return bytes(data) + return None + except Exception as e: + logging.error(f"Error reading from FTDI: {e}") + return None + + def close(self): + """Close FTDI device""" + if self.ftdi and self.is_open: + self.ftdi.close() + self.is_open = False + +class RadarProcessor: + def __init__(self): + self.range_doppler_map = np.zeros((1024, 32)) + self.detected_targets = [] + self.track_id_counter = 0 + self.tracks = {} + self.frame_count = 0 + + def dual_cpi_fusion(self, range_profiles_1, range_profiles_2): + """Dual-CPI fusion for better detection""" + fused_profile = np.mean(range_profiles_1, axis=0) + np.mean(range_profiles_2, axis=0) + return fused_profile + + def multi_prf_unwrap(self, doppler_measurements, prf1, prf2): + """Multi-PRF velocity unwrapping""" + lambda_wavelength = 3e8 / 10e9 + v_max1 = prf1 * lambda_wavelength / 2 + v_max2 = prf2 * lambda_wavelength / 2 + + unwrapped_velocities = [] + for doppler in doppler_measurements: + v1 = doppler * lambda_wavelength / 2 + v2 = doppler * lambda_wavelength / 2 + + velocity = self._solve_chinese_remainder(v1, v2, v_max1, v_max2) + unwrapped_velocities.append(velocity) + + return unwrapped_velocities + + def _solve_chinese_remainder(self, v1, v2, max1, max2): + for k in range(-5, 6): + candidate = v1 + k * max1 + if abs(candidate - v2) < max2 / 2: + return candidate + return v1 + + def clustering(self, detections, eps=100, min_samples=2): + """DBSCAN clustering of detections""" + if len(detections) == 0: + return [] + + points = np.array([[d.range, d.velocity] for d in detections]) + clustering = DBSCAN(eps=eps, min_samples=min_samples).fit(points) + + clusters = [] + for label in set(clustering.labels_): + if label != -1: + cluster_points = points[clustering.labels_ == label] + clusters.append({ + 'center': np.mean(cluster_points, axis=0), + 'points': cluster_points, + 'size': len(cluster_points) + }) + + return clusters + + def association(self, detections, clusters): + """Association of detections to tracks""" + associated_detections = [] + + for detection in detections: + best_track = None + min_distance = float('inf') + + for track_id, track in self.tracks.items(): + distance = np.sqrt( + (detection.range - track['state'][0])**2 + + (detection.velocity - track['state'][2])**2 + ) + + if distance < min_distance and distance < 500: + min_distance = distance + best_track = track_id + + if best_track is not None: + detection.track_id = best_track + associated_detections.append(detection) + else: + detection.track_id = self.track_id_counter + self.track_id_counter += 1 + associated_detections.append(detection) + + return associated_detections + + def tracking(self, associated_detections): + """Kalman filter tracking""" + current_time = time.time() + + for detection in associated_detections: + if detection.track_id not in self.tracks: + kf = KalmanFilter(dim_x=4, dim_z=2) + kf.x = np.array([detection.range, 0, detection.velocity, 0]) + kf.F = np.array([[1, 1, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 1], + [0, 0, 0, 1]]) + kf.H = np.array([[1, 0, 0, 0], + [0, 0, 1, 0]]) + kf.P *= 1000 + kf.R = np.diag([10, 1]) + kf.Q = np.eye(4) * 0.1 + + self.tracks[detection.track_id] = { + 'filter': kf, + 'state': kf.x, + 'last_update': current_time, + 'hits': 1 + } + else: + track = self.tracks[detection.track_id] + track['filter'].predict() + track['filter'].update([detection.range, detection.velocity]) + track['state'] = track['filter'].x + track['last_update'] = current_time + track['hits'] += 1 + + stale_tracks = [tid for tid, track in self.tracks.items() + if current_time - track['last_update'] > 5.0] + for tid in stale_tracks: + del self.tracks[tid] + +class USBPacketParser: + def __init__(self): + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_gps_data(self, data): + """Parse GPS data from STM32 USB CDC with pitch angle""" + if not data: + return None + + try: + # Try text format first: "GPS:lat,lon,alt,pitch\r\n" + text_data = data.decode('utf-8', errors='ignore').strip() + if text_data.startswith('GPS:'): + parts = text_data.split(':')[1].split(',') + if len(parts) == 4: # Now expecting 4 values + lat = float(parts[0]) + lon = float(parts[1]) + alt = float(parts[2]) + pitch = float(parts[3]) # Pitch angle in degrees + return GPSData(latitude=lat, longitude=lon, altitude=alt, pitch=pitch, timestamp=time.time()) + + # Try binary format (30 bytes with pitch) + if len(data) >= 30 and data[0:4] == b'GPSB': + return self._parse_binary_gps_with_pitch(data) + + except Exception as e: + logging.error(f"Error parsing GPS data: {e}") + + return None + + def _parse_binary_gps_with_pitch(self, data): + """Parse binary GPS format with pitch angle (30 bytes)""" + try: + # Binary format: [Header 4][Latitude 8][Longitude 8][Altitude 4][Pitch 4][CRC 2] + if len(data) < 30: + return None + + # Verify CRC (simple checksum) + crc_received = (data[28] << 8) | data[29] + crc_calculated = sum(data[0:28]) & 0xFFFF + + if crc_received != crc_calculated: + logging.warning("GPS CRC mismatch") + return None + + # Parse latitude (double, big-endian) + lat_bits = 0 + for i in range(8): + lat_bits = (lat_bits << 8) | data[4 + i] + latitude = struct.unpack('>d', struct.pack('>Q', lat_bits))[0] + + # Parse longitude (double, big-endian) + lon_bits = 0 + for i in range(8): + lon_bits = (lon_bits << 8) | data[12 + i] + longitude = struct.unpack('>d', struct.pack('>Q', lon_bits))[0] + + # Parse altitude (float, big-endian) + alt_bits = 0 + for i in range(4): + alt_bits = (alt_bits << 8) | data[20 + i] + altitude = struct.unpack('>f', struct.pack('>I', alt_bits))[0] + + # Parse pitch angle (float, big-endian) + pitch_bits = 0 + for i in range(4): + pitch_bits = (pitch_bits << 8) | data[24 + i] + pitch = struct.unpack('>f', struct.pack('>I', pitch_bits))[0] + + return GPSData( + latitude=latitude, + longitude=longitude, + altitude=altitude, + pitch=pitch, + timestamp=time.time() + ) + + except Exception as e: + logging.error(f"Error parsing binary GPS with pitch: {e}") + return None + +class RadarPacketParser: + def __init__(self): + self.sync_pattern = b'\xA5\xC3' + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_packet(self, data): + if len(data) < 6: + return None + + sync_index = data.find(self.sync_pattern) + if sync_index == -1: + return None + + packet = data[sync_index:] + + if len(packet) < 6: + return None + + sync = packet[0:2] + packet_type = packet[2] + length = packet[3] + + if len(packet) < (4 + length + 2): + return None + + payload = packet[4:4+length] + crc_received = struct.unpack('I', payload[0:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'range', + 'range': range_value, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing range packet: {e}") + return None + + def parse_doppler_packet(self, payload): + if len(payload) < 12: + return None + + try: + doppler_real = struct.unpack('>h', payload[0:2])[0] + doppler_imag = struct.unpack('>h', payload[2:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'doppler', + 'doppler_real': doppler_real, + 'doppler_imag': doppler_imag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing Doppler packet: {e}") + return None + + def parse_detection_packet(self, payload): + if len(payload) < 8: + return None + + try: + detection_flag = (payload[0] & 0x01) != 0 + elevation = payload[1] & 0x1F + azimuth = payload[2] & 0x3F + chirp_counter = payload[3] & 0x1F + + return { + 'type': 'detection', + 'detected': detection_flag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing detection packet: {e}") + return None + +class RadarGUI: + def __init__(self, root): + self.root = root + self.root.title("Advanced Radar System GUI - USB CDC with Google Maps") + self.root.geometry("1400x900") + + # Apply dark theme to root window + self.root.configure(bg=DARK_BG) + + # Configure ttk style for dark theme + self.style = ttk.Style() + self.style.theme_use('clam') # Use 'clam' as base for better customization + + # Configure dark theme colors + self.configure_dark_theme() + + # Initialize interfaces + self.stm32_usb_interface = STM32USBInterface() + self.ftdi_interface = FTDIInterface() + self.radar_processor = RadarProcessor() + self.usb_packet_parser = USBPacketParser() + self.radar_packet_parser = RadarPacketParser() + self.map_generator = MapGenerator() + self.settings = RadarSettings() + + # Data queues + self.radar_data_queue = queue.Queue() + self.gps_data_queue = queue.Queue() + + # Thread control + self.running = False + self.radar_thread = None + self.gps_thread = None + + # Counters + self.received_packets = 0 + self.current_gps = GPSData(latitude=41.9028, longitude=12.4964, altitude=0, pitch=0.0, timestamp=0) + self.corrected_elevations = [] # Store corrected elevation values + self.map_file_path = None + self.google_maps_api_key = "YOUR_GOOGLE_MAPS_API_KEY" # Replace with your API key + + self.create_gui() + self.start_background_threads() + + def configure_dark_theme(self): + """Configure ttk style for dark mercury theme""" + self.style.configure('.', + background=DARK_BG, + foreground=DARK_FG, + fieldbackground=DARK_ACCENT, + selectbackground=DARK_HIGHLIGHT, + selectforeground=DARK_FG, + troughcolor=DARK_ACCENT, + borderwidth=1, + focuscolor=DARK_BORDER) + + # Configure specific widgets + self.style.configure('TFrame', background=DARK_BG) + self.style.configure('TLabel', background=DARK_BG, foreground=DARK_FG) + self.style.configure('TButton', + background=DARK_BUTTON, + foreground=DARK_FG, + borderwidth=1, + focuscolor=DARK_BORDER) + self.style.map('TButton', + background=[('active', DARK_BUTTON_HOVER), + ('pressed', DARK_HIGHLIGHT)]) + + self.style.configure('TCombobox', + fieldbackground=DARK_ACCENT, + background=DARK_BG, + foreground=DARK_FG, + arrowcolor=DARK_FG) + self.style.map('TCombobox', + fieldbackground=[('readonly', DARK_ACCENT)], + selectbackground=[('readonly', DARK_HIGHLIGHT)], + selectforeground=[('readonly', DARK_FG)]) + + self.style.configure('TNotebook', background=DARK_BG, borderwidth=0) + self.style.configure('TNotebook.Tab', + background=DARK_ACCENT, + foreground=DARK_FG, + padding=[10, 5]) + self.style.map('TNotebook.Tab', + background=[('selected', DARK_HIGHLIGHT), + ('active', DARK_BUTTON_HOVER)]) + + self.style.configure('Treeview', + background=DARK_TREEVIEW, + foreground=DARK_FG, + fieldbackground=DARK_TREEVIEW, + borderwidth=0) + self.style.map('Treeview', + background=[('selected', DARK_HIGHLIGHT)]) + + self.style.configure('Treeview.Heading', + background=DARK_ACCENT, + foreground=DARK_FG, + relief='flat') + self.style.map('Treeview.Heading', + background=[('active', DARK_BUTTON_HOVER)]) + + self.style.configure('TEntry', + fieldbackground=DARK_ACCENT, + foreground=DARK_FG, + insertcolor=DARK_FG) + + self.style.configure('Vertical.TScrollbar', + background=DARK_ACCENT, + troughcolor=DARK_BG, + borderwidth=0, + arrowsize=12) + self.style.configure('Horizontal.TScrollbar', + background=DARK_ACCENT, + troughcolor=DARK_BG, + borderwidth=0, + arrowsize=12) + + self.style.configure('TLabelFrame', + background=DARK_BG, + foreground=DARK_FG, + bordercolor=DARK_BORDER) + self.style.configure('TLabelFrame.Label', + background=DARK_BG, + foreground=DARK_FG) + + def create_gui(self): + """Create the main GUI with tabs""" + self.notebook = ttk.Notebook(self.root) + self.notebook.pack(fill='both', expand=True, padx=10, pady=10) + + self.tab_main = ttk.Frame(self.notebook) + self.tab_map = ttk.Frame(self.notebook) + self.tab_diagnostics = ttk.Frame(self.notebook) + self.tab_settings = ttk.Frame(self.notebook) + + self.notebook.add(self.tab_main, text='Main View') + self.notebook.add(self.tab_map, text='Map View') + self.notebook.add(self.tab_diagnostics, text='Diagnostics') + self.notebook.add(self.tab_settings, text='Settings') + + self.setup_main_tab() + self.setup_map_tab() + self.setup_settings_tab() + + def setup_main_tab(self): + """Setup the main radar display tab""" + # Control frame + control_frame = ttk.Frame(self.tab_main) + control_frame.pack(fill='x', padx=10, pady=5) + + # USB Device selection + ttk.Label(control_frame, text="STM32 USB Device:").grid(row=0, column=0, padx=5) + self.stm32_usb_combo = ttk.Combobox(control_frame, state="readonly", width=40) + self.stm32_usb_combo.grid(row=0, column=1, padx=5) + + ttk.Label(control_frame, text="FTDI Device:").grid(row=0, column=2, padx=5) + self.ftdi_combo = ttk.Combobox(control_frame, state="readonly", width=30) + self.ftdi_combo.grid(row=0, column=3, padx=5) + + ttk.Button(control_frame, text="Refresh Devices", + command=self.refresh_devices).grid(row=0, column=4, padx=5) + + self.start_button = ttk.Button(control_frame, text="Start Radar", + command=self.start_radar) + self.start_button.grid(row=0, column=5, padx=5) + + self.stop_button = ttk.Button(control_frame, text="Stop Radar", + command=self.stop_radar, state="disabled") + self.stop_button.grid(row=0, column=6, padx=5) + + # GPS and Pitch info + self.gps_label = ttk.Label(control_frame, text="GPS: Waiting for data...") + self.gps_label.grid(row=1, column=0, columnspan=4, sticky='w', padx=5, pady=2) + + # Pitch display + self.pitch_label = ttk.Label(control_frame, text="Pitch: --.--°") + self.pitch_label.grid(row=1, column=4, columnspan=2, padx=5, pady=2) + + # Status info + self.status_label = ttk.Label(control_frame, text="Status: Ready") + self.status_label.grid(row=1, column=6, sticky='e', padx=5, pady=2) + + # Main display area + display_frame = ttk.Frame(self.tab_main) + display_frame.pack(fill='both', expand=True, padx=10, pady=5) + + # Range-Doppler Map with dark theme + plt.style.use('dark_background') + fig = Figure(figsize=(10, 6), facecolor=DARK_BG) + self.range_doppler_ax = fig.add_subplot(111, facecolor=DARK_ACCENT) + self.range_doppler_plot = self.range_doppler_ax.imshow( + np.random.rand(1024, 32), aspect='auto', cmap='hot', + extent=[0, 32, 0, 1024]) + self.range_doppler_ax.set_title('Range-Doppler Map (Pitch Corrected)', color=DARK_FG) + self.range_doppler_ax.set_xlabel('Doppler Bin', color=DARK_FG) + self.range_doppler_ax.set_ylabel('Range Bin', color=DARK_FG) + self.range_doppler_ax.tick_params(colors=DARK_FG) + self.range_doppler_ax.spines['bottom'].set_color(DARK_FG) + self.range_doppler_ax.spines['top'].set_color(DARK_FG) + self.range_doppler_ax.spines['left'].set_color(DARK_FG) + self.range_doppler_ax.spines['right'].set_color(DARK_FG) + + self.canvas = FigureCanvasTkAgg(fig, display_frame) + self.canvas.draw() + self.canvas.get_tk_widget().pack(side='left', fill='both', expand=True) + + # Targets list with corrected elevation + targets_frame = ttk.LabelFrame(display_frame, text="Detected Targets (Pitch Corrected)") + targets_frame.pack(side='right', fill='y', padx=5) + + self.targets_tree = ttk.Treeview(targets_frame, + columns=('ID', 'Range', 'Velocity', 'Azimuth', 'Elevation', 'Corrected Elev', 'SNR'), + show='headings', height=20) + self.targets_tree.heading('ID', text='Track ID') + self.targets_tree.heading('Range', text='Range (m)') + self.targets_tree.heading('Velocity', text='Velocity (m/s)') + self.targets_tree.heading('Azimuth', text='Azimuth') + self.targets_tree.heading('Elevation', text='Raw Elev') + self.targets_tree.heading('Corrected Elev', text='Corr Elev') + self.targets_tree.heading('SNR', text='SNR (dB)') + + self.targets_tree.column('ID', width=70) + self.targets_tree.column('Range', width=90) + self.targets_tree.column('Velocity', width=90) + self.targets_tree.column('Azimuth', width=70) + self.targets_tree.column('Elevation', width=70) + self.targets_tree.column('Corrected Elev', width=70) + self.targets_tree.column('SNR', width=70) + + # Add scrollbar to targets tree + tree_scroll = ttk.Scrollbar(targets_frame, orient="vertical", command=self.targets_tree.yview) + self.targets_tree.configure(yscrollcommand=tree_scroll.set) + self.targets_tree.pack(side='left', fill='both', expand=True, padx=5, pady=5) + tree_scroll.pack(side='right', fill='y', padx=(0, 5), pady=5) + + def setup_map_tab(self): + """Setup the map display tab with Google Maps""" + map_frame = ttk.Frame(self.tab_map) + map_frame.pack(fill='both', expand=True, padx=10, pady=10) + + # Map controls + controls_frame = ttk.Frame(map_frame) + controls_frame.pack(fill='x', pady=5) + + ttk.Button(controls_frame, text="Open Map in Browser", + command=self.open_map_in_browser).pack(side='left', padx=5) + + ttk.Button(controls_frame, text="Refresh Map", + command=self.refresh_map).pack(side='left', padx=5) + + self.map_status_label = ttk.Label(controls_frame, text="Map: Ready to generate") + self.map_status_label.pack(side='left', padx=20) + + # Map info display + info_frame = ttk.Frame(map_frame) + info_frame.pack(fill='x', pady=5) + + self.map_info_label = ttk.Label(info_frame, text="No GPS data received yet", font=('Arial', 10)) + self.map_info_label.pack() + + def setup_settings_tab(self): + """Setup the settings tab with additional chirp durations and map size""" + settings_frame = ttk.Frame(self.tab_settings) + settings_frame.pack(fill='both', expand=True, padx=10, pady=10) + + entries = [ + ('System Frequency (Hz):', 'system_frequency', 10e9), + ('Chirp Duration 1 - Long (s):', 'chirp_duration_1', 30e-6), + ('Chirp Duration 2 - Short (s):', 'chirp_duration_2', 0.5e-6), + ('Chirps per Position:', 'chirps_per_position', 32), + ('Frequency Min (Hz):', 'freq_min', 10e6), + ('Frequency Max (Hz):', 'freq_max', 30e6), + ('PRF1 (Hz):', 'prf1', 1000), + ('PRF2 (Hz):', 'prf2', 2000), + ('Max Distance (m):', 'max_distance', 50000), + ('Map Size (m):', 'map_size', 50000), + ('Google Maps API Key:', 'google_maps_api_key', 'YOUR_GOOGLE_MAPS_API_KEY') + ] + + self.settings_vars = {} + + for i, (label, attr, default) in enumerate(entries): + ttk.Label(settings_frame, text=label).grid(row=i, column=0, sticky='w', padx=5, pady=5) + var = tk.StringVar(value=str(default)) + entry = ttk.Entry(settings_frame, textvariable=var, width=25) + entry.grid(row=i, column=1, padx=5, pady=5) + self.settings_vars[attr] = var + + ttk.Button(settings_frame, text="Apply Settings", + command=self.apply_settings).grid(row=len(entries), column=0, columnspan=2, pady=10) + + def apply_pitch_correction(self, raw_elevation, pitch_angle): + """ + Apply pitch correction to elevation angle + raw_elevation: measured elevation from radar (degrees) + pitch_angle: antenna pitch angle from IMU (degrees) + Returns: corrected elevation angle (degrees) + """ + # Convert to radians for trigonometric functions + raw_elev_rad = math.radians(raw_elevation) + pitch_rad = math.radians(pitch_angle) + + # Apply pitch correction: corrected_elev = raw_elev - pitch + # This assumes the pitch angle is positive when antenna is tilted up + corrected_elev_rad = raw_elev_rad - pitch_rad + + # Convert back to degrees and ensure it's within valid range + corrected_elev_deg = math.degrees(corrected_elev_rad) + + # Normalize to 0-180 degree range + corrected_elev_deg = corrected_elev_deg % 180 + if corrected_elev_deg < 0: + corrected_elev_deg += 180 + + return corrected_elev_deg + + def refresh_devices(self): + """Refresh available USB devices""" + # STM32 USB devices + stm32_devices = self.stm32_usb_interface.list_devices() + stm32_names = [dev['description'] for dev in stm32_devices] + self.stm32_usb_combo['values'] = stm32_names + + # FTDI devices + ftdi_devices = self.ftdi_interface.list_devices() + ftdi_names = [dev['description'] for dev in ftdi_devices] + self.ftdi_combo['values'] = ftdi_names + + if stm32_names: + self.stm32_usb_combo.current(0) + if ftdi_names: + self.ftdi_combo.current(0) + + def start_radar(self): + """Step 11: Start button pressed - Begin radar operation""" + try: + # Open STM32 USB device + stm32_index = self.stm32_usb_combo.current() + if stm32_index == -1: + messagebox.showerror("Error", "Please select an STM32 USB device") + return + + stm32_devices = self.stm32_usb_interface.list_devices() + if stm32_index >= len(stm32_devices): + messagebox.showerror("Error", "Invalid STM32 device selection") + return + + if not self.stm32_usb_interface.open_device(stm32_devices[stm32_index]): + messagebox.showerror("Error", "Failed to open STM32 USB device") + return + + # Open FTDI device + if FTDI_AVAILABLE: + ftdi_index = self.ftdi_combo.current() + if ftdi_index != -1: + ftdi_devices = self.ftdi_interface.list_devices() + if ftdi_index < len(ftdi_devices): + device_url = ftdi_devices[ftdi_index]['url'] + if not self.ftdi_interface.open_device(device_url): + logging.warning("Failed to open FTDI device, continuing without radar data") + else: + logging.warning("No FTDI device selected, continuing without radar data") + else: + logging.warning("FTDI not available, continuing without radar data") + + # Step 12: Send start flag to STM32 via USB + if not self.stm32_usb_interface.send_start_flag(): + messagebox.showerror("Error", "Failed to send start flag to STM32") + return + + # Step 13: Send settings to STM32 via USB + self.apply_settings() + + # Start radar operation + self.running = True + self.start_button.config(state="disabled") + self.stop_button.config(state="normal") + self.status_label.config(text="Status: Radar running - Waiting for GPS data...") + + logging.info("Radar system started successfully via USB CDC") + + except Exception as e: + messagebox.showerror("Error", f"Failed to start radar: {e}") + logging.error(f"Start radar error: {e}") + + def stop_radar(self): + """Stop radar operation""" + self.running = False + self.start_button.config(state="normal") + self.stop_button.config(state="disabled") + self.status_label.config(text="Status: Radar stopped") + + self.stm32_usb_interface.close() + self.ftdi_interface.close() + + logging.info("Radar system stopped") + + def apply_settings(self): + """Step 13: Apply and send radar settings via USB""" + try: + self.settings.system_frequency = float(self.settings_vars['system_frequency'].get()) + self.settings.chirp_duration_1 = float(self.settings_vars['chirp_duration_1'].get()) + self.settings.chirp_duration_2 = float(self.settings_vars['chirp_duration_2'].get()) + self.settings.chirps_per_position = int(self.settings_vars['chirps_per_position'].get()) + self.settings.freq_min = float(self.settings_vars['freq_min'].get()) + self.settings.freq_max = float(self.settings_vars['freq_max'].get()) + self.settings.prf1 = float(self.settings_vars['prf1'].get()) + self.settings.prf2 = float(self.settings_vars['prf2'].get()) + self.settings.max_distance = float(self.settings_vars['max_distance'].get()) + self.settings.map_size = float(self.settings_vars['map_size'].get()) + self.google_maps_api_key = self.settings_vars['google_maps_api_key'].get() + + if self.stm32_usb_interface.is_open: + self.stm32_usb_interface.send_settings(self.settings) + + messagebox.showinfo("Success", "Settings applied and sent to STM32 via USB") + logging.info("Radar settings applied via USB") + + except ValueError as e: + messagebox.showerror("Error", f"Invalid setting value: {e}") + + def start_background_threads(self): + """Start background data processing threads""" + self.radar_thread = threading.Thread(target=self.process_radar_data, daemon=True) + self.radar_thread.start() + + self.gps_thread = threading.Thread(target=self.process_gps_data, daemon=True) + self.gps_thread.start() + + self.root.after(100, self.update_gui) + + def process_radar_data(self): + """Step 39: Process incoming radar data from FTDI""" + buffer = b'' + while True: + if self.running and self.ftdi_interface.is_open: + try: + data = self.ftdi_interface.read_data(4096) + if data: + buffer += data + + while len(buffer) >= 6: + packet = self.radar_packet_parser.parse_packet(buffer) + if packet: + self.process_radar_packet(packet) + packet_length = 4 + len(packet.get('payload', b'')) + 2 + buffer = buffer[packet_length:] + self.received_packets += 1 + else: + break + + except Exception as e: + logging.error(f"Error processing radar data: {e}") + time.sleep(0.1) + else: + time.sleep(0.1) + + def process_gps_data(self): + """Step 16/17: Process GPS data from STM32 via USB CDC""" + while True: + if self.running and self.stm32_usb_interface.is_open: + try: + # Read data from STM32 USB + data = self.stm32_usb_interface.read_data(64, timeout=100) + if data: + gps_data = self.usb_packet_parser.parse_gps_data(data) + if gps_data: + self.gps_data_queue.put(gps_data) + logging.info(f"GPS Data received via USB: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m, Pitch {gps_data.pitch:.1f}°") + except Exception as e: + logging.error(f"Error processing GPS data via USB: {e}") + time.sleep(0.1) + + def process_radar_packet(self, packet): + """Step 40: Process radar data and apply pitch correction""" + try: + if packet['type'] == 'range': + range_meters = packet['range'] * 0.1 + + # Apply pitch correction to elevation + raw_elevation = packet['elevation'] + corrected_elevation = self.apply_pitch_correction(raw_elevation, self.current_gps.pitch) + + # Store correction for display + self.corrected_elevations.append({ + 'raw': raw_elevation, + 'corrected': corrected_elevation, + 'pitch': self.current_gps.pitch, + 'timestamp': packet['timestamp'] + }) + + # Keep only recent corrections + if len(self.corrected_elevations) > 100: + self.corrected_elevations = self.corrected_elevations[-100:] + + target = RadarTarget( + id=packet['chirp'], + range=range_meters, + velocity=0, + azimuth=packet['azimuth'], + elevation=corrected_elevation, # Use corrected elevation + snr=20.0, + timestamp=packet['timestamp'] + ) + + self.update_range_doppler_map(target) + + elif packet['type'] == 'doppler': + lambda_wavelength = 3e8 / self.settings.system_frequency + velocity = (packet['doppler_real'] / 32767.0) * (self.settings.prf1 * lambda_wavelength / 2) + self.update_target_velocity(packet, velocity) + + elif packet['type'] == 'detection': + if packet['detected']: + # Apply pitch correction to detection elevation + raw_elevation = packet['elevation'] + corrected_elevation = self.apply_pitch_correction(raw_elevation, self.current_gps.pitch) + + logging.info(f"CFAR Detection: Raw Elev {raw_elevation}°, Corrected Elev {corrected_elevation:.1f}°, Pitch {self.current_gps.pitch:.1f}°") + + except Exception as e: + logging.error(f"Error processing radar packet: {e}") + + def update_range_doppler_map(self, target): + """Update range-Doppler map with new target""" + range_bin = min(int(target.range / 50), 1023) + doppler_bin = min(abs(int(target.velocity)), 31) + + self.radar_processor.range_doppler_map[range_bin, doppler_bin] += 1 + + self.radar_processor.detected_targets.append(target) + + if len(self.radar_processor.detected_targets) > 100: + self.radar_processor.detected_targets = self.radar_processor.detected_targets[-100:] + + def update_target_velocity(self, packet, velocity): + """Update target velocity information""" + for target in self.radar_processor.detected_targets: + if (target.azimuth == packet['azimuth'] and + target.elevation == packet['elevation'] and + target.id == packet['chirp']): + target.velocity = velocity + break + + def open_map_in_browser(self): + """Open the generated map in the default web browser""" + if self.map_file_path and os.path.exists(self.map_file_path): + webbrowser.open('file://' + os.path.abspath(self.map_file_path)) + else: + messagebox.showwarning("Warning", "No map file available. Generate map first by receiving GPS data.") + + def refresh_map(self): + """Refresh the map with current data""" + self.generate_map() + + def generate_map(self): + """Generate Google Maps HTML file with current targets""" + if self.current_gps.latitude == 0 and self.current_gps.longitude == 0: + self.map_status_label.config(text="Map: Waiting for GPS data") + return + + try: + # Create temporary HTML file + with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, encoding='utf-8') as f: + map_html = self.map_generator.generate_map( + self.current_gps, + self.radar_processor.detected_targets, + self.settings.map_size, + self.google_maps_api_key + ) + f.write(map_html) + self.map_file_path = f.name + + self.map_status_label.config(text=f"Map: Generated at {self.map_file_path}") + self.map_info_label.config( + text=f"Radar: {self.current_gps.latitude:.6f}, {self.current_gps.longitude:.6f} | " + f"Targets: {len(self.radar_processor.detected_targets)} | " + f"Coverage: {self.settings.map_size/1000:.1f}km" + ) + logging.info(f"Map generated: {self.map_file_path}") + + except Exception as e: + logging.error(f"Error generating map: {e}") + self.map_status_label.config(text=f"Map: Error - {str(e)}") + + def update_gps_display(self): + """Step 18: Update GPS and pitch display""" + try: + while not self.gps_data_queue.empty(): + gps_data = self.gps_data_queue.get_nowait() + self.current_gps = gps_data + + # Update GPS label + self.gps_label.config( + text=f"GPS: Lat {gps_data.latitude:.6f}, Lon {gps_data.longitude:.6f}, Alt {gps_data.altitude:.1f}m") + + # Update pitch label with color coding + pitch_text = f"Pitch: {gps_data.pitch:+.1f}°" + self.pitch_label.config(text=pitch_text) + + # Color code based on pitch magnitude + if abs(gps_data.pitch) > 10: + self.pitch_label.config(foreground='red') # High pitch warning + elif abs(gps_data.pitch) > 5: + self.pitch_label.config(foreground='orange') # Medium pitch + else: + self.pitch_label.config(foreground='green') # Normal pitch + + # Generate/update map when new GPS data arrives + self.generate_map() + + except queue.Empty: + pass + + def update_targets_list(self): + """Update the targets list display with corrected elevations""" + for item in self.targets_tree.get_children(): + self.targets_tree.delete(item) + + for target in self.radar_processor.detected_targets[-20:]: + # Find the corresponding raw elevation if available + raw_elevation = "N/A" + for correction in self.corrected_elevations[-20:]: + if abs(correction['corrected'] - target.elevation) < 0.1: # Fuzzy match + raw_elevation = f"{correction['raw']}" + break + + self.targets_tree.insert('', 'end', values=( + target.track_id, + f"{target.range:.1f}", + f"{target.velocity:.1f}", + target.azimuth, + raw_elevation, # Show raw elevation + f"{target.elevation:.1f}", # Show corrected elevation + f"{target.snr:.1f}" + )) + + + def update_gui(self): + """Step 40: Update all GUI displays""" + try: + # Update status with pitch information + if self.running: + self.status_label.config( + text=f"Status: Running - Packets: {self.received_packets} - Pitch: {self.current_gps.pitch:+.1f}°") + + # Update range-Doppler map + if hasattr(self, 'range_doppler_plot'): + display_data = np.log10(self.radar_processor.range_doppler_map + 1) + self.range_doppler_plot.set_array(display_data) + self.canvas.draw_idle() + + # Update targets list + self.update_targets_list() + + # Update GPS and pitch display + self.update_gps_display() + + except Exception as e: + logging.error(f"Error updating GUI: {e}") + + self.root.after(100, self.update_gui) + +def main(): + """Main application entry point""" + try: + root = tk.Tk() + app = RadarGUI(root) + root.mainloop() + except Exception as e: + logging.error(f"Application error: {e}") + messagebox.showerror("Fatal Error", f"Application failed to start: {e}") + +if __name__ == "__main__": + main() diff --git a/9_Firmware/9_3_GUI/GUI_V5_Demo.py b/9_Firmware/9_3_GUI/GUI_V5_Demo.py new file mode 100644 index 0000000..7a88b94 --- /dev/null +++ b/9_Firmware/9_3_GUI/GUI_V5_Demo.py @@ -0,0 +1,1356 @@ +import tkinter as tk +from tkinter import ttk, messagebox +import threading +import queue +import time +import struct +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +from matplotlib.figure import Figure +import matplotlib.patches as patches +import logging +from dataclasses import dataclass +from typing import Dict, List, Tuple, Optional +from scipy import signal +from sklearn.cluster import DBSCAN +from filterpy.kalman import KalmanFilter +import crcmod +import math +import webbrowser +import tempfile +import os +import random +import json + +# Try to import tkinterweb for embedded browser +try: + import tkinterweb + TKINTERWEB_AVAILABLE = True + logging.info("tkinterweb available - Embedded browser enabled") +except ImportError: + TKINTERWEB_AVAILABLE = False + logging.warning("tkinterweb not available. Please install: pip install tkinterweb") + +try: + import usb.core + import usb.util + USB_AVAILABLE = True +except ImportError: + USB_AVAILABLE = False + logging.warning("pyusb not available. USB CDC functionality will be disabled.") + +try: + from pyftdi.ftdi import Ftdi + from pyftdi.usbtools import UsbTools + FTDI_AVAILABLE = True +except ImportError: + FTDI_AVAILABLE = False + logging.warning("pyftdi not available. FTDI functionality will be disabled.") + +# Configure logging +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +# Dark theme colors +DARK_BG = "#2b2b2b" +DARK_FG = "#e0e0e0" +DARK_ACCENT = "#3c3f41" +DARK_HIGHLIGHT = "#4e5254" +DARK_BORDER = "#555555" +DARK_TEXT = "#cccccc" +DARK_BUTTON = "#3c3f41" +DARK_BUTTON_HOVER = "#4e5254" +DARK_TREEVIEW = "#3c3f41" +DARK_TREEVIEW_ALT = "#404040" + +@dataclass +class RadarTarget: + id: int + range: float + velocity: float + azimuth: int + elevation: int + latitude: float = 0.0 + longitude: float = 0.0 + snr: float = 0.0 + timestamp: float = 0.0 + track_id: int = -1 + +@dataclass +class RadarSettings: + system_frequency: float = 10e9 + chirp_duration_1: float = 30e-6 # Long chirp duration + chirp_duration_2: float = 0.5e-6 # Short chirp duration + chirps_per_position: int = 32 + freq_min: float = 10e6 + freq_max: float = 30e6 + prf1: float = 1000 + prf2: float = 2000 + max_distance: float = 50000 + map_size: float = 50000 # Map size in meters + +@dataclass +class GPSData: + latitude: float + longitude: float + altitude: float + pitch: float # Pitch angle in degrees + timestamp: float + +class RadarProcessor: + def __init__(self): + self.range_doppler_map = np.zeros((1024, 32)) + self.detected_targets = [] + self.track_id_counter = 0 + self.tracks = {} + self.frame_count = 0 + + def dual_cpi_fusion(self, range_profiles_1, range_profiles_2): + """Dual-CPI fusion for better detection""" + fused_profile = np.mean(range_profiles_1, axis=0) + np.mean(range_profiles_2, axis=0) + return fused_profile + + def multi_prf_unwrap(self, doppler_measurements, prf1, prf2): + """Multi-PRF velocity unwrapping""" + lambda_wavelength = 3e8 / 10e9 + v_max1 = prf1 * lambda_wavelength / 2 + v_max2 = prf2 * lambda_wavelength / 2 + + unwrapped_velocities = [] + for doppler in doppler_measurements: + v1 = doppler * lambda_wavelength / 2 + v2 = doppler * lambda_wavelength / 2 + + velocity = self._solve_chinese_remainder(v1, v2, v_max1, v_max2) + unwrapped_velocities.append(velocity) + + return unwrapped_velocities + + def _solve_chinese_remainder(self, v1, v2, max1, max2): + for k in range(-5, 6): + candidate = v1 + k * max1 + if abs(candidate - v2) < max2 / 2: + return candidate + return v1 + + def clustering(self, detections, eps=100, min_samples=2): + """DBSCAN clustering of detections""" + if len(detections) == 0: + return [] + + points = np.array([[d.range, d.velocity] for d in detections]) + clustering = DBSCAN(eps=eps, min_samples=min_samples).fit(points) + + clusters = [] + for label in set(clustering.labels_): + if label != -1: + cluster_points = points[clustering.labels_ == label] + clusters.append({ + 'center': np.mean(cluster_points, axis=0), + 'points': cluster_points, + 'size': len(cluster_points) + }) + + return clusters + + def association(self, detections, clusters): + """Association of detections to tracks""" + associated_detections = [] + + for detection in detections: + best_track = None + min_distance = float('inf') + + for track_id, track in self.tracks.items(): + distance = np.sqrt( + (detection.range - track['state'][0])**2 + + (detection.velocity - track['state'][2])**2 + ) + + if distance < min_distance and distance < 500: + min_distance = distance + best_track = track_id + + if best_track is not None: + detection.track_id = best_track + associated_detections.append(detection) + else: + detection.track_id = self.track_id_counter + self.track_id_counter += 1 + associated_detections.append(detection) + + return associated_detections + + def tracking(self, associated_detections): + """Kalman filter tracking""" + current_time = time.time() + + for detection in associated_detections: + if detection.track_id not in self.tracks: + kf = KalmanFilter(dim_x=4, dim_z=2) + kf.x = np.array([detection.range, 0, detection.velocity, 0]) + kf.F = np.array([[1, 1, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 1], + [0, 0, 0, 1]]) + kf.H = np.array([[1, 0, 0, 0], + [0, 0, 1, 0]]) + kf.P *= 1000 + kf.R = np.diag([10, 1]) + kf.Q = np.eye(4) * 0.1 + + self.tracks[detection.track_id] = { + 'filter': kf, + 'state': kf.x, + 'last_update': current_time, + 'hits': 1 + } + else: + track = self.tracks[detection.track_id] + track['filter'].predict() + track['filter'].update([detection.range, detection.velocity]) + track['state'] = track['filter'].x + track['last_update'] = current_time + track['hits'] += 1 + + stale_tracks = [tid for tid, track in self.tracks.items() + if current_time - track['last_update'] > 5.0] + for tid in stale_tracks: + del self.tracks[tid] + +class USBPacketParser: + def __init__(self): + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_gps_data(self, data): + """Parse GPS data from STM32 USB CDC with pitch angle""" + if not data: + return None + + try: + # Try text format first: "GPS:lat,lon,alt,pitch\r\n" + text_data = data.decode('utf-8', errors='ignore').strip() + if text_data.startswith('GPS:'): + parts = text_data.split(':')[1].split(',') + if len(parts) == 4: # Now expecting 4 values + lat = float(parts[0]) + lon = float(parts[1]) + alt = float(parts[2]) + pitch = float(parts[3]) # Pitch angle in degrees + return GPSData(latitude=lat, longitude=lon, altitude=alt, pitch=pitch, timestamp=time.time()) + + # Try binary format (30 bytes with pitch) + if len(data) >= 30 and data[0:4] == b'GPSB': + return self._parse_binary_gps_with_pitch(data) + + except Exception as e: + logging.error(f"Error parsing GPS data: {e}") + + return None + + def _parse_binary_gps_with_pitch(self, data): + """Parse binary GPS format with pitch angle (30 bytes)""" + try: + # Binary format: [Header 4][Latitude 8][Longitude 8][Altitude 4][Pitch 4][CRC 2] + if len(data) < 30: + return None + + # Verify CRC (simple checksum) + crc_received = (data[28] << 8) | data[29] + crc_calculated = sum(data[0:28]) & 0xFFFF + + if crc_received != crc_calculated: + logging.warning("GPS CRC mismatch") + return None + + # Parse latitude (double, big-endian) + lat_bits = 0 + for i in range(8): + lat_bits = (lat_bits << 8) | data[4 + i] + latitude = struct.unpack('>d', struct.pack('>Q', lat_bits))[0] + + # Parse longitude (double, big-endian) + lon_bits = 0 + for i in range(8): + lon_bits = (lon_bits << 8) | data[12 + i] + longitude = struct.unpack('>d', struct.pack('>Q', lon_bits))[0] + + # Parse altitude (float, big-endian) + alt_bits = 0 + for i in range(4): + alt_bits = (alt_bits << 8) | data[20 + i] + altitude = struct.unpack('>f', struct.pack('>I', alt_bits))[0] + + # Parse pitch angle (float, big-endian) + pitch_bits = 0 + for i in range(4): + pitch_bits = (pitch_bits << 8) | data[24 + i] + pitch = struct.unpack('>f', struct.pack('>I', pitch_bits))[0] + + return GPSData( + latitude=latitude, + longitude=longitude, + altitude=altitude, + pitch=pitch, + timestamp=time.time() + ) + + except Exception as e: + logging.error(f"Error parsing binary GPS with pitch: {e}") + return None + +class RadarPacketParser: + def __init__(self): + self.sync_pattern = b'\xA5\xC3' + self.crc16_func = crcmod.mkCrcFun(0x11021, rev=False, initCrc=0xFFFF, xorOut=0x0000) + + def parse_packet(self, data): + if len(data) < 6: + return None + + sync_index = data.find(self.sync_pattern) + if sync_index == -1: + return None + + packet = data[sync_index:] + + if len(packet) < 6: + return None + + sync = packet[0:2] + packet_type = packet[2] + length = packet[3] + + if len(packet) < (4 + length + 2): + return None + + payload = packet[4:4+length] + crc_received = struct.unpack('I', payload[0:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'range', + 'range': range_value, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing range packet: {e}") + return None + + def parse_doppler_packet(self, payload): + if len(payload) < 12: + return None + + try: + doppler_real = struct.unpack('>h', payload[0:2])[0] + doppler_imag = struct.unpack('>h', payload[2:4])[0] + elevation = payload[4] & 0x1F + azimuth = payload[5] & 0x3F + chirp_counter = payload[6] & 0x1F + + return { + 'type': 'doppler', + 'doppler_real': doppler_real, + 'doppler_imag': doppler_imag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing Doppler packet: {e}") + return None + + def parse_detection_packet(self, payload): + if len(payload) < 8: + return None + + try: + detection_flag = (payload[0] & 0x01) != 0 + elevation = payload[1] & 0x1F + azimuth = payload[2] & 0x3F + chirp_counter = payload[3] & 0x1F + + return { + 'type': 'detection', + 'detected': detection_flag, + 'elevation': elevation, + 'azimuth': azimuth, + 'chirp': chirp_counter, + 'timestamp': time.time() + } + except Exception as e: + logging.error(f"Error parsing detection packet: {e}") + return None + +class MapGenerator: + def __init__(self): + self.map_file_path = None + self.map_html_template = """ + + + Radar Live Map - OpenStreetMap + + + + + + + +
Loading radar map...
+
+ + + +""" + + def generate_map_html_content(self, gps_data, targets, coverage_radius): + """Generate map HTML as string (for embedded browser)""" + # Convert targets for JavaScript + map_targets = [] + for target in targets: + target_lat, target_lon = self.polar_to_geographic( + gps_data.latitude, gps_data.longitude, + target.range, target.azimuth + ) + map_targets.append({ + 'id': target.id, + 'lat': target_lat, + 'lng': target_lon, + 'range': target.range, + 'velocity': target.velocity, + 'azimuth': target.azimuth, + 'elevation': target.elevation, + 'snr': target.snr, + 'track_id': target.track_id + }) + + # Calculate coverage radius in km + coverage_radius_km = coverage_radius / 1000.0 + + # Generate HTML content + map_html = self.map_html_template.replace('{lat}', str(gps_data.latitude)) + map_html = map_html.replace('{lon}', str(gps_data.longitude)) + map_html = map_html.replace('{alt:.1f}', f"{gps_data.altitude:.1f}") + map_html = map_html.replace('{pitch:+.1f}', f"{gps_data.pitch:+.1f}") + map_html = map_html.replace('{coverage_radius}', str(coverage_radius)) + map_html = map_html.replace('{coverage_radius_km:.1f}', f"{coverage_radius_km:.1f}") + map_html = map_html.replace('{target_count}', str(len(map_targets))) + + # Inject initial targets as JavaScript variable + targets_json = json.dumps(map_targets) + map_html = map_html.replace( + '// Display initial targets if any', + f'window.initialTargets = {targets_json};\n // Display initial targets if any' + ) + + return map_html + + def polar_to_geographic(self, radar_lat, radar_lon, range_m, azimuth_deg): + """ + Convert polar coordinates (range, azimuth) to geographic coordinates + using simple flat-earth approximation (good for small distances) + """ + # Earth radius in meters + earth_radius = 6371000 + + # Convert azimuth to radians (0° = North, 90° = East) + azimuth_rad = math.radians(90 - azimuth_deg) # Convert to math convention + + # Convert range to angular distance + angular_distance = range_m / earth_radius + + # Convert to geographic coordinates + target_lat = radar_lat + math.cos(azimuth_rad) * angular_distance * (180 / math.pi) + target_lon = radar_lon + math.sin(azimuth_rad) * angular_distance * (180 / math.pi) / math.cos(math.radians(radar_lat)) + + return target_lat, target_lon + +# ... [Other classes remain the same: STM32USBInterface, FTDIInterface, RadarProcessor, USBPacketParser, RadarPacketParser] ... +class STM32USBInterface: + def __init__(self): + self.device = None + self.is_open = False + self.ep_in = None + self.ep_out = None + + def list_devices(self): + """List available STM32 USB CDC devices""" + if not USB_AVAILABLE: + logging.warning("USB not available - please install pyusb") + return [] + + try: + devices = [] + # STM32 USB CDC devices typically use these vendor/product IDs + stm32_vid_pids = [ + (0x0483, 0x5740), # STM32 Virtual COM Port + (0x0483, 0x3748), # STM32 Discovery + (0x0483, 0x374B), # STM32 CDC + (0x0483, 0x374D), # STM32 CDC + (0x0483, 0x374E), # STM32 CDC + (0x0483, 0x3752), # STM32 CDC + ] + + for vid, pid in stm32_vid_pids: + found_devices = usb.core.find(find_all=True, idVendor=vid, idProduct=pid) + for dev in found_devices: + try: + product = usb.util.get_string(dev, dev.iProduct) if dev.iProduct else "STM32 CDC" + serial = usb.util.get_string(dev, dev.iSerialNumber) if dev.iSerialNumber else "Unknown" + devices.append({ + 'description': f"{product} ({serial})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + except: + devices.append({ + 'description': f"STM32 CDC (VID:{vid:04X}, PID:{pid:04X})", + 'vendor_id': vid, + 'product_id': pid, + 'device': dev + }) + + return devices + except Exception as e: + logging.error(f"Error listing USB devices: {e}") + # Return mock devices for testing + return [{'description': 'STM32 Virtual COM Port', 'vendor_id': 0x0483, 'product_id': 0x5740}] + + def open_device(self, device_info): + """Open STM32 USB CDC device""" + if not USB_AVAILABLE: + logging.error("USB not available - cannot open device") + return False + + try: + self.device = device_info['device'] + + # Detach kernel driver if active + if self.device.is_kernel_driver_active(0): + self.device.detach_kernel_driver(0) + + # Set configuration + self.device.set_configuration() + + # Get CDC endpoints + cfg = self.device.get_active_configuration() + intf = cfg[(0,0)] + + # Find bulk endpoints (CDC data interface) + self.ep_out = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT + ) + + self.ep_in = usb.util.find_descriptor( + intf, + custom_match=lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN + ) + + if self.ep_out is None or self.ep_in is None: + logging.error("Could not find CDC endpoints") + return False + + self.is_open = True + logging.info(f"STM32 USB device opened: {device_info['description']}") + return True + + except Exception as e: + logging.error(f"Error opening USB device: {e}") + return False + + def send_start_flag(self): + """Step 12: Send start flag to STM32 via USB""" + start_packet = bytes([23, 46, 158, 237]) + logging.info("Sending start flag to STM32 via USB...") + return self._send_data(start_packet) + + def send_settings(self, settings): + """Step 13: Send radar settings to STM32 via USB""" + try: + packet = self._create_settings_packet(settings) + logging.info("Sending radar settings to STM32 via USB...") + return self._send_data(packet) + except Exception as e: + logging.error(f"Error sending settings via USB: {e}") + return False + + def read_data(self, size=64, timeout=1000): + """Read data from STM32 via USB""" + if not self.is_open or self.ep_in is None: + return None + + try: + data = self.ep_in.read(size, timeout=timeout) + return bytes(data) + except usb.core.USBError as e: + if e.errno == 110: # Timeout + return None + logging.error(f"USB read error: {e}") + return None + except Exception as e: + logging.error(f"Error reading from USB: {e}") + return None + + def _send_data(self, data): + """Send data to STM32 via USB""" + if not self.is_open or self.ep_out is None: + return False + + try: + # USB CDC typically uses 64-byte packets + packet_size = 64 + for i in range(0, len(data), packet_size): + chunk = data[i:i + packet_size] + # Pad to packet size if needed + if len(chunk) < packet_size: + chunk += b'\x00' * (packet_size - len(chunk)) + self.ep_out.write(chunk) + + return True + except Exception as e: + logging.error(f"Error sending data via USB: {e}") + return False + + def _create_settings_packet(self, settings): + """Create binary settings packet for USB transmission""" + packet = b'SET' + packet += struct.pack('>d', settings.system_frequency) + packet += struct.pack('>d', settings.chirp_duration_1) + packet += struct.pack('>d', settings.chirp_duration_2) + packet += struct.pack('>I', settings.chirps_per_position) + packet += struct.pack('>d', settings.freq_min) + packet += struct.pack('>d', settings.freq_max) + packet += struct.pack('>d', settings.prf1) + packet += struct.pack('>d', settings.prf2) + packet += struct.pack('>d', settings.max_distance) + packet += struct.pack('>d', settings.map_size) + packet += b'END' + return packet + + def close(self): + """Close USB device""" + if self.device and self.is_open: + try: + usb.util.dispose_resources(self.device) + self.is_open = False + except Exception as e: + logging.error(f"Error closing USB device: {e}") + +class FTDIInterface: + def __init__(self): + self.ftdi = None + self.is_open = False + + def list_devices(self): + """List available FTDI devices using pyftdi""" + if not FTDI_AVAILABLE: + logging.warning("FTDI not available - please install pyftdi") + return [] + + try: + devices = [] + # Get list of all FTDI devices + for device in UsbTools.find_all([(0x0403, 0x6010)]): # FT2232H vendor/product ID + devices.append({ + 'description': f"FTDI Device {device}", + 'url': f"ftdi://{device}/1" + }) + return devices + except Exception as e: + logging.error(f"Error listing FTDI devices: {e}") + # Return mock devices for testing + return [{'description': 'FT2232H Device A', 'url': 'ftdi://device/1'}] + + def open_device(self, device_url): + """Open FTDI device using pyftdi""" + if not FTDI_AVAILABLE: + logging.error("FTDI not available - cannot open device") + return False + + try: + self.ftdi = Ftdi() + self.ftdi.open_from_url(device_url) + + # Configure for synchronous FIFO mode + self.ftdi.set_bitmode(0xFF, Ftdi.BitMode.SYNCFF) + + # Set latency timer + self.ftdi.set_latency_timer(2) + + # Purge buffers + self.ftdi.purge_buffers() + + self.is_open = True + logging.info(f"FTDI device opened: {device_url}") + return True + + except Exception as e: + logging.error(f"Error opening FTDI device: {e}") + return False + + def read_data(self, bytes_to_read): + """Read data from FTDI""" + if not self.is_open or self.ftdi is None: + return None + + try: + data = self.ftdi.read_data(bytes_to_read) + if data: + return bytes(data) + return None + except Exception as e: + logging.error(f"Error reading from FTDI: {e}") + return None + + def close(self): + """Close FTDI device""" + if self.ftdi and self.is_open: + self.ftdi.close() + self.is_open = False + +class RadarGUI: + def __init__(self, root): + self.root = root + self.root.title("Advanced Radar System GUI - USB CDC with Embedded Map") + self.root.geometry("1400x900") + + # Apply dark theme to root window + self.root.configure(bg=DARK_BG) + + # Configure ttk style for dark theme + self.style = ttk.Style() + self.style.theme_use('clam') # Use 'clam' as base for better customization + + # Configure dark theme colors + self.configure_dark_theme() + + # Initialize interfaces + self.stm32_usb_interface = STM32USBInterface() + self.ftdi_interface = FTDIInterface() + self.radar_processor = RadarProcessor() + self.usb_packet_parser = USBPacketParser() + self.radar_packet_parser = RadarPacketParser() + self.map_generator = MapGenerator() + self.last_map_update = 0 + self.map_update_interval = 5 # Update map every 5 seconds + self.settings = RadarSettings() + + # Embedded browser + self.browser_frame = None + self.browser = None + self.current_map_html = "" + + # Data queues + self.radar_data_queue = queue.Queue() + self.gps_data_queue = queue.Queue() + + # Thread control + self.running = False + self.radar_thread = None + self.gps_thread = None + + # Counters + self.received_packets = 0 + self.current_gps = GPSData(latitude=41.9028, longitude=12.4964, altitude=0, pitch=0.0, timestamp=0) + self.corrected_elevations = [] # Store corrected elevation values + + self.create_gui() + self.start_background_threads() + + + # Demo mode variables + self.demo_mode_active = False + self.demo_thread = None + self.demo_targets = [] + + def create_gui(self): + """Create the main GUI with tabs""" + self.notebook = ttk.Notebook(self.root) + self.notebook.pack(fill='both', expand=True, padx=10, pady=10) + + self.tab_main = ttk.Frame(self.notebook) + self.tab_map = ttk.Frame(self.notebook) + self.tab_diagnostics = ttk.Frame(self.notebook) + self.tab_settings = ttk.Frame(self.notebook) + + self.notebook.add(self.tab_main, text='Main View') + self.notebook.add(self.tab_map, text='Map View') + self.notebook.add(self.tab_diagnostics, text='Diagnostics') + self.notebook.add(self.tab_settings, text='Settings') + + self.setup_main_tab() + self.setup_map_tab() + self.setup_settings_tab() + + def setup_main_tab(self): + """Setup the main radar display tab""" + # Control frame + control_frame = ttk.Frame(self.tab_main) + control_frame.pack(fill='x', padx=10, pady=5) + + # USB Device selection + ttk.Label(control_frame, text="STM32 USB Device:").grid(row=0, column=0, padx=5) + self.stm32_usb_combo = ttk.Combobox(control_frame, state="readonly", width=40) + self.stm32_usb_combo.grid(row=0, column=1, padx=5) + + ttk.Label(control_frame, text="FTDI Device:").grid(row=0, column=2, padx=5) + self.ftdi_combo = ttk.Combobox(control_frame, state="readonly", width=30) + self.ftdi_combo.grid(row=0, column=3, padx=5) + + ttk.Button(control_frame, text="Refresh Devices", + command=self.refresh_devices).grid(row=0, column=4, padx=5) + + self.start_button = ttk.Button(control_frame, text="Start Radar", + command=self.start_radar) + self.start_button.grid(row=0, column=5, padx=5) + + self.stop_button = ttk.Button(control_frame, text="Stop Radar", + command=self.stop_radar, state="disabled") + self.stop_button.grid(row=0, column=6, padx=5) + + # DEMO BUTTONS + self.demo_button = ttk.Button(control_frame, text="Start Demo", + command=self.start_demo_mode) + self.demo_button.grid(row=0, column=7, padx=5) + + self.stop_demo_button = ttk.Button(control_frame, text="Stop Demo", + command=self.stop_demo_mode, state="disabled") + self.stop_demo_button.grid(row=0, column=8, padx=5) + + # GPS and Pitch info + self.gps_label = ttk.Label(control_frame, text="GPS: Waiting for data...") + self.gps_label.grid(row=1, column=0, columnspan=4, sticky='w', padx=5, pady=2) + + # Pitch display + self.pitch_label = ttk.Label(control_frame, text="Pitch: --.--°") + self.pitch_label.grid(row=1, column=4, columnspan=2, padx=5, pady=2) + + # Status info + self.status_label = ttk.Label(control_frame, text="Status: Ready") + self.status_label.grid(row=1, column=6, sticky='e', padx=5, pady=2) + + # Main display area + display_frame = ttk.Frame(self.tab_main) + display_frame.pack(fill='both', expand=True, padx=10, pady=5) + + # Range-Doppler Map with dark theme + plt.style.use('dark_background') + fig = Figure(figsize=(10, 6), facecolor=DARK_BG) + self.range_doppler_ax = fig.add_subplot(111, facecolor=DARK_ACCENT) + self.range_doppler_plot = self.range_doppler_ax.imshow( + np.random.rand(1024, 32), aspect='auto', cmap='hot', + extent=[0, 32, 0, 1024]) + self.range_doppler_ax.set_title('Range-Doppler Map (Pitch Corrected)', color=DARK_FG) + self.range_doppler_ax.set_xlabel('Doppler Bin', color=DARK_FG) + self.range_doppler_ax.set_ylabel('Range Bin', color=DARK_FG) + self.range_doppler_ax.tick_params(colors=DARK_FG) + self.range_doppler_ax.spines['bottom'].set_color(DARK_FG) + self.range_doppler_ax.spines['top'].set_color(DARK_FG) + self.range_doppler_ax.spines['left'].set_color(DARK_FG) + self.range_doppler_ax.spines['right'].set_color(DARK_FG) + + self.canvas = FigureCanvasTkAgg(fig, display_frame) + self.canvas.draw() + self.canvas.get_tk_widget().pack(side='left', fill='both', expand=True) + + # Targets list + targets_frame = ttk.LabelFrame(display_frame, text="Detected Targets") + targets_frame.pack(side='right', fill='y', padx=5) + + self.targets_tree = ttk.Treeview(targets_frame, + columns=('ID', 'Range', 'Velocity', 'Azimuth', 'Elevation', 'SNR'), + show='headings', height=20) + self.targets_tree.heading('ID', text='Track ID') + self.targets_tree.heading('Range', text='Range (m)') + self.targets_tree.heading('Velocity', text='Velocity (m/s)') + self.targets_tree.heading('Azimuth', text='Azimuth') + self.targets_tree.heading('Elevation', text='Elevation') + self.targets_tree.heading('SNR', text='SNR (dB)') + + self.targets_tree.column('ID', width=70) + self.targets_tree.column('Range', width=90) + self.targets_tree.column('Velocity', width=90) + self.targets_tree.column('Azimuth', width=70) + self.targets_tree.column('Elevation', width=70) + self.targets_tree.column('SNR', width=70) + + # Add scrollbar to targets tree + tree_scroll = ttk.Scrollbar(targets_frame, orient="vertical", command=self.targets_tree.yview) + self.targets_tree.configure(yscrollcommand=tree_scroll.set) + self.targets_tree.pack(side='left', fill='both', expand=True, padx=5, pady=5) + tree_scroll.pack(side='right', fill='y', padx=(0, 5), pady=5) + + def setup_map_tab(self): + """Setup the map display tab with embedded browser""" + # Main container + main_container = ttk.Frame(self.tab_map) + main_container.pack(fill='both', expand=True, padx=10, pady=10) + + # Top frame for controls + controls_frame = ttk.Frame(main_container) + controls_frame.pack(fill='x', pady=(0, 10)) + + # Map controls + ttk.Button(controls_frame, text="Generate/Refresh Map", + command=self.generate_map).pack(side='left', padx=5) + + if TKINTERWEB_AVAILABLE: + ttk.Button(controls_frame, text="Open in External Browser", + command=self.open_external_browser).pack(side='left', padx=5) + else: + ttk.Label(controls_frame, text="Install tkinterweb: pip install tkinterweb", + foreground='orange', font=('Arial', 9)).pack(side='left', padx=5) + ttk.Button(controls_frame, text="Open in Browser", + command=self.open_external_browser).pack(side='left', padx=5) + + self.map_status_label = ttk.Label(controls_frame, text="Map: Ready to generate") + self.map_status_label.pack(side='left', padx=20) + + # Map info display + info_frame = ttk.Frame(main_container) + info_frame.pack(fill='x', pady=(0, 10)) + + self.map_info_label = ttk.Label(info_frame, text="No GPS data received yet", font=('Arial', 10)) + self.map_info_label.pack() + + # Embedded browser area - This is where the map will appear + self.browser_container = ttk.Frame(main_container) + self.browser_container.pack(fill='both', expand=True) + + # Create browser widget if tkinterweb is available + if TKINTERWEB_AVAILABLE: + try: + self.browser = tkinterweb.HtmlFrame(self.browser_container) + self.browser.pack(fill='both', expand=True) + + # Initial placeholder HTML + placeholder_html = """ + + +

Radar Map Display

+

Click "Generate/Refresh Map" button to load the interactive map.

+

The map will display:

+
    +
  • Radar position (red marker)
  • +
  • Coverage area (red circle)
  • +
  • Detected targets (colored markers)
  • +
+

Map updates automatically every 5 seconds when new data is available.

+ + + """ + self.browser.load_html(placeholder_html) + + except Exception as e: + logging.error(f"Failed to create embedded browser: {e}") + self.create_browser_fallback() + else: + self.create_browser_fallback() + + def setup_settings_tab(self): + """Setup the settings tab""" + settings_frame = ttk.Frame(self.tab_settings) + settings_frame.pack(fill='both', expand=True, padx=10, pady=10) + + entries = [ + ('System Frequency (Hz):', 'system_frequency', 10e9), + ('Chirp Duration 1 - Long (s):', 'chirp_duration_1', 30e-6), + ('Chirp Duration 2 - Short (s):', 'chirp_duration_2', 0.5e-6), + ('Chirps per Position:', 'chirps_per_position', 32), + ('Frequency Min (Hz):', 'freq_min', 10e6), + ('Frequency Max (Hz):', 'freq_max', 30e6), + ('PRF1 (Hz):', 'prf1', 1000), + ('PRF2 (Hz):', 'prf2', 2000), + ('Max Distance (m):', 'max_distance', 50000), + ('Map Size (m):', 'map_size', 50000) + ] + + self.settings_vars = {} + + for i, (label, attr, default) in enumerate(entries): + ttk.Label(settings_frame, text=label).grid(row=i, column=0, sticky='w', padx=5, pady=5) + var = tk.StringVar(value=str(default)) + entry = ttk.Entry(settings_frame, textvariable=var, width=25) + entry.grid(row=i, column=1, padx=5, pady=5) + self.settings_vars[attr] = var + + # Map type info + ttk.Label(settings_frame, text="Map Type:", font=('Arial', 10, 'bold')).grid( + row=len(entries), column=0, sticky='w', padx=5, pady=10) + ttk.Label(settings_frame, text="OpenStreetMap (Free)", foreground='green').grid( + row=len(entries), column=1, sticky='w', padx=5, pady=10) + + ttk.Button(settings_frame, text="Apply Settings", + command=self.apply_settings).grid(row=len(entries)+1, column=0, columnspan=2, pady=10) + + def create_browser_fallback(self): + """Create a fallback display when tkinterweb is not available""" + for widget in self.browser_container.winfo_children(): + widget.destroy() + + # Create text widget as fallback + text_frame = ttk.Frame(self.browser_container) + text_frame.pack(fill='both', expand=True) + + text_widget = tk.Text(text_frame, wrap='word', bg=DARK_ACCENT, fg=DARK_FG, + font=('Courier', 10)) + scrollbar = ttk.Scrollbar(text_frame, orient='vertical', command=text_widget.yview) + text_widget.configure(yscrollcommand=scrollbar.set) + + text_widget.pack(side='left', fill='both', expand=True) + scrollbar.pack(side='right', fill='y') + + # Insert placeholder text + placeholder = """EMBEDDED BROWSER NOT AVAILABLE + +To enable the interactive map viewer, please install tkinterweb: + + pip install tkinterweb + +Without tkinterweb, you can still: +1. Generate maps using the button above +2. View them in your external browser +3. See map data in the text display below + +Map HTML will appear here when generated. +""" + text_widget.insert('1.0', placeholder) + text_widget.configure(state='disabled') + + # Store reference for later updates + self.fallback_text = text_widget + + def update_embedded_browser(self, html_content): + """Update the embedded browser with new HTML content""" + try: + if TKINTERWEB_AVAILABLE and hasattr(self, 'browser') and self.browser: + # Update existing browser + self.browser.load_html(html_content) + logging.info("Embedded browser updated with new map") + elif hasattr(self, 'fallback_text'): + # Update fallback text widget + self.fallback_text.configure(state='normal') + self.fallback_text.delete('1.0', tk.END) + self.fallback_text.insert('1.0', html_content) + self.fallback_text.configure(state='disabled') + self.fallback_text.see('1.0') # Scroll to top + logging.info("Fallback text widget updated with map HTML") + except Exception as e: + logging.error(f"Error updating embedded browser: {e}") + + def generate_map(self): + """Generate or update the map display""" + if self.current_gps.latitude == 0 and self.current_gps.longitude == 0: + messagebox.showinfo("Info", "No GPS data available yet. Start demo mode or wait for GPS data.") + return + + current_time = time.time() + + # Only update map at specified intervals + if current_time - self.last_map_update < 1.0: # 1 second minimum between updates + return + + try: + # Get current targets (demo + real) + targets = self.get_combined_targets() + + # Generate map HTML + map_html = self.map_generator.generate_map_html_content( + self.current_gps, + targets, + self.settings.map_size + ) + + self.current_map_html = map_html + + # Update embedded browser + self.update_embedded_browser(map_html) + + # Update map status + self.map_status_label.config(text=f"Map: Generated with {len(targets)} targets") + + # Update map info display + self.map_info_label.config( + text=f"Radar: {self.current_gps.latitude:.6f}, {self.current_gps.longitude:.6f} | " + f"Targets: {len(targets)} | " + f"Pitch: {self.current_gps.pitch:+.1f}° | " + f"Coverage: {self.settings.map_size/1000:.1f}km" + ) + + self.last_map_update = current_time + + logging.info(f"Map generated with {len(targets)} targets") + + except Exception as e: + logging.error(f"Error generating map: {e}") + self.map_status_label.config(text=f"Map: Error - {str(e)[:50]}") + + def open_external_browser(self): + """Open map in external browser""" + if not self.current_map_html: + messagebox.showinfo("Info", "Generate a map first using 'Generate/Refresh Map' button.") + return + + try: + # Create temporary HTML file + import tempfile + temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, encoding='utf-8') + temp_file.write(self.current_map_html) + temp_file.close() + + # Open in default browser + webbrowser.open('file://' + os.path.abspath(temp_file.name)) + logging.info(f"Map opened in external browser: {temp_file.name}") + + except Exception as e: + logging.error(f"Error opening external browser: {e}") + messagebox.showerror("Error", f"Failed to open browser: {e}") + + # ... [Rest of the methods remain the same - demo mode, radar processing, etc.] ... + +# IMPORTANT: You need to install tkinterweb first! +# Run: pip install tkinterweb + +def main(): + """Main application entry point""" + try: + root = tk.Tk() + app = RadarGUI(root) + root.mainloop() + except Exception as e: + logging.error(f"Application error: {e}") + messagebox.showerror("Fatal Error", f"Application failed to start: {e}") + +if __name__ == "__main__": + main() + diff --git a/9_Firmware/9_3_GUI/GUI_versions.txt b/9_Firmware/9_3_GUI/GUI_versions.txt new file mode 100644 index 0000000..9ae3a74 --- /dev/null +++ b/9_Firmware/9_3_GUI/GUI_versions.txt @@ -0,0 +1,6 @@ +GUI_V1 ==> +GUI_V2 ==> added STM32 USB CDC +GUI_V3 ==> added Pitch to STM32 USB Packet and pitch correction to the Elevation +GUI_V3 ==> Added Google_Map, real time target plot, Chirp duration_2 +GUI_V4 ==> Added pitch correction +GUI_V5 ==> Added Mercury Color \ No newline at end of file diff --git a/9_Firmware/9_3_GUI/test_radar_data.csv b/9_Firmware/9_3_GUI/test_radar_data.csv new file mode 100644 index 0000000..d0d7331 --- /dev/null +++ b/9_Firmware/9_3_GUI/test_radar_data.csv @@ -0,0 +1,16385 @@ +timestamp_ns,chirp_number,chirp_type,sample_index,I_value,Q_value,magnitude_squared +0,0,LONG,0,-15,16,499 +2,0,LONG,1,-12,17,484 +4,0,LONG,2,0,9,94 +6,0,LONG,3,-12,-8,228 +8,0,LONG,4,-2,-4,26 +10,0,LONG,5,-10,-2,124 +12,0,LONG,6,-4,-13,195 +14,0,LONG,7,-3,-5,44 +16,0,LONG,8,-12,14,356 +18,0,LONG,9,-3,-5,40 +20,0,LONG,10,0,-8,76 +22,0,LONG,11,-11,26,846 +24,0,LONG,12,-7,1,53 +26,0,LONG,13,-10,10,216 +28,0,LONG,14,3,-3,27 +30,0,LONG,15,21,8,517 +32,0,LONG,16,17,3,317 +34,0,LONG,17,15,-5,279 +36,0,LONG,18,29,-1,886 +38,0,LONG,19,-16,0,268 +40,0,LONG,20,-6,-9,129 +42,0,LONG,21,0,0,0 +44,0,LONG,22,-5,1,30 +46,0,LONG,23,12,11,300 +48,0,LONG,24,10,1,116 +50,0,LONG,25,-5,-14,255 +52,0,LONG,26,-2,3,18 +54,0,LONG,27,0,11,135 +56,0,LONG,28,9,19,466 +58,0,LONG,29,15,6,280 +60,0,LONG,30,-13,4,187 +62,0,LONG,31,2,-8,76 +64,0,LONG,32,0,-8,65 +66,0,LONG,33,-6,9,136 +68,0,LONG,34,-28,-3,835 +70,0,LONG,35,6,-2,55 +72,0,LONG,36,-12,8,210 +74,0,LONG,37,-15,2,252 +76,0,LONG,38,16,-6,306 +78,0,LONG,39,8,15,321 +80,0,LONG,40,-8,10,191 +82,0,LONG,41,11,-1,131 +84,0,LONG,42,-10,-11,240 +86,0,LONG,43,7,-16,324 +88,0,LONG,44,12,-9,254 +90,0,LONG,45,-2,2,11 +92,0,LONG,46,-14,-10,336 +94,0,LONG,47,0,16,272 +96,0,LONG,48,0,10,117 +98,0,LONG,49,-6,6,91 +100,0,LONG,50,12,-1,158 +102,0,LONG,51,4,7,73 +104,0,LONG,52,8,13,247 +106,0,LONG,53,15,7,302 +108,0,LONG,54,9,0,87 +110,0,LONG,55,-4,5,44 +112,0,LONG,56,-3,14,234 +114,0,LONG,57,-9,0,89 +116,0,LONG,58,7,5,78 +118,0,LONG,59,21,-5,481 +120,0,LONG,60,2,9,95 +122,0,LONG,61,27,1,757 +124,0,LONG,62,9,5,122 +126,0,LONG,63,9,7,147 +128,0,LONG,64,-1,5,37 +130,0,LONG,65,15,-7,300 +132,0,LONG,66,-14,7,273 +134,0,LONG,67,5,-18,362 +136,0,LONG,68,-6,-8,115 +138,0,LONG,69,-13,-3,208 +140,0,LONG,70,5,-4,60 +142,0,LONG,71,-6,-12,207 +144,0,LONG,72,-17,1,298 +146,0,LONG,73,-11,14,352 +148,0,LONG,74,-5,23,582 +150,0,LONG,75,-7,-12,216 +152,0,LONG,76,7,0,62 +154,0,LONG,77,-1,13,171 +156,0,LONG,78,1,-4,20 +158,0,LONG,79,-5,-5,64 +160,0,LONG,80,5,1,36 +162,0,LONG,81,-1,17,308 +164,0,LONG,82,8,2,72 +166,0,LONG,83,-1,7,54 +168,0,LONG,84,4,-23,590 +170,0,LONG,85,-7,-15,310 +172,0,LONG,86,-11,4,154 +174,0,LONG,87,2,-5,42 +176,0,LONG,88,-4,-3,27 +178,0,LONG,89,9,12,250 +180,0,LONG,90,-1,-20,442 +182,0,LONG,91,3,-5,41 +184,0,LONG,92,-5,-6,69 +186,0,LONG,93,3,-29,877 +188,0,LONG,94,13,-2,190 +190,0,LONG,95,-4,-9,118 +192,0,LONG,96,5,-2,32 +194,0,LONG,97,-4,-16,299 +196,0,LONG,98,-8,6,124 +198,0,LONG,99,-1,-8,69 +200,0,LONG,100,0,-5,35 +202,0,LONG,101,3,1,15 +204,0,LONG,102,2,-1,5 +206,0,LONG,103,-5,-2,30 +208,0,LONG,104,4,4,36 +210,0,LONG,105,-9,-3,97 +212,0,LONG,106,2,11,145 +214,0,LONG,107,4,-9,99 +216,0,LONG,108,-3,-1,12 +218,0,LONG,109,3,0,11 +220,0,LONG,110,-4,2,28 +222,0,LONG,111,-1,7,64 +224,0,LONG,112,0,5,35 +226,0,LONG,113,-1,0,2 +228,0,LONG,114,4,-3,33 +230,0,LONG,115,0,4,21 +232,0,LONG,116,-5,-5,61 +234,0,LONG,117,0,-6,41 +236,0,LONG,118,-5,3,46 +238,0,LONG,119,0,0,0 +240,0,LONG,120,-1,9,97 +242,0,LONG,121,-2,2,9 +244,0,LONG,122,-4,1,22 +246,0,LONG,123,-5,3,47 +248,0,LONG,124,-10,7,167 +250,0,LONG,125,-4,8,105 +252,0,LONG,126,2,-3,16 +254,0,LONG,127,4,0,25 +256,0,LONG,128,0,6,36 +258,0,LONG,129,-4,-2,25 +260,0,LONG,130,-4,-1,23 +262,0,LONG,131,-8,-5,107 +264,0,LONG,132,-8,-5,97 +266,0,LONG,133,8,7,134 +268,0,LONG,134,4,-3,30 +270,0,LONG,135,0,11,121 +272,0,LONG,136,4,-1,26 +274,0,LONG,137,-7,-3,64 +276,0,LONG,138,-2,-14,231 +278,0,LONG,139,-2,1,8 +280,0,LONG,140,2,1,8 +282,0,LONG,141,46,-84,9285 +284,0,LONG,142,50,-98,12354 +286,0,LONG,143,67,-71,9709 +288,0,LONG,144,76,-65,10122 +290,0,LONG,145,83,-48,9379 +292,0,LONG,146,90,-39,9780 +294,0,LONG,147,88,-40,9518 +296,0,LONG,148,90,-24,8737 +298,0,LONG,149,96,-13,9506 +300,0,LONG,150,102,-1,10449 +302,0,LONG,151,95,11,9271 +304,0,LONG,152,96,27,10071 +306,0,LONG,153,92,37,9945 +308,0,LONG,154,85,53,10229 +310,0,LONG,155,84,64,11256 +312,0,LONG,156,80,70,11355 +314,0,LONG,157,56,74,8769 +316,0,LONG,158,53,87,10429 +318,0,LONG,159,47,88,9992 +320,0,LONG,160,-6,0,39 +322,0,LONG,161,0,7,50 +324,0,LONG,162,-6,-4,68 +326,0,LONG,163,4,-5,49 +328,0,LONG,164,6,1,51 +330,0,LONG,165,4,3,36 +332,0,LONG,166,-6,1,43 +334,0,LONG,167,2,4,21 +336,0,LONG,168,-3,3,26 +338,0,LONG,169,-5,-1,35 +340,0,LONG,170,3,6,47 +342,0,LONG,171,1,1,5 +344,0,LONG,172,-3,1,16 +346,0,LONG,173,-4,-6,57 +348,0,LONG,174,-6,-4,60 +350,0,LONG,175,9,5,126 +352,0,LONG,176,-4,-1,21 +354,0,LONG,177,4,1,24 +356,0,LONG,178,0,-1,3 +358,0,LONG,179,-1,3,16 +360,0,LONG,180,1,3,15 +362,0,LONG,181,5,2,31 +364,0,LONG,182,2,-6,47 +366,0,LONG,183,3,0,10 +368,0,LONG,184,-4,-2,20 +370,0,LONG,185,-3,5,43 +372,0,LONG,186,-1,0,3 +374,0,LONG,187,3,0,11 +376,0,LONG,188,-1,-4,18 +378,0,LONG,189,-5,-13,200 +380,0,LONG,190,4,0,20 +382,0,LONG,191,8,-1,82 +384,0,LONG,192,-9,-13,266 +386,0,LONG,193,2,1,10 +388,0,LONG,194,1,4,28 +390,0,LONG,195,-8,0,74 +392,0,LONG,196,0,2,4 +394,0,LONG,197,0,-4,17 +396,0,LONG,198,2,1,6 +398,0,LONG,199,-3,7,66 +400,0,LONG,200,4,0,23 +402,0,LONG,201,-5,-1,34 +404,0,LONG,202,-1,-7,59 +406,0,LONG,203,-3,0,9 +408,0,LONG,204,-7,1,64 +410,0,LONG,205,-3,1,16 +412,0,LONG,206,-6,-4,66 +414,0,LONG,207,-8,-5,97 +416,0,LONG,208,5,-10,148 +418,0,LONG,209,-2,-5,33 +420,0,LONG,210,2,-3,19 +422,0,LONG,211,-3,0,13 +424,0,LONG,212,1,2,10 +426,0,LONG,213,2,-6,42 +428,0,LONG,214,-14,-6,269 +430,0,LONG,215,4,1,26 +432,0,LONG,216,-1,9,101 +434,0,LONG,217,-7,8,132 +436,0,LONG,218,5,-2,36 +438,0,LONG,219,7,-1,61 +440,0,LONG,220,2,3,15 +442,0,LONG,221,-2,-12,160 +444,0,LONG,222,0,4,17 +446,0,LONG,223,9,-2,94 +448,0,LONG,224,-16,-7,309 +450,0,LONG,225,7,-1,52 +452,0,LONG,226,2,-1,9 +454,0,LONG,227,-4,-1,24 +456,0,LONG,228,-4,6,54 +458,0,LONG,229,2,10,108 +460,0,LONG,230,5,-7,96 +462,0,LONG,231,-3,-1,17 +464,0,LONG,232,-3,0,14 +466,0,LONG,233,-5,-9,126 +468,0,LONG,234,1,2,8 +470,0,LONG,235,-3,2,20 +472,0,LONG,236,3,-3,28 +474,0,LONG,237,-5,-4,46 +476,0,LONG,238,-2,-3,21 +478,0,LONG,239,1,-8,68 +480,0,LONG,240,7,4,67 +482,0,LONG,241,15,-40,1927 +484,0,LONG,242,29,-42,2741 +486,0,LONG,243,33,-43,3004 +488,0,LONG,244,44,-26,2671 +490,0,LONG,245,42,-32,2843 +492,0,LONG,246,41,-23,2260 +494,0,LONG,247,49,-27,3198 +496,0,LONG,248,42,-10,1904 +498,0,LONG,249,52,-10,2888 +500,0,LONG,250,53,-3,2891 +502,0,LONG,251,51,13,2832 +504,0,LONG,252,51,8,2697 +506,0,LONG,253,46,12,2320 +508,0,LONG,254,39,28,2428 +510,0,LONG,255,42,32,2899 +512,0,LONG,256,36,42,3125 +514,0,LONG,257,33,36,2413 +516,0,LONG,258,19,53,3253 +518,0,LONG,259,21,46,2634 +520,0,LONG,260,1,5,28 +522,0,LONG,261,3,2,14 +524,0,LONG,262,-3,1,12 +526,0,LONG,263,4,0,21 +528,0,LONG,264,-3,2,19 +530,0,LONG,265,4,-6,61 +532,0,LONG,266,4,0,18 +534,0,LONG,267,0,-10,109 +536,0,LONG,268,-1,-1,3 +538,0,LONG,269,6,-9,126 +540,0,LONG,270,-3,-3,24 +542,0,LONG,271,1,-1,3 +544,0,LONG,272,8,0,72 +546,0,LONG,273,0,-8,69 +548,0,LONG,274,1,-7,58 +550,0,LONG,275,-2,-5,31 +552,0,LONG,276,9,5,115 +554,0,LONG,277,-2,-4,25 +556,0,LONG,278,2,3,16 +558,0,LONG,279,-5,8,100 +560,0,LONG,280,-3,-7,70 +562,0,LONG,281,0,-8,77 +564,0,LONG,282,7,4,67 +566,0,LONG,283,-1,-10,103 +568,0,LONG,284,-3,1,12 +570,0,LONG,285,6,1,51 +572,0,LONG,286,-10,4,124 +574,0,LONG,287,3,7,74 +576,0,LONG,288,0,0,0 +578,0,LONG,289,3,-2,18 +580,0,LONG,290,-1,0,2 +582,0,LONG,291,-1,-4,24 +584,0,LONG,292,0,5,28 +586,0,LONG,293,11,2,138 +588,0,LONG,294,-1,3,14 +590,0,LONG,295,-8,-2,82 +592,0,LONG,296,-1,2,6 +594,0,LONG,297,-1,-1,7 +596,0,LONG,298,-4,-1,22 +598,0,LONG,299,0,0,0 +600,0,LONG,300,7,10,160 +602,0,LONG,301,-9,0,82 +604,0,LONG,302,4,0,23 +606,0,LONG,303,5,-2,40 +608,0,LONG,304,-2,3,19 +610,0,LONG,305,-7,-1,54 +612,0,LONG,306,-4,-4,45 +614,0,LONG,307,1,5,33 +616,0,LONG,308,4,1,23 +618,0,LONG,309,4,-2,25 +620,0,LONG,310,0,0,0 +622,0,LONG,311,-2,-3,17 +624,0,LONG,312,2,-4,28 +626,0,LONG,313,5,-3,46 +628,0,LONG,314,-1,-1,5 +630,0,LONG,315,2,7,64 +632,0,LONG,316,2,0,6 +634,0,LONG,317,4,0,21 +636,0,LONG,318,0,0,0 +638,0,LONG,319,-7,-2,62 +640,0,LONG,320,-3,3,23 +642,0,LONG,321,-6,-6,73 +644,0,LONG,322,0,3,13 +646,0,LONG,323,3,-8,89 +648,0,LONG,324,-5,-3,41 +650,0,LONG,325,-1,0,4 +652,0,LONG,326,-8,3,87 +654,0,LONG,327,-3,-7,64 +656,0,LONG,328,6,-5,72 +658,0,LONG,329,4,1,19 +660,0,LONG,330,0,-6,37 +662,0,LONG,331,-5,-6,77 +664,0,LONG,332,7,2,64 +666,0,LONG,333,7,-2,58 +668,0,LONG,334,3,1,13 +670,0,LONG,335,-5,7,83 +672,0,LONG,336,-3,9,94 +674,0,LONG,337,-2,-3,17 +676,0,LONG,338,6,-6,77 +678,0,LONG,339,2,4,26 +680,0,LONG,340,8,7,133 +682,0,LONG,341,4,-4,33 +684,0,LONG,342,1,1,5 +686,0,LONG,343,5,8,110 +688,0,LONG,344,5,0,34 +690,0,LONG,345,6,-9,117 +692,0,LONG,346,-1,2,9 +694,0,LONG,347,0,-5,25 +696,0,LONG,348,0,-3,9 +698,0,LONG,349,6,2,45 +700,0,LONG,350,7,-1,54 +702,0,LONG,351,1,4,24 +704,0,LONG,352,9,0,87 +706,0,LONG,353,3,-8,78 +708,0,LONG,354,5,12,186 +710,0,LONG,355,0,-4,25 +712,0,LONG,356,8,-4,90 +714,0,LONG,357,5,-2,33 +716,0,LONG,358,-3,0,12 +718,0,LONG,359,4,4,36 +720,0,LONG,360,-10,-2,114 +722,0,LONG,361,1,0,2 +724,0,LONG,362,-7,3,72 +726,0,LONG,363,-5,-1,30 +728,0,LONG,364,1,-1,5 +730,0,LONG,365,1,-10,123 +732,0,LONG,366,-4,3,31 +734,0,LONG,367,0,-7,53 +736,0,LONG,368,5,0,28 +738,0,LONG,369,-6,-1,47 +740,0,LONG,370,-3,1,14 +742,0,LONG,371,-2,5,33 +744,0,LONG,372,0,-2,5 +746,0,LONG,373,9,5,126 +748,0,LONG,374,0,-10,112 +750,0,LONG,375,1,1,5 +752,0,LONG,376,-1,-7,52 +754,0,LONG,377,-1,-3,14 +756,0,LONG,378,2,-9,92 +758,0,LONG,379,8,1,70 +760,0,LONG,380,-1,6,39 +762,0,LONG,381,0,-3,11 +764,0,LONG,382,1,10,119 +766,0,LONG,383,1,2,6 +768,0,LONG,384,1,-3,12 +770,0,LONG,385,4,-3,31 +772,0,LONG,386,6,1,42 +774,0,LONG,387,-1,-7,66 +776,0,LONG,388,-2,-5,42 +778,0,LONG,389,1,6,39 +780,0,LONG,390,5,0,34 +782,0,LONG,391,13,-16,454 +784,0,LONG,392,11,-13,299 +786,0,LONG,393,27,-14,964 +788,0,LONG,394,12,-22,665 +790,0,LONG,395,21,-17,767 +792,0,LONG,396,20,0,439 +794,0,LONG,397,24,-9,692 +796,0,LONG,398,19,-12,552 +798,0,LONG,399,30,3,968 +800,0,LONG,400,20,7,473 +802,0,LONG,401,23,11,704 +804,0,LONG,402,25,2,636 +806,0,LONG,403,11,8,192 +808,0,LONG,404,14,16,483 +810,0,LONG,405,19,10,463 +812,0,LONG,406,14,12,364 +814,0,LONG,407,22,18,832 +816,0,LONG,408,9,16,361 +818,0,LONG,409,0,26,710 +820,0,LONG,410,-3,4,33 +822,0,LONG,411,0,10,103 +824,0,LONG,412,-10,3,126 +826,0,LONG,413,1,1,4 +828,0,LONG,414,0,2,8 +830,0,LONG,415,-2,2,8 +832,0,LONG,416,5,4,48 +834,0,LONG,417,0,0,1 +836,0,LONG,418,-5,-3,37 +838,0,LONG,419,9,-6,132 +840,0,LONG,420,5,-9,130 +842,0,LONG,421,-1,1,4 +844,0,LONG,422,0,10,115 +846,0,LONG,423,-4,-1,21 +848,0,LONG,424,3,-5,44 +850,0,LONG,425,-4,0,18 +852,0,LONG,426,-6,3,57 +854,0,LONG,427,-1,-2,9 +856,0,LONG,428,-1,-4,20 +858,0,LONG,429,5,-7,88 +860,0,LONG,430,1,1,4 +862,0,LONG,431,2,0,4 +864,0,LONG,432,-2,4,25 +866,0,LONG,433,0,-7,54 +868,0,LONG,434,-4,0,16 +870,0,LONG,435,0,-1,4 +872,0,LONG,436,3,-3,22 +874,0,LONG,437,5,-2,34 +876,0,LONG,438,6,0,47 +878,0,LONG,439,-9,0,95 +880,0,LONG,440,2,-5,36 +882,0,LONG,441,-8,-2,68 +884,0,LONG,442,-2,1,5 +886,0,LONG,443,-4,0,16 +888,0,LONG,444,-7,1,64 +890,0,LONG,445,5,-1,34 +892,0,LONG,446,0,4,17 +894,0,LONG,447,0,0,0 +896,0,LONG,448,-1,-7,61 +898,0,LONG,449,2,6,46 +900,0,LONG,450,-6,0,41 +902,0,LONG,451,1,9,100 +904,0,LONG,452,9,2,91 +906,0,LONG,453,3,2,19 +908,0,LONG,454,3,-3,19 +910,0,LONG,455,11,0,135 +912,0,LONG,456,-6,1,50 +914,0,LONG,457,-3,0,11 +916,0,LONG,458,8,3,95 +918,0,LONG,459,0,-2,5 +920,0,LONG,460,-8,-1,69 +922,0,LONG,461,2,10,124 +924,0,LONG,462,0,-8,72 +926,0,LONG,463,7,-2,56 +928,0,LONG,464,-4,2,27 +930,0,LONG,465,-1,0,1 +932,0,LONG,466,-6,0,41 +934,0,LONG,467,1,1,3 +936,0,LONG,468,-4,-2,27 +938,0,LONG,469,-3,4,35 +940,0,LONG,470,-2,-11,142 +942,0,LONG,471,-2,2,15 +944,0,LONG,472,3,6,54 +946,0,LONG,473,-1,0,3 +948,0,LONG,474,0,1,1 +950,0,LONG,475,6,6,85 +952,0,LONG,476,-12,-3,173 +954,0,LONG,477,-2,1,7 +956,0,LONG,478,-5,-2,33 +958,0,LONG,479,-3,0,14 +960,0,LONG,480,1,6,50 +962,0,LONG,481,-10,-5,128 +964,0,LONG,482,-1,7,54 +966,0,LONG,483,0,0,0 +968,0,LONG,484,4,1,20 +970,0,LONG,485,3,0,11 +972,0,LONG,486,1,7,53 +974,0,LONG,487,-7,-3,64 +976,0,LONG,488,2,3,18 +978,0,LONG,489,7,2,71 +980,0,LONG,490,-1,3,13 +982,0,LONG,491,-8,0,64 +984,0,LONG,492,3,3,19 +986,0,LONG,493,8,-8,142 +988,0,LONG,494,-1,2,8 +990,0,LONG,495,-9,-2,97 +992,0,LONG,496,-5,-3,38 +994,0,LONG,497,-3,-8,79 +996,0,LONG,498,5,0,33 +998,0,LONG,499,-11,0,127 +1000,0,LONG,500,7,-15,295 +1002,0,LONG,501,-1,-4,22 +1004,0,LONG,502,-1,6,39 +1006,0,LONG,503,-1,3,13 +1008,0,LONG,504,7,7,110 +1010,0,LONG,505,1,5,33 +1012,0,LONG,506,-3,-4,26 +1014,0,LONG,507,-4,3,33 +1016,0,LONG,508,-1,-3,10 +1018,0,LONG,509,8,0,68 +1020,0,LONG,510,-7,-6,95 +1022,0,LONG,511,-12,3,176 +138024,1,LONG,0,0,0,0 +138026,1,LONG,1,14,14,444 +138028,1,LONG,2,9,-12,229 +138030,1,LONG,3,-13,-9,255 +138032,1,LONG,4,8,0,68 +138034,1,LONG,5,-6,-7,96 +138036,1,LONG,6,-4,0,19 +138038,1,LONG,7,-1,-6,44 +138040,1,LONG,8,-12,5,175 +138042,1,LONG,9,-9,-1,89 +138044,1,LONG,10,5,-12,185 +138046,1,LONG,11,-12,-5,182 +138048,1,LONG,12,-5,8,107 +138050,1,LONG,13,-2,31,1015 +138052,1,LONG,14,-2,-3,18 +138054,1,LONG,15,3,-6,54 +138056,1,LONG,16,5,24,643 +138058,1,LONG,17,0,32,1031 +138060,1,LONG,18,14,24,825 +138062,1,LONG,19,0,21,448 +138064,1,LONG,20,0,10,102 +138066,1,LONG,21,1,4,20 +138068,1,LONG,22,-10,1,111 +138070,1,LONG,23,-4,10,126 +138072,1,LONG,24,15,-2,249 +138074,1,LONG,25,-12,10,258 +138076,1,LONG,26,14,-10,319 +138078,1,LONG,27,-4,-7,78 +138080,1,LONG,28,1,3,13 +138082,1,LONG,29,-1,-2,9 +138084,1,LONG,30,6,-1,41 +138086,1,LONG,31,8,-3,81 +138088,1,LONG,32,6,18,384 +138090,1,LONG,33,20,-9,522 +138092,1,LONG,34,-7,-9,142 +138094,1,LONG,35,8,-14,293 +138096,1,LONG,36,-10,1,113 +138098,1,LONG,37,-7,-7,120 +138100,1,LONG,38,-1,-2,6 +138102,1,LONG,39,7,-1,62 +138104,1,LONG,40,-3,-1,13 +138106,1,LONG,41,0,12,145 +138108,1,LONG,42,-15,-1,229 +138110,1,LONG,43,0,-1,2 +138112,1,LONG,44,14,7,260 +138114,1,LONG,45,-3,22,522 +138116,1,LONG,46,1,-4,26 +138118,1,LONG,47,-12,17,435 +138120,1,LONG,48,-3,-5,41 +138122,1,LONG,49,6,-18,385 +138124,1,LONG,50,20,-9,496 +138126,1,LONG,51,34,-11,1345 +138128,1,LONG,52,0,10,112 +138130,1,LONG,53,3,0,14 +138132,1,LONG,54,-8,20,480 +138134,1,LONG,55,15,2,248 +138136,1,LONG,56,0,-19,362 +138138,1,LONG,57,-5,-12,186 +138140,1,LONG,58,14,-12,349 +138142,1,LONG,59,-1,5,35 +138144,1,LONG,60,-3,7,73 +138146,1,LONG,61,2,-12,166 +138148,1,LONG,62,19,11,538 +138150,1,LONG,63,0,2,5 +138152,1,LONG,64,-2,4,22 +138154,1,LONG,65,0,-9,97 +138156,1,LONG,66,2,4,32 +138158,1,LONG,67,-8,9,151 +138160,1,LONG,68,2,-3,19 +138162,1,LONG,69,-9,2,100 +138164,1,LONG,70,-14,0,207 +138166,1,LONG,71,-4,-5,57 +138168,1,LONG,72,-5,-23,598 +138170,1,LONG,73,-11,-1,142 +138172,1,LONG,74,15,-18,580 +138174,1,LONG,75,2,-10,116 +138176,1,LONG,76,-3,31,1027 +138178,1,LONG,77,1,-11,124 +138180,1,LONG,78,6,7,87 +138182,1,LONG,79,12,-7,210 +138184,1,LONG,80,17,15,540 +138186,1,LONG,81,25,2,674 +138188,1,LONG,82,-24,-9,658 +138190,1,LONG,83,4,9,100 +138192,1,LONG,84,23,24,1166 +138194,1,LONG,85,-10,-4,138 +138196,1,LONG,86,-7,-13,225 +138198,1,LONG,87,1,-3,14 +138200,1,LONG,88,-9,-6,138 +138202,1,LONG,89,7,-9,140 +138204,1,LONG,90,-2,-5,31 +138206,1,LONG,91,-8,-10,174 +138208,1,LONG,92,5,-4,41 +138210,1,LONG,93,-3,0,16 +138212,1,LONG,94,0,-2,5 +138214,1,LONG,95,0,-3,10 +138216,1,LONG,96,-19,3,389 +138218,1,LONG,97,20,10,509 +138220,1,LONG,98,8,-27,837 +138222,1,LONG,99,-5,-11,159 +138224,1,LONG,100,2,-6,48 +138226,1,LONG,101,0,-5,29 +138228,1,LONG,102,-3,2,19 +138230,1,LONG,103,-3,12,170 +138232,1,LONG,104,-2,-1,8 +138234,1,LONG,105,10,6,140 +138236,1,LONG,106,-7,-9,141 +138238,1,LONG,107,11,-2,128 +138240,1,LONG,108,8,-3,83 +138242,1,LONG,109,1,-6,44 +138244,1,LONG,110,2,3,24 +138246,1,LONG,111,-8,-2,69 +138248,1,LONG,112,-9,4,106 +138250,1,LONG,113,3,-7,74 +138252,1,LONG,114,-5,0,36 +138254,1,LONG,115,-4,0,23 +138256,1,LONG,116,6,-8,111 +138258,1,LONG,117,0,0,1 +138260,1,LONG,118,-7,5,86 +138262,1,LONG,119,4,-1,19 +138264,1,LONG,120,0,2,4 +138266,1,LONG,121,2,3,14 +138268,1,LONG,122,-1,-5,32 +138270,1,LONG,123,3,-3,24 +138272,1,LONG,124,0,0,1 +138274,1,LONG,125,2,-3,17 +138276,1,LONG,126,-7,8,119 +138278,1,LONG,127,1,-6,45 +138280,1,LONG,128,0,0,0 +138282,1,LONG,129,3,-2,18 +138284,1,LONG,130,0,-7,49 +138286,1,LONG,131,1,-1,3 +138288,1,LONG,132,7,4,80 +138290,1,LONG,133,-5,-1,36 +138292,1,LONG,134,0,-4,17 +138294,1,LONG,135,0,-1,1 +138296,1,LONG,136,4,-9,109 +138298,1,LONG,137,1,8,67 +138300,1,LONG,138,2,0,5 +138302,1,LONG,139,-2,-6,46 +138304,1,LONG,140,3,0,11 +138306,1,LONG,141,87,48,10084 +138308,1,LONG,142,93,44,10802 +138310,1,LONG,143,83,65,11127 +138312,1,LONG,144,62,76,9745 +138314,1,LONG,145,53,79,9202 +138316,1,LONG,146,52,95,11841 +138318,1,LONG,147,35,86,8802 +138320,1,LONG,148,18,96,9604 +138322,1,LONG,149,9,104,10925 +138324,1,LONG,150,-3,107,11644 +138326,1,LONG,151,-19,97,9829 +138328,1,LONG,152,-24,95,9813 +138330,1,LONG,153,-37,83,8316 +138332,1,LONG,154,-46,85,9537 +138334,1,LONG,155,-58,88,11234 +138336,1,LONG,156,-67,75,10168 +138338,1,LONG,157,-73,62,9345 +138340,1,LONG,158,-86,49,9910 +138342,1,LONG,159,-89,40,9711 +138344,1,LONG,160,3,4,32 +138346,1,LONG,161,9,-8,165 +138348,1,LONG,162,-8,-4,84 +138350,1,LONG,163,7,5,88 +138352,1,LONG,164,1,2,10 +138354,1,LONG,165,-5,-5,53 +138356,1,LONG,166,-1,-3,17 +138358,1,LONG,167,5,-1,28 +138360,1,LONG,168,0,5,31 +138362,1,LONG,169,12,-8,241 +138364,1,LONG,170,-7,6,96 +138366,1,LONG,171,0,1,2 +138368,1,LONG,172,-7,-4,72 +138370,1,LONG,173,1,-5,27 +138372,1,LONG,174,4,-7,82 +138374,1,LONG,175,-8,0,80 +138376,1,LONG,176,0,1,1 +138378,1,LONG,177,2,-5,37 +138380,1,LONG,178,6,0,38 +138382,1,LONG,179,-2,-11,143 +138384,1,LONG,180,1,6,49 +138386,1,LONG,181,0,3,13 +138388,1,LONG,182,-1,-3,14 +138390,1,LONG,183,-5,3,40 +138392,1,LONG,184,5,6,79 +138394,1,LONG,185,1,9,99 +138396,1,LONG,186,-7,-9,143 +138398,1,LONG,187,-5,0,29 +138400,1,LONG,188,2,0,6 +138402,1,LONG,189,-3,0,15 +138404,1,LONG,190,-3,-2,20 +138406,1,LONG,191,6,-5,74 +138408,1,LONG,192,9,0,81 +138410,1,LONG,193,4,2,23 +138412,1,LONG,194,11,6,179 +138414,1,LONG,195,4,0,17 +138416,1,LONG,196,1,1,5 +138418,1,LONG,197,4,-4,40 +138420,1,LONG,198,2,-5,34 +138422,1,LONG,199,0,0,1 +138424,1,LONG,200,-3,2,18 +138426,1,LONG,201,-6,3,54 +138428,1,LONG,202,1,8,68 +138430,1,LONG,203,-2,4,23 +138432,1,LONG,204,0,-3,11 +138434,1,LONG,205,-2,9,105 +138436,1,LONG,206,2,1,10 +138438,1,LONG,207,1,8,77 +138440,1,LONG,208,0,-8,70 +138442,1,LONG,209,-1,-7,53 +138444,1,LONG,210,1,4,22 +138446,1,LONG,211,0,-1,4 +138448,1,LONG,212,0,-1,1 +138450,1,LONG,213,-2,8,82 +138452,1,LONG,214,-7,1,54 +138454,1,LONG,215,-5,2,33 +138456,1,LONG,216,0,-1,2 +138458,1,LONG,217,0,2,5 +138460,1,LONG,218,-2,-1,7 +138462,1,LONG,219,-5,0,26 +138464,1,LONG,220,-2,2,13 +138466,1,LONG,221,4,0,21 +138468,1,LONG,222,7,-3,62 +138470,1,LONG,223,0,3,13 +138472,1,LONG,224,6,5,76 +138474,1,LONG,225,3,-6,50 +138476,1,LONG,226,6,-5,81 +138478,1,LONG,227,11,-2,138 +138480,1,LONG,228,1,1,6 +138482,1,LONG,229,0,-2,5 +138484,1,LONG,230,-10,5,144 +138486,1,LONG,231,7,2,63 +138488,1,LONG,232,5,2,40 +138490,1,LONG,233,5,-5,61 +138492,1,LONG,234,2,-8,83 +138494,1,LONG,235,-9,3,102 +138496,1,LONG,236,2,0,7 +138498,1,LONG,237,2,-2,10 +138500,1,LONG,238,-8,-11,195 +138502,1,LONG,239,0,-5,25 +138504,1,LONG,240,-1,8,69 +138506,1,LONG,241,-20,-32,1458 +138508,1,LONG,242,-25,-49,3060 +138510,1,LONG,243,-13,-48,2556 +138512,1,LONG,244,-4,-49,2469 +138514,1,LONG,245,2,-59,3520 +138516,1,LONG,246,9,-48,2470 +138518,1,LONG,247,15,-35,1512 +138520,1,LONG,248,21,-45,2548 +138522,1,LONG,249,14,-46,2384 +138524,1,LONG,250,22,-39,2043 +138526,1,LONG,251,38,-32,2592 +138528,1,LONG,252,35,-36,2563 +138530,1,LONG,253,37,-21,1876 +138532,1,LONG,254,45,-14,2277 +138534,1,LONG,255,44,-16,2252 +138536,1,LONG,256,52,-7,2788 +138538,1,LONG,257,41,-1,1758 +138540,1,LONG,258,57,5,3328 +138542,1,LONG,259,49,18,2839 +138544,1,LONG,260,0,-3,14 +138546,1,LONG,261,-3,6,53 +138548,1,LONG,262,-5,2,31 +138550,1,LONG,263,3,-4,32 +138552,1,LONG,264,2,2,15 +138554,1,LONG,265,-1,0,2 +138556,1,LONG,266,-4,-4,37 +138558,1,LONG,267,8,5,99 +138560,1,LONG,268,6,13,214 +138562,1,LONG,269,-4,-3,37 +138564,1,LONG,270,2,1,10 +138566,1,LONG,271,-1,3,13 +138568,1,LONG,272,1,7,60 +138570,1,LONG,273,-8,1,68 +138572,1,LONG,274,-1,0,3 +138574,1,LONG,275,0,3,11 +138576,1,LONG,276,-8,7,139 +138578,1,LONG,277,-1,0,2 +138580,1,LONG,278,0,-6,42 +138582,1,LONG,279,0,4,20 +138584,1,LONG,280,8,2,78 +138586,1,LONG,281,0,7,58 +138588,1,LONG,282,-3,0,9 +138590,1,LONG,283,-4,0,18 +138592,1,LONG,284,-5,-16,290 +138594,1,LONG,285,6,-6,87 +138596,1,LONG,286,-5,0,35 +138598,1,LONG,287,0,4,21 +138600,1,LONG,288,2,0,6 +138602,1,LONG,289,7,2,66 +138604,1,LONG,290,-10,2,116 +138606,1,LONG,291,-3,4,40 +138608,1,LONG,292,-3,3,27 +138610,1,LONG,293,1,-5,28 +138612,1,LONG,294,3,0,11 +138614,1,LONG,295,-1,4,21 +138616,1,LONG,296,-2,-3,18 +138618,1,LONG,297,0,-3,14 +138620,1,LONG,298,-2,-7,58 +138622,1,LONG,299,5,-8,103 +138624,1,LONG,300,-2,-7,59 +138626,1,LONG,301,-4,3,29 +138628,1,LONG,302,0,2,8 +138630,1,LONG,303,0,5,29 +138632,1,LONG,304,-1,0,3 +138634,1,LONG,305,-4,-6,70 +138636,1,LONG,306,1,1,3 +138638,1,LONG,307,6,2,42 +138640,1,LONG,308,-1,-2,7 +138642,1,LONG,309,-1,1,2 +138644,1,LONG,310,2,2,14 +138646,1,LONG,311,-2,3,17 +138648,1,LONG,312,-12,-1,157 +138650,1,LONG,313,-2,2,14 +138652,1,LONG,314,0,2,7 +138654,1,LONG,315,10,4,139 +138656,1,LONG,316,-3,-2,19 +138658,1,LONG,317,0,-1,1 +138660,1,LONG,318,-2,0,7 +138662,1,LONG,319,-1,-7,55 +138664,1,LONG,320,3,1,16 +138666,1,LONG,321,-4,9,101 +138668,1,LONG,322,-2,-1,7 +138670,1,LONG,323,1,3,15 +138672,1,LONG,324,-1,1,6 +138674,1,LONG,325,3,8,78 +138676,1,LONG,326,-2,2,15 +138678,1,LONG,327,-6,0,38 +138680,1,LONG,328,0,-3,11 +138682,1,LONG,329,2,-5,37 +138684,1,LONG,330,2,3,21 +138686,1,LONG,331,-6,3,49 +138688,1,LONG,332,-5,-2,34 +138690,1,LONG,333,-4,-1,23 +138692,1,LONG,334,8,4,83 +138694,1,LONG,335,-6,-1,47 +138696,1,LONG,336,4,-1,22 +138698,1,LONG,337,4,1,20 +138700,1,LONG,338,2,6,45 +138702,1,LONG,339,2,-2,13 +138704,1,LONG,340,-2,-3,14 +138706,1,LONG,341,-1,-2,7 +138708,1,LONG,342,-9,1,94 +138710,1,LONG,343,1,-5,28 +138712,1,LONG,344,5,-1,36 +138714,1,LONG,345,0,-1,3 +138716,1,LONG,346,3,-7,63 +138718,1,LONG,347,4,5,45 +138720,1,LONG,348,0,7,62 +138722,1,LONG,349,-8,-1,74 +138724,1,LONG,350,-1,-5,33 +138726,1,LONG,351,0,3,10 +138728,1,LONG,352,5,2,38 +138730,1,LONG,353,5,0,32 +138732,1,LONG,354,-6,3,52 +138734,1,LONG,355,-1,-2,7 +138736,1,LONG,356,3,4,38 +138738,1,LONG,357,-3,2,19 +138740,1,LONG,358,0,9,97 +138742,1,LONG,359,-7,1,53 +138744,1,LONG,360,-7,0,58 +138746,1,LONG,361,-9,-3,103 +138748,1,LONG,362,-6,0,38 +138750,1,LONG,363,-7,9,138 +138752,1,LONG,364,1,0,4 +138754,1,LONG,365,3,2,17 +138756,1,LONG,366,8,-1,72 +138758,1,LONG,367,-3,10,124 +138760,1,LONG,368,2,1,7 +138762,1,LONG,369,-4,-7,85 +138764,1,LONG,370,0,1,3 +138766,1,LONG,371,-1,-6,49 +138768,1,LONG,372,-8,2,87 +138770,1,LONG,373,-7,4,82 +138772,1,LONG,374,-1,2,7 +138774,1,LONG,375,3,-7,70 +138776,1,LONG,376,0,-6,37 +138778,1,LONG,377,-2,-1,11 +138780,1,LONG,378,4,4,37 +138782,1,LONG,379,-1,8,73 +138784,1,LONG,380,-3,4,30 +138786,1,LONG,381,1,5,31 +138788,1,LONG,382,-3,3,20 +138790,1,LONG,383,5,0,25 +138792,1,LONG,384,6,0,39 +138794,1,LONG,385,-13,-1,191 +138796,1,LONG,386,6,4,66 +138798,1,LONG,387,0,0,0 +138800,1,LONG,388,-1,0,1 +138802,1,LONG,389,-2,0,4 +138804,1,LONG,390,-1,1,5 +138806,1,LONG,391,25,-20,1065 +138808,1,LONG,392,10,-26,804 +138810,1,LONG,393,24,-13,792 +138812,1,LONG,394,30,-8,1009 +138814,1,LONG,395,17,-12,454 +138816,1,LONG,396,19,-7,437 +138818,1,LONG,397,29,-2,887 +138820,1,LONG,398,30,0,925 +138822,1,LONG,399,27,10,869 +138824,1,LONG,400,20,16,695 +138826,1,LONG,401,14,12,373 +138828,1,LONG,402,20,18,757 +138830,1,LONG,403,14,6,255 +138832,1,LONG,404,16,25,885 +138834,1,LONG,405,8,21,513 +138836,1,LONG,406,13,26,906 +138838,1,LONG,407,8,24,690 +138840,1,LONG,408,10,26,793 +138842,1,LONG,409,-2,25,673 +138844,1,LONG,410,5,6,67 +138846,1,LONG,411,-1,8,74 +138848,1,LONG,412,0,0,1 +138850,1,LONG,413,7,5,81 +138852,1,LONG,414,9,1,84 +138854,1,LONG,415,0,3,15 +138856,1,LONG,416,0,6,45 +138858,1,LONG,417,1,-3,13 +138860,1,LONG,418,-3,-1,12 +138862,1,LONG,419,0,7,63 +138864,1,LONG,420,-6,-1,47 +138866,1,LONG,421,6,-1,38 +138868,1,LONG,422,4,2,28 +138870,1,LONG,423,-4,1,22 +138872,1,LONG,424,4,-3,28 +138874,1,LONG,425,2,6,44 +138876,1,LONG,426,1,-8,66 +138878,1,LONG,427,-4,0,20 +138880,1,LONG,428,1,1,4 +138882,1,LONG,429,0,-9,82 +138884,1,LONG,430,3,4,27 +138886,1,LONG,431,1,0,1 +138888,1,LONG,432,3,-1,19 +138890,1,LONG,433,2,3,16 +138892,1,LONG,434,0,10,102 +138894,1,LONG,435,5,-3,46 +138896,1,LONG,436,5,-5,57 +138898,1,LONG,437,2,-2,15 +138900,1,LONG,438,4,-1,18 +138902,1,LONG,439,5,-1,28 +138904,1,LONG,440,4,4,48 +138906,1,LONG,441,-3,-6,56 +138908,1,LONG,442,11,4,162 +138910,1,LONG,443,-5,-1,34 +138912,1,LONG,444,1,2,5 +138914,1,LONG,445,1,0,1 +138916,1,LONG,446,3,2,16 +138918,1,LONG,447,1,0,3 +138920,1,LONG,448,-3,0,13 +138922,1,LONG,449,0,-1,1 +138924,1,LONG,450,-2,-2,11 +138926,1,LONG,451,2,0,8 +138928,1,LONG,452,-4,0,18 +138930,1,LONG,453,8,-10,170 +138932,1,LONG,454,-2,6,51 +138934,1,LONG,455,3,3,23 +138936,1,LONG,456,-7,-5,95 +138938,1,LONG,457,-7,-5,82 +138940,1,LONG,458,0,-3,13 +138942,1,LONG,459,2,0,8 +138944,1,LONG,460,-8,2,83 +138946,1,LONG,461,2,0,8 +138948,1,LONG,462,4,0,21 +138950,1,LONG,463,-13,7,241 +138952,1,LONG,464,2,-2,14 +138954,1,LONG,465,-2,-3,16 +138956,1,LONG,466,-1,4,21 +138958,1,LONG,467,10,0,120 +138960,1,LONG,468,0,3,14 +138962,1,LONG,469,0,1,3 +138964,1,LONG,470,4,-2,27 +138966,1,LONG,471,2,0,5 +138968,1,LONG,472,3,1,15 +138970,1,LONG,473,-2,-1,6 +138972,1,LONG,474,3,-2,20 +138974,1,LONG,475,-7,-8,125 +138976,1,LONG,476,-7,0,55 +138978,1,LONG,477,-1,-10,118 +138980,1,LONG,478,-4,4,39 +138982,1,LONG,479,2,2,12 +138984,1,LONG,480,-4,2,28 +138986,1,LONG,481,-2,1,7 +138988,1,LONG,482,6,1,42 +138990,1,LONG,483,-3,0,12 +138992,1,LONG,484,-6,5,71 +138994,1,LONG,485,-3,3,22 +138996,1,LONG,486,0,3,14 +138998,1,LONG,487,-1,-7,54 +139000,1,LONG,488,-3,5,42 +139002,1,LONG,489,-3,15,255 +139004,1,LONG,490,-3,1,18 +139006,1,LONG,491,-1,6,41 +139008,1,LONG,492,-9,5,122 +139010,1,LONG,493,-2,-2,11 +139012,1,LONG,494,0,0,0 +139014,1,LONG,495,-3,-14,234 +139016,1,LONG,496,-3,-3,29 +139018,1,LONG,497,-2,8,76 +139020,1,LONG,498,-3,-3,26 +139022,1,LONG,499,-8,2,88 +139024,1,LONG,500,1,8,76 +139026,1,LONG,501,0,-6,47 +139028,1,LONG,502,0,3,12 +139030,1,LONG,503,-4,0,17 +139032,1,LONG,504,2,-1,10 +139034,1,LONG,505,7,-5,84 +139036,1,LONG,506,-8,4,89 +139038,1,LONG,507,1,-1,7 +139040,1,LONG,508,0,1,3 +139042,1,LONG,509,-4,0,19 +139044,1,LONG,510,5,2,37 +139046,1,LONG,511,-4,-1,23 +276048,2,LONG,0,-5,0,26 +276050,2,LONG,1,8,-10,179 +276052,2,LONG,2,14,20,633 +276054,2,LONG,3,5,-5,62 +276056,2,LONG,4,6,-3,54 +276058,2,LONG,5,-18,0,327 +276060,2,LONG,6,-5,12,181 +276062,2,LONG,7,-12,-4,175 +276064,2,LONG,8,-4,-18,362 +276066,2,LONG,9,7,-5,81 +276068,2,LONG,10,16,5,305 +276070,2,LONG,11,9,-3,107 +276072,2,LONG,12,-19,1,388 +276074,2,LONG,13,-5,-7,87 +276076,2,LONG,14,-4,7,70 +276078,2,LONG,15,0,0,0 +276080,2,LONG,16,-4,-8,88 +276082,2,LONG,17,12,10,250 +276084,2,LONG,18,5,-16,295 +276086,2,LONG,19,2,4,28 +276088,2,LONG,20,5,-16,323 +276090,2,LONG,21,-20,-4,443 +276092,2,LONG,22,13,-10,292 +276094,2,LONG,23,-11,-17,424 +276096,2,LONG,24,-9,2,89 +276098,2,LONG,25,8,3,79 +276100,2,LONG,26,17,0,291 +276102,2,LONG,27,19,-3,395 +276104,2,LONG,28,0,14,221 +276106,2,LONG,29,18,11,469 +276108,2,LONG,30,8,17,373 +276110,2,LONG,31,3,16,291 +276112,2,LONG,32,11,2,143 +276114,2,LONG,33,-6,2,52 +276116,2,LONG,34,-13,-16,454 +276118,2,LONG,35,-7,5,89 +276120,2,LONG,36,7,5,77 +276122,2,LONG,37,1,0,2 +276124,2,LONG,38,-11,26,847 +276126,2,LONG,39,16,22,770 +276128,2,LONG,40,-2,8,74 +276130,2,LONG,41,-22,4,511 +276132,2,LONG,42,-1,1,5 +276134,2,LONG,43,0,12,165 +276136,2,LONG,44,12,0,165 +276138,2,LONG,45,8,-3,80 +276140,2,LONG,46,-19,6,418 +276142,2,LONG,47,-4,-17,312 +276144,2,LONG,48,5,-27,760 +276146,2,LONG,49,10,-1,107 +276148,2,LONG,50,19,31,1389 +276150,2,LONG,51,7,1,54 +276152,2,LONG,52,17,17,601 +276154,2,LONG,53,7,14,279 +276156,2,LONG,54,13,-11,331 +276158,2,LONG,55,4,3,30 +276160,2,LONG,56,2,9,96 +276162,2,LONG,57,5,-1,30 +276164,2,LONG,58,25,-28,1453 +276166,2,LONG,59,0,-10,114 +276168,2,LONG,60,5,4,50 +276170,2,LONG,61,17,26,979 +276172,2,LONG,62,5,-1,35 +276174,2,LONG,63,-2,5,38 +276176,2,LONG,64,3,-6,46 +276178,2,LONG,65,16,-10,386 +276180,2,LONG,66,10,12,267 +276182,2,LONG,67,3,7,70 +276184,2,LONG,68,11,-4,144 +276186,2,LONG,69,0,4,18 +276188,2,LONG,70,-20,-6,484 +276190,2,LONG,71,14,1,210 +276192,2,LONG,72,-5,9,117 +276194,2,LONG,73,-3,7,65 +276196,2,LONG,74,6,0,49 +276198,2,LONG,75,-20,9,515 +276200,2,LONG,76,1,1,5 +276202,2,LONG,77,-11,-11,277 +276204,2,LONG,78,-15,3,263 +276206,2,LONG,79,-9,8,148 +276208,2,LONG,80,0,14,211 +276210,2,LONG,81,-3,8,83 +276212,2,LONG,82,12,-16,410 +276214,2,LONG,83,21,-7,513 +276216,2,LONG,84,12,0,168 +276218,2,LONG,85,6,15,267 +276220,2,LONG,86,1,-9,83 +276222,2,LONG,87,10,12,257 +276224,2,LONG,88,-1,0,1 +276226,2,LONG,89,15,2,244 +276228,2,LONG,90,3,-6,50 +276230,2,LONG,91,-10,30,1057 +276232,2,LONG,92,1,-7,56 +276234,2,LONG,93,-6,-19,435 +276236,2,LONG,94,-14,-7,261 +276238,2,LONG,95,10,4,137 +276240,2,LONG,96,18,-1,353 +276242,2,LONG,97,-5,-9,118 +276244,2,LONG,98,1,-18,347 +276246,2,LONG,99,-14,11,337 +276248,2,LONG,100,0,2,6 +276250,2,LONG,101,4,9,104 +276252,2,LONG,102,7,-2,63 +276254,2,LONG,103,4,-6,57 +276256,2,LONG,104,-3,-10,112 +276258,2,LONG,105,4,-5,49 +276260,2,LONG,106,-2,1,7 +276262,2,LONG,107,0,2,5 +276264,2,LONG,108,4,2,25 +276266,2,LONG,109,4,-6,61 +276268,2,LONG,110,-1,-3,16 +276270,2,LONG,111,-1,-6,37 +276272,2,LONG,112,7,-1,59 +276274,2,LONG,113,0,-5,25 +276276,2,LONG,114,-3,1,14 +276278,2,LONG,115,-5,-2,40 +276280,2,LONG,116,1,0,2 +276282,2,LONG,117,-6,1,46 +276284,2,LONG,118,-2,0,6 +276286,2,LONG,119,-8,-2,75 +276288,2,LONG,120,0,8,71 +276290,2,LONG,121,-4,0,18 +276292,2,LONG,122,-3,0,11 +276294,2,LONG,123,0,6,37 +276296,2,LONG,124,1,-1,2 +276298,2,LONG,125,-3,-2,18 +276300,2,LONG,126,3,2,20 +276302,2,LONG,127,-1,-2,6 +276304,2,LONG,128,0,-4,18 +276306,2,LONG,129,-12,-1,162 +276308,2,LONG,130,-8,-1,81 +276310,2,LONG,131,0,-4,19 +276312,2,LONG,132,1,-4,18 +276314,2,LONG,133,5,0,27 +276316,2,LONG,134,4,-1,24 +276318,2,LONG,135,1,4,19 +276320,2,LONG,136,3,-12,159 +276322,2,LONG,137,2,0,6 +276324,2,LONG,138,4,-12,176 +276326,2,LONG,139,0,2,8 +276328,2,LONG,140,-8,4,95 +276330,2,LONG,141,-42,88,9682 +276332,2,LONG,142,-48,79,8601 +276334,2,LONG,143,-70,80,11383 +276336,2,LONG,144,-70,64,9109 +276338,2,LONG,145,-80,56,9599 +276340,2,LONG,146,-94,47,11145 +276342,2,LONG,147,-84,30,8002 +276344,2,LONG,148,-98,28,10501 +276346,2,LONG,149,-102,15,10709 +276348,2,LONG,150,-101,9,10427 +276350,2,LONG,151,-104,-11,11052 +276352,2,LONG,152,-102,-15,10768 +276354,2,LONG,153,-90,-32,9342 +276356,2,LONG,154,-90,-42,10051 +276358,2,LONG,155,-79,-58,9682 +276360,2,LONG,156,-73,-74,10984 +276362,2,LONG,157,-57,-78,9430 +276364,2,LONG,158,-61,-79,10047 +276366,2,LONG,159,-43,-87,9558 +276368,2,LONG,160,-2,0,4 +276370,2,LONG,161,-2,9,103 +276372,2,LONG,162,-6,4,62 +276374,2,LONG,163,7,-1,52 +276376,2,LONG,164,0,-1,3 +276378,2,LONG,165,2,-1,6 +276380,2,LONG,166,-5,-1,35 +276382,2,LONG,167,-3,6,46 +276384,2,LONG,168,2,-3,17 +276386,2,LONG,169,1,3,17 +276388,2,LONG,170,5,1,30 +276390,2,LONG,171,-6,7,100 +276392,2,LONG,172,0,-5,27 +276394,2,LONG,173,3,0,13 +276396,2,LONG,174,-5,-1,31 +276398,2,LONG,175,-3,4,28 +276400,2,LONG,176,-2,-2,15 +276402,2,LONG,177,1,-10,104 +276404,2,LONG,178,-3,0,10 +276406,2,LONG,179,-5,-1,34 +276408,2,LONG,180,0,0,0 +276410,2,LONG,181,3,0,12 +276412,2,LONG,182,0,1,3 +276414,2,LONG,183,2,0,7 +276416,2,LONG,184,5,-3,45 +276418,2,LONG,185,7,-1,66 +276420,2,LONG,186,0,-3,13 +276422,2,LONG,187,-9,5,116 +276424,2,LONG,188,2,2,11 +276426,2,LONG,189,0,5,27 +276428,2,LONG,190,-7,-3,76 +276430,2,LONG,191,2,3,17 +276432,2,LONG,192,1,7,57 +276434,2,LONG,193,-5,-3,45 +276436,2,LONG,194,-4,7,69 +276438,2,LONG,195,0,4,23 +276440,2,LONG,196,5,5,67 +276442,2,LONG,197,1,5,33 +276444,2,LONG,198,1,6,40 +276446,2,LONG,199,-2,-4,24 +276448,2,LONG,200,-4,0,25 +276450,2,LONG,201,0,4,20 +276452,2,LONG,202,4,1,20 +276454,2,LONG,203,0,0,0 +276456,2,LONG,204,-1,5,30 +276458,2,LONG,205,0,-8,73 +276460,2,LONG,206,0,10,101 +276462,2,LONG,207,-5,0,25 +276464,2,LONG,208,0,0,1 +276466,2,LONG,209,3,1,12 +276468,2,LONG,210,-4,0,20 +276470,2,LONG,211,3,-3,23 +276472,2,LONG,212,5,0,35 +276474,2,LONG,213,0,0,0 +276476,2,LONG,214,4,3,30 +276478,2,LONG,215,0,10,110 +276480,2,LONG,216,-2,-5,32 +276482,2,LONG,217,1,-9,98 +276484,2,LONG,218,-2,-8,84 +276486,2,LONG,219,1,0,2 +276488,2,LONG,220,-1,3,18 +276490,2,LONG,221,-3,6,60 +276492,2,LONG,222,0,-4,20 +276494,2,LONG,223,7,-1,53 +276496,2,LONG,224,-2,1,10 +276498,2,LONG,225,0,-3,16 +276500,2,LONG,226,2,2,9 +276502,2,LONG,227,4,-10,127 +276504,2,LONG,228,2,-3,16 +276506,2,LONG,229,0,-3,16 +276508,2,LONG,230,-8,5,103 +276510,2,LONG,231,-6,2,46 +276512,2,LONG,232,3,-3,24 +276514,2,LONG,233,-3,0,15 +276516,2,LONG,234,2,3,17 +276518,2,LONG,235,13,1,182 +276520,2,LONG,236,-2,-3,19 +276522,2,LONG,237,-3,-10,118 +276524,2,LONG,238,-3,-7,76 +276526,2,LONG,239,2,-5,32 +276528,2,LONG,240,2,3,15 +276530,2,LONG,241,-40,-11,1774 +276532,2,LONG,242,-53,-1,2826 +276534,2,LONG,243,-43,-19,2266 +276536,2,LONG,244,-46,-27,2909 +276538,2,LONG,245,-37,-28,2211 +276540,2,LONG,246,-35,-29,2130 +276542,2,LONG,247,-33,-42,2920 +276544,2,LONG,248,-40,-42,3468 +276546,2,LONG,249,-19,-47,2604 +276548,2,LONG,250,-7,-45,2148 +276550,2,LONG,251,-5,-38,1540 +276552,2,LONG,252,-2,-56,3185 +276554,2,LONG,253,0,-50,2588 +276556,2,LONG,254,9,-42,1908 +276558,2,LONG,255,18,-51,2953 +276560,2,LONG,256,20,-43,2297 +276562,2,LONG,257,19,-36,1725 +276564,2,LONG,258,32,-38,2483 +276566,2,LONG,259,40,-35,2956 +276568,2,LONG,260,3,6,45 +276570,2,LONG,261,-1,5,38 +276572,2,LONG,262,6,0,43 +276574,2,LONG,263,-2,0,6 +276576,2,LONG,264,1,4,23 +276578,2,LONG,265,-3,2,20 +276580,2,LONG,266,7,-7,115 +276582,2,LONG,267,1,0,2 +276584,2,LONG,268,1,3,11 +276586,2,LONG,269,-2,-10,125 +276588,2,LONG,270,4,2,31 +276590,2,LONG,271,-3,6,50 +276592,2,LONG,272,0,1,4 +276594,2,LONG,273,4,-2,23 +276596,2,LONG,274,-4,3,34 +276598,2,LONG,275,4,-4,36 +276600,2,LONG,276,3,-13,178 +276602,2,LONG,277,-5,-3,42 +276604,2,LONG,278,2,1,9 +276606,2,LONG,279,5,-1,37 +276608,2,LONG,280,-4,-2,23 +276610,2,LONG,281,10,-5,142 +276612,2,LONG,282,-5,0,33 +276614,2,LONG,283,-3,-4,33 +276616,2,LONG,284,-4,-6,55 +276618,2,LONG,285,2,-1,8 +276620,2,LONG,286,3,2,18 +276622,2,LONG,287,3,-2,17 +276624,2,LONG,288,-9,0,91 +276626,2,LONG,289,-7,3,77 +276628,2,LONG,290,2,-5,36 +276630,2,LONG,291,-4,-2,22 +276632,2,LONG,292,0,0,1 +276634,2,LONG,293,1,0,1 +276636,2,LONG,294,0,-1,2 +276638,2,LONG,295,-5,-4,49 +276640,2,LONG,296,-4,-4,44 +276642,2,LONG,297,6,-8,125 +276644,2,LONG,298,0,-6,38 +276646,2,LONG,299,-5,-1,33 +276648,2,LONG,300,3,-9,104 +276650,2,LONG,301,3,0,15 +276652,2,LONG,302,-6,3,58 +276654,2,LONG,303,0,4,20 +276656,2,LONG,304,9,12,233 +276658,2,LONG,305,2,-1,6 +276660,2,LONG,306,2,-3,18 +276662,2,LONG,307,-3,1,13 +276664,2,LONG,308,5,-1,33 +276666,2,LONG,309,0,-14,206 +276668,2,LONG,310,5,-1,30 +276670,2,LONG,311,1,1,3 +276672,2,LONG,312,0,-2,9 +276674,2,LONG,313,1,0,1 +276676,2,LONG,314,9,0,98 +276678,2,LONG,315,1,2,7 +276680,2,LONG,316,-5,-1,32 +276682,2,LONG,317,3,-10,119 +276684,2,LONG,318,0,6,46 +276686,2,LONG,319,5,4,49 +276688,2,LONG,320,-4,6,62 +276690,2,LONG,321,2,0,7 +276692,2,LONG,322,-6,0,40 +276694,2,LONG,323,-6,10,154 +276696,2,LONG,324,6,6,87 +276698,2,LONG,325,0,7,59 +276700,2,LONG,326,-5,8,104 +276702,2,LONG,327,1,3,13 +276704,2,LONG,328,-2,2,13 +276706,2,LONG,329,1,0,4 +276708,2,LONG,330,3,-3,25 +276710,2,LONG,331,0,-3,12 +276712,2,LONG,332,-2,-5,31 +276714,2,LONG,333,2,3,17 +276716,2,LONG,334,-5,-8,103 +276718,2,LONG,335,3,1,11 +276720,2,LONG,336,7,1,62 +276722,2,LONG,337,0,1,1 +276724,2,LONG,338,1,0,2 +276726,2,LONG,339,-8,0,66 +276728,2,LONG,340,-7,-3,63 +276730,2,LONG,341,0,3,9 +276732,2,LONG,342,-4,0,23 +276734,2,LONG,343,-2,3,15 +276736,2,LONG,344,0,-3,12 +276738,2,LONG,345,2,2,10 +276740,2,LONG,346,-1,-3,17 +276742,2,LONG,347,-1,-5,29 +276744,2,LONG,348,-4,10,121 +276746,2,LONG,349,-7,-1,65 +276748,2,LONG,350,-7,-2,69 +276750,2,LONG,351,5,0,34 +276752,2,LONG,352,9,0,94 +276754,2,LONG,353,-4,3,29 +276756,2,LONG,354,-2,-3,13 +276758,2,LONG,355,2,9,102 +276760,2,LONG,356,0,-4,18 +276762,2,LONG,357,-3,4,34 +276764,2,LONG,358,-6,-1,37 +276766,2,LONG,359,0,6,46 +276768,2,LONG,360,1,1,3 +276770,2,LONG,361,-7,8,131 +276772,2,LONG,362,0,-2,6 +276774,2,LONG,363,1,2,7 +276776,2,LONG,364,-14,0,219 +276778,2,LONG,365,0,1,1 +276780,2,LONG,366,0,3,13 +276782,2,LONG,367,0,1,3 +276784,2,LONG,368,-3,-2,16 +276786,2,LONG,369,-2,1,6 +276788,2,LONG,370,-3,2,16 +276790,2,LONG,371,4,-1,21 +276792,2,LONG,372,-6,0,38 +276794,2,LONG,373,8,0,77 +276796,2,LONG,374,-3,0,9 +276798,2,LONG,375,2,0,4 +276800,2,LONG,376,1,-3,14 +276802,2,LONG,377,9,0,90 +276804,2,LONG,378,5,0,27 +276806,2,LONG,379,-4,-3,34 +276808,2,LONG,380,4,-4,42 +276810,2,LONG,381,0,5,30 +276812,2,LONG,382,-4,1,21 +276814,2,LONG,383,2,-3,21 +276816,2,LONG,384,2,1,10 +276818,2,LONG,385,1,5,33 +276820,2,LONG,386,0,-3,14 +276822,2,LONG,387,3,-6,50 +276824,2,LONG,388,1,3,13 +276826,2,LONG,389,3,0,12 +276828,2,LONG,390,9,-6,134 +276830,2,LONG,391,25,-8,734 +276832,2,LONG,392,28,-8,899 +276834,2,LONG,393,26,-6,729 +276836,2,LONG,394,18,0,339 +276838,2,LONG,395,24,1,614 +276840,2,LONG,396,27,5,790 +276842,2,LONG,397,26,2,686 +276844,2,LONG,398,16,8,341 +276846,2,LONG,399,27,18,1101 +276848,2,LONG,400,21,14,660 +276850,2,LONG,401,19,20,800 +276852,2,LONG,402,25,20,1076 +276854,2,LONG,403,17,25,935 +276856,2,LONG,404,11,21,621 +276858,2,LONG,405,10,18,445 +276860,2,LONG,406,2,20,446 +276862,2,LONG,407,5,19,421 +276864,2,LONG,408,-5,25,669 +276866,2,LONG,409,0,17,290 +276868,2,LONG,410,1,2,7 +276870,2,LONG,411,-11,1,141 +276872,2,LONG,412,2,1,10 +276874,2,LONG,413,0,0,0 +276876,2,LONG,414,6,-1,46 +276878,2,LONG,415,2,-1,8 +276880,2,LONG,416,-4,5,45 +276882,2,LONG,417,0,-5,27 +276884,2,LONG,418,-6,2,51 +276886,2,LONG,419,4,5,45 +276888,2,LONG,420,-6,1,42 +276890,2,LONG,421,11,-5,170 +276892,2,LONG,422,-1,3,13 +276894,2,LONG,423,1,2,9 +276896,2,LONG,424,15,-4,252 +276898,2,LONG,425,-3,-1,16 +276900,2,LONG,426,0,0,0 +276902,2,LONG,427,-6,-1,44 +276904,2,LONG,428,3,-2,19 +276906,2,LONG,429,7,9,145 +276908,2,LONG,430,7,4,79 +276910,2,LONG,431,-2,0,8 +276912,2,LONG,432,2,3,19 +276914,2,LONG,433,4,-3,34 +276916,2,LONG,434,8,4,97 +276918,2,LONG,435,9,-2,95 +276920,2,LONG,436,-2,-2,8 +276922,2,LONG,437,11,-4,160 +276924,2,LONG,438,-5,-1,35 +276926,2,LONG,439,2,-1,10 +276928,2,LONG,440,-1,0,2 +276930,2,LONG,441,0,5,29 +276932,2,LONG,442,14,-2,206 +276934,2,LONG,443,6,5,68 +276936,2,LONG,444,8,2,74 +276938,2,LONG,445,3,5,45 +276940,2,LONG,446,0,11,142 +276942,2,LONG,447,-6,-8,122 +276944,2,LONG,448,-2,4,28 +276946,2,LONG,449,7,-1,64 +276948,2,LONG,450,-5,0,31 +276950,2,LONG,451,-1,2,7 +276952,2,LONG,452,9,0,87 +276954,2,LONG,453,0,3,10 +276956,2,LONG,454,0,0,0 +276958,2,LONG,455,2,4,32 +276960,2,LONG,456,-5,4,42 +276962,2,LONG,457,2,7,65 +276964,2,LONG,458,0,-7,64 +276966,2,LONG,459,-3,-6,60 +276968,2,LONG,460,-2,0,8 +276970,2,LONG,461,2,0,6 +276972,2,LONG,462,6,0,44 +276974,2,LONG,463,6,3,45 +276976,2,LONG,464,0,-6,44 +276978,2,LONG,465,4,-4,42 +276980,2,LONG,466,5,-1,31 +276982,2,LONG,467,-11,-2,132 +276984,2,LONG,468,-7,2,57 +276986,2,LONG,469,5,3,38 +276988,2,LONG,470,6,-3,58 +276990,2,LONG,471,-3,-3,23 +276992,2,LONG,472,4,10,119 +276994,2,LONG,473,3,-7,63 +276996,2,LONG,474,0,5,35 +276998,2,LONG,475,0,0,1 +277000,2,LONG,476,9,8,153 +277002,2,LONG,477,-5,-5,60 +277004,2,LONG,478,4,10,118 +277006,2,LONG,479,-4,0,20 +277008,2,LONG,480,-8,-3,87 +277010,2,LONG,481,1,-6,41 +277012,2,LONG,482,0,1,4 +277014,2,LONG,483,-2,-3,13 +277016,2,LONG,484,5,0,30 +277018,2,LONG,485,1,5,34 +277020,2,LONG,486,4,-3,32 +277022,2,LONG,487,-1,4,26 +277024,2,LONG,488,2,0,8 +277026,2,LONG,489,-3,-12,160 +277028,2,LONG,490,1,3,11 +277030,2,LONG,491,-3,1,17 +277032,2,LONG,492,0,-12,164 +277034,2,LONG,493,0,-1,1 +277036,2,LONG,494,3,-3,22 +277038,2,LONG,495,-3,1,13 +277040,2,LONG,496,5,3,44 +277042,2,LONG,497,0,-9,88 +277044,2,LONG,498,2,5,42 +277046,2,LONG,499,-5,-3,41 +277048,2,LONG,500,-1,5,29 +277050,2,LONG,501,-2,-5,43 +277052,2,LONG,502,-4,0,21 +277054,2,LONG,503,-3,1,12 +277056,2,LONG,504,-1,-5,26 +277058,2,LONG,505,-3,1,15 +277060,2,LONG,506,0,4,19 +277062,2,LONG,507,7,1,63 +277064,2,LONG,508,-5,15,290 +277066,2,LONG,509,0,12,160 +277068,2,LONG,510,0,0,1 +277070,2,LONG,511,-4,1,24 +414072,3,LONG,0,23,15,792 +414074,3,LONG,1,2,-15,252 +414076,3,LONG,2,24,-11,709 +414078,3,LONG,3,-9,-9,180 +414080,3,LONG,4,-1,3,10 +414082,3,LONG,5,-5,17,342 +414084,3,LONG,6,-7,7,108 +414086,3,LONG,7,22,-4,525 +414088,3,LONG,8,3,-6,50 +414090,3,LONG,9,-3,-12,172 +414092,3,LONG,10,-8,3,79 +414094,3,LONG,11,6,-1,39 +414096,3,LONG,12,6,11,166 +414098,3,LONG,13,-6,24,664 +414100,3,LONG,14,9,0,91 +414102,3,LONG,15,-1,-19,374 +414104,3,LONG,16,-2,-10,116 +414106,3,LONG,17,-3,3,28 +414108,3,LONG,18,1,10,103 +414110,3,LONG,19,5,1,27 +414112,3,LONG,20,11,1,128 +414114,3,LONG,21,-2,11,130 +414116,3,LONG,22,6,8,106 +414118,3,LONG,23,-2,14,219 +414120,3,LONG,24,-4,-1,20 +414122,3,LONG,25,11,-3,141 +414124,3,LONG,26,4,-20,449 +414126,3,LONG,27,-24,5,632 +414128,3,LONG,28,7,9,163 +414130,3,LONG,29,6,-5,69 +414132,3,LONG,30,22,-5,560 +414134,3,LONG,31,-3,-3,27 +414136,3,LONG,32,2,3,16 +414138,3,LONG,33,27,-11,874 +414140,3,LONG,34,22,7,586 +414142,3,LONG,35,-5,-15,273 +414144,3,LONG,36,11,-1,135 +414146,3,LONG,37,20,-2,443 +414148,3,LONG,38,4,-1,21 +414150,3,LONG,39,5,9,124 +414152,3,LONG,40,14,-2,229 +414154,3,LONG,41,14,-27,980 +414156,3,LONG,42,1,5,28 +414158,3,LONG,43,13,13,356 +414160,3,LONG,44,-18,-18,670 +414162,3,LONG,45,6,1,41 +414164,3,LONG,46,-11,-23,677 +414166,3,LONG,47,21,-21,933 +414168,3,LONG,48,-2,0,6 +414170,3,LONG,49,-5,22,557 +414172,3,LONG,50,-4,-11,148 +414174,3,LONG,51,6,0,42 +414176,3,LONG,52,4,8,98 +414178,3,LONG,53,9,-8,150 +414180,3,LONG,54,-4,-18,363 +414182,3,LONG,55,-1,11,137 +414184,3,LONG,56,-17,13,499 +414186,3,LONG,57,6,19,423 +414188,3,LONG,58,-5,21,495 +414190,3,LONG,59,-13,-5,208 +414192,3,LONG,60,10,8,187 +414194,3,LONG,61,-1,-5,36 +414196,3,LONG,62,-1,9,97 +414198,3,LONG,63,3,-4,27 +414200,3,LONG,64,-10,-11,244 +414202,3,LONG,65,-1,18,347 +414204,3,LONG,66,-27,2,762 +414206,3,LONG,67,8,-14,277 +414208,3,LONG,68,8,7,135 +414210,3,LONG,69,12,3,163 +414212,3,LONG,70,2,0,5 +414214,3,LONG,71,-2,19,382 +414216,3,LONG,72,10,-2,124 +414218,3,LONG,73,-12,17,459 +414220,3,LONG,74,-5,19,424 +414222,3,LONG,75,14,-4,232 +414224,3,LONG,76,-3,14,228 +414226,3,LONG,77,18,-9,437 +414228,3,LONG,78,5,-5,54 +414230,3,LONG,79,-7,-12,200 +414232,3,LONG,80,0,7,52 +414234,3,LONG,81,-1,4,17 +414236,3,LONG,82,-12,1,148 +414238,3,LONG,83,0,-3,14 +414240,3,LONG,84,-6,-1,48 +414242,3,LONG,85,0,-8,73 +414244,3,LONG,86,0,-12,146 +414246,3,LONG,87,0,19,392 +414248,3,LONG,88,9,11,212 +414250,3,LONG,89,-4,0,18 +414252,3,LONG,90,6,-6,76 +414254,3,LONG,91,5,9,115 +414256,3,LONG,92,4,0,16 +414258,3,LONG,93,-14,-4,238 +414260,3,LONG,94,0,23,574 +414262,3,LONG,95,19,-26,1047 +414264,3,LONG,96,-7,-1,52 +414266,3,LONG,97,-12,6,206 +414268,3,LONG,98,1,9,96 +414270,3,LONG,99,-27,-11,860 +414272,3,LONG,100,-5,-5,62 +414274,3,LONG,101,-2,-2,13 +414276,3,LONG,102,-11,1,125 +414278,3,LONG,103,0,-1,1 +414280,3,LONG,104,-1,5,27 +414282,3,LONG,105,4,-3,27 +414284,3,LONG,106,-12,0,166 +414286,3,LONG,107,1,-2,8 +414288,3,LONG,108,0,-1,2 +414290,3,LONG,109,8,-1,79 +414292,3,LONG,110,-3,7,66 +414294,3,LONG,111,-3,2,21 +414296,3,LONG,112,4,6,68 +414298,3,LONG,113,-2,6,54 +414300,3,LONG,114,-1,-4,20 +414302,3,LONG,115,-5,0,33 +414304,3,LONG,116,-5,-5,63 +414306,3,LONG,117,2,-9,95 +414308,3,LONG,118,-5,-1,37 +414310,3,LONG,119,-1,-5,33 +414312,3,LONG,120,5,-12,177 +414314,3,LONG,121,2,-3,14 +414316,3,LONG,122,10,4,128 +414318,3,LONG,123,-3,10,112 +414320,3,LONG,124,-1,2,8 +414322,3,LONG,125,5,-7,90 +414324,3,LONG,126,9,0,91 +414326,3,LONG,127,5,5,54 +414328,3,LONG,128,-1,6,40 +414330,3,LONG,129,-15,6,285 +414332,3,LONG,130,-2,-1,6 +414334,3,LONG,131,-6,0,48 +414336,3,LONG,132,1,1,5 +414338,3,LONG,133,-10,3,124 +414340,3,LONG,134,-3,-6,48 +414342,3,LONG,135,1,-6,49 +414344,3,LONG,136,1,7,52 +414346,3,LONG,137,4,6,69 +414348,3,LONG,138,11,1,144 +414350,3,LONG,139,1,1,5 +414352,3,LONG,140,1,1,4 +414354,3,LONG,141,-98,-44,11675 +414356,3,LONG,142,-85,-49,9845 +414358,3,LONG,143,-84,-66,11574 +414360,3,LONG,144,-73,-68,10081 +414362,3,LONG,145,-56,-69,8002 +414364,3,LONG,146,-40,-97,11124 +414366,3,LONG,147,-34,-85,8539 +414368,3,LONG,148,-20,-99,10316 +414370,3,LONG,149,-17,-97,9844 +414372,3,LONG,150,-2,-110,12216 +414374,3,LONG,151,22,-107,12118 +414376,3,LONG,152,17,-87,8025 +414378,3,LONG,153,36,-86,8810 +414380,3,LONG,154,46,-84,9286 +414382,3,LONG,155,65,-70,9382 +414384,3,LONG,156,66,-82,11150 +414386,3,LONG,157,74,-55,8614 +414388,3,LONG,158,84,-50,9742 +414390,3,LONG,159,87,-34,8887 +414392,3,LONG,160,-4,-6,62 +414394,3,LONG,161,-9,1,92 +414396,3,LONG,162,0,0,0 +414398,3,LONG,163,0,2,6 +414400,3,LONG,164,-2,0,5 +414402,3,LONG,165,-3,-6,56 +414404,3,LONG,166,8,0,68 +414406,3,LONG,167,3,0,15 +414408,3,LONG,168,-2,-6,54 +414410,3,LONG,169,4,-1,26 +414412,3,LONG,170,9,0,93 +414414,3,LONG,171,3,7,61 +414416,3,LONG,172,-1,-7,61 +414418,3,LONG,173,2,0,4 +414420,3,LONG,174,3,3,22 +414422,3,LONG,175,9,5,131 +414424,3,LONG,176,3,-8,80 +414426,3,LONG,177,-2,-10,125 +414428,3,LONG,178,-3,-6,53 +414430,3,LONG,179,-8,-1,66 +414432,3,LONG,180,-3,-2,14 +414434,3,LONG,181,-1,5,30 +414436,3,LONG,182,3,-13,190 +414438,3,LONG,183,-5,-4,49 +414440,3,LONG,184,-5,4,48 +414442,3,LONG,185,2,-4,29 +414444,3,LONG,186,-4,-5,48 +414446,3,LONG,187,4,1,20 +414448,3,LONG,188,-10,-7,174 +414450,3,LONG,189,2,2,13 +414452,3,LONG,190,9,-1,87 +414454,3,LONG,191,1,-3,12 +414456,3,LONG,192,3,-7,69 +414458,3,LONG,193,-2,-4,26 +414460,3,LONG,194,0,2,6 +414462,3,LONG,195,-8,-4,86 +414464,3,LONG,196,-6,0,39 +414466,3,LONG,197,-1,-15,229 +414468,3,LONG,198,-3,2,19 +414470,3,LONG,199,-2,-1,11 +414472,3,LONG,200,0,-3,12 +414474,3,LONG,201,-8,3,88 +414476,3,LONG,202,-3,-8,85 +414478,3,LONG,203,2,5,38 +414480,3,LONG,204,5,-10,127 +414482,3,LONG,205,6,3,60 +414484,3,LONG,206,4,0,17 +414486,3,LONG,207,6,1,46 +414488,3,LONG,208,0,6,48 +414490,3,LONG,209,2,-6,44 +414492,3,LONG,210,9,-1,84 +414494,3,LONG,211,-3,3,29 +414496,3,LONG,212,-1,6,51 +414498,3,LONG,213,-2,0,8 +414500,3,LONG,214,11,0,134 +414502,3,LONG,215,-10,-4,121 +414504,3,LONG,216,1,-2,6 +414506,3,LONG,217,0,2,7 +414508,3,LONG,218,0,6,44 +414510,3,LONG,219,-6,0,45 +414512,3,LONG,220,0,-8,77 +414514,3,LONG,221,3,-2,17 +414516,3,LONG,222,-2,1,9 +414518,3,LONG,223,-6,3,57 +414520,3,LONG,224,10,0,115 +414522,3,LONG,225,-3,6,49 +414524,3,LONG,226,-1,-3,11 +414526,3,LONG,227,4,0,21 +414528,3,LONG,228,-8,2,75 +414530,3,LONG,229,0,6,37 +414532,3,LONG,230,5,-10,134 +414534,3,LONG,231,-10,1,107 +414536,3,LONG,232,-6,2,49 +414538,3,LONG,233,0,0,0 +414540,3,LONG,234,0,6,46 +414542,3,LONG,235,3,0,11 +414544,3,LONG,236,7,7,104 +414546,3,LONG,237,3,2,17 +414548,3,LONG,238,0,-1,2 +414550,3,LONG,239,2,1,7 +414552,3,LONG,240,-2,-7,67 +414554,3,LONG,241,-30,33,2049 +414556,3,LONG,242,-43,36,3191 +414558,3,LONG,243,-37,20,1862 +414560,3,LONG,244,-55,33,4120 +414562,3,LONG,245,-52,19,3105 +414564,3,LONG,246,-49,21,2910 +414566,3,LONG,247,-46,1,2199 +414568,3,LONG,248,-44,-4,1976 +414570,3,LONG,249,-54,-11,3099 +414572,3,LONG,250,-52,-11,2889 +414574,3,LONG,251,-52,-15,3007 +414576,3,LONG,252,-40,-25,2297 +414578,3,LONG,253,-43,-33,3051 +414580,3,LONG,254,-33,-26,1843 +414582,3,LONG,255,-34,-48,3480 +414584,3,LONG,256,-25,-40,2323 +414586,3,LONG,257,-21,-44,2446 +414588,3,LONG,258,-19,-48,2704 +414590,3,LONG,259,-13,-56,3403 +414592,3,LONG,260,-5,1,27 +414594,3,LONG,261,4,-3,38 +414596,3,LONG,262,-4,-2,25 +414598,3,LONG,263,4,4,38 +414600,3,LONG,264,4,0,19 +414602,3,LONG,265,-3,5,40 +414604,3,LONG,266,-1,-7,63 +414606,3,LONG,267,-7,-4,80 +414608,3,LONG,268,1,-11,145 +414610,3,LONG,269,-14,2,211 +414612,3,LONG,270,-1,1,5 +414614,3,LONG,271,-6,2,45 +414616,3,LONG,272,-1,8,68 +414618,3,LONG,273,1,3,17 +414620,3,LONG,274,-5,-1,32 +414622,3,LONG,275,0,2,7 +414624,3,LONG,276,-5,0,28 +414626,3,LONG,277,-1,13,178 +414628,3,LONG,278,0,-2,8 +414630,3,LONG,279,0,10,114 +414632,3,LONG,280,1,7,65 +414634,3,LONG,281,-3,3,24 +414636,3,LONG,282,1,0,2 +414638,3,LONG,283,-8,6,108 +414640,3,LONG,284,-2,2,16 +414642,3,LONG,285,5,-3,42 +414644,3,LONG,286,-1,8,71 +414646,3,LONG,287,1,-5,29 +414648,3,LONG,288,0,8,73 +414650,3,LONG,289,-4,-2,31 +414652,3,LONG,290,-9,2,90 +414654,3,LONG,291,1,1,3 +414656,3,LONG,292,-5,7,98 +414658,3,LONG,293,-1,-3,12 +414660,3,LONG,294,6,-2,46 +414662,3,LONG,295,5,-1,34 +414664,3,LONG,296,-2,-3,18 +414666,3,LONG,297,7,1,60 +414668,3,LONG,298,0,-1,1 +414670,3,LONG,299,1,-8,79 +414672,3,LONG,300,0,0,1 +414674,3,LONG,301,-1,-6,47 +414676,3,LONG,302,-2,0,6 +414678,3,LONG,303,-1,-5,30 +414680,3,LONG,304,0,0,1 +414682,3,LONG,305,1,-3,14 +414684,3,LONG,306,2,2,12 +414686,3,LONG,307,2,2,14 +414688,3,LONG,308,-4,-6,65 +414690,3,LONG,309,-11,-3,135 +414692,3,LONG,310,-7,-2,56 +414694,3,LONG,311,3,7,70 +414696,3,LONG,312,-7,0,57 +414698,3,LONG,313,5,1,33 +414700,3,LONG,314,-2,8,79 +414702,3,LONG,315,3,1,13 +414704,3,LONG,316,-8,-2,75 +414706,3,LONG,317,-1,2,11 +414708,3,LONG,318,0,-6,39 +414710,3,LONG,319,-8,5,107 +414712,3,LONG,320,1,0,2 +414714,3,LONG,321,0,1,1 +414716,3,LONG,322,0,-8,67 +414718,3,LONG,323,1,0,1 +414720,3,LONG,324,-9,6,131 +414722,3,LONG,325,0,-4,19 +414724,3,LONG,326,-7,3,60 +414726,3,LONG,327,7,6,101 +414728,3,LONG,328,0,-3,12 +414730,3,LONG,329,-2,4,23 +414732,3,LONG,330,-2,-1,7 +414734,3,LONG,331,0,5,26 +414736,3,LONG,332,0,-2,7 +414738,3,LONG,333,-2,-3,13 +414740,3,LONG,334,11,-4,157 +414742,3,LONG,335,0,0,0 +414744,3,LONG,336,-11,0,143 +414746,3,LONG,337,8,1,71 +414748,3,LONG,338,-6,6,77 +414750,3,LONG,339,-1,1,6 +414752,3,LONG,340,3,-3,28 +414754,3,LONG,341,-5,-1,33 +414756,3,LONG,342,-2,3,14 +414758,3,LONG,343,-2,-5,41 +414760,3,LONG,344,3,-5,41 +414762,3,LONG,345,-5,7,81 +414764,3,LONG,346,-5,-4,45 +414766,3,LONG,347,-3,8,85 +414768,3,LONG,348,2,-7,63 +414770,3,LONG,349,2,-5,40 +414772,3,LONG,350,1,0,3 +414774,3,LONG,351,10,6,154 +414776,3,LONG,352,-8,-2,76 +414778,3,LONG,353,-5,9,114 +414780,3,LONG,354,4,3,28 +414782,3,LONG,355,-1,1,3 +414784,3,LONG,356,-1,-1,4 +414786,3,LONG,357,0,-3,13 +414788,3,LONG,358,-5,-7,88 +414790,3,LONG,359,2,-6,56 +414792,3,LONG,360,0,9,99 +414794,3,LONG,361,9,1,83 +414796,3,LONG,362,0,2,7 +414798,3,LONG,363,-1,0,3 +414800,3,LONG,364,-1,6,41 +414802,3,LONG,365,0,6,38 +414804,3,LONG,366,-6,8,102 +414806,3,LONG,367,-2,-4,28 +414808,3,LONG,368,5,11,165 +414810,3,LONG,369,-7,-3,63 +414812,3,LONG,370,-8,4,96 +414814,3,LONG,371,1,0,1 +414816,3,LONG,372,0,-9,81 +414818,3,LONG,373,1,-2,8 +414820,3,LONG,374,0,-1,4 +414822,3,LONG,375,-1,0,4 +414824,3,LONG,376,0,3,11 +414826,3,LONG,377,9,10,188 +414828,3,LONG,378,4,-1,25 +414830,3,LONG,379,3,3,26 +414832,3,LONG,380,-2,3,21 +414834,3,LONG,381,-3,6,58 +414836,3,LONG,382,0,3,11 +414838,3,LONG,383,-1,-4,21 +414840,3,LONG,384,1,0,1 +414842,3,LONG,385,1,-8,75 +414844,3,LONG,386,-3,2,22 +414846,3,LONG,387,3,1,12 +414848,3,LONG,388,3,-9,106 +414850,3,LONG,389,0,2,4 +414852,3,LONG,390,-4,-4,33 +414854,3,LONG,391,28,-10,944 +414856,3,LONG,392,30,-19,1287 +414858,3,LONG,393,21,-5,471 +414860,3,LONG,394,22,5,523 +414862,3,LONG,395,23,12,703 +414864,3,LONG,396,12,16,424 +414866,3,LONG,397,24,11,746 +414868,3,LONG,398,16,17,600 +414870,3,LONG,399,14,23,755 +414872,3,LONG,400,16,22,786 +414874,3,LONG,401,12,21,620 +414876,3,LONG,402,13,17,489 +414878,3,LONG,403,7,21,502 +414880,3,LONG,404,6,19,417 +414882,3,LONG,405,7,32,1124 +414884,3,LONG,406,-13,31,1139 +414886,3,LONG,407,-4,22,525 +414888,3,LONG,408,-9,30,1039 +414890,3,LONG,409,-18,15,567 +414892,3,LONG,410,-1,12,156 +414894,3,LONG,411,-4,1,19 +414896,3,LONG,412,5,5,62 +414898,3,LONG,413,9,-3,107 +414900,3,LONG,414,0,-4,22 +414902,3,LONG,415,4,5,51 +414904,3,LONG,416,-5,-6,69 +414906,3,LONG,417,2,3,16 +414908,3,LONG,418,2,2,14 +414910,3,LONG,419,3,-7,64 +414912,3,LONG,420,0,6,37 +414914,3,LONG,421,9,-6,132 +414916,3,LONG,422,1,-2,11 +414918,3,LONG,423,-2,0,7 +414920,3,LONG,424,-7,-1,62 +414922,3,LONG,425,-4,-5,45 +414924,3,LONG,426,0,-4,21 +414926,3,LONG,427,-3,9,106 +414928,3,LONG,428,-3,-2,19 +414930,3,LONG,429,3,1,14 +414932,3,LONG,430,-5,4,47 +414934,3,LONG,431,4,3,27 +414936,3,LONG,432,-6,1,51 +414938,3,LONG,433,-6,-5,70 +414940,3,LONG,434,3,-10,125 +414942,3,LONG,435,-4,-1,25 +414944,3,LONG,436,-2,2,10 +414946,3,LONG,437,-5,1,31 +414948,3,LONG,438,4,7,67 +414950,3,LONG,439,0,-12,165 +414952,3,LONG,440,-1,-2,6 +414954,3,LONG,441,-1,-1,4 +414956,3,LONG,442,-7,0,54 +414958,3,LONG,443,0,-8,74 +414960,3,LONG,444,-4,5,55 +414962,3,LONG,445,-4,1,24 +414964,3,LONG,446,5,-7,80 +414966,3,LONG,447,-1,-6,46 +414968,3,LONG,448,-13,-2,178 +414970,3,LONG,449,-5,-3,40 +414972,3,LONG,450,-3,-7,68 +414974,3,LONG,451,5,-1,28 +414976,3,LONG,452,2,4,28 +414978,3,LONG,453,0,6,47 +414980,3,LONG,454,-1,-10,107 +414982,3,LONG,455,3,11,156 +414984,3,LONG,456,-2,-10,112 +414986,3,LONG,457,-2,-2,8 +414988,3,LONG,458,-4,-2,28 +414990,3,LONG,459,-3,4,36 +414992,3,LONG,460,0,1,3 +414994,3,LONG,461,-5,0,33 +414996,3,LONG,462,2,2,12 +414998,3,LONG,463,-2,-3,20 +415000,3,LONG,464,3,8,77 +415002,3,LONG,465,4,8,86 +415004,3,LONG,466,18,5,352 +415006,3,LONG,467,8,8,152 +415008,3,LONG,468,-3,-3,25 +415010,3,LONG,469,-4,13,198 +415012,3,LONG,470,-2,3,19 +415014,3,LONG,471,1,-8,80 +415016,3,LONG,472,0,-7,53 +415018,3,LONG,473,-2,0,5 +415020,3,LONG,474,-3,-6,52 +415022,3,LONG,475,7,0,60 +415024,3,LONG,476,0,1,1 +415026,3,LONG,477,-1,2,10 +415028,3,LONG,478,0,3,11 +415030,3,LONG,479,2,-5,35 +415032,3,LONG,480,0,-1,1 +415034,3,LONG,481,-11,4,146 +415036,3,LONG,482,8,-2,74 +415038,3,LONG,483,-3,-2,18 +415040,3,LONG,484,-5,1,29 +415042,3,LONG,485,-5,0,26 +415044,3,LONG,486,-3,1,15 +415046,3,LONG,487,0,16,262 +415048,3,LONG,488,-2,0,8 +415050,3,LONG,489,2,0,4 +415052,3,LONG,490,4,7,69 +415054,3,LONG,491,4,-10,130 +415056,3,LONG,492,-1,0,3 +415058,3,LONG,493,6,-4,68 +415060,3,LONG,494,5,4,50 +415062,3,LONG,495,1,10,116 +415064,3,LONG,496,4,0,20 +415066,3,LONG,497,5,-2,35 +415068,3,LONG,498,-6,-3,57 +415070,3,LONG,499,-5,3,45 +415072,3,LONG,500,0,4,18 +415074,3,LONG,501,0,-1,1 +415076,3,LONG,502,0,-4,24 +415078,3,LONG,503,0,4,20 +415080,3,LONG,504,-3,3,20 +415082,3,LONG,505,2,-7,60 +415084,3,LONG,506,2,2,13 +415086,3,LONG,507,-6,6,79 +415088,3,LONG,508,-1,1,4 +415090,3,LONG,509,0,-1,2 +415092,3,LONG,510,-3,4,28 +415094,3,LONG,511,-11,1,141 +552096,4,LONG,0,-6,0,40 +552098,4,LONG,1,-3,3,22 +552100,4,LONG,2,3,-8,83 +552102,4,LONG,3,-31,1,976 +552104,4,LONG,4,2,-9,86 +552106,4,LONG,5,-21,1,460 +552108,4,LONG,6,-17,2,304 +552110,4,LONG,7,-12,10,277 +552112,4,LONG,8,-12,9,243 +552114,4,LONG,9,-4,-10,136 +552116,4,LONG,10,3,3,20 +552118,4,LONG,11,-5,-9,118 +552120,4,LONG,12,2,0,9 +552122,4,LONG,13,5,-10,125 +552124,4,LONG,14,5,19,417 +552126,4,LONG,15,-5,-24,626 +552128,4,LONG,16,-16,0,281 +552130,4,LONG,17,7,-11,197 +552132,4,LONG,18,1,-7,65 +552134,4,LONG,19,3,15,252 +552136,4,LONG,20,-3,4,31 +552138,4,LONG,21,3,-4,32 +552140,4,LONG,22,-1,-1,6 +552142,4,LONG,23,-11,-4,158 +552144,4,LONG,24,0,-14,224 +552146,4,LONG,25,3,4,34 +552148,4,LONG,26,-4,1,24 +552150,4,LONG,27,7,-1,52 +552152,4,LONG,28,-6,-2,46 +552154,4,LONG,29,-1,-10,121 +552156,4,LONG,30,-8,5,96 +552158,4,LONG,31,19,7,432 +552160,4,LONG,32,-1,5,29 +552162,4,LONG,33,-11,-9,228 +552164,4,LONG,34,2,-5,33 +552166,4,LONG,35,-27,14,962 +552168,4,LONG,36,8,28,868 +552170,4,LONG,37,5,6,75 +552172,4,LONG,38,-9,-9,172 +552174,4,LONG,39,-6,25,669 +552176,4,LONG,40,8,4,90 +552178,4,LONG,41,12,0,157 +552180,4,LONG,42,0,16,278 +552182,4,LONG,43,7,-3,66 +552184,4,LONG,44,3,-3,22 +552186,4,LONG,45,-13,7,239 +552188,4,LONG,46,-7,-13,233 +552190,4,LONG,47,4,-1,18 +552192,4,LONG,48,1,-9,91 +552194,4,LONG,49,-16,5,298 +552196,4,LONG,50,7,7,127 +552198,4,LONG,51,-16,9,345 +552200,4,LONG,52,-13,-19,562 +552202,4,LONG,53,6,3,50 +552204,4,LONG,54,7,6,91 +552206,4,LONG,55,0,-13,190 +552208,4,LONG,56,-2,2,14 +552210,4,LONG,57,17,4,325 +552212,4,LONG,58,-16,0,279 +552214,4,LONG,59,7,8,129 +552216,4,LONG,60,5,9,119 +552218,4,LONG,61,5,4,50 +552220,4,LONG,62,-24,-6,633 +552222,4,LONG,63,-9,1,101 +552224,4,LONG,64,-7,20,465 +552226,4,LONG,65,11,8,220 +552228,4,LONG,66,-4,-9,113 +552230,4,LONG,67,8,-10,167 +552232,4,LONG,68,13,1,185 +552234,4,LONG,69,-9,30,1018 +552236,4,LONG,70,16,-10,360 +552238,4,LONG,71,17,0,297 +552240,4,LONG,72,-4,-2,28 +552242,4,LONG,73,0,1,1 +552244,4,LONG,74,8,-16,356 +552246,4,LONG,75,0,9,94 +552248,4,LONG,76,2,5,40 +552250,4,LONG,77,3,13,186 +552252,4,LONG,78,-12,-8,236 +552254,4,LONG,79,3,10,134 +552256,4,LONG,80,-8,14,276 +552258,4,LONG,81,-3,-2,15 +552260,4,LONG,82,11,-15,387 +552262,4,LONG,83,3,-3,23 +552264,4,LONG,84,-15,-6,288 +552266,4,LONG,85,2,-6,44 +552268,4,LONG,86,1,-7,58 +552270,4,LONG,87,-9,-1,85 +552272,4,LONG,88,-11,-28,943 +552274,4,LONG,89,-15,-2,256 +552276,4,LONG,90,16,15,527 +552278,4,LONG,91,-3,20,443 +552280,4,LONG,92,7,3,68 +552282,4,LONG,93,4,-1,22 +552284,4,LONG,94,10,-12,274 +552286,4,LONG,95,6,-10,143 +552288,4,LONG,96,16,14,484 +552290,4,LONG,97,29,-14,1056 +552292,4,LONG,98,-2,6,48 +552294,4,LONG,99,3,-3,23 +552296,4,LONG,100,-6,-2,46 +552298,4,LONG,101,-4,0,18 +552300,4,LONG,102,1,-2,8 +552302,4,LONG,103,-1,-1,4 +552304,4,LONG,104,3,-5,46 +552306,4,LONG,105,1,-1,4 +552308,4,LONG,106,0,0,0 +552310,4,LONG,107,3,1,11 +552312,4,LONG,108,3,-1,12 +552314,4,LONG,109,-7,-3,76 +552316,4,LONG,110,2,-2,14 +552318,4,LONG,111,0,-1,1 +552320,4,LONG,112,3,5,45 +552322,4,LONG,113,5,1,28 +552324,4,LONG,114,-5,7,79 +552326,4,LONG,115,3,-7,72 +552328,4,LONG,116,-3,3,24 +552330,4,LONG,117,-1,6,39 +552332,4,LONG,118,-3,-5,40 +552334,4,LONG,119,7,-2,57 +552336,4,LONG,120,1,5,37 +552338,4,LONG,121,0,-10,106 +552340,4,LONG,122,2,-2,10 +552342,4,LONG,123,5,-4,47 +552344,4,LONG,124,4,-2,30 +552346,4,LONG,125,6,-3,53 +552348,4,LONG,126,4,-3,32 +552350,4,LONG,127,6,-2,53 +552352,4,LONG,128,-1,3,13 +552354,4,LONG,129,5,3,35 +552356,4,LONG,130,0,0,0 +552358,4,LONG,131,-2,7,63 +552360,4,LONG,132,0,-4,21 +552362,4,LONG,133,-6,-4,52 +552364,4,LONG,134,2,2,11 +552366,4,LONG,135,4,-4,37 +552368,4,LONG,136,-6,5,64 +552370,4,LONG,137,-8,0,76 +552372,4,LONG,138,0,3,10 +552374,4,LONG,139,-6,-5,80 +552376,4,LONG,140,-4,7,67 +552378,4,LONG,141,38,-91,9914 +552380,4,LONG,142,56,-74,8805 +552382,4,LONG,143,53,-78,8937 +552384,4,LONG,144,66,-74,9915 +552386,4,LONG,145,82,-51,9503 +552388,4,LONG,146,88,-53,10687 +552390,4,LONG,147,91,-40,10026 +552392,4,LONG,148,102,-23,11028 +552394,4,LONG,149,94,-10,9079 +552396,4,LONG,150,101,0,10358 +552398,4,LONG,151,95,3,9154 +552400,4,LONG,152,99,32,11001 +552402,4,LONG,153,89,33,9192 +552404,4,LONG,154,90,48,10550 +552406,4,LONG,155,83,58,10424 +552408,4,LONG,156,67,67,9058 +552410,4,LONG,157,63,69,8832 +552412,4,LONG,158,50,82,9347 +552414,4,LONG,159,42,96,11054 +552416,4,LONG,160,-5,6,73 +552418,4,LONG,161,0,0,0 +552420,4,LONG,162,-1,-11,145 +552422,4,LONG,163,5,-5,66 +552424,4,LONG,164,-5,-1,38 +552426,4,LONG,165,2,-7,67 +552428,4,LONG,166,12,4,187 +552430,4,LONG,167,0,5,33 +552432,4,LONG,168,3,-2,15 +552434,4,LONG,169,12,1,163 +552436,4,LONG,170,11,6,167 +552438,4,LONG,171,-7,-4,68 +552440,4,LONG,172,3,0,15 +552442,4,LONG,173,4,3,35 +552444,4,LONG,174,0,-6,39 +552446,4,LONG,175,0,-3,10 +552448,4,LONG,176,0,-3,12 +552450,4,LONG,177,2,2,8 +552452,4,LONG,178,0,2,5 +552454,4,LONG,179,3,0,15 +552456,4,LONG,180,0,-5,35 +552458,4,LONG,181,-7,-2,66 +552460,4,LONG,182,6,-2,43 +552462,4,LONG,183,4,0,16 +552464,4,LONG,184,1,0,4 +552466,4,LONG,185,-3,1,18 +552468,4,LONG,186,-1,-7,62 +552470,4,LONG,187,-10,1,105 +552472,4,LONG,188,6,-7,101 +552474,4,LONG,189,-4,-2,24 +552476,4,LONG,190,-3,0,15 +552478,4,LONG,191,-2,-9,98 +552480,4,LONG,192,2,-9,95 +552482,4,LONG,193,6,-10,139 +552484,4,LONG,194,-12,2,169 +552486,4,LONG,195,-1,8,74 +552488,4,LONG,196,0,2,9 +552490,4,LONG,197,0,-5,27 +552492,4,LONG,198,0,-3,13 +552494,4,LONG,199,1,6,42 +552496,4,LONG,200,0,1,2 +552498,4,LONG,201,3,-10,120 +552500,4,LONG,202,-1,5,35 +552502,4,LONG,203,8,4,97 +552504,4,LONG,204,5,1,35 +552506,4,LONG,205,4,-1,20 +552508,4,LONG,206,-1,0,3 +552510,4,LONG,207,1,-1,4 +552512,4,LONG,208,6,-1,46 +552514,4,LONG,209,-4,-2,22 +552516,4,LONG,210,8,-2,70 +552518,4,LONG,211,2,-4,25 +552520,4,LONG,212,-2,1,8 +552522,4,LONG,213,-5,-7,78 +552524,4,LONG,214,5,-6,67 +552526,4,LONG,215,3,0,10 +552528,4,LONG,216,2,3,18 +552530,4,LONG,217,-1,1,4 +552532,4,LONG,218,6,0,42 +552534,4,LONG,219,-6,0,41 +552536,4,LONG,220,0,0,0 +552538,4,LONG,221,-7,0,61 +552540,4,LONG,222,3,8,83 +552542,4,LONG,223,8,1,70 +552544,4,LONG,224,0,3,9 +552546,4,LONG,225,-7,-8,119 +552548,4,LONG,226,0,6,47 +552550,4,LONG,227,4,-4,45 +552552,4,LONG,228,-1,2,9 +552554,4,LONG,229,-7,-1,60 +552556,4,LONG,230,-1,4,25 +552558,4,LONG,231,0,-7,53 +552560,4,LONG,232,0,-7,60 +552562,4,LONG,233,0,7,59 +552564,4,LONG,234,-2,-1,6 +552566,4,LONG,235,7,-2,54 +552568,4,LONG,236,-3,14,228 +552570,4,LONG,237,6,-3,48 +552572,4,LONG,238,-7,-2,64 +552574,4,LONG,239,-2,-5,36 +552576,4,LONG,240,0,-2,6 +552578,4,LONG,241,8,49,2493 +552580,4,LONG,242,-2,47,2262 +552582,4,LONG,243,1,60,3639 +552584,4,LONG,244,-4,43,1931 +552586,4,LONG,245,-17,51,2997 +552588,4,LONG,246,-21,46,2633 +552590,4,LONG,247,-17,40,1920 +552592,4,LONG,248,-27,37,2180 +552594,4,LONG,249,-39,31,2538 +552596,4,LONG,250,-41,18,2047 +552598,4,LONG,251,-39,27,2323 +552600,4,LONG,252,-56,14,3347 +552602,4,LONG,253,-46,22,2659 +552604,4,LONG,254,-55,6,3099 +552606,4,LONG,255,-57,-5,3302 +552608,4,LONG,256,-50,-12,2664 +552610,4,LONG,257,-53,-25,3514 +552612,4,LONG,258,-47,-21,2700 +552614,4,LONG,259,-42,-29,2695 +552616,4,LONG,260,-9,-1,92 +552618,4,LONG,261,-13,1,177 +552620,4,LONG,262,0,-1,1 +552622,4,LONG,263,3,0,14 +552624,4,LONG,264,6,-1,39 +552626,4,LONG,265,-7,-3,67 +552628,4,LONG,266,-3,-2,14 +552630,4,LONG,267,0,3,13 +552632,4,LONG,268,-2,2,10 +552634,4,LONG,269,0,0,0 +552636,4,LONG,270,6,2,50 +552638,4,LONG,271,-3,2,14 +552640,4,LONG,272,3,4,34 +552642,4,LONG,273,2,-6,51 +552644,4,LONG,274,-1,-2,6 +552646,4,LONG,275,-6,0,40 +552648,4,LONG,276,0,0,0 +552650,4,LONG,277,-3,-6,48 +552652,4,LONG,278,-3,6,51 +552654,4,LONG,279,-11,-5,147 +552656,4,LONG,280,9,3,113 +552658,4,LONG,281,-5,3,48 +552660,4,LONG,282,1,2,9 +552662,4,LONG,283,3,2,19 +552664,4,LONG,284,-9,10,196 +552666,4,LONG,285,-2,4,29 +552668,4,LONG,286,-6,9,132 +552670,4,LONG,287,-2,3,16 +552672,4,LONG,288,0,-9,89 +552674,4,LONG,289,7,1,55 +552676,4,LONG,290,-1,-2,6 +552678,4,LONG,291,-4,-2,22 +552680,4,LONG,292,8,0,69 +552682,4,LONG,293,5,10,137 +552684,4,LONG,294,3,-2,18 +552686,4,LONG,295,0,12,166 +552688,4,LONG,296,0,0,0 +552690,4,LONG,297,3,0,11 +552692,4,LONG,298,-6,4,65 +552694,4,LONG,299,0,-2,7 +552696,4,LONG,300,-1,2,8 +552698,4,LONG,301,2,-5,37 +552700,4,LONG,302,0,0,0 +552702,4,LONG,303,10,0,115 +552704,4,LONG,304,-6,-1,42 +552706,4,LONG,305,-1,4,21 +552708,4,LONG,306,5,-2,30 +552710,4,LONG,307,-8,3,75 +552712,4,LONG,308,-4,4,42 +552714,4,LONG,309,0,-7,62 +552716,4,LONG,310,0,2,4 +552718,4,LONG,311,5,-1,34 +552720,4,LONG,312,1,12,153 +552722,4,LONG,313,0,3,11 +552724,4,LONG,314,-4,0,20 +552726,4,LONG,315,-1,1,4 +552728,4,LONG,316,2,1,6 +552730,4,LONG,317,-11,1,135 +552732,4,LONG,318,2,-6,48 +552734,4,LONG,319,5,-7,84 +552736,4,LONG,320,-5,-10,136 +552738,4,LONG,321,8,0,70 +552740,4,LONG,322,-2,2,11 +552742,4,LONG,323,-4,3,31 +552744,4,LONG,324,1,-1,5 +552746,4,LONG,325,9,-1,94 +552748,4,LONG,326,7,0,61 +552750,4,LONG,327,0,0,0 +552752,4,LONG,328,-1,1,3 +552754,4,LONG,329,-5,3,37 +552756,4,LONG,330,2,-6,42 +552758,4,LONG,331,2,3,16 +552760,4,LONG,332,-8,0,81 +552762,4,LONG,333,4,0,23 +552764,4,LONG,334,-3,-2,17 +552766,4,LONG,335,3,3,27 +552768,4,LONG,336,-7,-8,133 +552770,4,LONG,337,7,3,73 +552772,4,LONG,338,-3,2,20 +552774,4,LONG,339,3,10,119 +552776,4,LONG,340,0,-5,29 +552778,4,LONG,341,8,-7,114 +552780,4,LONG,342,5,-5,59 +552782,4,LONG,343,0,0,0 +552784,4,LONG,344,7,-1,61 +552786,4,LONG,345,-1,-1,3 +552788,4,LONG,346,-3,9,111 +552790,4,LONG,347,4,4,34 +552792,4,LONG,348,-5,5,60 +552794,4,LONG,349,2,-1,6 +552796,4,LONG,350,-4,-7,81 +552798,4,LONG,351,0,-10,112 +552800,4,LONG,352,-1,-8,72 +552802,4,LONG,353,6,-2,49 +552804,4,LONG,354,1,9,84 +552806,4,LONG,355,5,0,28 +552808,4,LONG,356,-4,3,32 +552810,4,LONG,357,-3,-3,25 +552812,4,LONG,358,-2,-5,36 +552814,4,LONG,359,0,-2,8 +552816,4,LONG,360,2,-3,17 +552818,4,LONG,361,2,2,11 +552820,4,LONG,362,2,-3,17 +552822,4,LONG,363,0,-1,1 +552824,4,LONG,364,3,-11,134 +552826,4,LONG,365,2,13,200 +552828,4,LONG,366,8,-3,85 +552830,4,LONG,367,1,3,12 +552832,4,LONG,368,11,-1,137 +552834,4,LONG,369,3,-9,103 +552836,4,LONG,370,3,0,15 +552838,4,LONG,371,1,-6,40 +552840,4,LONG,372,2,3,21 +552842,4,LONG,373,3,10,128 +552844,4,LONG,374,-8,3,81 +552846,4,LONG,375,-5,1,26 +552848,4,LONG,376,4,5,56 +552850,4,LONG,377,-3,-5,40 +552852,4,LONG,378,0,0,0 +552854,4,LONG,379,6,0,38 +552856,4,LONG,380,2,0,6 +552858,4,LONG,381,7,-3,69 +552860,4,LONG,382,7,5,89 +552862,4,LONG,383,5,3,45 +552864,4,LONG,384,-1,14,208 +552866,4,LONG,385,0,-5,34 +552868,4,LONG,386,1,-6,50 +552870,4,LONG,387,-2,0,7 +552872,4,LONG,388,3,0,10 +552874,4,LONG,389,4,5,46 +552876,4,LONG,390,-1,5,34 +552878,4,LONG,391,30,9,1046 +552880,4,LONG,392,23,-6,574 +552882,4,LONG,393,26,6,714 +552884,4,LONG,394,21,14,679 +552886,4,LONG,395,19,13,569 +552888,4,LONG,396,23,13,733 +552890,4,LONG,397,16,15,517 +552892,4,LONG,398,8,17,386 +552894,4,LONG,399,7,24,634 +552896,4,LONG,400,5,27,813 +552898,4,LONG,401,14,25,860 +552900,4,LONG,402,6,26,752 +552902,4,LONG,403,3,22,514 +552904,4,LONG,404,-2,22,537 +552906,4,LONG,405,-6,22,546 +552908,4,LONG,406,-7,27,824 +552910,4,LONG,407,-14,26,930 +552912,4,LONG,408,-22,13,686 +552914,4,LONG,409,-10,10,222 +552916,4,LONG,410,-6,3,52 +552918,4,LONG,411,-9,0,93 +552920,4,LONG,412,-3,-7,77 +552922,4,LONG,413,2,6,52 +552924,4,LONG,414,-1,0,2 +552926,4,LONG,415,-2,-3,18 +552928,4,LONG,416,2,1,7 +552930,4,LONG,417,6,0,47 +552932,4,LONG,418,-2,6,44 +552934,4,LONG,419,-4,-5,54 +552936,4,LONG,420,0,5,26 +552938,4,LONG,421,2,9,91 +552940,4,LONG,422,-9,-8,153 +552942,4,LONG,423,4,-4,42 +552944,4,LONG,424,-4,4,46 +552946,4,LONG,425,3,0,12 +552948,4,LONG,426,2,0,7 +552950,4,LONG,427,-14,0,221 +552952,4,LONG,428,6,-1,43 +552954,4,LONG,429,10,5,135 +552956,4,LONG,430,0,1,4 +552958,4,LONG,431,-5,3,40 +552960,4,LONG,432,-3,-9,96 +552962,4,LONG,433,-2,-1,11 +552964,4,LONG,434,-4,0,20 +552966,4,LONG,435,2,-5,34 +552968,4,LONG,436,-2,1,6 +552970,4,LONG,437,-1,-1,5 +552972,4,LONG,438,3,2,16 +552974,4,LONG,439,5,0,34 +552976,4,LONG,440,7,4,71 +552978,4,LONG,441,4,6,67 +552980,4,LONG,442,-2,-2,11 +552982,4,LONG,443,5,-1,27 +552984,4,LONG,444,2,1,9 +552986,4,LONG,445,8,-3,79 +552988,4,LONG,446,6,0,47 +552990,4,LONG,447,0,-3,10 +552992,4,LONG,448,-6,5,68 +552994,4,LONG,449,-6,5,66 +552996,4,LONG,450,3,-2,17 +552998,4,LONG,451,0,0,0 +553000,4,LONG,452,-5,6,77 +553002,4,LONG,453,0,-9,94 +553004,4,LONG,454,0,-2,8 +553006,4,LONG,455,-5,0,34 +553008,4,LONG,456,6,8,104 +553010,4,LONG,457,-4,-2,23 +553012,4,LONG,458,0,0,0 +553014,4,LONG,459,-2,9,86 +553016,4,LONG,460,2,-3,19 +553018,4,LONG,461,-1,-1,4 +553020,4,LONG,462,4,16,308 +553022,4,LONG,463,1,2,6 +553024,4,LONG,464,-8,8,139 +553026,4,LONG,465,0,-1,3 +553028,4,LONG,466,0,3,12 +553030,4,LONG,467,7,6,103 +553032,4,LONG,468,-2,-5,37 +553034,4,LONG,469,-9,5,130 +553036,4,LONG,470,11,3,139 +553038,4,LONG,471,3,7,62 +553040,4,LONG,472,2,4,26 +553042,4,LONG,473,0,8,72 +553044,4,LONG,474,0,4,17 +553046,4,LONG,475,2,0,6 +553048,4,LONG,476,-8,4,85 +553050,4,LONG,477,1,-7,59 +553052,4,LONG,478,-7,0,57 +553054,4,LONG,479,7,0,50 +553056,4,LONG,480,-6,-4,56 +553058,4,LONG,481,-1,-4,21 +553060,4,LONG,482,-2,-4,26 +553062,4,LONG,483,1,2,12 +553064,4,LONG,484,-1,3,13 +553066,4,LONG,485,0,11,137 +553068,4,LONG,486,1,-2,8 +553070,4,LONG,487,10,8,179 +553072,4,LONG,488,-3,-5,39 +553074,4,LONG,489,1,-1,6 +553076,4,LONG,490,-4,-6,63 +553078,4,LONG,491,9,-2,89 +553080,4,LONG,492,-1,2,9 +553082,4,LONG,493,-3,-2,17 +553084,4,LONG,494,4,-3,27 +553086,4,LONG,495,0,12,151 +553088,4,LONG,496,4,-6,65 +553090,4,LONG,497,6,5,77 +553092,4,LONG,498,0,-5,33 +553094,4,LONG,499,-3,-2,16 +553096,4,LONG,500,1,8,69 +553098,4,LONG,501,1,6,41 +553100,4,LONG,502,-2,6,45 +553102,4,LONG,503,1,0,3 +553104,4,LONG,504,2,-7,65 +553106,4,LONG,505,-7,-4,85 +553108,4,LONG,506,-2,-2,12 +553110,4,LONG,507,-4,-9,112 +553112,4,LONG,508,10,-1,110 +553114,4,LONG,509,0,-3,9 +553116,4,LONG,510,-8,2,75 +553118,4,LONG,511,1,8,78 +690120,5,LONG,0,1,-7,59 +690122,5,LONG,1,29,-12,1026 +690124,5,LONG,2,-1,0,1 +690126,5,LONG,3,0,-4,22 +690128,5,LONG,4,2,3,24 +690130,5,LONG,5,33,2,1143 +690132,5,LONG,6,0,12,157 +690134,5,LONG,7,9,-1,96 +690136,5,LONG,8,-10,5,143 +690138,5,LONG,9,6,-6,82 +690140,5,LONG,10,-1,-6,38 +690142,5,LONG,11,8,5,94 +690144,5,LONG,12,-15,-7,279 +690146,5,LONG,13,10,2,114 +690148,5,LONG,14,7,-6,97 +690150,5,LONG,15,-5,5,64 +690152,5,LONG,16,24,7,649 +690154,5,LONG,17,-3,-3,22 +690156,5,LONG,18,-5,15,276 +690158,5,LONG,19,18,18,695 +690160,5,LONG,20,1,-25,637 +690162,5,LONG,21,0,14,206 +690164,5,LONG,22,6,-16,321 +690166,5,LONG,23,-3,-6,59 +690168,5,LONG,24,-3,9,101 +690170,5,LONG,25,-20,-13,596 +690172,5,LONG,26,7,-16,332 +690174,5,LONG,27,-3,15,248 +690176,5,LONG,28,2,-9,105 +690178,5,LONG,29,-11,-4,163 +690180,5,LONG,30,-16,0,287 +690182,5,LONG,31,-3,15,247 +690184,5,LONG,32,-11,-6,177 +690186,5,LONG,33,1,-3,15 +690188,5,LONG,34,-14,6,251 +690190,5,LONG,35,7,4,80 +690192,5,LONG,36,-3,-1,11 +690194,5,LONG,37,11,-14,339 +690196,5,LONG,38,-9,-3,102 +690198,5,LONG,39,-12,10,270 +690200,5,LONG,40,-6,-2,47 +690202,5,LONG,41,8,23,618 +690204,5,LONG,42,-3,11,140 +690206,5,LONG,43,-4,10,134 +690208,5,LONG,44,1,-6,47 +690210,5,LONG,45,14,0,213 +690212,5,LONG,46,-2,18,363 +690214,5,LONG,47,5,16,302 +690216,5,LONG,48,-13,1,175 +690218,5,LONG,49,-15,10,340 +690220,5,LONG,50,20,7,459 +690222,5,LONG,51,16,9,346 +690224,5,LONG,52,-6,5,74 +690226,5,LONG,53,-6,19,402 +690228,5,LONG,54,-19,0,368 +690230,5,LONG,55,-17,-16,564 +690232,5,LONG,56,2,-18,365 +690234,5,LONG,57,-1,13,194 +690236,5,LONG,58,14,-7,259 +690238,5,LONG,59,3,-13,192 +690240,5,LONG,60,15,-1,255 +690242,5,LONG,61,-16,23,818 +690244,5,LONG,62,4,-15,275 +690246,5,LONG,63,0,-8,80 +690248,5,LONG,64,11,0,142 +690250,5,LONG,65,8,7,123 +690252,5,LONG,66,10,20,503 +690254,5,LONG,67,-9,26,778 +690256,5,LONG,68,-8,21,547 +690258,5,LONG,69,-7,-1,64 +690260,5,LONG,70,-4,11,143 +690262,5,LONG,71,-20,-21,875 +690264,5,LONG,72,-6,-2,53 +690266,5,LONG,73,-6,2,52 +690268,5,LONG,74,16,0,277 +690270,5,LONG,75,-11,-4,153 +690272,5,LONG,76,-2,-6,52 +690274,5,LONG,77,3,-21,475 +690276,5,LONG,78,-19,-9,482 +690278,5,LONG,79,-16,-11,429 +690280,5,LONG,80,7,7,113 +690282,5,LONG,81,-11,16,383 +690284,5,LONG,82,-4,6,68 +690286,5,LONG,83,0,2,6 +690288,5,LONG,84,13,-10,313 +690290,5,LONG,85,-5,1,38 +690292,5,LONG,86,12,-32,1230 +690294,5,LONG,87,13,0,169 +690296,5,LONG,88,-5,23,582 +690298,5,LONG,89,-18,1,330 +690300,5,LONG,90,4,20,465 +690302,5,LONG,91,-14,2,211 +690304,5,LONG,92,4,-10,133 +690306,5,LONG,93,7,-12,220 +690308,5,LONG,94,9,0,85 +690310,5,LONG,95,12,-5,190 +690312,5,LONG,96,7,1,63 +690314,5,LONG,97,0,9,94 +690316,5,LONG,98,-9,-7,155 +690318,5,LONG,99,3,0,10 +690320,5,LONG,100,-1,0,3 +690322,5,LONG,101,3,-9,106 +690324,5,LONG,102,1,-3,13 +690326,5,LONG,103,-1,-2,8 +690328,5,LONG,104,-4,0,21 +690330,5,LONG,105,0,0,1 +690332,5,LONG,106,1,2,9 +690334,5,LONG,107,4,-3,33 +690336,5,LONG,108,-6,-1,50 +690338,5,LONG,109,6,0,40 +690340,5,LONG,110,-7,-3,72 +690342,5,LONG,111,-3,3,24 +690344,5,LONG,112,-3,0,15 +690346,5,LONG,113,-2,-2,12 +690348,5,LONG,114,-7,-2,65 +690350,5,LONG,115,-5,-1,27 +690352,5,LONG,116,0,0,0 +690354,5,LONG,117,-7,2,57 +690356,5,LONG,118,0,-4,18 +690358,5,LONG,119,2,8,86 +690360,5,LONG,120,2,6,49 +690362,5,LONG,121,1,2,6 +690364,5,LONG,122,-5,-5,59 +690366,5,LONG,123,0,3,12 +690368,5,LONG,124,-1,7,53 +690370,5,LONG,125,-9,2,96 +690372,5,LONG,126,-6,0,45 +690374,5,LONG,127,-5,11,169 +690376,5,LONG,128,9,0,82 +690378,5,LONG,129,-1,-4,19 +690380,5,LONG,130,-4,2,30 +690382,5,LONG,131,5,-1,37 +690384,5,LONG,132,-2,6,53 +690386,5,LONG,133,-1,1,3 +690388,5,LONG,134,6,-7,97 +690390,5,LONG,135,-3,-13,192 +690392,5,LONG,136,3,-11,143 +690394,5,LONG,137,0,-6,46 +690396,5,LONG,138,0,8,79 +690398,5,LONG,139,0,-4,19 +690400,5,LONG,140,9,3,101 +690402,5,LONG,141,92,43,10567 +690404,5,LONG,142,87,54,10643 +690406,5,LONG,143,69,65,9193 +690408,5,LONG,144,62,75,9626 +690410,5,LONG,145,58,87,11015 +690412,5,LONG,146,46,86,9669 +690414,5,LONG,147,33,86,8491 +690416,5,LONG,148,24,93,9269 +690418,5,LONG,149,3,105,11059 +690420,5,LONG,150,-7,105,11142 +690422,5,LONG,151,-10,104,10942 +690424,5,LONG,152,-17,99,10205 +690426,5,LONG,153,-43,91,10277 +690428,5,LONG,154,-52,87,10399 +690430,5,LONG,155,-60,81,10287 +690432,5,LONG,156,-67,72,9817 +690434,5,LONG,157,-77,68,10649 +690436,5,LONG,158,-86,59,10959 +690438,5,LONG,159,-88,40,9553 +690440,5,LONG,160,-1,5,28 +690442,5,LONG,161,0,1,1 +690444,5,LONG,162,-2,-3,15 +690446,5,LONG,163,3,-3,25 +690448,5,LONG,164,0,0,0 +690450,5,LONG,165,7,-8,139 +690452,5,LONG,166,0,-10,112 +690454,5,LONG,167,3,-8,89 +690456,5,LONG,168,10,1,119 +690458,5,LONG,169,-2,-1,8 +690460,5,LONG,170,-2,2,13 +690462,5,LONG,171,4,3,32 +690464,5,LONG,172,7,3,64 +690466,5,LONG,173,0,-1,3 +690468,5,LONG,174,4,-14,239 +690470,5,LONG,175,8,-2,75 +690472,5,LONG,176,-9,0,88 +690474,5,LONG,177,5,-11,148 +690476,5,LONG,178,0,0,0 +690478,5,LONG,179,-1,-2,10 +690480,5,LONG,180,-5,-6,71 +690482,5,LONG,181,10,-11,223 +690484,5,LONG,182,3,-2,21 +690486,5,LONG,183,3,-2,20 +690488,5,LONG,184,9,3,91 +690490,5,LONG,185,1,-1,6 +690492,5,LONG,186,-7,1,62 +690494,5,LONG,187,0,2,4 +690496,5,LONG,188,1,0,4 +690498,5,LONG,189,-4,-7,82 +690500,5,LONG,190,-6,-2,44 +690502,5,LONG,191,-3,0,12 +690504,5,LONG,192,-3,7,64 +690506,5,LONG,193,-1,0,1 +690508,5,LONG,194,-6,11,189 +690510,5,LONG,195,-11,-7,189 +690512,5,LONG,196,-1,-5,34 +690514,5,LONG,197,7,2,68 +690516,5,LONG,198,0,3,11 +690518,5,LONG,199,1,-2,10 +690520,5,LONG,200,3,-8,85 +690522,5,LONG,201,9,3,94 +690524,5,LONG,202,-3,0,10 +690526,5,LONG,203,0,3,13 +690528,5,LONG,204,-6,4,67 +690530,5,LONG,205,-1,9,102 +690532,5,LONG,206,-7,1,52 +690534,5,LONG,207,-2,-5,38 +690536,5,LONG,208,4,8,95 +690538,5,LONG,209,0,2,5 +690540,5,LONG,210,0,2,5 +690542,5,LONG,211,1,-4,26 +690544,5,LONG,212,-14,-5,248 +690546,5,LONG,213,-5,-2,38 +690548,5,LONG,214,-2,-3,18 +690550,5,LONG,215,1,-5,26 +690552,5,LONG,216,4,2,26 +690554,5,LONG,217,-7,3,68 +690556,5,LONG,218,2,-7,56 +690558,5,LONG,219,1,-2,6 +690560,5,LONG,220,-4,-3,30 +690562,5,LONG,221,1,6,41 +690564,5,LONG,222,3,-5,45 +690566,5,LONG,223,-6,0,38 +690568,5,LONG,224,-4,15,264 +690570,5,LONG,225,3,8,84 +690572,5,LONG,226,-3,4,29 +690574,5,LONG,227,2,0,6 +690576,5,LONG,228,7,-9,150 +690578,5,LONG,229,1,1,5 +690580,5,LONG,230,0,-5,25 +690582,5,LONG,231,-1,-8,78 +690584,5,LONG,232,0,0,0 +690586,5,LONG,233,7,1,52 +690588,5,LONG,234,-3,-1,11 +690590,5,LONG,235,5,-7,85 +690592,5,LONG,236,-9,3,102 +690594,5,LONG,237,-6,1,44 +690596,5,LONG,238,7,-2,57 +690598,5,LONG,239,-6,8,112 +690600,5,LONG,240,2,-1,6 +690602,5,LONG,241,49,21,2965 +690604,5,LONG,242,50,26,3303 +690606,5,LONG,243,43,24,2532 +690608,5,LONG,244,37,37,2859 +690610,5,LONG,245,29,52,3594 +690612,5,LONG,246,27,48,3069 +690614,5,LONG,247,12,47,2390 +690616,5,LONG,248,16,44,2237 +690618,5,LONG,249,7,46,2224 +690620,5,LONG,250,-1,52,2785 +690622,5,LONG,251,-5,52,2788 +690624,5,LONG,252,-13,43,2073 +690626,5,LONG,253,-18,53,3231 +690628,5,LONG,254,-25,38,2169 +690630,5,LONG,255,-30,36,2239 +690632,5,LONG,256,-26,43,2612 +690634,5,LONG,257,-32,39,2660 +690636,5,LONG,258,-41,28,2527 +690638,5,LONG,259,-45,26,2728 +690640,5,LONG,260,-2,-7,57 +690642,5,LONG,261,-4,1,25 +690644,5,LONG,262,0,-2,9 +690646,5,LONG,263,1,-8,79 +690648,5,LONG,264,4,-3,29 +690650,5,LONG,265,-1,-6,45 +690652,5,LONG,266,1,-8,67 +690654,5,LONG,267,-2,0,7 +690656,5,LONG,268,0,-1,2 +690658,5,LONG,269,-4,-1,24 +690660,5,LONG,270,0,-1,1 +690662,5,LONG,271,-11,3,136 +690664,5,LONG,272,7,6,93 +690666,5,LONG,273,0,4,18 +690668,5,LONG,274,-3,7,68 +690670,5,LONG,275,-1,1,4 +690672,5,LONG,276,-2,1,10 +690674,5,LONG,277,0,-3,11 +690676,5,LONG,278,5,-9,125 +690678,5,LONG,279,-5,9,123 +690680,5,LONG,280,-3,-7,72 +690682,5,LONG,281,-6,0,36 +690684,5,LONG,282,-2,7,59 +690686,5,LONG,283,0,-10,115 +690688,5,LONG,284,2,-9,89 +690690,5,LONG,285,0,-10,109 +690692,5,LONG,286,5,6,77 +690694,5,LONG,287,6,10,145 +690696,5,LONG,288,16,0,277 +690698,5,LONG,289,2,-2,9 +690700,5,LONG,290,-5,0,26 +690702,5,LONG,291,-4,-2,24 +690704,5,LONG,292,2,-2,9 +690706,5,LONG,293,1,-1,3 +690708,5,LONG,294,5,-8,95 +690710,5,LONG,295,0,-4,20 +690712,5,LONG,296,-2,0,6 +690714,5,LONG,297,0,0,1 +690716,5,LONG,298,-2,-5,36 +690718,5,LONG,299,9,2,102 +690720,5,LONG,300,-2,-1,10 +690722,5,LONG,301,11,-4,157 +690724,5,LONG,302,-3,10,127 +690726,5,LONG,303,-1,7,58 +690728,5,LONG,304,-1,0,2 +690730,5,LONG,305,3,-1,11 +690732,5,LONG,306,-3,-8,78 +690734,5,LONG,307,-10,-3,126 +690736,5,LONG,308,-5,-10,148 +690738,5,LONG,309,-8,-4,85 +690740,5,LONG,310,1,5,35 +690742,5,LONG,311,1,1,3 +690744,5,LONG,312,-3,2,18 +690746,5,LONG,313,-6,0,41 +690748,5,LONG,314,9,-6,130 +690750,5,LONG,315,0,1,1 +690752,5,LONG,316,3,7,63 +690754,5,LONG,317,-9,-5,122 +690756,5,LONG,318,7,-11,185 +690758,5,LONG,319,13,1,181 +690760,5,LONG,320,5,-8,93 +690762,5,LONG,321,4,1,23 +690764,5,LONG,322,-1,-1,4 +690766,5,LONG,323,-2,0,5 +690768,5,LONG,324,1,-5,31 +690770,5,LONG,325,3,4,26 +690772,5,LONG,326,11,4,151 +690774,5,LONG,327,0,-8,73 +690776,5,LONG,328,1,0,1 +690778,5,LONG,329,3,6,53 +690780,5,LONG,330,-1,0,1 +690782,5,LONG,331,1,-2,7 +690784,5,LONG,332,-2,1,8 +690786,5,LONG,333,2,0,4 +690788,5,LONG,334,8,-2,68 +690790,5,LONG,335,-2,-2,9 +690792,5,LONG,336,0,2,7 +690794,5,LONG,337,2,0,5 +690796,5,LONG,338,-2,-9,92 +690798,5,LONG,339,4,1,20 +690800,5,LONG,340,5,-6,67 +690802,5,LONG,341,0,4,20 +690804,5,LONG,342,4,1,24 +690806,5,LONG,343,-3,2,24 +690808,5,LONG,344,-5,3,40 +690810,5,LONG,345,3,4,31 +690812,5,LONG,346,1,1,4 +690814,5,LONG,347,-7,-3,77 +690816,5,LONG,348,6,0,49 +690818,5,LONG,349,8,0,79 +690820,5,LONG,350,7,0,59 +690822,5,LONG,351,6,0,37 +690824,5,LONG,352,-1,2,7 +690826,5,LONG,353,0,1,1 +690828,5,LONG,354,-5,0,28 +690830,5,LONG,355,0,-3,10 +690832,5,LONG,356,-1,2,9 +690834,5,LONG,357,-7,-1,64 +690836,5,LONG,358,3,8,79 +690838,5,LONG,359,10,6,146 +690840,5,LONG,360,-5,-8,93 +690842,5,LONG,361,-5,1,31 +690844,5,LONG,362,0,5,28 +690846,5,LONG,363,3,-2,15 +690848,5,LONG,364,-4,0,24 +690850,5,LONG,365,2,0,7 +690852,5,LONG,366,4,6,59 +690854,5,LONG,367,-3,-2,18 +690856,5,LONG,368,3,3,30 +690858,5,LONG,369,-3,-1,15 +690860,5,LONG,370,3,2,19 +690862,5,LONG,371,-4,8,87 +690864,5,LONG,372,-2,0,6 +690866,5,LONG,373,3,-6,58 +690868,5,LONG,374,-1,1,4 +690870,5,LONG,375,0,-3,11 +690872,5,LONG,376,2,9,100 +690874,5,LONG,377,-4,3,30 +690876,5,LONG,378,1,5,37 +690878,5,LONG,379,0,0,0 +690880,5,LONG,380,3,0,9 +690882,5,LONG,381,0,0,0 +690884,5,LONG,382,7,2,62 +690886,5,LONG,383,8,-4,88 +690888,5,LONG,384,1,1,2 +690890,5,LONG,385,5,2,32 +690892,5,LONG,386,0,7,57 +690894,5,LONG,387,2,-4,24 +690896,5,LONG,388,7,0,58 +690898,5,LONG,389,0,-4,19 +690900,5,LONG,390,-7,-2,60 +690902,5,LONG,391,18,5,376 +690904,5,LONG,392,17,17,620 +690906,5,LONG,393,17,14,508 +690908,5,LONG,394,14,21,668 +690910,5,LONG,395,10,33,1204 +690912,5,LONG,396,5,15,278 +690914,5,LONG,397,3,25,647 +690916,5,LONG,398,9,27,855 +690918,5,LONG,399,9,25,742 +690920,5,LONG,400,5,19,418 +690922,5,LONG,401,-7,24,640 +690924,5,LONG,402,-2,25,652 +690926,5,LONG,403,-12,23,694 +690928,5,LONG,404,-10,14,302 +690930,5,LONG,405,-17,22,808 +690932,5,LONG,406,-18,19,735 +690934,5,LONG,407,-22,19,912 +690936,5,LONG,408,-18,9,448 +690938,5,LONG,409,-20,10,525 +690940,5,LONG,410,-2,0,8 +690942,5,LONG,411,3,-2,17 +690944,5,LONG,412,-5,1,26 +690946,5,LONG,413,-2,4,27 +690948,5,LONG,414,2,-4,26 +690950,5,LONG,415,-2,0,4 +690952,5,LONG,416,1,-12,155 +690954,5,LONG,417,1,2,9 +690956,5,LONG,418,1,-1,4 +690958,5,LONG,419,0,-1,4 +690960,5,LONG,420,1,-1,3 +690962,5,LONG,421,-2,-4,29 +690964,5,LONG,422,0,3,14 +690966,5,LONG,423,4,0,22 +690968,5,LONG,424,-5,2,33 +690970,5,LONG,425,0,7,54 +690972,5,LONG,426,5,-3,39 +690974,5,LONG,427,1,-1,4 +690976,5,LONG,428,0,3,13 +690978,5,LONG,429,-8,0,78 +690980,5,LONG,430,9,-1,87 +690982,5,LONG,431,-11,-2,144 +690984,5,LONG,432,3,-8,79 +690986,5,LONG,433,-9,0,81 +690988,5,LONG,434,0,-1,4 +690990,5,LONG,435,1,2,9 +690992,5,LONG,436,-3,4,26 +690994,5,LONG,437,-2,-4,24 +690996,5,LONG,438,0,0,1 +690998,5,LONG,439,8,-1,80 +691000,5,LONG,440,-4,-4,39 +691002,5,LONG,441,2,-2,13 +691004,5,LONG,442,6,1,45 +691006,5,LONG,443,11,6,163 +691008,5,LONG,444,-1,-1,4 +691010,5,LONG,445,2,5,41 +691012,5,LONG,446,2,5,31 +691014,5,LONG,447,3,-3,26 +691016,5,LONG,448,-1,0,3 +691018,5,LONG,449,-9,0,85 +691020,5,LONG,450,0,9,92 +691022,5,LONG,451,-4,10,119 +691024,5,LONG,452,-3,6,50 +691026,5,LONG,453,0,6,42 +691028,5,LONG,454,5,-1,35 +691030,5,LONG,455,-5,7,93 +691032,5,LONG,456,-1,-5,29 +691034,5,LONG,457,0,0,0 +691036,5,LONG,458,4,0,22 +691038,5,LONG,459,4,-1,25 +691040,5,LONG,460,-5,2,38 +691042,5,LONG,461,-2,3,16 +691044,5,LONG,462,-3,-6,56 +691046,5,LONG,463,3,5,44 +691048,5,LONG,464,-2,-1,9 +691050,5,LONG,465,6,-4,57 +691052,5,LONG,466,0,-2,4 +691054,5,LONG,467,-3,-7,72 +691056,5,LONG,468,-7,-1,52 +691058,5,LONG,469,1,-1,5 +691060,5,LONG,470,0,7,56 +691062,5,LONG,471,-1,-7,60 +691064,5,LONG,472,-4,-1,20 +691066,5,LONG,473,-2,-2,11 +691068,5,LONG,474,11,0,127 +691070,5,LONG,475,2,-4,29 +691072,5,LONG,476,-1,7,59 +691074,5,LONG,477,7,6,105 +691076,5,LONG,478,0,-2,5 +691078,5,LONG,479,4,1,21 +691080,5,LONG,480,-5,-7,84 +691082,5,LONG,481,-3,-1,18 +691084,5,LONG,482,-1,3,14 +691086,5,LONG,483,3,6,61 +691088,5,LONG,484,-7,-1,55 +691090,5,LONG,485,-10,4,138 +691092,5,LONG,486,4,-5,53 +691094,5,LONG,487,8,-6,116 +691096,5,LONG,488,0,0,1 +691098,5,LONG,489,-3,1,15 +691100,5,LONG,490,2,2,9 +691102,5,LONG,491,-14,2,230 +691104,5,LONG,492,4,1,22 +691106,5,LONG,493,1,-2,10 +691108,5,LONG,494,3,-12,160 +691110,5,LONG,495,6,1,38 +691112,5,LONG,496,-4,-3,27 +691114,5,LONG,497,-4,-9,116 +691116,5,LONG,498,1,4,21 +691118,5,LONG,499,0,-10,107 +691120,5,LONG,500,4,0,21 +691122,5,LONG,501,1,-4,23 +691124,5,LONG,502,-1,4,22 +691126,5,LONG,503,-6,0,44 +691128,5,LONG,504,-5,3,35 +691130,5,LONG,505,-3,-2,19 +691132,5,LONG,506,3,-7,64 +691134,5,LONG,507,-3,0,11 +691136,5,LONG,508,-4,-4,38 +691138,5,LONG,509,-4,1,20 +691140,5,LONG,510,11,0,133 +691142,5,LONG,511,-6,-5,70 +828144,6,LONG,0,4,2,24 +828146,6,LONG,1,9,27,850 +828148,6,LONG,2,0,-6,40 +828150,6,LONG,3,-19,-3,404 +828152,6,LONG,4,-3,-3,26 +828154,6,LONG,5,-1,6,50 +828156,6,LONG,6,12,6,185 +828158,6,LONG,7,18,-1,357 +828160,6,LONG,8,6,-12,181 +828162,6,LONG,9,13,-4,193 +828164,6,LONG,10,8,0,69 +828166,6,LONG,11,23,-2,563 +828168,6,LONG,12,-7,-17,352 +828170,6,LONG,13,3,10,128 +828172,6,LONG,14,-3,13,195 +828174,6,LONG,15,-6,-10,159 +828176,6,LONG,16,-22,-7,572 +828178,6,LONG,17,-27,-3,757 +828180,6,LONG,18,-2,25,680 +828182,6,LONG,19,-10,-23,648 +828184,6,LONG,20,20,-1,427 +828186,6,LONG,21,-2,-6,40 +828188,6,LONG,22,10,-8,199 +828190,6,LONG,23,0,-26,701 +828192,6,LONG,24,8,-19,426 +828194,6,LONG,25,-6,0,47 +828196,6,LONG,26,7,3,62 +828198,6,LONG,27,1,2,6 +828200,6,LONG,28,-10,4,131 +828202,6,LONG,29,-7,21,502 +828204,6,LONG,30,3,23,560 +828206,6,LONG,31,-3,-7,63 +828208,6,LONG,32,-1,-13,197 +828210,6,LONG,33,2,12,162 +828212,6,LONG,34,7,2,69 +828214,6,LONG,35,3,16,298 +828216,6,LONG,36,-7,10,166 +828218,6,LONG,37,1,9,99 +828220,6,LONG,38,-8,6,114 +828222,6,LONG,39,-20,-5,437 +828224,6,LONG,40,-6,2,56 +828226,6,LONG,41,13,-6,211 +828228,6,LONG,42,-11,-11,265 +828230,6,LONG,43,0,-7,52 +828232,6,LONG,44,12,7,204 +828234,6,LONG,45,-3,8,82 +828236,6,LONG,46,-14,-9,278 +828238,6,LONG,47,-18,3,357 +828240,6,LONG,48,1,15,241 +828242,6,LONG,49,-16,-2,267 +828244,6,LONG,50,-5,12,180 +828246,6,LONG,51,-6,-2,45 +828248,6,LONG,52,2,-1,7 +828250,6,LONG,53,2,6,44 +828252,6,LONG,54,-6,-3,56 +828254,6,LONG,55,1,-7,59 +828256,6,LONG,56,-8,0,75 +828258,6,LONG,57,0,-7,58 +828260,6,LONG,58,7,7,120 +828262,6,LONG,59,-24,0,584 +828264,6,LONG,60,-3,3,23 +828266,6,LONG,61,1,11,132 +828268,6,LONG,62,-1,10,111 +828270,6,LONG,63,2,-3,19 +828272,6,LONG,64,-2,4,31 +828274,6,LONG,65,20,-16,704 +828276,6,LONG,66,-7,-10,163 +828278,6,LONG,67,6,-9,130 +828280,6,LONG,68,-12,12,321 +828282,6,LONG,69,5,0,27 +828284,6,LONG,70,10,0,100 +828286,6,LONG,71,-4,10,131 +828288,6,LONG,72,6,11,174 +828290,6,LONG,73,-7,0,56 +828292,6,LONG,74,9,-5,120 +828294,6,LONG,75,-1,11,134 +828296,6,LONG,76,4,1,19 +828298,6,LONG,77,-1,-5,31 +828300,6,LONG,78,24,-2,606 +828302,6,LONG,79,8,-3,82 +828304,6,LONG,80,-11,-2,143 +828306,6,LONG,81,5,-17,318 +828308,6,LONG,82,-1,-21,444 +828310,6,LONG,83,-16,-1,282 +828312,6,LONG,84,-2,18,334 +828314,6,LONG,85,10,-13,304 +828316,6,LONG,86,2,-13,181 +828318,6,LONG,87,13,-3,196 +828320,6,LONG,88,3,1,14 +828322,6,LONG,89,-4,-23,591 +828324,6,LONG,90,-9,-4,115 +828326,6,LONG,91,1,-12,166 +828328,6,LONG,92,6,-3,51 +828330,6,LONG,93,-4,-9,116 +828332,6,LONG,94,2,1,9 +828334,6,LONG,95,-8,-1,82 +828336,6,LONG,96,-10,15,352 +828338,6,LONG,97,-10,-16,385 +828340,6,LONG,98,-3,17,333 +828342,6,LONG,99,-9,14,316 +828344,6,LONG,100,0,-14,203 +828346,6,LONG,101,5,-8,97 +828348,6,LONG,102,1,0,3 +828350,6,LONG,103,2,2,13 +828352,6,LONG,104,1,4,21 +828354,6,LONG,105,-11,0,137 +828356,6,LONG,106,-3,0,12 +828358,6,LONG,107,1,3,14 +828360,6,LONG,108,0,-6,37 +828362,6,LONG,109,7,-6,105 +828364,6,LONG,110,7,-1,65 +828366,6,LONG,111,-6,9,126 +828368,6,LONG,112,5,3,42 +828370,6,LONG,113,-6,0,43 +828372,6,LONG,114,4,6,60 +828374,6,LONG,115,3,3,25 +828376,6,LONG,116,2,0,7 +828378,6,LONG,117,-2,11,137 +828380,6,LONG,118,6,0,43 +828382,6,LONG,119,0,2,5 +828384,6,LONG,120,-7,-16,318 +828386,6,LONG,121,-7,0,58 +828388,6,LONG,122,7,0,51 +828390,6,LONG,123,1,-13,173 +828392,6,LONG,124,4,-3,32 +828394,6,LONG,125,11,3,149 +828396,6,LONG,126,-3,-2,22 +828398,6,LONG,127,1,11,132 +828400,6,LONG,128,4,4,42 +828402,6,LONG,129,-2,0,5 +828404,6,LONG,130,5,3,42 +828406,6,LONG,131,3,-4,38 +828408,6,LONG,132,0,3,12 +828410,6,LONG,133,-3,0,13 +828412,6,LONG,134,-8,-2,76 +828414,6,LONG,135,-3,-3,22 +828416,6,LONG,136,1,1,3 +828418,6,LONG,137,-2,2,11 +828420,6,LONG,138,12,-6,206 +828422,6,LONG,139,-5,1,34 +828424,6,LONG,140,1,-5,31 +828426,6,LONG,141,-47,86,9689 +828428,6,LONG,142,-65,89,12260 +828430,6,LONG,143,-75,87,13364 +828432,6,LONG,144,-74,62,9484 +828434,6,LONG,145,-87,62,11666 +828436,6,LONG,146,-92,45,10630 +828438,6,LONG,147,-90,36,9549 +828440,6,LONG,148,-91,28,9259 +828442,6,LONG,149,-103,12,10825 +828444,6,LONG,150,-100,-2,10067 +828446,6,LONG,151,-89,-5,8121 +828448,6,LONG,152,-96,-25,9903 +828450,6,LONG,153,-89,-36,9412 +828452,6,LONG,154,-97,-56,12828 +828454,6,LONG,155,-80,-57,9812 +828456,6,LONG,156,-70,-65,9351 +828458,6,LONG,157,-65,-77,10291 +828460,6,LONG,158,-53,-86,10295 +828462,6,LONG,159,-49,-84,9526 +828464,6,LONG,160,-2,6,43 +828466,6,LONG,161,-1,3,11 +828468,6,LONG,162,-1,-5,29 +828470,6,LONG,163,-2,-1,10 +828472,6,LONG,164,-4,10,127 +828474,6,LONG,165,6,2,43 +828476,6,LONG,166,2,-3,16 +828478,6,LONG,167,0,-10,119 +828480,6,LONG,168,-7,1,64 +828482,6,LONG,169,0,0,0 +828484,6,LONG,170,0,4,22 +828486,6,LONG,171,0,-10,101 +828488,6,LONG,172,2,7,61 +828490,6,LONG,173,3,3,24 +828492,6,LONG,174,2,-4,25 +828494,6,LONG,175,0,-2,5 +828496,6,LONG,176,1,4,19 +828498,6,LONG,177,-1,-1,3 +828500,6,LONG,178,1,0,1 +828502,6,LONG,179,0,-2,7 +828504,6,LONG,180,1,2,6 +828506,6,LONG,181,1,4,21 +828508,6,LONG,182,3,1,16 +828510,6,LONG,183,-9,8,149 +828512,6,LONG,184,8,0,80 +828514,6,LONG,185,-8,-5,92 +828516,6,LONG,186,2,0,4 +828518,6,LONG,187,-3,-8,89 +828520,6,LONG,188,-4,-2,26 +828522,6,LONG,189,7,2,58 +828524,6,LONG,190,-7,0,51 +828526,6,LONG,191,4,7,69 +828528,6,LONG,192,-5,-5,61 +828530,6,LONG,193,5,0,28 +828532,6,LONG,194,-2,0,6 +828534,6,LONG,195,0,-4,19 +828536,6,LONG,196,2,3,21 +828538,6,LONG,197,0,1,3 +828540,6,LONG,198,2,-7,58 +828542,6,LONG,199,2,-2,13 +828544,6,LONG,200,1,-1,3 +828546,6,LONG,201,10,-2,120 +828548,6,LONG,202,-1,-9,84 +828550,6,LONG,203,2,-8,72 +828552,6,LONG,204,0,-6,45 +828554,6,LONG,205,3,-4,27 +828556,6,LONG,206,-3,2,16 +828558,6,LONG,207,10,8,177 +828560,6,LONG,208,3,-1,14 +828562,6,LONG,209,-1,4,25 +828564,6,LONG,210,-4,-4,41 +828566,6,LONG,211,-2,0,6 +828568,6,LONG,212,-2,2,10 +828570,6,LONG,213,10,1,110 +828572,6,LONG,214,8,-11,201 +828574,6,LONG,215,0,-2,7 +828576,6,LONG,216,0,-2,5 +828578,6,LONG,217,0,5,34 +828580,6,LONG,218,-7,-2,64 +828582,6,LONG,219,0,2,5 +828584,6,LONG,220,4,-3,34 +828586,6,LONG,221,-3,0,14 +828588,6,LONG,222,2,-11,148 +828590,6,LONG,223,2,7,70 +828592,6,LONG,224,0,7,62 +828594,6,LONG,225,0,2,4 +828596,6,LONG,226,-4,-2,32 +828598,6,LONG,227,-6,2,53 +828600,6,LONG,228,4,1,22 +828602,6,LONG,229,-3,7,58 +828604,6,LONG,230,-1,-7,58 +828606,6,LONG,231,4,2,23 +828608,6,LONG,232,0,-2,4 +828610,6,LONG,233,-9,0,90 +828612,6,LONG,234,7,3,71 +828614,6,LONG,235,0,-3,13 +828616,6,LONG,236,6,-5,66 +828618,6,LONG,237,-1,-3,18 +828620,6,LONG,238,-7,0,49 +828622,6,LONG,239,-4,7,81 +828624,6,LONG,240,-1,-2,8 +828626,6,LONG,241,42,-23,2365 +828628,6,LONG,242,55,-24,3699 +828630,6,LONG,243,48,-7,2458 +828632,6,LONG,244,42,-10,1892 +828634,6,LONG,245,51,-6,2657 +828636,6,LONG,246,57,12,3458 +828638,6,LONG,247,50,16,2830 +828640,6,LONG,248,52,20,3154 +828642,6,LONG,249,48,25,3053 +828644,6,LONG,250,46,32,3223 +828646,6,LONG,251,43,34,3031 +828648,6,LONG,252,33,41,2872 +828650,6,LONG,253,18,44,2325 +828652,6,LONG,254,22,40,2177 +828654,6,LONG,255,9,49,2497 +828656,6,LONG,256,7,51,2680 +828658,6,LONG,257,11,54,3056 +828660,6,LONG,258,-4,48,2353 +828662,6,LONG,259,-4,53,2868 +828664,6,LONG,260,0,1,4 +828666,6,LONG,261,2,-5,36 +828668,6,LONG,262,-2,-1,11 +828670,6,LONG,263,2,3,22 +828672,6,LONG,264,1,7,58 +828674,6,LONG,265,0,0,0 +828676,6,LONG,266,-3,-3,26 +828678,6,LONG,267,-8,-1,65 +828680,6,LONG,268,6,-6,85 +828682,6,LONG,269,4,-2,23 +828684,6,LONG,270,-3,-1,15 +828686,6,LONG,271,8,-13,244 +828688,6,LONG,272,-6,3,46 +828690,6,LONG,273,-9,4,118 +828692,6,LONG,274,-3,-1,14 +828694,6,LONG,275,1,3,13 +828696,6,LONG,276,-7,12,225 +828698,6,LONG,277,-7,3,65 +828700,6,LONG,278,4,0,17 +828702,6,LONG,279,-1,-8,68 +828704,6,LONG,280,2,3,18 +828706,6,LONG,281,-6,-3,59 +828708,6,LONG,282,0,0,1 +828710,6,LONG,283,-5,-3,37 +828712,6,LONG,284,-2,0,5 +828714,6,LONG,285,4,5,47 +828716,6,LONG,286,0,5,32 +828718,6,LONG,287,3,0,14 +828720,6,LONG,288,-1,4,21 +828722,6,LONG,289,6,-4,63 +828724,6,LONG,290,0,1,2 +828726,6,LONG,291,-2,-5,35 +828728,6,LONG,292,0,2,5 +828730,6,LONG,293,0,-3,14 +828732,6,LONG,294,3,10,114 +828734,6,LONG,295,-2,-10,115 +828736,6,LONG,296,0,2,4 +828738,6,LONG,297,-4,-8,96 +828740,6,LONG,298,-2,2,9 +828742,6,LONG,299,0,-2,8 +828744,6,LONG,300,0,-3,10 +828746,6,LONG,301,3,1,13 +828748,6,LONG,302,-5,-2,34 +828750,6,LONG,303,0,-1,2 +828752,6,LONG,304,-6,-6,75 +828754,6,LONG,305,1,1,4 +828756,6,LONG,306,-1,0,3 +828758,6,LONG,307,3,0,11 +828760,6,LONG,308,-8,4,95 +828762,6,LONG,309,-3,3,25 +828764,6,LONG,310,-5,8,101 +828766,6,LONG,311,0,0,0 +828768,6,LONG,312,3,3,25 +828770,6,LONG,313,-3,-4,35 +828772,6,LONG,314,0,1,2 +828774,6,LONG,315,0,-3,11 +828776,6,LONG,316,2,6,56 +828778,6,LONG,317,-4,0,23 +828780,6,LONG,318,0,0,0 +828782,6,LONG,319,0,6,39 +828784,6,LONG,320,0,0,0 +828786,6,LONG,321,-5,-6,69 +828788,6,LONG,322,0,3,11 +828790,6,LONG,323,0,8,79 +828792,6,LONG,324,-3,6,49 +828794,6,LONG,325,-1,2,5 +828796,6,LONG,326,0,0,0 +828798,6,LONG,327,9,1,88 +828800,6,LONG,328,3,-5,38 +828802,6,LONG,329,-4,-4,37 +828804,6,LONG,330,-6,-2,52 +828806,6,LONG,331,-5,-1,36 +828808,6,LONG,332,9,0,86 +828810,6,LONG,333,-2,2,14 +828812,6,LONG,334,-4,4,46 +828814,6,LONG,335,5,4,52 +828816,6,LONG,336,-4,-3,35 +828818,6,LONG,337,0,4,21 +828820,6,LONG,338,1,1,6 +828822,6,LONG,339,-2,0,5 +828824,6,LONG,340,2,5,31 +828826,6,LONG,341,0,6,46 +828828,6,LONG,342,4,0,23 +828830,6,LONG,343,6,-4,61 +828832,6,LONG,344,-8,-8,133 +828834,6,LONG,345,-3,3,27 +828836,6,LONG,346,1,-2,6 +828838,6,LONG,347,-1,0,2 +828840,6,LONG,348,-4,-9,122 +828842,6,LONG,349,-3,-3,22 +828844,6,LONG,350,2,-3,16 +828846,6,LONG,351,6,2,47 +828848,6,LONG,352,-4,4,39 +828850,6,LONG,353,8,7,131 +828852,6,LONG,354,4,1,19 +828854,6,LONG,355,-7,2,57 +828856,6,LONG,356,1,-2,5 +828858,6,LONG,357,-1,2,8 +828860,6,LONG,358,-5,-3,51 +828862,6,LONG,359,-1,-1,3 +828864,6,LONG,360,0,-2,4 +828866,6,LONG,361,0,-2,6 +828868,6,LONG,362,4,-3,27 +828870,6,LONG,363,6,0,39 +828872,6,LONG,364,7,1,50 +828874,6,LONG,365,-2,-4,23 +828876,6,LONG,366,0,-6,44 +828878,6,LONG,367,0,0,0 +828880,6,LONG,368,-3,-4,31 +828882,6,LONG,369,-4,5,43 +828884,6,LONG,370,-5,-3,44 +828886,6,LONG,371,-6,-7,97 +828888,6,LONG,372,-3,6,53 +828890,6,LONG,373,0,5,35 +828892,6,LONG,374,-1,7,61 +828894,6,LONG,375,0,-10,104 +828896,6,LONG,376,-5,1,28 +828898,6,LONG,377,-3,-5,40 +828900,6,LONG,378,2,9,97 +828902,6,LONG,379,3,-2,19 +828904,6,LONG,380,2,-4,23 +828906,6,LONG,381,1,1,3 +828908,6,LONG,382,0,0,1 +828910,6,LONG,383,1,1,4 +828912,6,LONG,384,-1,2,8 +828914,6,LONG,385,0,1,1 +828916,6,LONG,386,-10,6,165 +828918,6,LONG,387,1,4,18 +828920,6,LONG,388,-3,-8,92 +828922,6,LONG,389,-1,0,1 +828924,6,LONG,390,-5,-4,48 +828926,6,LONG,391,18,9,419 +828928,6,LONG,392,10,11,246 +828930,6,LONG,393,4,14,233 +828932,6,LONG,394,16,22,791 +828934,6,LONG,395,7,17,354 +828936,6,LONG,396,3,22,523 +828938,6,LONG,397,11,32,1204 +828940,6,LONG,398,-2,19,381 +828942,6,LONG,399,-2,17,329 +828944,6,LONG,400,-9,32,1157 +828946,6,LONG,401,-7,27,830 +828948,6,LONG,402,-8,28,905 +828950,6,LONG,403,-9,24,676 +828952,6,LONG,404,-13,26,883 +828954,6,LONG,405,-17,25,928 +828956,6,LONG,406,-17,13,503 +828958,6,LONG,407,-19,11,537 +828960,6,LONG,408,-13,2,186 +828962,6,LONG,409,-24,-4,604 +828964,6,LONG,410,-12,-10,282 +828966,6,LONG,411,0,1,3 +828968,6,LONG,412,-5,-5,60 +828970,6,LONG,413,2,0,6 +828972,6,LONG,414,9,-1,90 +828974,6,LONG,415,3,-9,101 +828976,6,LONG,416,0,-2,4 +828978,6,LONG,417,-2,-1,9 +828980,6,LONG,418,1,2,8 +828982,6,LONG,419,10,-8,171 +828984,6,LONG,420,5,0,32 +828986,6,LONG,421,-3,1,12 +828988,6,LONG,422,3,2,19 +828990,6,LONG,423,-2,-3,17 +828992,6,LONG,424,-14,6,250 +828994,6,LONG,425,-2,1,8 +828996,6,LONG,426,-6,0,38 +828998,6,LONG,427,1,5,34 +829000,6,LONG,428,1,-6,39 +829002,6,LONG,429,3,5,38 +829004,6,LONG,430,4,0,17 +829006,6,LONG,431,-9,2,104 +829008,6,LONG,432,-1,-1,6 +829010,6,LONG,433,-5,5,59 +829012,6,LONG,434,-15,0,255 +829014,6,LONG,435,-5,7,86 +829016,6,LONG,436,5,1,27 +829018,6,LONG,437,0,0,0 +829020,6,LONG,438,0,-3,13 +829022,6,LONG,439,-2,-2,14 +829024,6,LONG,440,5,10,129 +829026,6,LONG,441,1,-2,11 +829028,6,LONG,442,-5,-1,34 +829030,6,LONG,443,-7,0,52 +829032,6,LONG,444,-14,0,209 +829034,6,LONG,445,6,-13,230 +829036,6,LONG,446,-6,0,43 +829038,6,LONG,447,6,-1,50 +829040,6,LONG,448,-6,6,79 +829042,6,LONG,449,4,-8,101 +829044,6,LONG,450,-4,4,38 +829046,6,LONG,451,-3,8,88 +829048,6,LONG,452,-4,5,50 +829050,6,LONG,453,1,5,29 +829052,6,LONG,454,2,-2,12 +829054,6,LONG,455,0,-1,2 +829056,6,LONG,456,-4,1,27 +829058,6,LONG,457,2,3,20 +829060,6,LONG,458,-2,-7,64 +829062,6,LONG,459,0,3,15 +829064,6,LONG,460,-4,-6,70 +829066,6,LONG,461,1,2,11 +829068,6,LONG,462,7,9,148 +829070,6,LONG,463,-6,1,37 +829072,6,LONG,464,0,-2,7 +829074,6,LONG,465,4,2,31 +829076,6,LONG,466,-8,-3,81 +829078,6,LONG,467,8,0,68 +829080,6,LONG,468,7,-2,60 +829082,6,LONG,469,0,-4,19 +829084,6,LONG,470,4,-1,25 +829086,6,LONG,471,-1,1,3 +829088,6,LONG,472,-1,-3,12 +829090,6,LONG,473,4,0,24 +829092,6,LONG,474,0,4,21 +829094,6,LONG,475,3,0,9 +829096,6,LONG,476,4,5,42 +829098,6,LONG,477,4,-3,30 +829100,6,LONG,478,3,3,24 +829102,6,LONG,479,2,7,70 +829104,6,LONG,480,10,-3,119 +829106,6,LONG,481,0,-5,35 +829108,6,LONG,482,5,0,34 +829110,6,LONG,483,0,-4,20 +829112,6,LONG,484,4,3,29 +829114,6,LONG,485,3,-2,18 +829116,6,LONG,486,-6,3,54 +829118,6,LONG,487,-1,-3,11 +829120,6,LONG,488,-5,3,42 +829122,6,LONG,489,-2,-5,38 +829124,6,LONG,490,0,-9,97 +829126,6,LONG,491,-11,10,237 +829128,6,LONG,492,4,-7,80 +829130,6,LONG,493,8,-3,87 +829132,6,LONG,494,6,5,72 +829134,6,LONG,495,8,0,73 +829136,6,LONG,496,2,-6,41 +829138,6,LONG,497,4,3,28 +829140,6,LONG,498,0,-4,22 +829142,6,LONG,499,0,-1,1 +829144,6,LONG,500,-1,2,6 +829146,6,LONG,501,-2,-1,9 +829148,6,LONG,502,6,-4,66 +829150,6,LONG,503,2,0,4 +829152,6,LONG,504,1,1,4 +829154,6,LONG,505,-2,6,52 +829156,6,LONG,506,1,-5,36 +829158,6,LONG,507,1,-1,5 +829160,6,LONG,508,2,7,59 +829162,6,LONG,509,7,1,51 +829164,6,LONG,510,2,2,15 +829166,6,LONG,511,-1,-6,45 +966168,7,LONG,0,19,3,379 +966170,7,LONG,1,3,15,261 +966172,7,LONG,2,-4,-21,468 +966174,7,LONG,3,-3,-5,49 +966176,7,LONG,4,-6,-16,319 +966178,7,LONG,5,-6,18,393 +966180,7,LONG,6,-13,-6,218 +966182,7,LONG,7,-16,-4,304 +966184,7,LONG,8,3,-3,20 +966186,7,LONG,9,0,-6,43 +966188,7,LONG,10,18,2,359 +966190,7,LONG,11,4,-17,327 +966192,7,LONG,12,3,-12,158 +966194,7,LONG,13,-4,2,31 +966196,7,LONG,14,9,0,83 +966198,7,LONG,15,7,-8,126 +966200,7,LONG,16,0,-11,138 +966202,7,LONG,17,16,-5,313 +966204,7,LONG,18,14,-2,223 +966206,7,LONG,19,8,-6,114 +966208,7,LONG,20,-20,5,444 +966210,7,LONG,21,-13,1,172 +966212,7,LONG,22,-26,-3,707 +966214,7,LONG,23,10,1,108 +966216,7,LONG,24,2,-6,44 +966218,7,LONG,25,-6,17,332 +966220,7,LONG,26,-8,-13,246 +966222,7,LONG,27,-11,0,135 +966224,7,LONG,28,12,0,149 +966226,7,LONG,29,12,26,883 +966228,7,LONG,30,-6,10,152 +966230,7,LONG,31,-3,4,32 +966232,7,LONG,32,-12,0,144 +966234,7,LONG,33,1,15,245 +966236,7,LONG,34,-13,8,255 +966238,7,LONG,35,7,-2,58 +966240,7,LONG,36,-7,3,72 +966242,7,LONG,37,-5,8,99 +966244,7,LONG,38,-1,7,64 +966246,7,LONG,39,-8,0,69 +966248,7,LONG,40,6,-10,158 +966250,7,LONG,41,11,-2,150 +966252,7,LONG,42,-7,7,110 +966254,7,LONG,43,6,12,195 +966256,7,LONG,44,2,-1,7 +966258,7,LONG,45,9,15,328 +966260,7,LONG,46,-9,0,93 +966262,7,LONG,47,0,-5,28 +966264,7,LONG,48,-10,-20,535 +966266,7,LONG,49,-3,-4,40 +966268,7,LONG,50,-1,-4,21 +966270,7,LONG,51,3,-31,1037 +966272,7,LONG,52,-5,-12,189 +966274,7,LONG,53,0,-5,33 +966276,7,LONG,54,6,9,130 +966278,7,LONG,55,0,-23,559 +966280,7,LONG,56,3,-2,16 +966282,7,LONG,57,10,-2,110 +966284,7,LONG,58,4,-5,47 +966286,7,LONG,59,-9,3,94 +966288,7,LONG,60,4,16,272 +966290,7,LONG,61,5,7,83 +966292,7,LONG,62,1,6,45 +966294,7,LONG,63,-18,-3,374 +966296,7,LONG,64,3,3,26 +966298,7,LONG,65,25,-14,865 +966300,7,LONG,66,-14,5,251 +966302,7,LONG,67,4,2,31 +966304,7,LONG,68,12,3,166 +966306,7,LONG,69,27,2,774 +966308,7,LONG,70,0,7,54 +966310,7,LONG,71,1,-11,134 +966312,7,LONG,72,0,5,31 +966314,7,LONG,73,-1,13,192 +966316,7,LONG,74,12,14,367 +966318,7,LONG,75,3,2,18 +966320,7,LONG,76,-7,-10,170 +966322,7,LONG,77,2,10,108 +966324,7,LONG,78,0,-15,244 +966326,7,LONG,79,2,-8,73 +966328,7,LONG,80,-16,3,289 +966330,7,LONG,81,0,-8,71 +966332,7,LONG,82,1,-12,158 +966334,7,LONG,83,6,1,42 +966336,7,LONG,84,-28,-18,1149 +966338,7,LONG,85,-15,-4,261 +966340,7,LONG,86,20,0,431 +966342,7,LONG,87,2,-13,178 +966344,7,LONG,88,6,5,72 +966346,7,LONG,89,-3,13,184 +966348,7,LONG,90,11,10,237 +966350,7,LONG,91,19,-2,371 +966352,7,LONG,92,0,-15,226 +966354,7,LONG,93,-6,-14,271 +966356,7,LONG,94,-15,3,239 +966358,7,LONG,95,6,1,42 +966360,7,LONG,96,-13,12,346 +966362,7,LONG,97,4,10,141 +966364,7,LONG,98,-13,3,182 +966366,7,LONG,99,-6,-19,426 +966368,7,LONG,100,-1,-7,51 +966370,7,LONG,101,-3,-5,36 +966372,7,LONG,102,-3,-5,45 +966374,7,LONG,103,-1,-3,14 +966376,7,LONG,104,1,0,1 +966378,7,LONG,105,-8,1,68 +966380,7,LONG,106,0,2,4 +966382,7,LONG,107,-4,-1,23 +966384,7,LONG,108,8,-6,106 +966386,7,LONG,109,-4,0,16 +966388,7,LONG,110,-7,-4,76 +966390,7,LONG,111,0,3,12 +966392,7,LONG,112,5,-2,32 +966394,7,LONG,113,2,-3,20 +966396,7,LONG,114,2,0,5 +966398,7,LONG,115,0,8,69 +966400,7,LONG,116,-4,1,27 +966402,7,LONG,117,1,6,45 +966404,7,LONG,118,-7,4,73 +966406,7,LONG,119,0,0,1 +966408,7,LONG,120,0,-1,2 +966410,7,LONG,121,0,-4,16 +966412,7,LONG,122,-6,3,52 +966414,7,LONG,123,3,3,27 +966416,7,LONG,124,5,7,88 +966418,7,LONG,125,-6,1,41 +966420,7,LONG,126,7,5,86 +966422,7,LONG,127,-5,3,35 +966424,7,LONG,128,-1,-1,6 +966426,7,LONG,129,4,-4,35 +966428,7,LONG,130,3,-5,37 +966430,7,LONG,131,8,1,73 +966432,7,LONG,132,-1,-6,51 +966434,7,LONG,133,4,5,51 +966436,7,LONG,134,-5,3,35 +966438,7,LONG,135,1,5,27 +966440,7,LONG,136,3,-3,23 +966442,7,LONG,137,5,0,36 +966444,7,LONG,138,1,-4,18 +966446,7,LONG,139,-6,6,86 +966448,7,LONG,140,-6,12,196 +966450,7,LONG,141,-101,-44,12155 +966452,7,LONG,142,-87,-53,10459 +966454,7,LONG,143,-75,-61,9479 +966456,7,LONG,144,-67,-64,8714 +966458,7,LONG,145,-60,-74,9294 +966460,7,LONG,146,-53,-85,10187 +966462,7,LONG,147,-38,-96,10854 +966464,7,LONG,148,-24,-98,10339 +966466,7,LONG,149,-10,-103,10878 +966468,7,LONG,150,-2,-93,8730 +966470,7,LONG,151,7,-102,10473 +966472,7,LONG,152,24,-96,9943 +966474,7,LONG,153,33,-86,8660 +966476,7,LONG,154,45,-81,8667 +966478,7,LONG,155,62,-84,11051 +966480,7,LONG,156,70,-72,10158 +966482,7,LONG,157,69,-68,9516 +966484,7,LONG,158,87,-59,11198 +966486,7,LONG,159,88,-44,9865 +966488,7,LONG,160,-3,0,13 +966490,7,LONG,161,2,4,24 +966492,7,LONG,162,9,-3,102 +966494,7,LONG,163,-6,4,64 +966496,7,LONG,164,-1,-4,25 +966498,7,LONG,165,0,0,0 +966500,7,LONG,166,-2,-4,21 +966502,7,LONG,167,1,-6,44 +966504,7,LONG,168,3,-8,89 +966506,7,LONG,169,-4,-3,33 +966508,7,LONG,170,-7,5,79 +966510,7,LONG,171,-10,5,148 +966512,7,LONG,172,0,5,35 +966514,7,LONG,173,-6,4,69 +966516,7,LONG,174,-1,2,6 +966518,7,LONG,175,0,5,28 +966520,7,LONG,176,-5,11,164 +966522,7,LONG,177,0,10,119 +966524,7,LONG,178,6,4,69 +966526,7,LONG,179,3,-3,27 +966528,7,LONG,180,2,-4,28 +966530,7,LONG,181,3,0,11 +966532,7,LONG,182,9,-1,83 +966534,7,LONG,183,4,1,18 +966536,7,LONG,184,0,7,60 +966538,7,LONG,185,-5,-7,91 +966540,7,LONG,186,-1,3,14 +966542,7,LONG,187,5,4,43 +966544,7,LONG,188,2,-6,53 +966546,7,LONG,189,-6,-1,43 +966548,7,LONG,190,-1,4,27 +966550,7,LONG,191,-10,2,114 +966552,7,LONG,192,2,0,4 +966554,7,LONG,193,5,5,60 +966556,7,LONG,194,-2,-1,10 +966558,7,LONG,195,9,0,83 +966560,7,LONG,196,-6,-4,64 +966562,7,LONG,197,0,1,3 +966564,7,LONG,198,0,-1,2 +966566,7,LONG,199,6,2,54 +966568,7,LONG,200,-4,-1,19 +966570,7,LONG,201,4,12,163 +966572,7,LONG,202,-3,-3,20 +966574,7,LONG,203,-1,0,3 +966576,7,LONG,204,7,4,70 +966578,7,LONG,205,-1,-7,61 +966580,7,LONG,206,3,-4,35 +966582,7,LONG,207,13,-1,176 +966584,7,LONG,208,0,-3,15 +966586,7,LONG,209,-6,-8,116 +966588,7,LONG,210,5,-3,40 +966590,7,LONG,211,-6,-3,53 +966592,7,LONG,212,-1,8,76 +966594,7,LONG,213,1,2,9 +966596,7,LONG,214,-2,0,6 +966598,7,LONG,215,-3,-7,75 +966600,7,LONG,216,-4,-8,92 +966602,7,LONG,217,0,2,8 +966604,7,LONG,218,0,-2,4 +966606,7,LONG,219,-1,7,53 +966608,7,LONG,220,3,-3,25 +966610,7,LONG,221,4,11,146 +966612,7,LONG,222,-3,-1,11 +966614,7,LONG,223,-1,-13,188 +966616,7,LONG,224,-3,4,34 +966618,7,LONG,225,0,0,1 +966620,7,LONG,226,-2,3,13 +966622,7,LONG,227,0,0,0 +966624,7,LONG,228,0,7,53 +966626,7,LONG,229,7,-7,116 +966628,7,LONG,230,-8,-6,118 +966630,7,LONG,231,0,-1,4 +966632,7,LONG,232,5,1,36 +966634,7,LONG,233,-9,5,109 +966636,7,LONG,234,-9,-4,107 +966638,7,LONG,235,3,-1,12 +966640,7,LONG,236,-4,-11,141 +966642,7,LONG,237,-11,4,151 +966644,7,LONG,238,1,0,2 +966646,7,LONG,239,4,-8,94 +966648,7,LONG,240,-4,-7,80 +966650,7,LONG,241,8,-44,2028 +966652,7,LONG,242,15,-49,2733 +966654,7,LONG,243,20,-46,2561 +966656,7,LONG,244,25,-37,2048 +966658,7,LONG,245,24,-49,3024 +966660,7,LONG,246,25,-30,1566 +966662,7,LONG,247,45,-34,3230 +966664,7,LONG,248,44,-23,2546 +966666,7,LONG,249,45,-17,2349 +966668,7,LONG,250,43,-13,2079 +966670,7,LONG,251,38,-6,1503 +966672,7,LONG,252,51,-1,2623 +966674,7,LONG,253,48,3,2375 +966676,7,LONG,254,51,7,2724 +966678,7,LONG,255,45,17,2367 +966680,7,LONG,256,51,13,2833 +966682,7,LONG,257,41,34,2896 +966684,7,LONG,258,31,31,1978 +966686,7,LONG,259,28,34,2005 +966688,7,LONG,260,-3,10,135 +966690,7,LONG,261,0,1,2 +966692,7,LONG,262,4,0,22 +966694,7,LONG,263,0,2,6 +966696,7,LONG,264,7,-3,68 +966698,7,LONG,265,-8,-5,97 +966700,7,LONG,266,-2,1,7 +966702,7,LONG,267,6,-5,65 +966704,7,LONG,268,-1,10,116 +966706,7,LONG,269,7,0,55 +966708,7,LONG,270,0,-6,39 +966710,7,LONG,271,-2,4,28 +966712,7,LONG,272,4,4,47 +966714,7,LONG,273,1,2,8 +966716,7,LONG,274,-3,-1,14 +966718,7,LONG,275,1,-1,2 +966720,7,LONG,276,-7,-2,56 +966722,7,LONG,277,-3,-4,31 +966724,7,LONG,278,-5,8,104 +966726,7,LONG,279,5,1,28 +966728,7,LONG,280,1,-7,63 +966730,7,LONG,281,-4,6,57 +966732,7,LONG,282,3,0,15 +966734,7,LONG,283,3,5,35 +966736,7,LONG,284,9,1,83 +966738,7,LONG,285,0,-2,5 +966740,7,LONG,286,-5,2,39 +966742,7,LONG,287,0,4,18 +966744,7,LONG,288,11,-10,247 +966746,7,LONG,289,5,-2,31 +966748,7,LONG,290,-1,3,14 +966750,7,LONG,291,9,2,102 +966752,7,LONG,292,0,0,1 +966754,7,LONG,293,1,-2,7 +966756,7,LONG,294,-1,12,149 +966758,7,LONG,295,3,6,54 +966760,7,LONG,296,3,0,11 +966762,7,LONG,297,-6,4,65 +966764,7,LONG,298,-5,0,25 +966766,7,LONG,299,5,9,107 +966768,7,LONG,300,-1,3,18 +966770,7,LONG,301,1,-5,34 +966772,7,LONG,302,0,-2,5 +966774,7,LONG,303,-4,0,16 +966776,7,LONG,304,1,-9,95 +966778,7,LONG,305,2,0,6 +966780,7,LONG,306,2,6,50 +966782,7,LONG,307,1,0,1 +966784,7,LONG,308,4,0,22 +966786,7,LONG,309,4,5,52 +966788,7,LONG,310,-9,0,89 +966790,7,LONG,311,-1,0,1 +966792,7,LONG,312,-6,0,39 +966794,7,LONG,313,-1,4,23 +966796,7,LONG,314,3,5,49 +966798,7,LONG,315,4,-3,32 +966800,7,LONG,316,4,5,51 +966802,7,LONG,317,0,0,0 +966804,7,LONG,318,-1,-1,3 +966806,7,LONG,319,2,1,6 +966808,7,LONG,320,-4,-2,23 +966810,7,LONG,321,-6,-3,55 +966812,7,LONG,322,0,-7,62 +966814,7,LONG,323,0,-1,2 +966816,7,LONG,324,6,-2,51 +966818,7,LONG,325,-2,6,45 +966820,7,LONG,326,6,-2,55 +966822,7,LONG,327,-6,6,74 +966824,7,LONG,328,-5,-1,28 +966826,7,LONG,329,-7,1,55 +966828,7,LONG,330,-7,-1,62 +966830,7,LONG,331,-3,-6,50 +966832,7,LONG,332,2,-3,20 +966834,7,LONG,333,4,3,29 +966836,7,LONG,334,-4,8,99 +966838,7,LONG,335,-1,-6,44 +966840,7,LONG,336,-1,0,1 +966842,7,LONG,337,8,4,94 +966844,7,LONG,338,2,-1,9 +966846,7,LONG,339,0,-2,4 +966848,7,LONG,340,-6,8,115 +966850,7,LONG,341,0,3,12 +966852,7,LONG,342,0,0,1 +966854,7,LONG,343,-10,3,112 +966856,7,LONG,344,2,2,11 +966858,7,LONG,345,-3,7,77 +966860,7,LONG,346,6,0,44 +966862,7,LONG,347,-4,-9,113 +966864,7,LONG,348,-8,-6,118 +966866,7,LONG,349,3,-6,54 +966868,7,LONG,350,-2,-1,9 +966870,7,LONG,351,0,-3,13 +966872,7,LONG,352,11,2,132 +966874,7,LONG,353,-5,-2,43 +966876,7,LONG,354,3,-4,29 +966878,7,LONG,355,9,5,116 +966880,7,LONG,356,2,-1,5 +966882,7,LONG,357,3,-5,43 +966884,7,LONG,358,2,1,8 +966886,7,LONG,359,-1,1,5 +966888,7,LONG,360,-4,3,31 +966890,7,LONG,361,-5,0,28 +966892,7,LONG,362,3,-4,32 +966894,7,LONG,363,-2,5,36 +966896,7,LONG,364,0,4,23 +966898,7,LONG,365,0,-6,42 +966900,7,LONG,366,4,0,23 +966902,7,LONG,367,-9,-1,89 +966904,7,LONG,368,2,2,14 +966906,7,LONG,369,1,2,7 +966908,7,LONG,370,-7,2,64 +966910,7,LONG,371,6,-1,40 +966912,7,LONG,372,-18,0,353 +966914,7,LONG,373,-4,1,21 +966916,7,LONG,374,10,0,107 +966918,7,LONG,375,-9,0,98 +966920,7,LONG,376,1,-4,23 +966922,7,LONG,377,2,-7,62 +966924,7,LONG,378,3,-2,15 +966926,7,LONG,379,-5,-1,34 +966928,7,LONG,380,-5,4,50 +966930,7,LONG,381,-4,-9,100 +966932,7,LONG,382,-2,-6,51 +966934,7,LONG,383,2,11,145 +966936,7,LONG,384,4,4,38 +966938,7,LONG,385,0,-8,76 +966940,7,LONG,386,-3,2,17 +966942,7,LONG,387,0,16,273 +966944,7,LONG,388,-4,3,28 +966946,7,LONG,389,0,4,23 +966948,7,LONG,390,-2,-2,14 +966950,7,LONG,391,10,22,629 +966952,7,LONG,392,13,19,552 +966954,7,LONG,393,8,26,762 +966956,7,LONG,394,6,26,750 +966958,7,LONG,395,3,26,689 +966960,7,LONG,396,-3,25,648 +966962,7,LONG,397,-14,22,696 +966964,7,LONG,398,-7,32,1144 +966966,7,LONG,399,-15,26,936 +966968,7,LONG,400,-9,29,976 +966970,7,LONG,401,-11,18,457 +966972,7,LONG,402,-19,23,937 +966974,7,LONG,403,-20,9,525 +966976,7,LONG,404,-30,7,953 +966978,7,LONG,405,-26,10,801 +966980,7,LONG,406,-24,9,690 +966982,7,LONG,407,-24,-1,598 +966984,7,LONG,408,-25,3,657 +966986,7,LONG,409,-27,-4,781 +966988,7,LONG,410,3,9,110 +966990,7,LONG,411,2,0,6 +966992,7,LONG,412,0,-1,1 +966994,7,LONG,413,-6,0,45 +966996,7,LONG,414,3,1,16 +966998,7,LONG,415,0,13,175 +967000,7,LONG,416,-1,0,1 +967002,7,LONG,417,0,0,0 +967004,7,LONG,418,9,0,87 +967006,7,LONG,419,4,-3,31 +967008,7,LONG,420,13,-1,183 +967010,7,LONG,421,3,-5,38 +967012,7,LONG,422,14,9,300 +967014,7,LONG,423,3,-2,18 +967016,7,LONG,424,1,-7,52 +967018,7,LONG,425,-1,-2,11 +967020,7,LONG,426,1,-10,123 +967022,7,LONG,427,1,-4,25 +967024,7,LONG,428,5,-2,32 +967026,7,LONG,429,8,-6,109 +967028,7,LONG,430,-1,1,5 +967030,7,LONG,431,5,-7,83 +967032,7,LONG,432,-2,-3,20 +967034,7,LONG,433,8,5,110 +967036,7,LONG,434,-1,-6,46 +967038,7,LONG,435,4,3,25 +967040,7,LONG,436,4,0,22 +967042,7,LONG,437,3,-3,22 +967044,7,LONG,438,5,7,79 +967046,7,LONG,439,-4,0,18 +967048,7,LONG,440,1,4,20 +967050,7,LONG,441,-7,-5,81 +967052,7,LONG,442,8,4,93 +967054,7,LONG,443,6,-3,60 +967056,7,LONG,444,-1,-5,35 +967058,7,LONG,445,-3,15,242 +967060,7,LONG,446,-2,0,9 +967062,7,LONG,447,8,6,112 +967064,7,LONG,448,-6,-2,43 +967066,7,LONG,449,-3,0,12 +967068,7,LONG,450,-5,-10,133 +967070,7,LONG,451,-5,4,50 +967072,7,LONG,452,-4,1,26 +967074,7,LONG,453,4,1,17 +967076,7,LONG,454,8,4,96 +967078,7,LONG,455,0,-1,2 +967080,7,LONG,456,2,0,5 +967082,7,LONG,457,2,12,167 +967084,7,LONG,458,-3,4,35 +967086,7,LONG,459,12,-3,176 +967088,7,LONG,460,2,-1,10 +967090,7,LONG,461,-1,0,1 +967092,7,LONG,462,5,-11,154 +967094,7,LONG,463,1,1,5 +967096,7,LONG,464,4,6,62 +967098,7,LONG,465,0,-4,19 +967100,7,LONG,466,1,-3,12 +967102,7,LONG,467,4,-2,24 +967104,7,LONG,468,-6,8,118 +967106,7,LONG,469,8,3,83 +967108,7,LONG,470,3,0,9 +967110,7,LONG,471,2,8,79 +967112,7,LONG,472,4,-7,81 +967114,7,LONG,473,6,0,40 +967116,7,LONG,474,6,-2,41 +967118,7,LONG,475,-1,2,11 +967120,7,LONG,476,2,-2,11 +967122,7,LONG,477,1,1,4 +967124,7,LONG,478,-9,-10,189 +967126,7,LONG,479,-9,-4,104 +967128,7,LONG,480,-2,2,15 +967130,7,LONG,481,0,-4,24 +967132,7,LONG,482,1,4,23 +967134,7,LONG,483,8,-8,134 +967136,7,LONG,484,-2,9,91 +967138,7,LONG,485,0,3,14 +967140,7,LONG,486,0,-2,4 +967142,7,LONG,487,-1,-3,11 +967144,7,LONG,488,4,-2,24 +967146,7,LONG,489,-3,0,15 +967148,7,LONG,490,-2,5,37 +967150,7,LONG,491,-7,1,55 +967152,7,LONG,492,7,3,66 +967154,7,LONG,493,1,3,18 +967156,7,LONG,494,0,-4,16 +967158,7,LONG,495,-3,5,42 +967160,7,LONG,496,0,-3,9 +967162,7,LONG,497,4,0,17 +967164,7,LONG,498,-4,-3,31 +967166,7,LONG,499,-3,-2,20 +967168,7,LONG,500,2,0,5 +967170,7,LONG,501,5,1,30 +967172,7,LONG,502,-1,1,3 +967174,7,LONG,503,-6,6,85 +967176,7,LONG,504,9,0,83 +967178,7,LONG,505,1,6,42 +967180,7,LONG,506,7,0,59 +967182,7,LONG,507,-10,5,132 +967184,7,LONG,508,0,0,0 +967186,7,LONG,509,13,3,193 +967188,7,LONG,510,1,3,10 +967190,7,LONG,511,-12,1,150 +1104192,8,LONG,0,-15,3,243 +1104194,8,LONG,1,-4,20,443 +1104196,8,LONG,2,2,-8,73 +1104198,8,LONG,3,5,-11,159 +1104200,8,LONG,4,0,9,88 +1104202,8,LONG,5,-8,6,119 +1104204,8,LONG,6,6,8,111 +1104206,8,LONG,7,-4,-14,241 +1104208,8,LONG,8,27,13,927 +1104210,8,LONG,9,2,-13,199 +1104212,8,LONG,10,-31,-9,1103 +1104214,8,LONG,11,13,16,461 +1104216,8,LONG,12,-25,11,779 +1104218,8,LONG,13,22,17,809 +1104220,8,LONG,14,-3,-12,163 +1104222,8,LONG,15,-10,-2,113 +1104224,8,LONG,16,13,35,1456 +1104226,8,LONG,17,-15,-11,372 +1104228,8,LONG,18,-16,-37,1697 +1104230,8,LONG,19,1,21,449 +1104232,8,LONG,20,-3,5,42 +1104234,8,LONG,21,-2,10,105 +1104236,8,LONG,22,-10,-10,223 +1104238,8,LONG,23,10,11,241 +1104240,8,LONG,24,7,-13,227 +1104242,8,LONG,25,4,5,48 +1104244,8,LONG,26,-1,0,3 +1104246,8,LONG,27,16,12,436 +1104248,8,LONG,28,-28,-3,824 +1104250,8,LONG,29,-4,-18,365 +1104252,8,LONG,30,-12,-16,444 +1104254,8,LONG,31,11,-4,163 +1104256,8,LONG,32,-13,10,299 +1104258,8,LONG,33,-7,0,52 +1104260,8,LONG,34,-15,-7,298 +1104262,8,LONG,35,8,-22,589 +1104264,8,LONG,36,3,18,353 +1104266,8,LONG,37,-10,-8,173 +1104268,8,LONG,38,-11,-12,302 +1104270,8,LONG,39,5,-9,114 +1104272,8,LONG,40,-2,-11,131 +1104274,8,LONG,41,-5,16,293 +1104276,8,LONG,42,5,-1,28 +1104278,8,LONG,43,8,12,224 +1104280,8,LONG,44,-4,17,332 +1104282,8,LONG,45,14,-3,225 +1104284,8,LONG,46,-2,-17,309 +1104286,8,LONG,47,-5,-16,290 +1104288,8,LONG,48,-9,15,325 +1104290,8,LONG,49,-18,-15,586 +1104292,8,LONG,50,14,5,243 +1104294,8,LONG,51,3,9,111 +1104296,8,LONG,52,16,-8,328 +1104298,8,LONG,53,6,0,36 +1104300,8,LONG,54,11,-17,418 +1104302,8,LONG,55,-9,-14,309 +1104304,8,LONG,56,-14,13,399 +1104306,8,LONG,57,10,5,132 +1104308,8,LONG,58,-16,6,302 +1104310,8,LONG,59,11,-2,145 +1104312,8,LONG,60,-8,1,78 +1104314,8,LONG,61,-12,-15,399 +1104316,8,LONG,62,-5,-3,45 +1104318,8,LONG,63,-10,1,114 +1104320,8,LONG,64,7,-17,364 +1104322,8,LONG,65,-9,-13,269 +1104324,8,LONG,66,-1,0,2 +1104326,8,LONG,67,5,-13,227 +1104328,8,LONG,68,-2,-13,177 +1104330,8,LONG,69,14,9,308 +1104332,8,LONG,70,2,10,111 +1104334,8,LONG,71,-18,-13,508 +1104336,8,LONG,72,-1,18,343 +1104338,8,LONG,73,21,11,599 +1104340,8,LONG,74,-3,2,16 +1104342,8,LONG,75,1,5,33 +1104344,8,LONG,76,-1,2,11 +1104346,8,LONG,77,-1,14,206 +1104348,8,LONG,78,-6,-18,386 +1104350,8,LONG,79,3,-9,110 +1104352,8,LONG,80,6,0,46 +1104354,8,LONG,81,-6,-6,87 +1104356,8,LONG,82,6,-19,414 +1104358,8,LONG,83,28,-14,1000 +1104360,8,LONG,84,-14,-2,223 +1104362,8,LONG,85,5,-7,81 +1104364,8,LONG,86,21,0,450 +1104366,8,LONG,87,-5,6,79 +1104368,8,LONG,88,-10,-8,194 +1104370,8,LONG,89,-4,-6,68 +1104372,8,LONG,90,-13,0,175 +1104374,8,LONG,91,9,-10,188 +1104376,8,LONG,92,0,-9,91 +1104378,8,LONG,93,20,3,418 +1104380,8,LONG,94,-7,1,63 +1104382,8,LONG,95,-8,3,76 +1104384,8,LONG,96,12,-1,152 +1104386,8,LONG,97,-2,-1,7 +1104388,8,LONG,98,4,7,82 +1104390,8,LONG,99,3,-5,45 +1104392,8,LONG,100,4,7,74 +1104394,8,LONG,101,7,0,50 +1104396,8,LONG,102,-2,3,19 +1104398,8,LONG,103,2,-5,33 +1104400,8,LONG,104,0,3,10 +1104402,8,LONG,105,0,5,26 +1104404,8,LONG,106,9,-1,84 +1104406,8,LONG,107,9,6,122 +1104408,8,LONG,108,0,0,0 +1104410,8,LONG,109,0,-8,76 +1104412,8,LONG,110,-2,-1,6 +1104414,8,LONG,111,2,-5,31 +1104416,8,LONG,112,0,3,13 +1104418,8,LONG,113,0,-2,7 +1104420,8,LONG,114,-3,7,69 +1104422,8,LONG,115,8,-3,80 +1104424,8,LONG,116,0,-7,49 +1104426,8,LONG,117,0,-5,28 +1104428,8,LONG,118,1,-1,2 +1104430,8,LONG,119,0,6,42 +1104432,8,LONG,120,1,9,87 +1104434,8,LONG,121,0,-4,16 +1104436,8,LONG,122,5,-2,33 +1104438,8,LONG,123,1,3,14 +1104440,8,LONG,124,2,-3,17 +1104442,8,LONG,125,0,3,14 +1104444,8,LONG,126,-2,-4,29 +1104446,8,LONG,127,-4,-3,36 +1104448,8,LONG,128,-3,-4,28 +1104450,8,LONG,129,-5,4,46 +1104452,8,LONG,130,4,2,26 +1104454,8,LONG,131,2,-11,133 +1104456,8,LONG,132,11,0,125 +1104458,8,LONG,133,4,0,21 +1104460,8,LONG,134,5,1,38 +1104462,8,LONG,135,-8,5,101 +1104464,8,LONG,136,0,-9,93 +1104466,8,LONG,137,-7,7,102 +1104468,8,LONG,138,-4,3,34 +1104470,8,LONG,139,-7,-1,63 +1104472,8,LONG,140,-7,0,55 +1104474,8,LONG,141,46,-99,12017 +1104476,8,LONG,142,48,-98,12003 +1104478,8,LONG,143,57,-79,9611 +1104480,8,LONG,144,73,-66,9909 +1104482,8,LONG,145,79,-59,9917 +1104484,8,LONG,146,88,-49,10170 +1104486,8,LONG,147,98,-38,11160 +1104488,8,LONG,148,104,-28,11842 +1104490,8,LONG,149,97,-15,9733 +1104492,8,LONG,150,99,-7,9962 +1104494,8,LONG,151,99,4,9931 +1104496,8,LONG,152,94,25,9495 +1104498,8,LONG,153,99,40,11514 +1104500,8,LONG,154,84,50,9661 +1104502,8,LONG,155,87,62,11498 +1104504,8,LONG,156,77,66,10389 +1104506,8,LONG,157,64,81,10808 +1104508,8,LONG,158,54,95,12075 +1104510,8,LONG,159,47,90,10450 +1104512,8,LONG,160,2,-2,15 +1104514,8,LONG,161,4,3,29 +1104516,8,LONG,162,-3,2,13 +1104518,8,LONG,163,-3,0,9 +1104520,8,LONG,164,-1,2,7 +1104522,8,LONG,165,-3,2,20 +1104524,8,LONG,166,0,0,0 +1104526,8,LONG,167,9,9,171 +1104528,8,LONG,168,0,7,63 +1104530,8,LONG,169,-3,-4,35 +1104532,8,LONG,170,3,6,58 +1104534,8,LONG,171,1,1,4 +1104536,8,LONG,172,3,1,14 +1104538,8,LONG,173,-3,9,104 +1104540,8,LONG,174,-2,-12,159 +1104542,8,LONG,175,-2,-8,72 +1104544,8,LONG,176,5,1,29 +1104546,8,LONG,177,3,6,51 +1104548,8,LONG,178,-4,4,35 +1104550,8,LONG,179,-8,1,67 +1104552,8,LONG,180,-10,2,108 +1104554,8,LONG,181,-1,-10,124 +1104556,8,LONG,182,-4,4,47 +1104558,8,LONG,183,7,2,57 +1104560,8,LONG,184,4,-2,32 +1104562,8,LONG,185,-9,5,113 +1104564,8,LONG,186,1,2,6 +1104566,8,LONG,187,-6,-3,53 +1104568,8,LONG,188,1,0,2 +1104570,8,LONG,189,-2,9,100 +1104572,8,LONG,190,-2,0,8 +1104574,8,LONG,191,2,0,7 +1104576,8,LONG,192,0,-1,3 +1104578,8,LONG,193,-9,0,81 +1104580,8,LONG,194,1,-2,9 +1104582,8,LONG,195,7,-5,78 +1104584,8,LONG,196,0,10,102 +1104586,8,LONG,197,-8,-2,81 +1104588,8,LONG,198,-3,3,24 +1104590,8,LONG,199,-7,2,61 +1104592,8,LONG,200,2,0,4 +1104594,8,LONG,201,0,-4,20 +1104596,8,LONG,202,3,6,49 +1104598,8,LONG,203,5,4,46 +1104600,8,LONG,204,3,1,14 +1104602,8,LONG,205,0,9,93 +1104604,8,LONG,206,4,0,18 +1104606,8,LONG,207,5,1,27 +1104608,8,LONG,208,0,2,7 +1104610,8,LONG,209,-4,0,23 +1104612,8,LONG,210,0,0,0 +1104614,8,LONG,211,-3,-5,45 +1104616,8,LONG,212,-4,0,17 +1104618,8,LONG,213,-4,-3,31 +1104620,8,LONG,214,-6,-1,49 +1104622,8,LONG,215,-5,14,234 +1104624,8,LONG,216,-5,6,64 +1104626,8,LONG,217,4,-4,35 +1104628,8,LONG,218,1,4,21 +1104630,8,LONG,219,9,-7,148 +1104632,8,LONG,220,2,7,59 +1104634,8,LONG,221,4,-5,56 +1104636,8,LONG,222,0,-2,6 +1104638,8,LONG,223,2,3,15 +1104640,8,LONG,224,-3,-2,20 +1104642,8,LONG,225,-8,2,70 +1104644,8,LONG,226,7,-7,114 +1104646,8,LONG,227,-3,0,12 +1104648,8,LONG,228,-13,-4,195 +1104650,8,LONG,229,-3,5,41 +1104652,8,LONG,230,-7,0,52 +1104654,8,LONG,231,-4,0,16 +1104656,8,LONG,232,-6,-1,42 +1104658,8,LONG,233,-2,4,28 +1104660,8,LONG,234,0,3,11 +1104662,8,LONG,235,4,-1,23 +1104664,8,LONG,236,-3,-4,35 +1104666,8,LONG,237,0,-3,11 +1104668,8,LONG,238,1,-2,9 +1104670,8,LONG,239,-1,3,11 +1104672,8,LONG,240,4,7,73 +1104674,8,LONG,241,-30,-33,2091 +1104676,8,LONG,242,-34,-28,2006 +1104678,8,LONG,243,-30,-40,2572 +1104680,8,LONG,244,-10,-34,1321 +1104682,8,LONG,245,-13,-44,2160 +1104684,8,LONG,246,-4,-52,2770 +1104686,8,LONG,247,9,-45,2167 +1104688,8,LONG,248,-1,-49,2459 +1104690,8,LONG,249,8,-42,1845 +1104692,8,LONG,250,8,-37,1465 +1104694,8,LONG,251,27,-48,3094 +1104696,8,LONG,252,25,-47,2895 +1104698,8,LONG,253,33,-44,3053 +1104700,8,LONG,254,44,-38,3481 +1104702,8,LONG,255,39,-36,2845 +1104704,8,LONG,256,46,-29,2991 +1104706,8,LONG,257,45,-20,2494 +1104708,8,LONG,258,49,-11,2557 +1104710,8,LONG,259,50,0,2512 +1104712,8,LONG,260,6,-2,54 +1104714,8,LONG,261,1,6,41 +1104716,8,LONG,262,10,1,108 +1104718,8,LONG,263,-2,9,102 +1104720,8,LONG,264,-12,4,177 +1104722,8,LONG,265,0,2,8 +1104724,8,LONG,266,-4,4,37 +1104726,8,LONG,267,5,-8,110 +1104728,8,LONG,268,0,-4,20 +1104730,8,LONG,269,2,1,11 +1104732,8,LONG,270,9,11,216 +1104734,8,LONG,271,-1,0,3 +1104736,8,LONG,272,-6,-2,49 +1104738,8,LONG,273,-5,-3,40 +1104740,8,LONG,274,8,6,118 +1104742,8,LONG,275,1,0,2 +1104744,8,LONG,276,1,0,4 +1104746,8,LONG,277,-4,3,27 +1104748,8,LONG,278,3,2,19 +1104750,8,LONG,279,-12,0,158 +1104752,8,LONG,280,1,3,12 +1104754,8,LONG,281,0,-4,23 +1104756,8,LONG,282,6,0,46 +1104758,8,LONG,283,4,-2,31 +1104760,8,LONG,284,-3,1,13 +1104762,8,LONG,285,1,0,1 +1104764,8,LONG,286,-4,0,17 +1104766,8,LONG,287,10,2,127 +1104768,8,LONG,288,-1,4,23 +1104770,8,LONG,289,2,2,14 +1104772,8,LONG,290,-4,-1,20 +1104774,8,LONG,291,3,-1,13 +1104776,8,LONG,292,1,0,1 +1104778,8,LONG,293,0,-3,12 +1104780,8,LONG,294,-2,6,45 +1104782,8,LONG,295,1,-3,12 +1104784,8,LONG,296,-1,-7,67 +1104786,8,LONG,297,1,-5,30 +1104788,8,LONG,298,-5,3,39 +1104790,8,LONG,299,3,0,12 +1104792,8,LONG,300,-2,2,11 +1104794,8,LONG,301,-5,-4,46 +1104796,8,LONG,302,0,0,0 +1104798,8,LONG,303,2,4,25 +1104800,8,LONG,304,3,0,11 +1104802,8,LONG,305,1,-2,8 +1104804,8,LONG,306,-1,-5,36 +1104806,8,LONG,307,3,4,27 +1104808,8,LONG,308,0,1,2 +1104810,8,LONG,309,-5,-5,64 +1104812,8,LONG,310,-2,0,5 +1104814,8,LONG,311,-4,-5,49 +1104816,8,LONG,312,-2,-7,59 +1104818,8,LONG,313,8,2,81 +1104820,8,LONG,314,0,1,1 +1104822,8,LONG,315,4,2,23 +1104824,8,LONG,316,1,4,20 +1104826,8,LONG,317,7,-3,68 +1104828,8,LONG,318,-4,13,189 +1104830,8,LONG,319,0,6,42 +1104832,8,LONG,320,2,-4,26 +1104834,8,LONG,321,6,1,46 +1104836,8,LONG,322,-7,2,62 +1104838,8,LONG,323,-7,3,59 +1104840,8,LONG,324,4,-3,35 +1104842,8,LONG,325,2,0,6 +1104844,8,LONG,326,-1,-2,10 +1104846,8,LONG,327,-7,0,58 +1104848,8,LONG,328,3,4,33 +1104850,8,LONG,329,1,3,17 +1104852,8,LONG,330,12,8,223 +1104854,8,LONG,331,-2,0,8 +1104856,8,LONG,332,1,3,16 +1104858,8,LONG,333,5,9,126 +1104860,8,LONG,334,9,-2,92 +1104862,8,LONG,335,5,-2,42 +1104864,8,LONG,336,-7,-6,89 +1104866,8,LONG,337,0,2,5 +1104868,8,LONG,338,-2,4,28 +1104870,8,LONG,339,4,5,42 +1104872,8,LONG,340,1,-2,6 +1104874,8,LONG,341,4,-4,37 +1104876,8,LONG,342,0,-4,20 +1104878,8,LONG,343,0,1,1 +1104880,8,LONG,344,-5,-4,44 +1104882,8,LONG,345,10,0,114 +1104884,8,LONG,346,0,-6,37 +1104886,8,LONG,347,-9,3,97 +1104888,8,LONG,348,-3,1,13 +1104890,8,LONG,349,0,5,25 +1104892,8,LONG,350,0,6,42 +1104894,8,LONG,351,-3,5,41 +1104896,8,LONG,352,8,3,79 +1104898,8,LONG,353,2,0,5 +1104900,8,LONG,354,1,0,3 +1104902,8,LONG,355,1,-4,20 +1104904,8,LONG,356,4,-3,34 +1104906,8,LONG,357,-4,7,76 +1104908,8,LONG,358,0,-10,116 +1104910,8,LONG,359,-4,0,22 +1104912,8,LONG,360,-4,3,29 +1104914,8,LONG,361,-4,-8,96 +1104916,8,LONG,362,-3,-2,17 +1104918,8,LONG,363,3,6,55 +1104920,8,LONG,364,0,2,8 +1104922,8,LONG,365,-3,-1,17 +1104924,8,LONG,366,-1,-5,37 +1104926,8,LONG,367,8,0,78 +1104928,8,LONG,368,3,-5,45 +1104930,8,LONG,369,10,5,147 +1104932,8,LONG,370,-2,-3,23 +1104934,8,LONG,371,6,2,43 +1104936,8,LONG,372,2,5,37 +1104938,8,LONG,373,3,0,10 +1104940,8,LONG,374,-3,3,24 +1104942,8,LONG,375,-5,0,29 +1104944,8,LONG,376,-2,5,38 +1104946,8,LONG,377,2,0,4 +1104948,8,LONG,378,1,2,7 +1104950,8,LONG,379,0,-2,5 +1104952,8,LONG,380,-11,-4,156 +1104954,8,LONG,381,0,-1,1 +1104956,8,LONG,382,3,-4,28 +1104958,8,LONG,383,0,-4,22 +1104960,8,LONG,384,4,-1,21 +1104962,8,LONG,385,-1,-1,2 +1104964,8,LONG,386,0,0,0 +1104966,8,LONG,387,3,-6,58 +1104968,8,LONG,388,3,-3,30 +1104970,8,LONG,389,4,6,63 +1104972,8,LONG,390,1,-7,64 +1104974,8,LONG,391,2,26,716 +1104976,8,LONG,392,1,24,607 +1104978,8,LONG,393,-5,20,438 +1104980,8,LONG,394,-3,42,1838 +1104982,8,LONG,395,-9,24,709 +1104984,8,LONG,396,-9,24,682 +1104986,8,LONG,397,-1,23,536 +1104988,8,LONG,398,-19,14,602 +1104990,8,LONG,399,-9,12,245 +1104992,8,LONG,400,-11,22,623 +1104994,8,LONG,401,-31,15,1257 +1104996,8,LONG,402,-16,16,523 +1104998,8,LONG,403,-23,4,598 +1105000,8,LONG,404,-25,3,651 +1105002,8,LONG,405,-30,6,955 +1105004,8,LONG,406,-21,-7,502 +1105006,8,LONG,407,-17,-8,375 +1105008,8,LONG,408,-24,-18,954 +1105010,8,LONG,409,-17,-17,611 +1105012,8,LONG,410,0,0,0 +1105014,8,LONG,411,-1,2,9 +1105016,8,LONG,412,0,3,13 +1105018,8,LONG,413,7,-6,97 +1105020,8,LONG,414,3,0,11 +1105022,8,LONG,415,-5,4,52 +1105024,8,LONG,416,0,2,4 +1105026,8,LONG,417,-3,-9,101 +1105028,8,LONG,418,3,3,19 +1105030,8,LONG,419,10,-3,116 +1105032,8,LONG,420,-1,5,38 +1105034,8,LONG,421,5,10,128 +1105036,8,LONG,422,-7,6,110 +1105038,8,LONG,423,2,1,10 +1105040,8,LONG,424,-5,9,112 +1105042,8,LONG,425,-4,4,45 +1105044,8,LONG,426,0,-1,1 +1105046,8,LONG,427,4,11,148 +1105048,8,LONG,428,7,5,83 +1105050,8,LONG,429,-4,-8,84 +1105052,8,LONG,430,-2,1,7 +1105054,8,LONG,431,3,0,9 +1105056,8,LONG,432,6,0,45 +1105058,8,LONG,433,5,-2,33 +1105060,8,LONG,434,-2,-4,30 +1105062,8,LONG,435,3,4,34 +1105064,8,LONG,436,4,-9,104 +1105066,8,LONG,437,-3,3,23 +1105068,8,LONG,438,5,5,52 +1105070,8,LONG,439,0,0,1 +1105072,8,LONG,440,-3,0,16 +1105074,8,LONG,441,-1,0,1 +1105076,8,LONG,442,0,5,34 +1105078,8,LONG,443,1,-8,67 +1105080,8,LONG,444,5,-5,63 +1105082,8,LONG,445,3,0,13 +1105084,8,LONG,446,-8,-4,95 +1105086,8,LONG,447,5,-4,42 +1105088,8,LONG,448,0,3,10 +1105090,8,LONG,449,-3,5,47 +1105092,8,LONG,450,1,-4,24 +1105094,8,LONG,451,-2,1,7 +1105096,8,LONG,452,3,3,25 +1105098,8,LONG,453,-2,3,18 +1105100,8,LONG,454,3,5,45 +1105102,8,LONG,455,4,-1,25 +1105104,8,LONG,456,-5,-11,149 +1105106,8,LONG,457,-3,4,33 +1105108,8,LONG,458,-1,-4,19 +1105110,8,LONG,459,-16,7,321 +1105112,8,LONG,460,3,5,44 +1105114,8,LONG,461,-3,-2,18 +1105116,8,LONG,462,0,2,6 +1105118,8,LONG,463,0,-1,1 +1105120,8,LONG,464,1,5,29 +1105122,8,LONG,465,3,-1,17 +1105124,8,LONG,466,-9,1,85 +1105126,8,LONG,467,-7,8,138 +1105128,8,LONG,468,-2,-1,11 +1105130,8,LONG,469,-1,-1,3 +1105132,8,LONG,470,-1,3,16 +1105134,8,LONG,471,-5,-3,40 +1105136,8,LONG,472,-1,-5,28 +1105138,8,LONG,473,1,4,21 +1105140,8,LONG,474,5,0,25 +1105142,8,LONG,475,3,1,17 +1105144,8,LONG,476,-1,0,3 +1105146,8,LONG,477,-3,-4,33 +1105148,8,LONG,478,7,3,64 +1105150,8,LONG,479,-9,9,185 +1105152,8,LONG,480,0,-5,31 +1105154,8,LONG,481,-6,-3,50 +1105156,8,LONG,482,1,4,22 +1105158,8,LONG,483,-2,0,7 +1105160,8,LONG,484,-5,6,81 +1105162,8,LONG,485,-5,0,30 +1105164,8,LONG,486,4,1,21 +1105166,8,LONG,487,4,3,35 +1105168,8,LONG,488,5,2,37 +1105170,8,LONG,489,-4,-4,43 +1105172,8,LONG,490,7,-3,75 +1105174,8,LONG,491,-7,0,54 +1105176,8,LONG,492,6,1,45 +1105178,8,LONG,493,0,-3,11 +1105180,8,LONG,494,9,10,195 +1105182,8,LONG,495,0,5,34 +1105184,8,LONG,496,1,0,4 +1105186,8,LONG,497,1,-2,8 +1105188,8,LONG,498,-7,11,182 +1105190,8,LONG,499,0,2,4 +1105192,8,LONG,500,-4,3,35 +1105194,8,LONG,501,2,3,20 +1105196,8,LONG,502,-14,2,209 +1105198,8,LONG,503,0,-6,41 +1105200,8,LONG,504,1,2,9 +1105202,8,LONG,505,1,-10,103 +1105204,8,LONG,506,0,5,32 +1105206,8,LONG,507,-2,-5,33 +1105208,8,LONG,508,-7,-1,55 +1105210,8,LONG,509,-2,-5,35 +1105212,8,LONG,510,-6,-5,66 +1105214,8,LONG,511,-1,3,13 +1242216,9,LONG,0,0,0,0 +1242218,9,LONG,1,12,32,1230 +1242220,9,LONG,2,1,-15,235 +1242222,9,LONG,3,-8,-4,102 +1242224,9,LONG,4,18,-2,344 +1242226,9,LONG,5,-15,10,333 +1242228,9,LONG,6,-18,9,431 +1242230,9,LONG,7,11,7,179 +1242232,9,LONG,8,2,13,199 +1242234,9,LONG,9,6,-10,164 +1242236,9,LONG,10,-6,11,171 +1242238,9,LONG,11,9,-3,109 +1242240,9,LONG,12,-1,-1,3 +1242242,9,LONG,13,-4,3,34 +1242244,9,LONG,14,-16,6,315 +1242246,9,LONG,15,8,0,68 +1242248,9,LONG,16,7,7,114 +1242250,9,LONG,17,4,15,253 +1242252,9,LONG,18,-3,6,55 +1242254,9,LONG,19,-9,-21,560 +1242256,9,LONG,20,17,16,559 +1242258,9,LONG,21,8,13,253 +1242260,9,LONG,22,-3,-8,80 +1242262,9,LONG,23,0,-18,329 +1242264,9,LONG,24,-7,13,221 +1242266,9,LONG,25,0,24,580 +1242268,9,LONG,26,-6,13,229 +1242270,9,LONG,27,-12,6,207 +1242272,9,LONG,28,4,8,88 +1242274,9,LONG,29,-4,27,779 +1242276,9,LONG,30,7,-16,310 +1242278,9,LONG,31,-20,25,1060 +1242280,9,LONG,32,2,-3,22 +1242282,9,LONG,33,0,20,423 +1242284,9,LONG,34,-19,8,451 +1242286,9,LONG,35,24,6,642 +1242288,9,LONG,36,-23,23,1080 +1242290,9,LONG,37,3,-5,44 +1242292,9,LONG,38,0,1,2 +1242294,9,LONG,39,13,3,205 +1242296,9,LONG,40,-7,-4,74 +1242298,9,LONG,41,7,14,271 +1242300,9,LONG,42,2,-10,117 +1242302,9,LONG,43,14,-6,255 +1242304,9,LONG,44,2,6,48 +1242306,9,LONG,45,8,-18,403 +1242308,9,LONG,46,14,12,355 +1242310,9,LONG,47,-2,-6,48 +1242312,9,LONG,48,4,-8,97 +1242314,9,LONG,49,-18,-6,377 +1242316,9,LONG,50,-2,-25,660 +1242318,9,LONG,51,2,0,7 +1242320,9,LONG,52,-13,-8,244 +1242322,9,LONG,53,-11,7,183 +1242324,9,LONG,54,0,5,30 +1242326,9,LONG,55,-18,-10,475 +1242328,9,LONG,56,-1,11,140 +1242330,9,LONG,57,-17,9,390 +1242332,9,LONG,58,-13,0,186 +1242334,9,LONG,59,-11,0,121 +1242336,9,LONG,60,-8,21,537 +1242338,9,LONG,61,16,-4,296 +1242340,9,LONG,62,-2,5,37 +1242342,9,LONG,63,-6,8,109 +1242344,9,LONG,64,-16,5,305 +1242346,9,LONG,65,-22,-14,690 +1242348,9,LONG,66,-1,6,38 +1242350,9,LONG,67,6,6,83 +1242352,9,LONG,68,11,0,124 +1242354,9,LONG,69,-3,-11,147 +1242356,9,LONG,70,4,-16,287 +1242358,9,LONG,71,10,11,246 +1242360,9,LONG,72,16,-11,405 +1242362,9,LONG,73,-10,-8,174 +1242364,9,LONG,74,2,-20,407 +1242366,9,LONG,75,8,-18,408 +1242368,9,LONG,76,5,8,107 +1242370,9,LONG,77,-13,0,195 +1242372,9,LONG,78,-9,-1,95 +1242374,9,LONG,79,26,0,700 +1242376,9,LONG,80,-1,-2,10 +1242378,9,LONG,81,7,9,146 +1242380,9,LONG,82,10,14,312 +1242382,9,LONG,83,17,-2,328 +1242384,9,LONG,84,3,11,143 +1242386,9,LONG,85,-3,-21,493 +1242388,9,LONG,86,-7,-29,902 +1242390,9,LONG,87,-13,1,182 +1242392,9,LONG,88,-10,-6,158 +1242394,9,LONG,89,6,0,39 +1242396,9,LONG,90,11,7,178 +1242398,9,LONG,91,-21,-10,596 +1242400,9,LONG,92,23,8,633 +1242402,9,LONG,93,-2,-22,527 +1242404,9,LONG,94,10,0,100 +1242406,9,LONG,95,6,-4,66 +1242408,9,LONG,96,-6,3,51 +1242410,9,LONG,97,-7,7,115 +1242412,9,LONG,98,3,-2,19 +1242414,9,LONG,99,1,8,77 +1242416,9,LONG,100,1,2,8 +1242418,9,LONG,101,4,6,54 +1242420,9,LONG,102,-3,0,10 +1242422,9,LONG,103,1,4,21 +1242424,9,LONG,104,1,-4,26 +1242426,9,LONG,105,1,2,5 +1242428,9,LONG,106,8,-6,122 +1242430,9,LONG,107,-10,12,258 +1242432,9,LONG,108,-1,0,3 +1242434,9,LONG,109,-5,-1,32 +1242436,9,LONG,110,1,-6,49 +1242438,9,LONG,111,-3,-4,29 +1242440,9,LONG,112,-1,1,3 +1242442,9,LONG,113,3,-3,21 +1242444,9,LONG,114,3,-4,34 +1242446,9,LONG,115,4,-3,29 +1242448,9,LONG,116,5,-1,34 +1242450,9,LONG,117,1,-7,53 +1242452,9,LONG,118,2,5,34 +1242454,9,LONG,119,-1,0,3 +1242456,9,LONG,120,-5,1,33 +1242458,9,LONG,121,4,0,18 +1242460,9,LONG,122,-6,-3,58 +1242462,9,LONG,123,1,2,9 +1242464,9,LONG,124,3,4,30 +1242466,9,LONG,125,4,-2,31 +1242468,9,LONG,126,-1,-4,25 +1242470,9,LONG,127,5,3,44 +1242472,9,LONG,128,6,-2,54 +1242474,9,LONG,129,-5,2,43 +1242476,9,LONG,130,1,-4,24 +1242478,9,LONG,131,1,-3,18 +1242480,9,LONG,132,-2,1,9 +1242482,9,LONG,133,3,2,18 +1242484,9,LONG,134,-3,1,17 +1242486,9,LONG,135,6,0,43 +1242488,9,LONG,136,7,5,81 +1242490,9,LONG,137,2,6,45 +1242492,9,LONG,138,0,-2,5 +1242494,9,LONG,139,0,-7,53 +1242496,9,LONG,140,-10,-3,122 +1242498,9,LONG,141,90,39,9789 +1242500,9,LONG,142,91,62,12325 +1242502,9,LONG,143,79,69,11186 +1242504,9,LONG,144,71,79,11429 +1242506,9,LONG,145,61,72,9094 +1242508,9,LONG,146,51,80,9183 +1242510,9,LONG,147,41,92,10366 +1242512,9,LONG,148,17,96,9593 +1242514,9,LONG,149,6,97,9592 +1242516,9,LONG,150,2,94,8927 +1242518,9,LONG,151,0,93,8784 +1242520,9,LONG,152,-17,101,10678 +1242522,9,LONG,153,-35,83,8196 +1242524,9,LONG,154,-54,82,9827 +1242526,9,LONG,155,-63,77,10065 +1242528,9,LONG,156,-70,76,10700 +1242530,9,LONG,157,-82,62,10701 +1242532,9,LONG,158,-89,48,10348 +1242534,9,LONG,159,-97,46,11766 +1242536,9,LONG,160,-4,10,133 +1242538,9,LONG,161,-6,-1,48 +1242540,9,LONG,162,5,5,64 +1242542,9,LONG,163,-3,-4,32 +1242544,9,LONG,164,-2,-1,8 +1242546,9,LONG,165,8,-9,166 +1242548,9,LONG,166,-6,-1,39 +1242550,9,LONG,167,-1,1,4 +1242552,9,LONG,168,1,1,3 +1242554,9,LONG,169,-4,2,26 +1242556,9,LONG,170,9,-1,96 +1242558,9,LONG,171,-1,3,14 +1242560,9,LONG,172,0,-5,35 +1242562,9,LONG,173,4,7,82 +1242564,9,LONG,174,4,0,18 +1242566,9,LONG,175,-4,2,24 +1242568,9,LONG,176,1,-3,17 +1242570,9,LONG,177,2,5,32 +1242572,9,LONG,178,-1,1,4 +1242574,9,LONG,179,1,0,1 +1242576,9,LONG,180,6,-3,49 +1242578,9,LONG,181,2,2,13 +1242580,9,LONG,182,-4,0,17 +1242582,9,LONG,183,-2,8,82 +1242584,9,LONG,184,-2,0,6 +1242586,9,LONG,185,-1,-3,12 +1242588,9,LONG,186,5,-5,61 +1242590,9,LONG,187,-5,7,83 +1242592,9,LONG,188,1,-1,3 +1242594,9,LONG,189,-5,-14,249 +1242596,9,LONG,190,-4,-3,26 +1242598,9,LONG,191,1,4,25 +1242600,9,LONG,192,-1,-5,37 +1242602,9,LONG,193,0,3,15 +1242604,9,LONG,194,-7,-2,56 +1242606,9,LONG,195,-11,6,168 +1242608,9,LONG,196,0,-7,60 +1242610,9,LONG,197,3,4,28 +1242612,9,LONG,198,-1,-1,5 +1242614,9,LONG,199,1,0,3 +1242616,9,LONG,200,7,0,54 +1242618,9,LONG,201,2,0,6 +1242620,9,LONG,202,-2,3,20 +1242622,9,LONG,203,13,3,193 +1242624,9,LONG,204,7,0,56 +1242626,9,LONG,205,6,-7,93 +1242628,9,LONG,206,0,4,19 +1242630,9,LONG,207,7,2,63 +1242632,9,LONG,208,0,-1,2 +1242634,9,LONG,209,3,-6,56 +1242636,9,LONG,210,-7,-2,59 +1242638,9,LONG,211,6,0,38 +1242640,9,LONG,212,0,1,2 +1242642,9,LONG,213,-5,5,51 +1242644,9,LONG,214,-1,4,21 +1242646,9,LONG,215,-9,0,87 +1242648,9,LONG,216,-1,5,28 +1242650,9,LONG,217,0,12,169 +1242652,9,LONG,218,-7,0,61 +1242654,9,LONG,219,6,1,37 +1242656,9,LONG,220,10,0,110 +1242658,9,LONG,221,0,-3,9 +1242660,9,LONG,222,2,0,8 +1242662,9,LONG,223,0,1,2 +1242664,9,LONG,224,9,0,83 +1242666,9,LONG,225,3,-7,70 +1242668,9,LONG,226,0,-1,1 +1242670,9,LONG,227,-6,-8,108 +1242672,9,LONG,228,4,3,28 +1242674,9,LONG,229,3,12,171 +1242676,9,LONG,230,-2,0,6 +1242678,9,LONG,231,2,8,72 +1242680,9,LONG,232,2,-1,7 +1242682,9,LONG,233,2,3,20 +1242684,9,LONG,234,-3,-1,17 +1242686,9,LONG,235,-1,-5,29 +1242688,9,LONG,236,1,-2,8 +1242690,9,LONG,237,2,0,8 +1242692,9,LONG,238,0,18,356 +1242694,9,LONG,239,-3,0,13 +1242696,9,LONG,240,-2,0,7 +1242698,9,LONG,241,-50,6,2597 +1242700,9,LONG,242,-38,20,1890 +1242702,9,LONG,243,-46,0,2127 +1242704,9,LONG,244,-55,-13,3306 +1242706,9,LONG,245,-50,-20,2925 +1242708,9,LONG,246,-39,-23,2126 +1242710,9,LONG,247,-44,-23,2539 +1242712,9,LONG,248,-39,-42,3389 +1242714,9,LONG,249,-36,-29,2180 +1242716,9,LONG,250,-28,-31,1833 +1242718,9,LONG,251,-28,-52,3535 +1242720,9,LONG,252,-12,-43,2049 +1242722,9,LONG,253,-14,-41,1961 +1242724,9,LONG,254,-10,-46,2320 +1242726,9,LONG,255,0,-57,3299 +1242728,9,LONG,256,3,-36,1321 +1242730,9,LONG,257,-1,-48,2347 +1242732,9,LONG,258,20,-48,2759 +1242734,9,LONG,259,30,-47,3163 +1242736,9,LONG,260,6,0,46 +1242738,9,LONG,261,0,2,4 +1242740,9,LONG,262,-3,1,18 +1242742,9,LONG,263,-2,3,14 +1242744,9,LONG,264,3,0,12 +1242746,9,LONG,265,0,0,0 +1242748,9,LONG,266,3,-4,31 +1242750,9,LONG,267,-5,2,40 +1242752,9,LONG,268,0,-1,4 +1242754,9,LONG,269,-3,7,70 +1242756,9,LONG,270,0,7,53 +1242758,9,LONG,271,2,1,9 +1242760,9,LONG,272,4,-2,24 +1242762,9,LONG,273,5,8,99 +1242764,9,LONG,274,-1,0,2 +1242766,9,LONG,275,-7,-1,57 +1242768,9,LONG,276,7,-7,109 +1242770,9,LONG,277,-7,3,70 +1242772,9,LONG,278,2,1,9 +1242774,9,LONG,279,-3,-8,90 +1242776,9,LONG,280,0,-3,12 +1242778,9,LONG,281,-3,1,17 +1242780,9,LONG,282,5,1,29 +1242782,9,LONG,283,9,-1,88 +1242784,9,LONG,284,2,-1,5 +1242786,9,LONG,285,0,-4,17 +1242788,9,LONG,286,0,1,3 +1242790,9,LONG,287,-6,0,42 +1242792,9,LONG,288,2,-13,192 +1242794,9,LONG,289,3,0,9 +1242796,9,LONG,290,7,-6,89 +1242798,9,LONG,291,-11,0,141 +1242800,9,LONG,292,5,1,37 +1242802,9,LONG,293,1,4,21 +1242804,9,LONG,294,-3,-6,45 +1242806,9,LONG,295,-2,-7,64 +1242808,9,LONG,296,11,1,129 +1242810,9,LONG,297,-9,1,93 +1242812,9,LONG,298,4,0,18 +1242814,9,LONG,299,5,-1,37 +1242816,9,LONG,300,5,0,30 +1242818,9,LONG,301,7,-10,162 +1242820,9,LONG,302,-6,-3,58 +1242822,9,LONG,303,-2,6,53 +1242824,9,LONG,304,1,1,5 +1242826,9,LONG,305,1,5,32 +1242828,9,LONG,306,-13,0,188 +1242830,9,LONG,307,-3,7,62 +1242832,9,LONG,308,3,3,28 +1242834,9,LONG,309,3,2,16 +1242836,9,LONG,310,1,1,4 +1242838,9,LONG,311,-4,-2,23 +1242840,9,LONG,312,1,3,14 +1242842,9,LONG,313,0,0,0 +1242844,9,LONG,314,7,7,102 +1242846,9,LONG,315,1,-3,15 +1242848,9,LONG,316,-6,0,41 +1242850,9,LONG,317,0,-4,18 +1242852,9,LONG,318,-2,-4,25 +1242854,9,LONG,319,1,-4,25 +1242856,9,LONG,320,7,2,58 +1242858,9,LONG,321,9,-1,84 +1242860,9,LONG,322,-2,1,7 +1242862,9,LONG,323,5,-7,93 +1242864,9,LONG,324,0,-7,57 +1242866,9,LONG,325,-1,4,19 +1242868,9,LONG,326,7,8,141 +1242870,9,LONG,327,9,2,100 +1242872,9,LONG,328,7,0,63 +1242874,9,LONG,329,-1,2,10 +1242876,9,LONG,330,-4,-1,17 +1242878,9,LONG,331,6,-8,114 +1242880,9,LONG,332,3,3,25 +1242882,9,LONG,333,-3,5,36 +1242884,9,LONG,334,-5,0,30 +1242886,9,LONG,335,8,7,134 +1242888,9,LONG,336,5,-9,129 +1242890,9,LONG,337,0,-2,7 +1242892,9,LONG,338,2,-6,50 +1242894,9,LONG,339,-5,9,133 +1242896,9,LONG,340,8,-1,66 +1242898,9,LONG,341,-4,-3,34 +1242900,9,LONG,342,-5,-1,31 +1242902,9,LONG,343,6,-4,62 +1242904,9,LONG,344,-4,0,21 +1242906,9,LONG,345,2,-4,24 +1242908,9,LONG,346,-3,4,36 +1242910,9,LONG,347,-1,-4,20 +1242912,9,LONG,348,4,-3,36 +1242914,9,LONG,349,5,-8,98 +1242916,9,LONG,350,-6,4,70 +1242918,9,LONG,351,-1,1,5 +1242920,9,LONG,352,2,0,7 +1242922,9,LONG,353,9,3,108 +1242924,9,LONG,354,-2,-8,85 +1242926,9,LONG,355,1,2,9 +1242928,9,LONG,356,-2,0,8 +1242930,9,LONG,357,5,-1,29 +1242932,9,LONG,358,5,11,165 +1242934,9,LONG,359,5,-7,84 +1242936,9,LONG,360,2,-1,8 +1242938,9,LONG,361,-2,3,23 +1242940,9,LONG,362,4,2,23 +1242942,9,LONG,363,-3,-2,18 +1242944,9,LONG,364,-1,2,10 +1242946,9,LONG,365,3,-3,23 +1242948,9,LONG,366,-5,2,32 +1242950,9,LONG,367,-5,-2,39 +1242952,9,LONG,368,-3,0,10 +1242954,9,LONG,369,0,-5,25 +1242956,9,LONG,370,4,-3,30 +1242958,9,LONG,371,1,-5,31 +1242960,9,LONG,372,0,-9,93 +1242962,9,LONG,373,-8,-6,119 +1242964,9,LONG,374,5,0,27 +1242966,9,LONG,375,-8,-6,115 +1242968,9,LONG,376,-6,-1,41 +1242970,9,LONG,377,-2,4,28 +1242972,9,LONG,378,-6,0,42 +1242974,9,LONG,379,-1,-2,8 +1242976,9,LONG,380,5,0,32 +1242978,9,LONG,381,3,-4,30 +1242980,9,LONG,382,9,2,92 +1242982,9,LONG,383,-2,-7,64 +1242984,9,LONG,384,-8,-6,111 +1242986,9,LONG,385,11,1,145 +1242988,9,LONG,386,-6,-3,58 +1242990,9,LONG,387,-4,1,23 +1242992,9,LONG,388,-1,10,103 +1242994,9,LONG,389,2,-4,22 +1242996,9,LONG,390,3,-3,24 +1242998,9,LONG,391,-7,14,273 +1243000,9,LONG,392,0,27,766 +1243002,9,LONG,393,-5,16,299 +1243004,9,LONG,394,-14,13,399 +1243006,9,LONG,395,-16,9,374 +1243008,9,LONG,396,-26,21,1145 +1243010,9,LONG,397,-17,17,618 +1243012,9,LONG,398,-23,12,701 +1243014,9,LONG,399,-21,10,569 +1243016,9,LONG,400,-29,3,904 +1243018,9,LONG,401,-28,6,838 +1243020,9,LONG,402,-23,4,551 +1243022,9,LONG,403,-28,0,834 +1243024,9,LONG,404,-30,-5,979 +1243026,9,LONG,405,-21,-8,543 +1243028,9,LONG,406,-23,-9,620 +1243030,9,LONG,407,-18,-9,457 +1243032,9,LONG,408,-17,-11,462 +1243034,9,LONG,409,-16,-18,598 +1243036,9,LONG,410,-6,-3,50 +1243038,9,LONG,411,-1,-4,22 +1243040,9,LONG,412,-4,0,24 +1243042,9,LONG,413,-1,-9,90 +1243044,9,LONG,414,2,3,16 +1243046,9,LONG,415,3,-9,99 +1243048,9,LONG,416,-7,1,61 +1243050,9,LONG,417,3,0,13 +1243052,9,LONG,418,-4,9,113 +1243054,9,LONG,419,-3,4,34 +1243056,9,LONG,420,8,2,71 +1243058,9,LONG,421,2,2,12 +1243060,9,LONG,422,-1,3,18 +1243062,9,LONG,423,-1,0,2 +1243064,9,LONG,424,-3,-2,19 +1243066,9,LONG,425,8,-1,67 +1243068,9,LONG,426,-3,3,24 +1243070,9,LONG,427,-10,1,117 +1243072,9,LONG,428,-5,1,29 +1243074,9,LONG,429,-2,-1,7 +1243076,9,LONG,430,-2,0,7 +1243078,9,LONG,431,5,1,31 +1243080,9,LONG,432,-3,1,10 +1243082,9,LONG,433,4,0,17 +1243084,9,LONG,434,-4,-2,27 +1243086,9,LONG,435,-1,-8,71 +1243088,9,LONG,436,4,6,58 +1243090,9,LONG,437,2,-1,9 +1243092,9,LONG,438,-6,2,40 +1243094,9,LONG,439,0,11,142 +1243096,9,LONG,440,-2,-1,9 +1243098,9,LONG,441,0,-3,12 +1243100,9,LONG,442,0,-1,1 +1243102,9,LONG,443,-7,7,115 +1243104,9,LONG,444,12,3,171 +1243106,9,LONG,445,-4,3,36 +1243108,9,LONG,446,3,-1,15 +1243110,9,LONG,447,-3,0,15 +1243112,9,LONG,448,-3,0,10 +1243114,9,LONG,449,8,-23,610 +1243116,9,LONG,450,-2,1,11 +1243118,9,LONG,451,-2,3,19 +1243120,9,LONG,452,3,-4,34 +1243122,9,LONG,453,0,-3,12 +1243124,9,LONG,454,-10,-3,122 +1243126,9,LONG,455,0,0,0 +1243128,9,LONG,456,-1,0,3 +1243130,9,LONG,457,-2,0,8 +1243132,9,LONG,458,2,-5,36 +1243134,9,LONG,459,1,5,33 +1243136,9,LONG,460,-7,0,55 +1243138,9,LONG,461,-9,-1,93 +1243140,9,LONG,462,0,5,31 +1243142,9,LONG,463,-3,3,25 +1243144,9,LONG,464,-2,0,4 +1243146,9,LONG,465,-14,7,263 +1243148,9,LONG,466,4,1,23 +1243150,9,LONG,467,-3,-11,141 +1243152,9,LONG,468,1,-10,111 +1243154,9,LONG,469,-2,-3,16 +1243156,9,LONG,470,7,-4,70 +1243158,9,LONG,471,-5,-8,97 +1243160,9,LONG,472,8,2,79 +1243162,9,LONG,473,-3,6,52 +1243164,9,LONG,474,-2,8,82 +1243166,9,LONG,475,2,-6,49 +1243168,9,LONG,476,2,-3,21 +1243170,9,LONG,477,12,0,156 +1243172,9,LONG,478,-1,4,23 +1243174,9,LONG,479,-5,-16,286 +1243176,9,LONG,480,3,3,25 +1243178,9,LONG,481,0,-4,20 +1243180,9,LONG,482,4,-7,69 +1243182,9,LONG,483,-2,9,100 +1243184,9,LONG,484,1,-1,3 +1243186,9,LONG,485,5,-6,74 +1243188,9,LONG,486,-4,4,35 +1243190,9,LONG,487,4,0,22 +1243192,9,LONG,488,8,7,131 +1243194,9,LONG,489,0,6,38 +1243196,9,LONG,490,3,-6,54 +1243198,9,LONG,491,5,3,49 +1243200,9,LONG,492,13,4,190 +1243202,9,LONG,493,0,7,54 +1243204,9,LONG,494,0,-3,9 +1243206,9,LONG,495,3,1,15 +1243208,9,LONG,496,0,3,15 +1243210,9,LONG,497,0,11,128 +1243212,9,LONG,498,3,5,46 +1243214,9,LONG,499,-6,4,56 +1243216,9,LONG,500,-1,1,7 +1243218,9,LONG,501,-1,1,3 +1243220,9,LONG,502,-3,-3,22 +1243222,9,LONG,503,6,-6,85 +1243224,9,LONG,504,6,-1,39 +1243226,9,LONG,505,-1,-3,15 +1243228,9,LONG,506,2,1,12 +1243230,9,LONG,507,3,-4,31 +1243232,9,LONG,508,4,5,53 +1243234,9,LONG,509,5,-8,93 +1243236,9,LONG,510,11,8,208 +1243238,9,LONG,511,-2,5,32 +1380240,10,LONG,0,-2,3,21 +1380242,10,LONG,1,-13,11,320 +1380244,10,LONG,2,-6,16,323 +1380246,10,LONG,3,20,-5,459 +1380248,10,LONG,4,8,5,99 +1380250,10,LONG,5,14,0,210 +1380252,10,LONG,6,12,13,323 +1380254,10,LONG,7,29,21,1326 +1380256,10,LONG,8,0,18,337 +1380258,10,LONG,9,-15,-7,308 +1380260,10,LONG,10,0,-1,1 +1380262,10,LONG,11,-20,2,429 +1380264,10,LONG,12,-2,4,26 +1380266,10,LONG,13,10,-8,187 +1380268,10,LONG,14,-7,2,62 +1380270,10,LONG,15,22,3,519 +1380272,10,LONG,16,10,0,119 +1380274,10,LONG,17,-2,0,6 +1380276,10,LONG,18,-5,14,246 +1380278,10,LONG,19,-4,-7,73 +1380280,10,LONG,20,0,-8,69 +1380282,10,LONG,21,-5,3,37 +1380284,10,LONG,22,-1,-2,5 +1380286,10,LONG,23,-7,10,164 +1380288,10,LONG,24,4,-17,340 +1380290,10,LONG,25,2,-1,9 +1380292,10,LONG,26,-7,5,90 +1380294,10,LONG,27,15,6,290 +1380296,10,LONG,28,0,-7,62 +1380298,10,LONG,29,-11,-13,318 +1380300,10,LONG,30,3,-1,13 +1380302,10,LONG,31,-5,-1,32 +1380304,10,LONG,32,-12,-3,173 +1380306,10,LONG,33,-8,-6,111 +1380308,10,LONG,34,-1,4,23 +1380310,10,LONG,35,1,13,174 +1380312,10,LONG,36,13,-3,188 +1380314,10,LONG,37,16,-15,513 +1380316,10,LONG,38,1,8,75 +1380318,10,LONG,39,13,-2,190 +1380320,10,LONG,40,26,-11,858 +1380322,10,LONG,41,-3,11,153 +1380324,10,LONG,42,-16,15,522 +1380326,10,LONG,43,7,-6,91 +1380328,10,LONG,44,-5,-10,142 +1380330,10,LONG,45,-3,5,49 +1380332,10,LONG,46,-9,-14,290 +1380334,10,LONG,47,4,-12,164 +1380336,10,LONG,48,-20,5,450 +1380338,10,LONG,49,17,3,303 +1380340,10,LONG,50,-5,19,418 +1380342,10,LONG,51,6,10,143 +1380344,10,LONG,52,-21,-2,479 +1380346,10,LONG,53,-12,5,180 +1380348,10,LONG,54,-11,-2,127 +1380350,10,LONG,55,-2,-15,256 +1380352,10,LONG,56,4,-1,22 +1380354,10,LONG,57,20,-13,584 +1380356,10,LONG,58,6,2,45 +1380358,10,LONG,59,5,-16,314 +1380360,10,LONG,60,-7,-7,109 +1380362,10,LONG,61,1,6,49 +1380364,10,LONG,62,3,0,12 +1380366,10,LONG,63,-15,-5,261 +1380368,10,LONG,64,-4,-2,30 +1380370,10,LONG,65,4,-21,472 +1380372,10,LONG,66,11,14,339 +1380374,10,LONG,67,8,6,115 +1380376,10,LONG,68,8,18,416 +1380378,10,LONG,69,-21,-6,488 +1380380,10,LONG,70,-3,15,239 +1380382,10,LONG,71,1,4,25 +1380384,10,LONG,72,6,13,231 +1380386,10,LONG,73,-2,5,39 +1380388,10,LONG,74,18,-5,384 +1380390,10,LONG,75,4,0,18 +1380392,10,LONG,76,-9,15,350 +1380394,10,LONG,77,-13,10,292 +1380396,10,LONG,78,-5,-7,84 +1380398,10,LONG,79,23,15,794 +1380400,10,LONG,80,-11,0,138 +1380402,10,LONG,81,-2,-16,276 +1380404,10,LONG,82,2,-6,45 +1380406,10,LONG,83,9,-12,247 +1380408,10,LONG,84,-19,6,428 +1380410,10,LONG,85,6,0,38 +1380412,10,LONG,86,-15,-12,389 +1380414,10,LONG,87,-7,0,56 +1380416,10,LONG,88,27,-1,768 +1380418,10,LONG,89,14,5,227 +1380420,10,LONG,90,7,-21,512 +1380422,10,LONG,91,-14,-25,868 +1380424,10,LONG,92,2,-4,21 +1380426,10,LONG,93,-11,0,138 +1380428,10,LONG,94,7,9,154 +1380430,10,LONG,95,0,5,28 +1380432,10,LONG,96,-12,0,164 +1380434,10,LONG,97,8,-3,85 +1380436,10,LONG,98,1,-1,3 +1380438,10,LONG,99,21,-1,470 +1380440,10,LONG,100,-3,-8,93 +1380442,10,LONG,101,6,0,47 +1380444,10,LONG,102,4,3,36 +1380446,10,LONG,103,-7,-6,102 +1380448,10,LONG,104,0,-5,33 +1380450,10,LONG,105,3,0,11 +1380452,10,LONG,106,0,-2,8 +1380454,10,LONG,107,8,-3,87 +1380456,10,LONG,108,2,2,11 +1380458,10,LONG,109,2,-1,8 +1380460,10,LONG,110,-4,-4,36 +1380462,10,LONG,111,-6,1,46 +1380464,10,LONG,112,1,-3,14 +1380466,10,LONG,113,1,5,29 +1380468,10,LONG,114,4,-6,54 +1380470,10,LONG,115,8,-2,80 +1380472,10,LONG,116,-2,0,7 +1380474,10,LONG,117,-3,13,200 +1380476,10,LONG,118,2,-6,55 +1380478,10,LONG,119,5,4,55 +1380480,10,LONG,120,-4,2,29 +1380482,10,LONG,121,1,-2,7 +1380484,10,LONG,122,4,0,21 +1380486,10,LONG,123,1,6,38 +1380488,10,LONG,124,-7,-8,133 +1380490,10,LONG,125,-1,-2,11 +1380492,10,LONG,126,-1,0,2 +1380494,10,LONG,127,0,-4,17 +1380496,10,LONG,128,0,2,6 +1380498,10,LONG,129,-2,-6,46 +1380500,10,LONG,130,-3,13,183 +1380502,10,LONG,131,-12,-7,205 +1380504,10,LONG,132,3,8,86 +1380506,10,LONG,133,-9,4,100 +1380508,10,LONG,134,6,1,47 +1380510,10,LONG,135,1,7,63 +1380512,10,LONG,136,1,-4,24 +1380514,10,LONG,137,3,0,13 +1380516,10,LONG,138,10,-2,111 +1380518,10,LONG,139,-2,5,43 +1380520,10,LONG,140,0,8,69 +1380522,10,LONG,141,-43,91,10342 +1380524,10,LONG,142,-61,84,10938 +1380526,10,LONG,143,-68,74,10211 +1380528,10,LONG,144,-70,75,10622 +1380530,10,LONG,145,-76,55,8989 +1380532,10,LONG,146,-80,52,9247 +1380534,10,LONG,147,-94,45,11111 +1380536,10,LONG,148,-95,17,9373 +1380538,10,LONG,149,-107,10,11723 +1380540,10,LONG,150,-104,0,10934 +1380542,10,LONG,151,-95,-9,9139 +1380544,10,LONG,152,-100,-33,11189 +1380546,10,LONG,153,-93,-33,9897 +1380548,10,LONG,154,-91,-45,10439 +1380550,10,LONG,155,-77,-60,9607 +1380552,10,LONG,156,-73,-70,10347 +1380554,10,LONG,157,-68,-65,9024 +1380556,10,LONG,158,-58,-80,9991 +1380558,10,LONG,159,-44,-84,9123 +1380560,10,LONG,160,3,10,116 +1380562,10,LONG,161,11,-8,206 +1380564,10,LONG,162,3,-15,250 +1380566,10,LONG,163,0,1,3 +1380568,10,LONG,164,0,-4,20 +1380570,10,LONG,165,-6,4,64 +1380572,10,LONG,166,-6,0,48 +1380574,10,LONG,167,1,-11,125 +1380576,10,LONG,168,3,-4,28 +1380578,10,LONG,169,3,2,20 +1380580,10,LONG,170,3,3,28 +1380582,10,LONG,171,-7,-4,77 +1380584,10,LONG,172,-2,2,12 +1380586,10,LONG,173,-2,-2,13 +1380588,10,LONG,174,3,-1,11 +1380590,10,LONG,175,-7,-7,114 +1380592,10,LONG,176,-5,-1,32 +1380594,10,LONG,177,0,0,0 +1380596,10,LONG,178,2,2,13 +1380598,10,LONG,179,-7,10,174 +1380600,10,LONG,180,0,2,8 +1380602,10,LONG,181,-5,1,29 +1380604,10,LONG,182,-4,7,76 +1380606,10,LONG,183,0,-6,47 +1380608,10,LONG,184,4,4,35 +1380610,10,LONG,185,-9,-1,90 +1380612,10,LONG,186,4,5,55 +1380614,10,LONG,187,9,-2,102 +1380616,10,LONG,188,4,3,27 +1380618,10,LONG,189,-4,-6,58 +1380620,10,LONG,190,8,-1,70 +1380622,10,LONG,191,-7,-2,62 +1380624,10,LONG,192,-3,-3,22 +1380626,10,LONG,193,4,3,26 +1380628,10,LONG,194,7,8,134 +1380630,10,LONG,195,-2,6,48 +1380632,10,LONG,196,0,9,91 +1380634,10,LONG,197,4,-6,64 +1380636,10,LONG,198,-6,8,108 +1380638,10,LONG,199,0,12,146 +1380640,10,LONG,200,0,2,7 +1380642,10,LONG,201,0,0,0 +1380644,10,LONG,202,-5,5,64 +1380646,10,LONG,203,-4,-4,38 +1380648,10,LONG,204,-6,-1,42 +1380650,10,LONG,205,2,-5,38 +1380652,10,LONG,206,3,5,35 +1380654,10,LONG,207,0,-3,13 +1380656,10,LONG,208,11,0,137 +1380658,10,LONG,209,-2,4,22 +1380660,10,LONG,210,6,3,50 +1380662,10,LONG,211,-5,0,29 +1380664,10,LONG,212,6,8,125 +1380666,10,LONG,213,9,6,131 +1380668,10,LONG,214,1,-4,24 +1380670,10,LONG,215,-7,-2,55 +1380672,10,LONG,216,-1,-5,28 +1380674,10,LONG,217,-4,2,21 +1380676,10,LONG,218,-1,7,53 +1380678,10,LONG,219,3,-8,79 +1380680,10,LONG,220,-5,5,61 +1380682,10,LONG,221,-4,-6,56 +1380684,10,LONG,222,-3,0,10 +1380686,10,LONG,223,-5,0,27 +1380688,10,LONG,224,5,1,31 +1380690,10,LONG,225,2,2,10 +1380692,10,LONG,226,-7,5,84 +1380694,10,LONG,227,-7,0,52 +1380696,10,LONG,228,-5,-1,34 +1380698,10,LONG,229,3,1,16 +1380700,10,LONG,230,-6,-2,48 +1380702,10,LONG,231,0,-5,31 +1380704,10,LONG,232,4,2,22 +1380706,10,LONG,233,-8,-1,82 +1380708,10,LONG,234,12,16,422 +1380710,10,LONG,235,4,-1,20 +1380712,10,LONG,236,-9,-1,99 +1380714,10,LONG,237,-1,0,1 +1380716,10,LONG,238,-4,0,20 +1380718,10,LONG,239,-3,-5,37 +1380720,10,LONG,240,2,-4,25 +1380722,10,LONG,241,-22,43,2391 +1380724,10,LONG,242,-28,38,2313 +1380726,10,LONG,243,-42,30,2740 +1380728,10,LONG,244,-34,35,2466 +1380730,10,LONG,245,-40,33,2758 +1380732,10,LONG,246,-37,23,1967 +1380734,10,LONG,247,-42,16,2048 +1380736,10,LONG,248,-45,7,2094 +1380738,10,LONG,249,-52,10,2883 +1380740,10,LONG,250,-48,1,2336 +1380742,10,LONG,251,-44,-8,2041 +1380744,10,LONG,252,-51,-3,2650 +1380746,10,LONG,253,-30,-20,1333 +1380748,10,LONG,254,-41,-11,1890 +1380750,10,LONG,255,-44,-32,3087 +1380752,10,LONG,256,-32,-29,1946 +1380754,10,LONG,257,-28,-33,1990 +1380756,10,LONG,258,-21,-43,2343 +1380758,10,LONG,259,-24,-51,3275 +1380760,10,LONG,260,0,5,26 +1380762,10,LONG,261,3,-4,34 +1380764,10,LONG,262,-5,-4,49 +1380766,10,LONG,263,2,4,26 +1380768,10,LONG,264,3,9,110 +1380770,10,LONG,265,0,3,11 +1380772,10,LONG,266,0,0,1 +1380774,10,LONG,267,-6,-2,48 +1380776,10,LONG,268,0,2,5 +1380778,10,LONG,269,-4,0,20 +1380780,10,LONG,270,0,0,0 +1380782,10,LONG,271,-8,1,73 +1380784,10,LONG,272,8,7,119 +1380786,10,LONG,273,-7,5,88 +1380788,10,LONG,274,0,2,4 +1380790,10,LONG,275,3,8,88 +1380792,10,LONG,276,2,-8,76 +1380794,10,LONG,277,0,2,5 +1380796,10,LONG,278,0,0,0 +1380798,10,LONG,279,4,3,29 +1380800,10,LONG,280,4,2,31 +1380802,10,LONG,281,1,6,48 +1380804,10,LONG,282,0,1,4 +1380806,10,LONG,283,0,4,16 +1380808,10,LONG,284,3,-4,38 +1380810,10,LONG,285,8,-1,70 +1380812,10,LONG,286,2,6,47 +1380814,10,LONG,287,-13,1,197 +1380816,10,LONG,288,1,-3,14 +1380818,10,LONG,289,0,3,9 +1380820,10,LONG,290,1,2,10 +1380822,10,LONG,291,-12,3,176 +1380824,10,LONG,292,2,5,29 +1380826,10,LONG,293,-2,-1,5 +1380828,10,LONG,294,-6,-6,89 +1380830,10,LONG,295,-9,1,96 +1380832,10,LONG,296,1,0,1 +1380834,10,LONG,297,-3,2,18 +1380836,10,LONG,298,9,-2,99 +1380838,10,LONG,299,13,-2,196 +1380840,10,LONG,300,4,3,27 +1380842,10,LONG,301,8,2,83 +1380844,10,LONG,302,7,5,81 +1380846,10,LONG,303,-2,-6,54 +1380848,10,LONG,304,-5,-2,41 +1380850,10,LONG,305,3,6,47 +1380852,10,LONG,306,5,0,35 +1380854,10,LONG,307,0,7,53 +1380856,10,LONG,308,1,-3,13 +1380858,10,LONG,309,-8,0,66 +1380860,10,LONG,310,6,-2,42 +1380862,10,LONG,311,-5,5,58 +1380864,10,LONG,312,0,-5,27 +1380866,10,LONG,313,4,-4,42 +1380868,10,LONG,314,-14,-1,203 +1380870,10,LONG,315,6,-4,68 +1380872,10,LONG,316,-4,-3,26 +1380874,10,LONG,317,3,-8,87 +1380876,10,LONG,318,-1,0,1 +1380878,10,LONG,319,-6,-7,96 +1380880,10,LONG,320,-2,-2,16 +1380882,10,LONG,321,-4,-3,27 +1380884,10,LONG,322,-6,11,174 +1380886,10,LONG,323,1,-2,8 +1380888,10,LONG,324,-5,-7,90 +1380890,10,LONG,325,6,-2,48 +1380892,10,LONG,326,-3,0,12 +1380894,10,LONG,327,-2,5,31 +1380896,10,LONG,328,0,1,2 +1380898,10,LONG,329,0,-1,2 +1380900,10,LONG,330,-7,-9,155 +1380902,10,LONG,331,-4,2,20 +1380904,10,LONG,332,-2,-3,20 +1380906,10,LONG,333,5,4,53 +1380908,10,LONG,334,0,5,29 +1380910,10,LONG,335,-1,0,2 +1380912,10,LONG,336,4,0,19 +1380914,10,LONG,337,-6,8,120 +1380916,10,LONG,338,0,11,130 +1380918,10,LONG,339,4,-4,38 +1380920,10,LONG,340,2,2,16 +1380922,10,LONG,341,2,2,14 +1380924,10,LONG,342,-1,-3,14 +1380926,10,LONG,343,-4,-1,20 +1380928,10,LONG,344,4,2,26 +1380930,10,LONG,345,-6,14,248 +1380932,10,LONG,346,13,-5,201 +1380934,10,LONG,347,-5,0,25 +1380936,10,LONG,348,8,-2,71 +1380938,10,LONG,349,-5,1,30 +1380940,10,LONG,350,7,-1,62 +1380942,10,LONG,351,-12,0,155 +1380944,10,LONG,352,-4,-6,56 +1380946,10,LONG,353,-2,6,43 +1380948,10,LONG,354,0,0,1 +1380950,10,LONG,355,-2,-7,62 +1380952,10,LONG,356,0,3,13 +1380954,10,LONG,357,1,0,3 +1380956,10,LONG,358,1,-3,12 +1380958,10,LONG,359,4,-1,26 +1380960,10,LONG,360,-4,5,50 +1380962,10,LONG,361,-5,-4,48 +1380964,10,LONG,362,0,-4,17 +1380966,10,LONG,363,2,-1,8 +1380968,10,LONG,364,-1,-2,9 +1380970,10,LONG,365,-9,-4,122 +1380972,10,LONG,366,0,5,35 +1380974,10,LONG,367,1,5,35 +1380976,10,LONG,368,1,0,3 +1380978,10,LONG,369,0,-6,38 +1380980,10,LONG,370,0,-7,63 +1380982,10,LONG,371,5,0,29 +1380984,10,LONG,372,-2,-2,11 +1380986,10,LONG,373,-6,0,37 +1380988,10,LONG,374,3,-2,17 +1380990,10,LONG,375,-7,5,92 +1380992,10,LONG,376,5,-4,58 +1380994,10,LONG,377,2,3,20 +1380996,10,LONG,378,-6,1,45 +1380998,10,LONG,379,9,-5,117 +1381000,10,LONG,380,-4,-10,122 +1381002,10,LONG,381,-8,9,158 +1381004,10,LONG,382,-3,-1,16 +1381006,10,LONG,383,-6,-2,53 +1381008,10,LONG,384,0,0,0 +1381010,10,LONG,385,1,1,4 +1381012,10,LONG,386,-1,-4,26 +1381014,10,LONG,387,7,-10,162 +1381016,10,LONG,388,0,-3,15 +1381018,10,LONG,389,-3,-3,25 +1381020,10,LONG,390,2,-3,21 +1381022,10,LONG,391,-17,19,701 +1381024,10,LONG,392,-5,23,594 +1381026,10,LONG,393,-17,23,843 +1381028,10,LONG,394,-15,13,401 +1381030,10,LONG,395,-18,15,566 +1381032,10,LONG,396,-20,15,661 +1381034,10,LONG,397,-13,14,415 +1381036,10,LONG,398,-31,3,994 +1381038,10,LONG,399,-23,9,641 +1381040,10,LONG,400,-28,5,829 +1381042,10,LONG,401,-17,-9,383 +1381044,10,LONG,402,-27,-1,762 +1381046,10,LONG,403,-25,1,642 +1381048,10,LONG,404,-24,-8,659 +1381050,10,LONG,405,-28,-12,982 +1381052,10,LONG,406,-15,-23,808 +1381054,10,LONG,407,-19,-24,961 +1381056,10,LONG,408,-15,-23,769 +1381058,10,LONG,409,-12,-23,698 +1381060,10,LONG,410,3,-12,155 +1381062,10,LONG,411,4,10,120 +1381064,10,LONG,412,2,0,6 +1381066,10,LONG,413,-5,4,54 +1381068,10,LONG,414,-10,-4,123 +1381070,10,LONG,415,-9,-3,98 +1381072,10,LONG,416,5,11,166 +1381074,10,LONG,417,0,6,37 +1381076,10,LONG,418,-3,0,13 +1381078,10,LONG,419,3,7,60 +1381080,10,LONG,420,-5,1,37 +1381082,10,LONG,421,-4,3,32 +1381084,10,LONG,422,0,4,24 +1381086,10,LONG,423,13,3,199 +1381088,10,LONG,424,-6,-1,47 +1381090,10,LONG,425,-2,7,63 +1381092,10,LONG,426,-2,-4,29 +1381094,10,LONG,427,1,0,1 +1381096,10,LONG,428,-1,3,13 +1381098,10,LONG,429,0,0,0 +1381100,10,LONG,430,-1,-2,12 +1381102,10,LONG,431,-7,3,72 +1381104,10,LONG,432,-1,0,2 +1381106,10,LONG,433,2,-6,55 +1381108,10,LONG,434,5,7,98 +1381110,10,LONG,435,0,7,49 +1381112,10,LONG,436,-9,4,108 +1381114,10,LONG,437,-4,0,23 +1381116,10,LONG,438,-1,0,2 +1381118,10,LONG,439,2,3,15 +1381120,10,LONG,440,8,-4,87 +1381122,10,LONG,441,0,-4,21 +1381124,10,LONG,442,-4,11,142 +1381126,10,LONG,443,0,11,122 +1381128,10,LONG,444,6,-1,46 +1381130,10,LONG,445,2,7,66 +1381132,10,LONG,446,3,4,35 +1381134,10,LONG,447,4,1,20 +1381136,10,LONG,448,0,3,9 +1381138,10,LONG,449,-7,4,79 +1381140,10,LONG,450,-3,3,27 +1381142,10,LONG,451,5,6,78 +1381144,10,LONG,452,3,5,46 +1381146,10,LONG,453,0,-2,5 +1381148,10,LONG,454,7,-1,61 +1381150,10,LONG,455,9,2,93 +1381152,10,LONG,456,12,-3,153 +1381154,10,LONG,457,5,-12,189 +1381156,10,LONG,458,4,0,24 +1381158,10,LONG,459,-7,-3,68 +1381160,10,LONG,460,7,0,53 +1381162,10,LONG,461,-1,0,2 +1381164,10,LONG,462,1,9,87 +1381166,10,LONG,463,-5,-2,36 +1381168,10,LONG,464,3,0,10 +1381170,10,LONG,465,-7,0,52 +1381172,10,LONG,466,-7,-7,118 +1381174,10,LONG,467,-7,1,64 +1381176,10,LONG,468,8,8,134 +1381178,10,LONG,469,3,1,13 +1381180,10,LONG,470,6,-6,87 +1381182,10,LONG,471,2,-5,31 +1381184,10,LONG,472,12,-3,157 +1381186,10,LONG,473,1,1,6 +1381188,10,LONG,474,-1,-9,90 +1381190,10,LONG,475,-3,1,14 +1381192,10,LONG,476,7,0,50 +1381194,10,LONG,477,5,0,32 +1381196,10,LONG,478,7,-3,65 +1381198,10,LONG,479,6,5,65 +1381200,10,LONG,480,-3,-5,49 +1381202,10,LONG,481,1,0,3 +1381204,10,LONG,482,5,3,45 +1381206,10,LONG,483,0,0,0 +1381208,10,LONG,484,0,-3,12 +1381210,10,LONG,485,3,0,11 +1381212,10,LONG,486,6,5,63 +1381214,10,LONG,487,-3,-6,50 +1381216,10,LONG,488,1,0,2 +1381218,10,LONG,489,-2,-2,12 +1381220,10,LONG,490,-2,-5,39 +1381222,10,LONG,491,0,-3,14 +1381224,10,LONG,492,0,2,5 +1381226,10,LONG,493,2,2,14 +1381228,10,LONG,494,0,0,0 +1381230,10,LONG,495,3,-6,50 +1381232,10,LONG,496,9,3,93 +1381234,10,LONG,497,3,-6,48 +1381236,10,LONG,498,-4,8,93 +1381238,10,LONG,499,0,2,5 +1381240,10,LONG,500,-3,-4,34 +1381242,10,LONG,501,5,0,27 +1381244,10,LONG,502,0,0,0 +1381246,10,LONG,503,-5,2,31 +1381248,10,LONG,504,-2,-4,22 +1381250,10,LONG,505,0,0,1 +1381252,10,LONG,506,-7,-9,153 +1381254,10,LONG,507,2,-3,14 +1381256,10,LONG,508,1,-6,48 +1381258,10,LONG,509,-4,-8,90 +1381260,10,LONG,510,2,-4,23 +1381262,10,LONG,511,1,4,23 +1518264,11,LONG,0,16,-13,434 +1518266,11,LONG,1,0,-37,1386 +1518268,11,LONG,2,12,-9,260 +1518270,11,LONG,3,0,16,274 +1518272,11,LONG,4,-2,2,10 +1518274,11,LONG,5,4,-9,108 +1518276,11,LONG,6,-19,2,392 +1518278,11,LONG,7,-16,-8,326 +1518280,11,LONG,8,19,-5,424 +1518282,11,LONG,9,-18,6,399 +1518284,11,LONG,10,-5,-13,206 +1518286,11,LONG,11,-6,-7,97 +1518288,11,LONG,12,-29,2,880 +1518290,11,LONG,13,-14,-9,310 +1518292,11,LONG,14,14,8,284 +1518294,11,LONG,15,0,1,2 +1518296,11,LONG,16,7,1,63 +1518298,11,LONG,17,7,-7,110 +1518300,11,LONG,18,-7,-15,300 +1518302,11,LONG,19,3,15,243 +1518304,11,LONG,20,0,-12,152 +1518306,11,LONG,21,-5,8,100 +1518308,11,LONG,22,-23,-26,1264 +1518310,11,LONG,23,2,2,16 +1518312,11,LONG,24,-8,-3,82 +1518314,11,LONG,25,0,20,428 +1518316,11,LONG,26,8,8,146 +1518318,11,LONG,27,8,-1,77 +1518320,11,LONG,28,-4,-8,99 +1518322,11,LONG,29,-7,10,171 +1518324,11,LONG,30,-5,4,55 +1518326,11,LONG,31,-1,-17,305 +1518328,11,LONG,32,11,-26,826 +1518330,11,LONG,33,-2,-5,36 +1518332,11,LONG,34,-1,3,13 +1518334,11,LONG,35,-1,0,2 +1518336,11,LONG,36,-17,-11,432 +1518338,11,LONG,37,-3,-31,974 +1518340,11,LONG,38,-9,2,101 +1518342,11,LONG,39,-17,-1,290 +1518344,11,LONG,40,-13,-13,366 +1518346,11,LONG,41,5,-9,118 +1518348,11,LONG,42,-8,5,90 +1518350,11,LONG,43,-5,21,482 +1518352,11,LONG,44,-9,7,149 +1518354,11,LONG,45,-7,-17,355 +1518356,11,LONG,46,-17,15,565 +1518358,11,LONG,47,-1,4,20 +1518360,11,LONG,48,1,-18,332 +1518362,11,LONG,49,3,13,195 +1518364,11,LONG,50,-16,13,441 +1518366,11,LONG,51,-1,-12,154 +1518368,11,LONG,52,13,18,516 +1518370,11,LONG,53,4,2,32 +1518372,11,LONG,54,-6,6,96 +1518374,11,LONG,55,11,8,200 +1518376,11,LONG,56,19,0,367 +1518378,11,LONG,57,-15,-6,289 +1518380,11,LONG,58,-5,7,91 +1518382,11,LONG,59,5,0,26 +1518384,11,LONG,60,5,9,112 +1518386,11,LONG,61,3,-8,82 +1518388,11,LONG,62,0,-16,272 +1518390,11,LONG,63,-1,-9,91 +1518392,11,LONG,64,-11,0,129 +1518394,11,LONG,65,-15,12,377 +1518396,11,LONG,66,10,-17,397 +1518398,11,LONG,67,-9,13,266 +1518400,11,LONG,68,13,-4,193 +1518402,11,LONG,69,18,-1,337 +1518404,11,LONG,70,-10,-4,130 +1518406,11,LONG,71,21,-2,466 +1518408,11,LONG,72,14,-1,212 +1518410,11,LONG,73,4,14,232 +1518412,11,LONG,74,0,-15,237 +1518414,11,LONG,75,9,10,214 +1518416,11,LONG,76,-8,-10,174 +1518418,11,LONG,77,-4,13,203 +1518420,11,LONG,78,0,1,1 +1518422,11,LONG,79,3,-3,24 +1518424,11,LONG,80,-8,-22,572 +1518426,11,LONG,81,0,16,259 +1518428,11,LONG,82,3,11,143 +1518430,11,LONG,83,-11,-7,191 +1518432,11,LONG,84,2,-4,23 +1518434,11,LONG,85,-15,-1,241 +1518436,11,LONG,86,10,-8,192 +1518438,11,LONG,87,-4,-4,37 +1518440,11,LONG,88,0,2,4 +1518442,11,LONG,89,9,7,135 +1518444,11,LONG,90,4,-14,234 +1518446,11,LONG,91,-14,0,224 +1518448,11,LONG,92,8,17,392 +1518450,11,LONG,93,10,6,144 +1518452,11,LONG,94,11,2,150 +1518454,11,LONG,95,-5,0,27 +1518456,11,LONG,96,-15,15,477 +1518458,11,LONG,97,-12,3,163 +1518460,11,LONG,98,10,13,291 +1518462,11,LONG,99,8,-8,153 +1518464,11,LONG,100,-5,0,27 +1518466,11,LONG,101,0,-2,6 +1518468,11,LONG,102,6,5,71 +1518470,11,LONG,103,-3,-4,29 +1518472,11,LONG,104,-6,-4,62 +1518474,11,LONG,105,4,7,83 +1518476,11,LONG,106,-1,-5,29 +1518478,11,LONG,107,-2,4,26 +1518480,11,LONG,108,13,0,185 +1518482,11,LONG,109,0,-1,3 +1518484,11,LONG,110,-4,-3,30 +1518486,11,LONG,111,11,-6,173 +1518488,11,LONG,112,-4,1,26 +1518490,11,LONG,113,2,-2,14 +1518492,11,LONG,114,-6,0,44 +1518494,11,LONG,115,0,-2,8 +1518496,11,LONG,116,7,-4,71 +1518498,11,LONG,117,-2,7,60 +1518500,11,LONG,118,-1,-5,26 +1518502,11,LONG,119,2,-6,48 +1518504,11,LONG,120,-10,0,105 +1518506,11,LONG,121,-9,8,168 +1518508,11,LONG,122,1,2,11 +1518510,11,LONG,123,2,-2,13 +1518512,11,LONG,124,9,1,91 +1518514,11,LONG,125,-12,-3,168 +1518516,11,LONG,126,1,5,34 +1518518,11,LONG,127,14,8,298 +1518520,11,LONG,128,-5,1,38 +1518522,11,LONG,129,0,-3,13 +1518524,11,LONG,130,0,3,11 +1518526,11,LONG,131,-7,3,68 +1518528,11,LONG,132,-5,0,33 +1518530,11,LONG,133,-7,-3,75 +1518532,11,LONG,134,3,2,22 +1518534,11,LONG,135,0,8,68 +1518536,11,LONG,136,3,-2,21 +1518538,11,LONG,137,9,0,91 +1518540,11,LONG,138,4,0,18 +1518542,11,LONG,139,-5,-11,149 +1518544,11,LONG,140,-2,1,9 +1518546,11,LONG,141,-91,-44,10317 +1518548,11,LONG,142,-91,-61,12141 +1518550,11,LONG,143,-79,-66,10803 +1518552,11,LONG,144,-68,-60,8407 +1518554,11,LONG,145,-64,-83,11074 +1518556,11,LONG,146,-47,-89,10232 +1518558,11,LONG,147,-41,-90,9877 +1518560,11,LONG,148,-15,-97,9739 +1518562,11,LONG,149,-14,-106,11589 +1518564,11,LONG,150,-10,-103,10873 +1518566,11,LONG,151,4,-101,10268 +1518568,11,LONG,152,28,-102,11338 +1518570,11,LONG,153,33,-96,10366 +1518572,11,LONG,154,42,-91,10130 +1518574,11,LONG,155,60,-77,9743 +1518576,11,LONG,156,67,-76,10314 +1518578,11,LONG,157,71,-64,9231 +1518580,11,LONG,158,91,-43,10249 +1518582,11,LONG,159,86,-45,9514 +1518584,11,LONG,160,12,1,154 +1518586,11,LONG,161,5,0,30 +1518588,11,LONG,162,4,1,25 +1518590,11,LONG,163,-1,6,43 +1518592,11,LONG,164,0,8,77 +1518594,11,LONG,165,6,5,69 +1518596,11,LONG,166,-1,0,4 +1518598,11,LONG,167,-1,-1,4 +1518600,11,LONG,168,-5,9,127 +1518602,11,LONG,169,-7,2,61 +1518604,11,LONG,170,0,3,10 +1518606,11,LONG,171,1,3,13 +1518608,11,LONG,172,-11,0,132 +1518610,11,LONG,173,1,-8,67 +1518612,11,LONG,174,-1,8,75 +1518614,11,LONG,175,-4,-7,76 +1518616,11,LONG,176,1,-3,13 +1518618,11,LONG,177,-1,6,45 +1518620,11,LONG,178,-1,-7,59 +1518622,11,LONG,179,0,6,38 +1518624,11,LONG,180,3,3,30 +1518626,11,LONG,181,-2,-1,8 +1518628,11,LONG,182,0,1,2 +1518630,11,LONG,183,0,5,29 +1518632,11,LONG,184,-7,0,59 +1518634,11,LONG,185,12,-1,156 +1518636,11,LONG,186,0,0,1 +1518638,11,LONG,187,0,-2,7 +1518640,11,LONG,188,0,-8,64 +1518642,11,LONG,189,0,-5,30 +1518644,11,LONG,190,0,-2,8 +1518646,11,LONG,191,5,2,36 +1518648,11,LONG,192,0,7,56 +1518650,11,LONG,193,-5,-5,55 +1518652,11,LONG,194,-6,8,118 +1518654,11,LONG,195,-3,2,21 +1518656,11,LONG,196,-2,4,30 +1518658,11,LONG,197,0,-4,24 +1518660,11,LONG,198,0,-12,163 +1518662,11,LONG,199,3,-6,56 +1518664,11,LONG,200,5,-1,32 +1518666,11,LONG,201,1,2,9 +1518668,11,LONG,202,-7,-6,88 +1518670,11,LONG,203,1,-6,41 +1518672,11,LONG,204,-2,-5,43 +1518674,11,LONG,205,-8,-3,76 +1518676,11,LONG,206,-4,1,28 +1518678,11,LONG,207,3,-8,84 +1518680,11,LONG,208,10,6,158 +1518682,11,LONG,209,6,10,148 +1518684,11,LONG,210,8,3,87 +1518686,11,LONG,211,3,-2,15 +1518688,11,LONG,212,-11,-6,179 +1518690,11,LONG,213,-4,5,42 +1518692,11,LONG,214,2,1,11 +1518694,11,LONG,215,1,0,1 +1518696,11,LONG,216,-4,3,35 +1518698,11,LONG,217,-4,0,19 +1518700,11,LONG,218,-3,9,106 +1518702,11,LONG,219,-6,0,47 +1518704,11,LONG,220,-4,4,40 +1518706,11,LONG,221,0,-3,9 +1518708,11,LONG,222,1,-3,10 +1518710,11,LONG,223,-3,-7,66 +1518712,11,LONG,224,0,-9,94 +1518714,11,LONG,225,0,-2,6 +1518716,11,LONG,226,0,-3,14 +1518718,11,LONG,227,-2,1,6 +1518720,11,LONG,228,4,1,20 +1518722,11,LONG,229,-3,8,91 +1518724,11,LONG,230,8,0,79 +1518726,11,LONG,231,8,0,66 +1518728,11,LONG,232,6,0,39 +1518730,11,LONG,233,4,2,25 +1518732,11,LONG,234,0,-1,2 +1518734,11,LONG,235,0,4,20 +1518736,11,LONG,236,0,0,1 +1518738,11,LONG,237,-6,-1,46 +1518740,11,LONG,238,6,-6,76 +1518742,11,LONG,239,3,6,53 +1518744,11,LONG,240,5,2,40 +1518746,11,LONG,241,16,41,2033 +1518748,11,LONG,242,18,52,3122 +1518750,11,LONG,243,8,47,2360 +1518752,11,LONG,244,8,53,2924 +1518754,11,LONG,245,-8,54,2984 +1518756,11,LONG,246,5,53,2941 +1518758,11,LONG,247,-15,46,2430 +1518760,11,LONG,248,-26,42,2491 +1518762,11,LONG,249,-29,37,2233 +1518764,11,LONG,250,-28,36,2167 +1518766,11,LONG,251,-28,27,1593 +1518768,11,LONG,252,-41,38,3254 +1518770,11,LONG,253,-37,23,1981 +1518772,11,LONG,254,-55,23,3612 +1518774,11,LONG,255,-45,15,2303 +1518776,11,LONG,256,-47,6,2264 +1518778,11,LONG,257,-49,-3,2450 +1518780,11,LONG,258,-49,-5,2470 +1518782,11,LONG,259,-46,-6,2192 +1518784,11,LONG,260,-6,-1,42 +1518786,11,LONG,261,5,-9,114 +1518788,11,LONG,262,9,1,85 +1518790,11,LONG,263,-2,-4,24 +1518792,11,LONG,264,0,-2,4 +1518794,11,LONG,265,-3,-1,12 +1518796,11,LONG,266,-2,2,11 +1518798,11,LONG,267,2,0,9 +1518800,11,LONG,268,3,0,12 +1518802,11,LONG,269,-2,2,13 +1518804,11,LONG,270,-3,3,23 +1518806,11,LONG,271,0,2,9 +1518808,11,LONG,272,0,2,5 +1518810,11,LONG,273,3,-4,28 +1518812,11,LONG,274,-2,2,15 +1518814,11,LONG,275,1,6,45 +1518816,11,LONG,276,-2,7,60 +1518818,11,LONG,277,6,5,74 +1518820,11,LONG,278,-2,0,8 +1518822,11,LONG,279,-2,0,7 +1518824,11,LONG,280,3,1,15 +1518826,11,LONG,281,-5,-3,44 +1518828,11,LONG,282,-2,3,15 +1518830,11,LONG,283,5,0,26 +1518832,11,LONG,284,5,-9,121 +1518834,11,LONG,285,-6,14,244 +1518836,11,LONG,286,-6,-2,47 +1518838,11,LONG,287,4,4,45 +1518840,11,LONG,288,4,7,71 +1518842,11,LONG,289,0,6,47 +1518844,11,LONG,290,1,-2,5 +1518846,11,LONG,291,0,1,1 +1518848,11,LONG,292,4,-3,28 +1518850,11,LONG,293,1,-1,3 +1518852,11,LONG,294,-6,-6,91 +1518854,11,LONG,295,15,-5,273 +1518856,11,LONG,296,4,0,17 +1518858,11,LONG,297,-1,9,101 +1518860,11,LONG,298,2,5,32 +1518862,11,LONG,299,0,0,0 +1518864,11,LONG,300,2,0,6 +1518866,11,LONG,301,-2,0,8 +1518868,11,LONG,302,-2,-5,36 +1518870,11,LONG,303,7,7,106 +1518872,11,LONG,304,2,-9,100 +1518874,11,LONG,305,8,1,70 +1518876,11,LONG,306,-4,2,22 +1518878,11,LONG,307,-1,3,12 +1518880,11,LONG,308,-8,2,68 +1518882,11,LONG,309,-7,1,66 +1518884,11,LONG,310,-1,-1,3 +1518886,11,LONG,311,1,-3,17 +1518888,11,LONG,312,0,-1,1 +1518890,11,LONG,313,-3,-1,13 +1518892,11,LONG,314,12,-7,222 +1518894,11,LONG,315,3,6,47 +1518896,11,LONG,316,1,-2,9 +1518898,11,LONG,317,-5,2,38 +1518900,11,LONG,318,1,-1,5 +1518902,11,LONG,319,6,-3,51 +1518904,11,LONG,320,7,-3,69 +1518906,11,LONG,321,9,-7,141 +1518908,11,LONG,322,-6,-4,61 +1518910,11,LONG,323,-3,-8,94 +1518912,11,LONG,324,-4,2,23 +1518914,11,LONG,325,-2,2,13 +1518916,11,LONG,326,-9,0,83 +1518918,11,LONG,327,9,-5,118 +1518920,11,LONG,328,-4,1,19 +1518922,11,LONG,329,-6,-1,38 +1518924,11,LONG,330,9,3,107 +1518926,11,LONG,331,5,0,25 +1518928,11,LONG,332,-3,6,57 +1518930,11,LONG,333,-2,1,9 +1518932,11,LONG,334,-1,-4,17 +1518934,11,LONG,335,5,-4,43 +1518936,11,LONG,336,-3,-2,20 +1518938,11,LONG,337,1,-8,75 +1518940,11,LONG,338,5,-4,53 +1518942,11,LONG,339,0,7,58 +1518944,11,LONG,340,-2,7,53 +1518946,11,LONG,341,2,0,7 +1518948,11,LONG,342,-6,0,48 +1518950,11,LONG,343,6,0,40 +1518952,11,LONG,344,2,-2,8 +1518954,11,LONG,345,-8,1,68 +1518956,11,LONG,346,6,-11,162 +1518958,11,LONG,347,10,-2,113 +1518960,11,LONG,348,5,0,29 +1518962,11,LONG,349,5,2,37 +1518964,11,LONG,350,10,-1,102 +1518966,11,LONG,351,5,-1,35 +1518968,11,LONG,352,0,-3,16 +1518970,11,LONG,353,-5,-7,92 +1518972,11,LONG,354,4,4,40 +1518974,11,LONG,355,-2,8,79 +1518976,11,LONG,356,4,0,20 +1518978,11,LONG,357,-1,-8,73 +1518980,11,LONG,358,-9,-2,99 +1518982,11,LONG,359,0,0,0 +1518984,11,LONG,360,-7,3,67 +1518986,11,LONG,361,-3,1,19 +1518988,11,LONG,362,-6,6,83 +1518990,11,LONG,363,-2,0,8 +1518992,11,LONG,364,-4,6,65 +1518994,11,LONG,365,-2,2,11 +1518996,11,LONG,366,0,-5,27 +1518998,11,LONG,367,1,8,75 +1519000,11,LONG,368,8,-4,90 +1519002,11,LONG,369,-5,-9,127 +1519004,11,LONG,370,-2,8,78 +1519006,11,LONG,371,0,0,1 +1519008,11,LONG,372,4,7,80 +1519010,11,LONG,373,4,8,86 +1519012,11,LONG,374,0,-1,4 +1519014,11,LONG,375,2,-4,25 +1519016,11,LONG,376,1,-2,8 +1519018,11,LONG,377,6,-7,106 +1519020,11,LONG,378,0,-1,2 +1519022,11,LONG,379,2,-10,126 +1519024,11,LONG,380,1,3,11 +1519026,11,LONG,381,-6,-4,61 +1519028,11,LONG,382,0,1,4 +1519030,11,LONG,383,0,1,3 +1519032,11,LONG,384,1,-3,16 +1519034,11,LONG,385,5,-4,51 +1519036,11,LONG,386,2,0,5 +1519038,11,LONG,387,-1,-2,5 +1519040,11,LONG,388,-8,-7,128 +1519042,11,LONG,389,1,2,9 +1519044,11,LONG,390,3,2,18 +1519046,11,LONG,391,-14,16,481 +1519048,11,LONG,392,-15,13,423 +1519050,11,LONG,393,-16,12,409 +1519052,11,LONG,394,-17,14,523 +1519054,11,LONG,395,-23,0,542 +1519056,11,LONG,396,-20,5,443 +1519058,11,LONG,397,-20,6,448 +1519060,11,LONG,398,-27,-5,781 +1519062,11,LONG,399,-22,3,524 +1519064,11,LONG,400,-25,-11,769 +1519066,11,LONG,401,-20,-4,429 +1519068,11,LONG,402,-14,-8,287 +1519070,11,LONG,403,-7,-9,147 +1519072,11,LONG,404,-16,-18,606 +1519074,11,LONG,405,-14,-23,759 +1519076,11,LONG,406,-22,-29,1363 +1519078,11,LONG,407,-13,-14,375 +1519080,11,LONG,408,-8,-20,482 +1519082,11,LONG,409,0,-22,522 +1519084,11,LONG,410,0,11,126 +1519086,11,LONG,411,0,0,0 +1519088,11,LONG,412,-5,-3,39 +1519090,11,LONG,413,10,3,119 +1519092,11,LONG,414,4,-1,25 +1519094,11,LONG,415,4,1,20 +1519096,11,LONG,416,2,-3,17 +1519098,11,LONG,417,2,-3,19 +1519100,11,LONG,418,-3,3,28 +1519102,11,LONG,419,5,-7,80 +1519104,11,LONG,420,2,0,7 +1519106,11,LONG,421,10,-2,115 +1519108,11,LONG,422,0,1,1 +1519110,11,LONG,423,0,-4,24 +1519112,11,LONG,424,3,-1,17 +1519114,11,LONG,425,0,5,31 +1519116,11,LONG,426,5,7,75 +1519118,11,LONG,427,-1,-6,43 +1519120,11,LONG,428,-8,-1,72 +1519122,11,LONG,429,-3,0,9 +1519124,11,LONG,430,3,-7,70 +1519126,11,LONG,431,0,1,2 +1519128,11,LONG,432,0,0,0 +1519130,11,LONG,433,-1,12,153 +1519132,11,LONG,434,8,-3,90 +1519134,11,LONG,435,4,-5,54 +1519136,11,LONG,436,0,-1,2 +1519138,11,LONG,437,0,5,32 +1519140,11,LONG,438,1,7,61 +1519142,11,LONG,439,5,6,62 +1519144,11,LONG,440,1,-5,31 +1519146,11,LONG,441,3,0,15 +1519148,11,LONG,442,3,4,31 +1519150,11,LONG,443,0,-6,36 +1519152,11,LONG,444,0,-4,24 +1519154,11,LONG,445,-4,0,16 +1519156,11,LONG,446,2,8,80 +1519158,11,LONG,447,4,5,53 +1519160,11,LONG,448,-3,-3,28 +1519162,11,LONG,449,4,7,72 +1519164,11,LONG,450,-6,-6,86 +1519166,11,LONG,451,-1,0,3 +1519168,11,LONG,452,-4,2,26 +1519170,11,LONG,453,8,-5,100 +1519172,11,LONG,454,3,-1,15 +1519174,11,LONG,455,-1,-6,44 +1519176,11,LONG,456,4,0,23 +1519178,11,LONG,457,-7,4,79 +1519180,11,LONG,458,0,6,39 +1519182,11,LONG,459,-8,1,78 +1519184,11,LONG,460,-5,4,48 +1519186,11,LONG,461,-9,3,93 +1519188,11,LONG,462,2,-2,13 +1519190,11,LONG,463,-5,10,134 +1519192,11,LONG,464,-2,-5,38 +1519194,11,LONG,465,3,7,65 +1519196,11,LONG,466,0,-4,24 +1519198,11,LONG,467,-3,2,17 +1519200,11,LONG,468,11,0,122 +1519202,11,LONG,469,-10,-3,120 +1519204,11,LONG,470,-5,0,31 +1519206,11,LONG,471,-10,0,115 +1519208,11,LONG,472,0,1,2 +1519210,11,LONG,473,-1,-3,14 +1519212,11,LONG,474,1,-4,24 +1519214,11,LONG,475,0,0,0 +1519216,11,LONG,476,6,3,51 +1519218,11,LONG,477,-9,-3,109 +1519220,11,LONG,478,1,7,56 +1519222,11,LONG,479,-1,-6,46 +1519224,11,LONG,480,2,5,32 +1519226,11,LONG,481,1,2,6 +1519228,11,LONG,482,4,-5,52 +1519230,11,LONG,483,-1,3,16 +1519232,11,LONG,484,2,-4,23 +1519234,11,LONG,485,-3,0,15 +1519236,11,LONG,486,-5,-3,38 +1519238,11,LONG,487,7,-2,57 +1519240,11,LONG,488,0,2,7 +1519242,11,LONG,489,1,7,65 +1519244,11,LONG,490,-2,-8,78 +1519246,11,LONG,491,4,0,23 +1519248,11,LONG,492,0,-4,23 +1519250,11,LONG,493,-9,5,118 +1519252,11,LONG,494,-4,9,103 +1519254,11,LONG,495,0,0,0 +1519256,11,LONG,496,4,-9,114 +1519258,11,LONG,497,6,-2,43 +1519260,11,LONG,498,-2,0,4 +1519262,11,LONG,499,-5,1,35 +1519264,11,LONG,500,1,3,16 +1519266,11,LONG,501,1,-7,66 +1519268,11,LONG,502,-2,2,13 +1519270,11,LONG,503,9,0,93 +1519272,11,LONG,504,0,1,3 +1519274,11,LONG,505,1,0,2 +1519276,11,LONG,506,-6,6,84 +1519278,11,LONG,507,0,0,0 +1519280,11,LONG,508,3,-6,55 +1519282,11,LONG,509,11,0,144 +1519284,11,LONG,510,0,2,4 +1519286,11,LONG,511,5,0,32 +1656288,12,LONG,0,-16,-19,667 +1656290,12,LONG,1,-9,-2,104 +1656292,12,LONG,2,-4,0,18 +1656294,12,LONG,3,15,-4,249 +1656296,12,LONG,4,12,7,206 +1656298,12,LONG,5,16,14,474 +1656300,12,LONG,6,0,29,862 +1656302,12,LONG,7,2,9,86 +1656304,12,LONG,8,19,-5,404 +1656306,12,LONG,9,13,28,991 +1656308,12,LONG,10,-16,-8,351 +1656310,12,LONG,11,11,10,230 +1656312,12,LONG,12,7,-12,224 +1656314,12,LONG,13,-2,-16,263 +1656316,12,LONG,14,-1,9,87 +1656318,12,LONG,15,0,-16,288 +1656320,12,LONG,16,15,-3,268 +1656322,12,LONG,17,-10,-13,303 +1656324,12,LONG,18,5,16,317 +1656326,12,LONG,19,-29,0,892 +1656328,12,LONG,20,-4,9,110 +1656330,12,LONG,21,-21,10,568 +1656332,12,LONG,22,-6,-5,65 +1656334,12,LONG,23,-12,-1,161 +1656336,12,LONG,24,10,2,110 +1656338,12,LONG,25,-7,14,279 +1656340,12,LONG,26,-4,20,450 +1656342,12,LONG,27,3,2,18 +1656344,12,LONG,28,-18,2,333 +1656346,12,LONG,29,-2,3,15 +1656348,12,LONG,30,15,-8,290 +1656350,12,LONG,31,0,2,5 +1656352,12,LONG,32,-3,-1,13 +1656354,12,LONG,33,4,-3,32 +1656356,12,LONG,34,-21,4,482 +1656358,12,LONG,35,15,6,286 +1656360,12,LONG,36,9,-3,107 +1656362,12,LONG,37,13,2,188 +1656364,12,LONG,38,-16,-3,271 +1656366,12,LONG,39,7,-1,56 +1656368,12,LONG,40,5,11,171 +1656370,12,LONG,41,11,10,239 +1656372,12,LONG,42,0,-5,28 +1656374,12,LONG,43,-14,5,231 +1656376,12,LONG,44,8,-10,187 +1656378,12,LONG,45,-16,13,450 +1656380,12,LONG,46,-10,15,356 +1656382,12,LONG,47,16,-9,359 +1656384,12,LONG,48,-11,-21,601 +1656386,12,LONG,49,14,9,283 +1656388,12,LONG,50,8,-2,85 +1656390,12,LONG,51,-8,17,395 +1656392,12,LONG,52,9,14,313 +1656394,12,LONG,53,-1,-10,111 +1656396,12,LONG,54,22,5,527 +1656398,12,LONG,55,-10,-24,728 +1656400,12,LONG,56,8,18,400 +1656402,12,LONG,57,1,-8,71 +1656404,12,LONG,58,-9,9,186 +1656406,12,LONG,59,29,7,891 +1656408,12,LONG,60,9,11,227 +1656410,12,LONG,61,7,4,75 +1656412,12,LONG,62,-7,-11,196 +1656414,12,LONG,63,24,7,645 +1656416,12,LONG,64,2,2,10 +1656418,12,LONG,65,-6,-6,89 +1656420,12,LONG,66,3,3,28 +1656422,12,LONG,67,3,5,42 +1656424,12,LONG,68,-4,-23,559 +1656426,12,LONG,69,11,1,142 +1656428,12,LONG,70,-2,10,120 +1656430,12,LONG,71,0,-5,26 +1656432,12,LONG,72,7,-9,137 +1656434,12,LONG,73,9,-2,100 +1656436,12,LONG,74,-5,-5,60 +1656438,12,LONG,75,-15,7,299 +1656440,12,LONG,76,7,7,119 +1656442,12,LONG,77,-1,15,235 +1656444,12,LONG,78,-19,-11,498 +1656446,12,LONG,79,-8,-5,109 +1656448,12,LONG,80,24,5,633 +1656450,12,LONG,81,-7,12,209 +1656452,12,LONG,82,-28,-3,827 +1656454,12,LONG,83,1,27,735 +1656456,12,LONG,84,-22,7,552 +1656458,12,LONG,85,-1,3,18 +1656460,12,LONG,86,0,3,15 +1656462,12,LONG,87,-1,7,58 +1656464,12,LONG,88,-5,2,39 +1656466,12,LONG,89,18,-34,1574 +1656468,12,LONG,90,22,-9,610 +1656470,12,LONG,91,-8,-9,152 +1656472,12,LONG,92,17,4,323 +1656474,12,LONG,93,5,-12,195 +1656476,12,LONG,94,-11,-17,441 +1656478,12,LONG,95,6,-3,61 +1656480,12,LONG,96,-5,-6,66 +1656482,12,LONG,97,1,14,202 +1656484,12,LONG,98,6,-2,52 +1656486,12,LONG,99,0,15,237 +1656488,12,LONG,100,-5,2,34 +1656490,12,LONG,101,-3,-7,58 +1656492,12,LONG,102,0,-3,13 +1656494,12,LONG,103,0,-1,4 +1656496,12,LONG,104,2,-3,17 +1656498,12,LONG,105,5,-3,39 +1656500,12,LONG,106,-2,-2,13 +1656502,12,LONG,107,5,-2,41 +1656504,12,LONG,108,3,9,97 +1656506,12,LONG,109,0,1,2 +1656508,12,LONG,110,-3,0,13 +1656510,12,LONG,111,-5,7,76 +1656512,12,LONG,112,-3,2,17 +1656514,12,LONG,113,2,4,27 +1656516,12,LONG,114,-9,0,92 +1656518,12,LONG,115,-2,-8,83 +1656520,12,LONG,116,2,-2,10 +1656522,12,LONG,117,0,4,20 +1656524,12,LONG,118,4,4,40 +1656526,12,LONG,119,9,0,99 +1656528,12,LONG,120,2,8,76 +1656530,12,LONG,121,1,-1,4 +1656532,12,LONG,122,3,1,17 +1656534,12,LONG,123,-4,7,73 +1656536,12,LONG,124,3,3,24 +1656538,12,LONG,125,-6,1,49 +1656540,12,LONG,126,-3,0,15 +1656542,12,LONG,127,3,7,65 +1656544,12,LONG,128,-2,0,8 +1656546,12,LONG,129,-9,-2,92 +1656548,12,LONG,130,-7,-5,80 +1656550,12,LONG,131,8,1,79 +1656552,12,LONG,132,9,-2,103 +1656554,12,LONG,133,-1,3,14 +1656556,12,LONG,134,5,-5,57 +1656558,12,LONG,135,14,4,237 +1656560,12,LONG,136,-6,3,45 +1656562,12,LONG,137,1,1,5 +1656564,12,LONG,138,5,-5,61 +1656566,12,LONG,139,-4,-4,41 +1656568,12,LONG,140,0,7,53 +1656570,12,LONG,141,37,-92,9987 +1656572,12,LONG,142,50,-75,8242 +1656574,12,LONG,143,62,-71,9015 +1656576,12,LONG,144,86,-73,12747 +1656578,12,LONG,145,81,-48,8928 +1656580,12,LONG,146,92,-49,11043 +1656582,12,LONG,147,83,-40,8593 +1656584,12,LONG,148,101,-20,10818 +1656586,12,LONG,149,89,-12,8111 +1656588,12,LONG,150,107,1,11533 +1656590,12,LONG,151,96,0,9277 +1656592,12,LONG,152,97,21,10009 +1656594,12,LONG,153,104,37,12370 +1656596,12,LONG,154,82,53,9728 +1656598,12,LONG,155,71,68,9801 +1656600,12,LONG,156,83,67,11563 +1656602,12,LONG,157,63,76,9763 +1656604,12,LONG,158,51,80,9183 +1656606,12,LONG,159,34,94,10204 +1656608,12,LONG,160,3,3,24 +1656610,12,LONG,161,2,-11,125 +1656612,12,LONG,162,-6,0,42 +1656614,12,LONG,163,0,8,71 +1656616,12,LONG,164,8,-3,84 +1656618,12,LONG,165,0,1,3 +1656620,12,LONG,166,-10,8,182 +1656622,12,LONG,167,-7,-1,56 +1656624,12,LONG,168,0,-1,3 +1656626,12,LONG,169,0,2,8 +1656628,12,LONG,170,-3,-5,47 +1656630,12,LONG,171,-1,-2,10 +1656632,12,LONG,172,-4,2,30 +1656634,12,LONG,173,0,0,0 +1656636,12,LONG,174,-6,-5,75 +1656638,12,LONG,175,-3,-7,78 +1656640,12,LONG,176,5,-5,65 +1656642,12,LONG,177,3,-10,112 +1656644,12,LONG,178,2,0,5 +1656646,12,LONG,179,-11,3,148 +1656648,12,LONG,180,-5,0,28 +1656650,12,LONG,181,6,7,91 +1656652,12,LONG,182,-2,1,9 +1656654,12,LONG,183,0,0,1 +1656656,12,LONG,184,-6,-3,59 +1656658,12,LONG,185,0,0,0 +1656660,12,LONG,186,-1,-3,11 +1656662,12,LONG,187,0,-4,22 +1656664,12,LONG,188,3,-5,50 +1656666,12,LONG,189,-6,-7,91 +1656668,12,LONG,190,-5,-12,179 +1656670,12,LONG,191,1,5,31 +1656672,12,LONG,192,1,4,25 +1656674,12,LONG,193,-4,-2,22 +1656676,12,LONG,194,7,-7,108 +1656678,12,LONG,195,9,-2,99 +1656680,12,LONG,196,6,4,56 +1656682,12,LONG,197,5,0,25 +1656684,12,LONG,198,-4,-5,59 +1656686,12,LONG,199,1,-7,52 +1656688,12,LONG,200,6,1,45 +1656690,12,LONG,201,-1,-3,13 +1656692,12,LONG,202,-4,0,17 +1656694,12,LONG,203,-4,-2,26 +1656696,12,LONG,204,11,3,136 +1656698,12,LONG,205,2,6,48 +1656700,12,LONG,206,6,-5,71 +1656702,12,LONG,207,7,0,59 +1656704,12,LONG,208,7,5,82 +1656706,12,LONG,209,0,-1,1 +1656708,12,LONG,210,-2,7,72 +1656710,12,LONG,211,0,0,0 +1656712,12,LONG,212,2,-9,91 +1656714,12,LONG,213,-8,2,68 +1656716,12,LONG,214,9,0,90 +1656718,12,LONG,215,6,-6,93 +1656720,12,LONG,216,3,1,19 +1656722,12,LONG,217,4,-2,26 +1656724,12,LONG,218,-6,0,40 +1656726,12,LONG,219,0,2,6 +1656728,12,LONG,220,-4,4,38 +1656730,12,LONG,221,2,1,9 +1656732,12,LONG,222,-8,0,69 +1656734,12,LONG,223,-1,-4,21 +1656736,12,LONG,224,-5,0,28 +1656738,12,LONG,225,8,1,72 +1656740,12,LONG,226,-4,3,25 +1656742,12,LONG,227,-5,-4,49 +1656744,12,LONG,228,0,-1,3 +1656746,12,LONG,229,5,-4,55 +1656748,12,LONG,230,2,-3,16 +1656750,12,LONG,231,1,0,3 +1656752,12,LONG,232,3,1,11 +1656754,12,LONG,233,3,-10,125 +1656756,12,LONG,234,4,0,24 +1656758,12,LONG,235,-3,-1,14 +1656760,12,LONG,236,0,-2,5 +1656762,12,LONG,237,-7,0,62 +1656764,12,LONG,238,8,5,98 +1656766,12,LONG,239,3,5,44 +1656768,12,LONG,240,2,1,5 +1656770,12,LONG,241,54,7,2975 +1656772,12,LONG,242,42,6,1857 +1656774,12,LONG,243,45,12,2247 +1656776,12,LONG,244,41,24,2289 +1656778,12,LONG,245,40,27,2347 +1656780,12,LONG,246,31,36,2326 +1656782,12,LONG,247,32,30,2004 +1656784,12,LONG,248,31,42,2817 +1656786,12,LONG,249,24,46,2757 +1656788,12,LONG,250,19,45,2461 +1656790,12,LONG,251,11,53,3045 +1656792,12,LONG,252,8,49,2483 +1656794,12,LONG,253,-2,52,2757 +1656796,12,LONG,254,-7,45,2092 +1656798,12,LONG,255,-12,60,3780 +1656800,12,LONG,256,-26,45,2803 +1656802,12,LONG,257,-26,42,2565 +1656804,12,LONG,258,-35,40,2926 +1656806,12,LONG,259,-40,41,3345 +1656808,12,LONG,260,-5,4,47 +1656810,12,LONG,261,0,1,2 +1656812,12,LONG,262,-2,5,35 +1656814,12,LONG,263,-4,-5,53 +1656816,12,LONG,264,0,0,0 +1656818,12,LONG,265,0,4,21 +1656820,12,LONG,266,-6,1,41 +1656822,12,LONG,267,0,-2,7 +1656824,12,LONG,268,1,-1,3 +1656826,12,LONG,269,-7,3,62 +1656828,12,LONG,270,0,0,0 +1656830,12,LONG,271,-1,0,1 +1656832,12,LONG,272,0,2,5 +1656834,12,LONG,273,-1,3,16 +1656836,12,LONG,274,-7,-5,80 +1656838,12,LONG,275,1,1,3 +1656840,12,LONG,276,2,-1,6 +1656842,12,LONG,277,0,5,28 +1656844,12,LONG,278,0,4,19 +1656846,12,LONG,279,-2,-2,14 +1656848,12,LONG,280,0,0,0 +1656850,12,LONG,281,4,0,20 +1656852,12,LONG,282,-4,9,105 +1656854,12,LONG,283,-2,10,110 +1656856,12,LONG,284,-1,-10,104 +1656858,12,LONG,285,1,0,1 +1656860,12,LONG,286,-7,-10,165 +1656862,12,LONG,287,5,0,31 +1656864,12,LONG,288,-3,-2,17 +1656866,12,LONG,289,-1,-1,7 +1656868,12,LONG,290,-2,-3,15 +1656870,12,LONG,291,-3,-1,11 +1656872,12,LONG,292,0,-1,2 +1656874,12,LONG,293,-3,6,58 +1656876,12,LONG,294,4,-2,24 +1656878,12,LONG,295,-3,0,10 +1656880,12,LONG,296,-6,0,47 +1656882,12,LONG,297,-2,0,5 +1656884,12,LONG,298,-6,-5,75 +1656886,12,LONG,299,2,0,5 +1656888,12,LONG,300,0,3,9 +1656890,12,LONG,301,3,6,48 +1656892,12,LONG,302,1,1,4 +1656894,12,LONG,303,0,-1,1 +1656896,12,LONG,304,-2,3,21 +1656898,12,LONG,305,14,-8,289 +1656900,12,LONG,306,0,-10,103 +1656902,12,LONG,307,-8,9,151 +1656904,12,LONG,308,1,-8,79 +1656906,12,LONG,309,0,2,5 +1656908,12,LONG,310,0,3,11 +1656910,12,LONG,311,1,3,17 +1656912,12,LONG,312,0,-1,2 +1656914,12,LONG,313,-8,0,66 +1656916,12,LONG,314,-6,-3,50 +1656918,12,LONG,315,0,0,0 +1656920,12,LONG,316,-7,-1,54 +1656922,12,LONG,317,-5,0,27 +1656924,12,LONG,318,-12,-3,168 +1656926,12,LONG,319,-4,-2,24 +1656928,12,LONG,320,3,1,16 +1656930,12,LONG,321,1,11,127 +1656932,12,LONG,322,-2,0,7 +1656934,12,LONG,323,6,4,63 +1656936,12,LONG,324,0,6,45 +1656938,12,LONG,325,-9,0,93 +1656940,12,LONG,326,-9,1,96 +1656942,12,LONG,327,3,-1,14 +1656944,12,LONG,328,1,-3,12 +1656946,12,LONG,329,-6,0,42 +1656948,12,LONG,330,2,-10,107 +1656950,12,LONG,331,0,-5,30 +1656952,12,LONG,332,4,9,110 +1656954,12,LONG,333,-3,-1,13 +1656956,12,LONG,334,-6,6,80 +1656958,12,LONG,335,5,-4,54 +1656960,12,LONG,336,0,-6,40 +1656962,12,LONG,337,3,1,18 +1656964,12,LONG,338,-5,0,30 +1656966,12,LONG,339,2,-8,86 +1656968,12,LONG,340,-2,0,9 +1656970,12,LONG,341,2,12,164 +1656972,12,LONG,342,6,-8,109 +1656974,12,LONG,343,-8,-2,76 +1656976,12,LONG,344,-5,4,48 +1656978,12,LONG,345,4,0,16 +1656980,12,LONG,346,-1,-6,44 +1656982,12,LONG,347,-8,-7,133 +1656984,12,LONG,348,-6,-4,65 +1656986,12,LONG,349,0,-5,30 +1656988,12,LONG,350,6,7,95 +1656990,12,LONG,351,6,0,38 +1656992,12,LONG,352,-4,-2,23 +1656994,12,LONG,353,0,4,18 +1656996,12,LONG,354,0,-1,3 +1656998,12,LONG,355,-8,5,107 +1657000,12,LONG,356,0,2,7 +1657002,12,LONG,357,-1,-4,25 +1657004,12,LONG,358,-3,-3,31 +1657006,12,LONG,359,1,-2,5 +1657008,12,LONG,360,-8,-3,91 +1657010,12,LONG,361,0,4,19 +1657012,12,LONG,362,-5,3,45 +1657014,12,LONG,363,1,-2,6 +1657016,12,LONG,364,-1,0,2 +1657018,12,LONG,365,6,6,74 +1657020,12,LONG,366,-2,-1,8 +1657022,12,LONG,367,0,1,2 +1657024,12,LONG,368,5,1,35 +1657026,12,LONG,369,0,-6,37 +1657028,12,LONG,370,0,-2,5 +1657030,12,LONG,371,1,-6,38 +1657032,12,LONG,372,0,1,1 +1657034,12,LONG,373,-1,-1,5 +1657036,12,LONG,374,-1,-2,9 +1657038,12,LONG,375,0,-7,51 +1657040,12,LONG,376,-2,2,14 +1657042,12,LONG,377,5,-1,30 +1657044,12,LONG,378,-4,5,55 +1657046,12,LONG,379,0,3,11 +1657048,12,LONG,380,7,-4,77 +1657050,12,LONG,381,9,-11,225 +1657052,12,LONG,382,16,6,298 +1657054,12,LONG,383,1,8,75 +1657056,12,LONG,384,0,0,1 +1657058,12,LONG,385,-2,9,105 +1657060,12,LONG,386,-7,-7,108 +1657062,12,LONG,387,4,6,55 +1657064,12,LONG,388,0,8,71 +1657066,12,LONG,389,7,-2,70 +1657068,12,LONG,390,2,0,9 +1657070,12,LONG,391,-19,14,574 +1657072,12,LONG,392,-13,11,312 +1657074,12,LONG,393,-22,10,635 +1657076,12,LONG,394,-15,7,308 +1657078,12,LONG,395,-26,5,753 +1657080,12,LONG,396,-18,11,463 +1657082,12,LONG,397,-23,-5,585 +1657084,12,LONG,398,-21,-6,490 +1657086,12,LONG,399,-27,-14,966 +1657088,12,LONG,400,-14,-7,274 +1657090,12,LONG,401,-18,-15,560 +1657092,12,LONG,402,-14,-14,398 +1657094,12,LONG,403,-16,-20,674 +1657096,12,LONG,404,-13,-21,625 +1657098,12,LONG,405,-14,-22,699 +1657100,12,LONG,406,-7,-22,578 +1657102,12,LONG,407,-6,-28,838 +1657104,12,LONG,408,0,-20,419 +1657106,12,LONG,409,5,-23,560 +1657108,12,LONG,410,2,5,39 +1657110,12,LONG,411,2,2,12 +1657112,12,LONG,412,-3,1,12 +1657114,12,LONG,413,-3,1,13 +1657116,12,LONG,414,0,-2,5 +1657118,12,LONG,415,1,5,32 +1657120,12,LONG,416,-1,7,55 +1657122,12,LONG,417,0,-12,148 +1657124,12,LONG,418,-2,-4,27 +1657126,12,LONG,419,-7,4,70 +1657128,12,LONG,420,-1,-5,29 +1657130,12,LONG,421,1,16,283 +1657132,12,LONG,422,11,-1,132 +1657134,12,LONG,423,2,6,44 +1657136,12,LONG,424,-6,-2,44 +1657138,12,LONG,425,-9,0,93 +1657140,12,LONG,426,8,5,99 +1657142,12,LONG,427,-2,-2,11 +1657144,12,LONG,428,-5,-2,37 +1657146,12,LONG,429,-7,0,61 +1657148,12,LONG,430,-3,-3,25 +1657150,12,LONG,431,5,4,50 +1657152,12,LONG,432,6,-2,43 +1657154,12,LONG,433,-3,-4,38 +1657156,12,LONG,434,4,-1,27 +1657158,12,LONG,435,4,-4,41 +1657160,12,LONG,436,0,-7,50 +1657162,12,LONG,437,0,8,67 +1657164,12,LONG,438,-2,7,71 +1657166,12,LONG,439,0,-8,68 +1657168,12,LONG,440,1,3,13 +1657170,12,LONG,441,-5,-2,30 +1657172,12,LONG,442,-3,-11,135 +1657174,12,LONG,443,7,-5,89 +1657176,12,LONG,444,-8,9,146 +1657178,12,LONG,445,6,-3,57 +1657180,12,LONG,446,-6,4,58 +1657182,12,LONG,447,0,4,19 +1657184,12,LONG,448,7,0,57 +1657186,12,LONG,449,3,2,19 +1657188,12,LONG,450,0,-5,35 +1657190,12,LONG,451,-1,-8,70 +1657192,12,LONG,452,-6,1,37 +1657194,12,LONG,453,-3,4,37 +1657196,12,LONG,454,1,-3,13 +1657198,12,LONG,455,-3,-7,70 +1657200,12,LONG,456,4,-1,20 +1657202,12,LONG,457,2,-2,16 +1657204,12,LONG,458,-1,-10,113 +1657206,12,LONG,459,-3,-4,29 +1657208,12,LONG,460,2,0,5 +1657210,12,LONG,461,2,-12,162 +1657212,12,LONG,462,4,-2,22 +1657214,12,LONG,463,0,0,0 +1657216,12,LONG,464,8,-2,75 +1657218,12,LONG,465,3,0,9 +1657220,12,LONG,466,-2,6,51 +1657222,12,LONG,467,-1,1,4 +1657224,12,LONG,468,4,-3,28 +1657226,12,LONG,469,-3,8,82 +1657228,12,LONG,470,-1,-1,3 +1657230,12,LONG,471,-2,4,23 +1657232,12,LONG,472,-1,0,1 +1657234,12,LONG,473,5,5,57 +1657236,12,LONG,474,5,4,57 +1657238,12,LONG,475,0,5,27 +1657240,12,LONG,476,0,-4,23 +1657242,12,LONG,477,4,2,29 +1657244,12,LONG,478,6,-4,65 +1657246,12,LONG,479,5,-3,46 +1657248,12,LONG,480,10,6,160 +1657250,12,LONG,481,4,2,23 +1657252,12,LONG,482,2,0,4 +1657254,12,LONG,483,4,2,28 +1657256,12,LONG,484,-11,3,155 +1657258,12,LONG,485,-3,0,9 +1657260,12,LONG,486,3,7,70 +1657262,12,LONG,487,-2,6,44 +1657264,12,LONG,488,5,1,37 +1657266,12,LONG,489,3,0,13 +1657268,12,LONG,490,-7,-5,89 +1657270,12,LONG,491,-3,1,18 +1657272,12,LONG,492,4,0,17 +1657274,12,LONG,493,-3,6,55 +1657276,12,LONG,494,7,4,83 +1657278,12,LONG,495,9,5,115 +1657280,12,LONG,496,6,5,69 +1657282,12,LONG,497,0,-2,5 +1657284,12,LONG,498,1,-1,5 +1657286,12,LONG,499,-4,-1,22 +1657288,12,LONG,500,-7,2,53 +1657290,12,LONG,501,3,2,17 +1657292,12,LONG,502,-8,1,72 +1657294,12,LONG,503,-4,6,56 +1657296,12,LONG,504,5,-2,32 +1657298,12,LONG,505,0,-1,2 +1657300,12,LONG,506,7,-1,55 +1657302,12,LONG,507,4,-1,19 +1657304,12,LONG,508,5,-2,31 +1657306,12,LONG,509,6,9,133 +1657308,12,LONG,510,5,6,69 +1657310,12,LONG,511,0,3,15 +1794312,13,LONG,0,2,12,152 +1794314,13,LONG,1,12,-13,360 +1794316,13,LONG,2,5,9,130 +1794318,13,LONG,3,6,-8,116 +1794320,13,LONG,4,0,-18,341 +1794322,13,LONG,5,9,-3,102 +1794324,13,LONG,6,3,0,11 +1794326,13,LONG,7,15,-10,353 +1794328,13,LONG,8,-3,-2,18 +1794330,13,LONG,9,10,12,271 +1794332,13,LONG,10,-10,-13,310 +1794334,13,LONG,11,14,-2,212 +1794336,13,LONG,12,-9,14,315 +1794338,13,LONG,13,3,6,46 +1794340,13,LONG,14,3,4,26 +1794342,13,LONG,15,10,10,224 +1794344,13,LONG,16,21,5,494 +1794346,13,LONG,17,3,1,15 +1794348,13,LONG,18,-5,-20,465 +1794350,13,LONG,19,0,-10,115 +1794352,13,LONG,20,1,3,15 +1794354,13,LONG,21,2,3,16 +1794356,13,LONG,22,4,-7,75 +1794358,13,LONG,23,0,2,7 +1794360,13,LONG,24,0,-8,73 +1794362,13,LONG,25,-20,14,640 +1794364,13,LONG,26,10,2,122 +1794366,13,LONG,27,9,-9,196 +1794368,13,LONG,28,0,0,0 +1794370,13,LONG,29,5,-1,32 +1794372,13,LONG,30,-15,7,311 +1794374,13,LONG,31,6,7,97 +1794376,13,LONG,32,6,18,366 +1794378,13,LONG,33,-15,12,403 +1794380,13,LONG,34,-17,-7,351 +1794382,13,LONG,35,-30,-7,965 +1794384,13,LONG,36,5,17,346 +1794386,13,LONG,37,-9,-8,157 +1794388,13,LONG,38,19,-6,424 +1794390,13,LONG,39,10,8,174 +1794392,13,LONG,40,-16,18,624 +1794394,13,LONG,41,0,-3,15 +1794396,13,LONG,42,13,9,273 +1794398,13,LONG,43,-3,6,55 +1794400,13,LONG,44,0,-8,78 +1794402,13,LONG,45,-4,-8,89 +1794404,13,LONG,46,5,4,55 +1794406,13,LONG,47,-24,-19,979 +1794408,13,LONG,48,0,-7,61 +1794410,13,LONG,49,23,17,877 +1794412,13,LONG,50,-8,-9,161 +1794414,13,LONG,51,-7,7,114 +1794416,13,LONG,52,14,1,205 +1794418,13,LONG,53,-10,8,180 +1794420,13,LONG,54,19,6,407 +1794422,13,LONG,55,11,7,190 +1794424,13,LONG,56,7,-4,76 +1794426,13,LONG,57,-9,11,218 +1794428,13,LONG,58,-5,4,44 +1794430,13,LONG,59,-8,1,72 +1794432,13,LONG,60,-3,5,35 +1794434,13,LONG,61,-8,1,77 +1794436,13,LONG,62,22,0,515 +1794438,13,LONG,63,0,-16,263 +1794440,13,LONG,64,0,21,454 +1794442,13,LONG,65,6,-4,60 +1794444,13,LONG,66,-12,7,208 +1794446,13,LONG,67,6,-24,651 +1794448,13,LONG,68,-13,10,307 +1794450,13,LONG,69,9,-20,523 +1794452,13,LONG,70,-2,-4,30 +1794454,13,LONG,71,-1,-4,19 +1794456,13,LONG,72,-5,-17,331 +1794458,13,LONG,73,-15,-4,257 +1794460,13,LONG,74,11,-19,516 +1794462,13,LONG,75,-5,-13,217 +1794464,13,LONG,76,3,10,123 +1794466,13,LONG,77,26,-4,712 +1794468,13,LONG,78,-3,5,38 +1794470,13,LONG,79,-11,-11,262 +1794472,13,LONG,80,12,12,315 +1794474,13,LONG,81,-16,16,530 +1794476,13,LONG,82,-15,-3,244 +1794478,13,LONG,83,6,12,194 +1794480,13,LONG,84,9,-5,114 +1794482,13,LONG,85,-34,-7,1218 +1794484,13,LONG,86,7,14,261 +1794486,13,LONG,87,0,-18,334 +1794488,13,LONG,88,-18,1,360 +1794490,13,LONG,89,-13,8,253 +1794492,13,LONG,90,0,1,1 +1794494,13,LONG,91,1,-1,5 +1794496,13,LONG,92,-1,-15,233 +1794498,13,LONG,93,0,10,113 +1794500,13,LONG,94,-8,-5,92 +1794502,13,LONG,95,-28,3,816 +1794504,13,LONG,96,5,7,83 +1794506,13,LONG,97,1,16,260 +1794508,13,LONG,98,-4,-9,113 +1794510,13,LONG,99,-15,2,239 +1794512,13,LONG,100,-10,7,162 +1794514,13,LONG,101,-1,0,4 +1794516,13,LONG,102,3,-13,185 +1794518,13,LONG,103,0,7,55 +1794520,13,LONG,104,4,2,30 +1794522,13,LONG,105,3,0,12 +1794524,13,LONG,106,-2,0,8 +1794526,13,LONG,107,-4,0,22 +1794528,13,LONG,108,0,3,11 +1794530,13,LONG,109,5,0,26 +1794532,13,LONG,110,-8,8,142 +1794534,13,LONG,111,8,-1,72 +1794536,13,LONG,112,6,-4,64 +1794538,13,LONG,113,3,-2,20 +1794540,13,LONG,114,0,-3,9 +1794542,13,LONG,115,3,-4,39 +1794544,13,LONG,116,0,-4,19 +1794546,13,LONG,117,0,-8,76 +1794548,13,LONG,118,-5,-5,57 +1794550,13,LONG,119,0,7,50 +1794552,13,LONG,120,0,3,12 +1794554,13,LONG,121,3,0,10 +1794556,13,LONG,122,2,-5,36 +1794558,13,LONG,123,-8,-3,85 +1794560,13,LONG,124,-4,10,130 +1794562,13,LONG,125,-2,-8,86 +1794564,13,LONG,126,-4,-5,51 +1794566,13,LONG,127,2,0,4 +1794568,13,LONG,128,-2,2,9 +1794570,13,LONG,129,-7,-3,67 +1794572,13,LONG,130,0,-6,41 +1794574,13,LONG,131,1,-1,3 +1794576,13,LONG,132,-4,-1,24 +1794578,13,LONG,133,0,-7,52 +1794580,13,LONG,134,1,-4,21 +1794582,13,LONG,135,2,-5,37 +1794584,13,LONG,136,-6,0,41 +1794586,13,LONG,137,0,0,0 +1794588,13,LONG,138,3,-2,20 +1794590,13,LONG,139,-2,0,7 +1794592,13,LONG,140,-1,5,35 +1794594,13,LONG,141,98,51,12367 +1794596,13,LONG,142,81,47,8814 +1794598,13,LONG,143,71,75,10778 +1794600,13,LONG,144,67,70,9561 +1794602,13,LONG,145,55,89,11150 +1794604,13,LONG,146,47,80,8820 +1794606,13,LONG,147,32,91,9449 +1794608,13,LONG,148,22,93,9242 +1794610,13,LONG,149,19,103,10975 +1794612,13,LONG,150,-2,91,8434 +1794614,13,LONG,151,-13,97,9774 +1794616,13,LONG,152,-27,91,9065 +1794618,13,LONG,153,-36,98,11022 +1794620,13,LONG,154,-51,86,10236 +1794622,13,LONG,155,-57,77,9362 +1794624,13,LONG,156,-64,70,9039 +1794626,13,LONG,157,-81,70,11582 +1794628,13,LONG,158,-84,52,9871 +1794630,13,LONG,159,-93,51,11278 +1794632,13,LONG,160,-9,-4,99 +1794634,13,LONG,161,-3,-5,34 +1794636,13,LONG,162,1,2,7 +1794638,13,LONG,163,-6,0,48 +1794640,13,LONG,164,0,2,4 +1794642,13,LONG,165,2,-2,13 +1794644,13,LONG,166,0,6,42 +1794646,13,LONG,167,-1,1,2 +1794648,13,LONG,168,3,5,38 +1794650,13,LONG,169,2,4,28 +1794652,13,LONG,170,2,-6,49 +1794654,13,LONG,171,7,0,56 +1794656,13,LONG,172,3,1,14 +1794658,13,LONG,173,0,3,12 +1794660,13,LONG,174,1,-5,30 +1794662,13,LONG,175,0,-3,10 +1794664,13,LONG,176,1,-7,56 +1794666,13,LONG,177,-1,4,17 +1794668,13,LONG,178,7,7,123 +1794670,13,LONG,179,-2,3,19 +1794672,13,LONG,180,2,0,5 +1794674,13,LONG,181,4,0,20 +1794676,13,LONG,182,3,-1,16 +1794678,13,LONG,183,4,-3,33 +1794680,13,LONG,184,13,-3,210 +1794682,13,LONG,185,-1,8,67 +1794684,13,LONG,186,-5,-5,66 +1794686,13,LONG,187,13,-1,176 +1794688,13,LONG,188,-6,-3,51 +1794690,13,LONG,189,1,4,19 +1794692,13,LONG,190,1,5,36 +1794694,13,LONG,191,0,-1,2 +1794696,13,LONG,192,-1,-2,8 +1794698,13,LONG,193,0,0,1 +1794700,13,LONG,194,-6,-1,49 +1794702,13,LONG,195,2,-3,21 +1794704,13,LONG,196,-3,-1,16 +1794706,13,LONG,197,0,5,29 +1794708,13,LONG,198,0,-8,73 +1794710,13,LONG,199,6,0,45 +1794712,13,LONG,200,8,-6,102 +1794714,13,LONG,201,-5,8,96 +1794716,13,LONG,202,-4,-3,30 +1794718,13,LONG,203,2,1,9 +1794720,13,LONG,204,-1,4,21 +1794722,13,LONG,205,1,0,4 +1794724,13,LONG,206,-4,1,22 +1794726,13,LONG,207,8,-3,80 +1794728,13,LONG,208,2,4,27 +1794730,13,LONG,209,4,9,103 +1794732,13,LONG,210,5,-6,76 +1794734,13,LONG,211,0,0,0 +1794736,13,LONG,212,-5,4,50 +1794738,13,LONG,213,13,1,173 +1794740,13,LONG,214,6,-6,87 +1794742,13,LONG,215,-13,2,181 +1794744,13,LONG,216,-5,5,59 +1794746,13,LONG,217,-4,5,49 +1794748,13,LONG,218,0,-1,3 +1794750,13,LONG,219,0,4,18 +1794752,13,LONG,220,-3,7,67 +1794754,13,LONG,221,0,7,53 +1794756,13,LONG,222,5,2,33 +1794758,13,LONG,223,1,-7,59 +1794760,13,LONG,224,7,10,174 +1794762,13,LONG,225,-1,0,2 +1794764,13,LONG,226,0,-2,8 +1794766,13,LONG,227,0,-4,20 +1794768,13,LONG,228,-3,0,14 +1794770,13,LONG,229,1,4,19 +1794772,13,LONG,230,-4,-3,31 +1794774,13,LONG,231,2,-9,94 +1794776,13,LONG,232,-12,10,248 +1794778,13,LONG,233,7,-2,57 +1794780,13,LONG,234,-2,-4,27 +1794782,13,LONG,235,0,-7,59 +1794784,13,LONG,236,8,-7,126 +1794786,13,LONG,237,-4,-6,67 +1794788,13,LONG,238,-1,3,13 +1794790,13,LONG,239,7,3,64 +1794792,13,LONG,240,-5,6,71 +1794794,13,LONG,241,38,-37,2916 +1794796,13,LONG,242,41,-30,2687 +1794798,13,LONG,243,46,-34,3319 +1794800,13,LONG,244,49,-20,2864 +1794802,13,LONG,245,48,-15,2637 +1794804,13,LONG,246,46,0,2118 +1794806,13,LONG,247,48,-7,2443 +1794808,13,LONG,248,59,-1,3504 +1794810,13,LONG,249,54,15,3191 +1794812,13,LONG,250,44,11,2119 +1794814,13,LONG,251,48,22,2829 +1794816,13,LONG,252,45,25,2682 +1794818,13,LONG,253,34,37,2572 +1794820,13,LONG,254,25,43,2545 +1794822,13,LONG,255,28,37,2196 +1794824,13,LONG,256,21,43,2395 +1794826,13,LONG,257,20,53,3229 +1794828,13,LONG,258,13,37,1613 +1794830,13,LONG,259,5,45,2057 +1794832,13,LONG,260,0,3,12 +1794834,13,LONG,261,-2,-1,5 +1794836,13,LONG,262,0,-2,8 +1794838,13,LONG,263,0,-9,89 +1794840,13,LONG,264,-4,-2,28 +1794842,13,LONG,265,9,1,98 +1794844,13,LONG,266,-6,-7,92 +1794846,13,LONG,267,0,-7,52 +1794848,13,LONG,268,-6,-2,47 +1794850,13,LONG,269,4,14,220 +1794852,13,LONG,270,-2,-2,10 +1794854,13,LONG,271,2,7,65 +1794856,13,LONG,272,12,-2,153 +1794858,13,LONG,273,4,5,49 +1794860,13,LONG,274,-5,-4,59 +1794862,13,LONG,275,4,-5,48 +1794864,13,LONG,276,-2,2,10 +1794866,13,LONG,277,-1,6,49 +1794868,13,LONG,278,-1,0,3 +1794870,13,LONG,279,3,6,49 +1794872,13,LONG,280,4,4,33 +1794874,13,LONG,281,0,0,0 +1794876,13,LONG,282,0,-1,2 +1794878,13,LONG,283,-9,2,103 +1794880,13,LONG,284,-6,-4,67 +1794882,13,LONG,285,4,-1,19 +1794884,13,LONG,286,0,-2,4 +1794886,13,LONG,287,1,5,34 +1794888,13,LONG,288,3,10,119 +1794890,13,LONG,289,-5,2,31 +1794892,13,LONG,290,0,13,169 +1794894,13,LONG,291,-4,3,29 +1794896,13,LONG,292,-3,-3,22 +1794898,13,LONG,293,0,-6,37 +1794900,13,LONG,294,3,2,14 +1794902,13,LONG,295,-5,-11,150 +1794904,13,LONG,296,0,1,2 +1794906,13,LONG,297,-1,-3,11 +1794908,13,LONG,298,-2,2,13 +1794910,13,LONG,299,3,11,140 +1794912,13,LONG,300,5,-5,64 +1794914,13,LONG,301,9,5,125 +1794916,13,LONG,302,-4,1,23 +1794918,13,LONG,303,-7,-11,191 +1794920,13,LONG,304,-3,4,30 +1794922,13,LONG,305,-1,-7,62 +1794924,13,LONG,306,-6,2,43 +1794926,13,LONG,307,4,-1,20 +1794928,13,LONG,308,-7,11,174 +1794930,13,LONG,309,-6,0,37 +1794932,13,LONG,310,-4,-1,21 +1794934,13,LONG,311,0,2,8 +1794936,13,LONG,312,2,12,166 +1794938,13,LONG,313,-2,-1,5 +1794940,13,LONG,314,3,-8,87 +1794942,13,LONG,315,0,8,68 +1794944,13,LONG,316,-2,1,11 +1794946,13,LONG,317,-4,2,27 +1794948,13,LONG,318,1,5,27 +1794950,13,LONG,319,-1,3,18 +1794952,13,LONG,320,1,-8,74 +1794954,13,LONG,321,4,1,24 +1794956,13,LONG,322,3,3,25 +1794958,13,LONG,323,-2,3,18 +1794960,13,LONG,324,0,-4,19 +1794962,13,LONG,325,-4,-3,31 +1794964,13,LONG,326,0,1,3 +1794966,13,LONG,327,6,0,40 +1794968,13,LONG,328,-8,-12,238 +1794970,13,LONG,329,1,2,8 +1794972,13,LONG,330,8,0,65 +1794974,13,LONG,331,-5,10,140 +1794976,13,LONG,332,-1,2,8 +1794978,13,LONG,333,-4,-2,22 +1794980,13,LONG,334,-8,0,76 +1794982,13,LONG,335,-9,-2,98 +1794984,13,LONG,336,2,10,113 +1794986,13,LONG,337,-5,-6,66 +1794988,13,LONG,338,-10,9,204 +1794990,13,LONG,339,0,0,0 +1794992,13,LONG,340,-4,0,20 +1794994,13,LONG,341,1,5,33 +1794996,13,LONG,342,2,0,8 +1794998,13,LONG,343,0,-1,1 +1795000,13,LONG,344,-2,-3,19 +1795002,13,LONG,345,-5,2,36 +1795004,13,LONG,346,-6,0,37 +1795006,13,LONG,347,-4,2,27 +1795008,13,LONG,348,3,-1,14 +1795010,13,LONG,349,0,-1,2 +1795012,13,LONG,350,-7,3,69 +1795014,13,LONG,351,-5,9,108 +1795016,13,LONG,352,-3,-8,94 +1795018,13,LONG,353,0,-11,126 +1795020,13,LONG,354,-6,1,44 +1795022,13,LONG,355,1,-1,5 +1795024,13,LONG,356,2,4,27 +1795026,13,LONG,357,3,1,11 +1795028,13,LONG,358,2,2,14 +1795030,13,LONG,359,3,-7,67 +1795032,13,LONG,360,0,0,0 +1795034,13,LONG,361,-10,4,125 +1795036,13,LONG,362,-11,0,126 +1795038,13,LONG,363,3,-4,38 +1795040,13,LONG,364,-3,0,12 +1795042,13,LONG,365,-11,-3,147 +1795044,13,LONG,366,1,6,51 +1795046,13,LONG,367,0,-5,28 +1795048,13,LONG,368,3,0,13 +1795050,13,LONG,369,2,0,6 +1795052,13,LONG,370,-2,4,29 +1795054,13,LONG,371,0,0,0 +1795056,13,LONG,372,-4,-8,95 +1795058,13,LONG,373,3,-1,17 +1795060,13,LONG,374,-1,-4,19 +1795062,13,LONG,375,2,0,9 +1795064,13,LONG,376,4,-3,33 +1795066,13,LONG,377,10,2,105 +1795068,13,LONG,378,-4,5,48 +1795070,13,LONG,379,-4,-3,30 +1795072,13,LONG,380,-3,-2,22 +1795074,13,LONG,381,3,-13,184 +1795076,13,LONG,382,6,3,54 +1795078,13,LONG,383,4,1,25 +1795080,13,LONG,384,1,-2,5 +1795082,13,LONG,385,-1,2,10 +1795084,13,LONG,386,2,-3,17 +1795086,13,LONG,387,-3,11,135 +1795088,13,LONG,388,-2,0,9 +1795090,13,LONG,389,-4,-2,26 +1795092,13,LONG,390,0,0,1 +1795094,13,LONG,391,-25,9,755 +1795096,13,LONG,392,-26,4,722 +1795098,13,LONG,393,-35,0,1260 +1795100,13,LONG,394,-29,-4,897 +1795102,13,LONG,395,-19,-4,409 +1795104,13,LONG,396,-22,-19,869 +1795106,13,LONG,397,-21,-8,557 +1795108,13,LONG,398,-17,-15,534 +1795110,13,LONG,399,-21,-21,895 +1795112,13,LONG,400,-18,-20,746 +1795114,13,LONG,401,-25,-20,1080 +1795116,13,LONG,402,-9,-29,975 +1795118,13,LONG,403,-5,-19,408 +1795120,13,LONG,404,0,-16,264 +1795122,13,LONG,405,0,-19,366 +1795124,13,LONG,406,9,-27,824 +1795126,13,LONG,407,4,-20,428 +1795128,13,LONG,408,14,-20,608 +1795130,13,LONG,409,20,-21,865 +1795132,13,LONG,410,11,4,149 +1795134,13,LONG,411,0,-7,53 +1795136,13,LONG,412,-3,3,24 +1795138,13,LONG,413,-1,0,2 +1795140,13,LONG,414,3,-1,13 +1795142,13,LONG,415,-8,1,79 +1795144,13,LONG,416,-2,1,8 +1795146,13,LONG,417,-6,-8,109 +1795148,13,LONG,418,-5,-5,51 +1795150,13,LONG,419,-4,-8,88 +1795152,13,LONG,420,-3,-2,18 +1795154,13,LONG,421,4,-8,89 +1795156,13,LONG,422,7,1,59 +1795158,13,LONG,423,2,-1,8 +1795160,13,LONG,424,2,7,58 +1795162,13,LONG,425,-2,0,7 +1795164,13,LONG,426,1,-3,12 +1795166,13,LONG,427,0,3,10 +1795168,13,LONG,428,-8,-2,76 +1795170,13,LONG,429,0,-2,5 +1795172,13,LONG,430,-4,0,17 +1795174,13,LONG,431,-1,0,3 +1795176,13,LONG,432,0,-9,89 +1795178,13,LONG,433,-10,-1,102 +1795180,13,LONG,434,-1,-5,32 +1795182,13,LONG,435,-5,10,141 +1795184,13,LONG,436,3,3,24 +1795186,13,LONG,437,-3,-3,23 +1795188,13,LONG,438,-2,4,28 +1795190,13,LONG,439,-3,-6,56 +1795192,13,LONG,440,-3,4,35 +1795194,13,LONG,441,-11,0,129 +1795196,13,LONG,442,-1,-2,11 +1795198,13,LONG,443,-2,-1,7 +1795200,13,LONG,444,-2,5,34 +1795202,13,LONG,445,-3,0,9 +1795204,13,LONG,446,3,0,15 +1795206,13,LONG,447,-2,0,5 +1795208,13,LONG,448,2,-1,5 +1795210,13,LONG,449,-2,-1,6 +1795212,13,LONG,450,3,1,15 +1795214,13,LONG,451,-2,9,94 +1795216,13,LONG,452,-2,0,6 +1795218,13,LONG,453,2,0,9 +1795220,13,LONG,454,8,-1,71 +1795222,13,LONG,455,-11,-3,138 +1795224,13,LONG,456,-10,1,117 +1795226,13,LONG,457,4,0,17 +1795228,13,LONG,458,-2,0,9 +1795230,13,LONG,459,-7,9,143 +1795232,13,LONG,460,-6,0,38 +1795234,13,LONG,461,-13,5,201 +1795236,13,LONG,462,-2,0,6 +1795238,13,LONG,463,-1,0,2 +1795240,13,LONG,464,9,-1,87 +1795242,13,LONG,465,-6,-3,60 +1795244,13,LONG,466,3,-4,31 +1795246,13,LONG,467,4,0,23 +1795248,13,LONG,468,-7,8,113 +1795250,13,LONG,469,10,5,144 +1795252,13,LONG,470,8,-2,83 +1795254,13,LONG,471,5,0,29 +1795256,13,LONG,472,6,5,79 +1795258,13,LONG,473,1,0,3 +1795260,13,LONG,474,-5,-1,29 +1795262,13,LONG,475,0,-6,48 +1795264,13,LONG,476,-1,-1,5 +1795266,13,LONG,477,-2,-1,9 +1795268,13,LONG,478,2,3,15 +1795270,13,LONG,479,6,0,48 +1795272,13,LONG,480,6,-8,119 +1795274,13,LONG,481,-2,-1,6 +1795276,13,LONG,482,0,0,0 +1795278,13,LONG,483,3,2,21 +1795280,13,LONG,484,0,0,0 +1795282,13,LONG,485,-4,2,28 +1795284,13,LONG,486,-6,1,46 +1795286,13,LONG,487,5,1,30 +1795288,13,LONG,488,7,0,57 +1795290,13,LONG,489,0,5,27 +1795292,13,LONG,490,9,-4,100 +1795294,13,LONG,491,14,-2,200 +1795296,13,LONG,492,-4,1,28 +1795298,13,LONG,493,11,0,136 +1795300,13,LONG,494,2,2,13 +1795302,13,LONG,495,-3,-1,16 +1795304,13,LONG,496,0,-8,64 +1795306,13,LONG,497,5,0,32 +1795308,13,LONG,498,2,0,6 +1795310,13,LONG,499,1,0,1 +1795312,13,LONG,500,4,3,30 +1795314,13,LONG,501,-4,1,20 +1795316,13,LONG,502,-4,0,24 +1795318,13,LONG,503,-3,3,20 +1795320,13,LONG,504,-1,1,4 +1795322,13,LONG,505,-1,1,4 +1795324,13,LONG,506,-3,1,11 +1795326,13,LONG,507,0,2,6 +1795328,13,LONG,508,-1,-5,35 +1795330,13,LONG,509,-7,0,53 +1795332,13,LONG,510,-3,3,21 +1795334,13,LONG,511,-3,-6,56 +1932336,14,LONG,0,15,-3,250 +1932338,14,LONG,1,-7,6,102 +1932340,14,LONG,2,-4,7,81 +1932342,14,LONG,3,14,6,238 +1932344,14,LONG,4,7,2,68 +1932346,14,LONG,5,-19,1,392 +1932348,14,LONG,6,-11,-1,138 +1932350,14,LONG,7,-2,6,52 +1932352,14,LONG,8,-11,15,381 +1932354,14,LONG,9,6,1,46 +1932356,14,LONG,10,15,10,368 +1932358,14,LONG,11,-8,19,433 +1932360,14,LONG,12,-3,7,74 +1932362,14,LONG,13,10,8,190 +1932364,14,LONG,14,-8,8,142 +1932366,14,LONG,15,-18,-22,856 +1932368,14,LONG,16,1,3,18 +1932370,14,LONG,17,12,9,244 +1932372,14,LONG,18,2,12,163 +1932374,14,LONG,19,3,0,15 +1932376,14,LONG,20,9,10,191 +1932378,14,LONG,21,-2,-3,17 +1932380,14,LONG,22,13,-5,206 +1932382,14,LONG,23,-22,5,521 +1932384,14,LONG,24,1,28,790 +1932386,14,LONG,25,-10,10,203 +1932388,14,LONG,26,-4,8,89 +1932390,14,LONG,27,-3,-19,377 +1932392,14,LONG,28,-11,-6,175 +1932394,14,LONG,29,-2,-5,36 +1932396,14,LONG,30,-11,10,253 +1932398,14,LONG,31,-4,-21,489 +1932400,14,LONG,32,-4,1,24 +1932402,14,LONG,33,0,5,29 +1932404,14,LONG,34,-3,-13,204 +1932406,14,LONG,35,-13,7,249 +1932408,14,LONG,36,-1,3,14 +1932410,14,LONG,37,11,13,294 +1932412,14,LONG,38,-11,14,346 +1932414,14,LONG,39,-4,-5,47 +1932416,14,LONG,40,-11,-9,224 +1932418,14,LONG,41,12,11,284 +1932420,14,LONG,42,3,6,57 +1932422,14,LONG,43,11,0,122 +1932424,14,LONG,44,-3,1,15 +1932426,14,LONG,45,2,0,5 +1932428,14,LONG,46,16,-4,295 +1932430,14,LONG,47,5,-6,75 +1932432,14,LONG,48,-20,24,1058 +1932434,14,LONG,49,-8,-19,461 +1932436,14,LONG,50,-10,-13,290 +1932438,14,LONG,51,9,-7,149 +1932440,14,LONG,52,5,5,62 +1932442,14,LONG,53,-6,-5,69 +1932444,14,LONG,54,-9,4,118 +1932446,14,LONG,55,-2,-5,37 +1932448,14,LONG,56,-21,24,1096 +1932450,14,LONG,57,10,-25,763 +1932452,14,LONG,58,2,-3,19 +1932454,14,LONG,59,-6,0,41 +1932456,14,LONG,60,-13,-7,240 +1932458,14,LONG,61,0,0,0 +1932460,14,LONG,62,7,-6,100 +1932462,14,LONG,63,-4,-1,27 +1932464,14,LONG,64,-10,11,236 +1932466,14,LONG,65,19,-1,376 +1932468,14,LONG,66,2,4,28 +1932470,14,LONG,67,-6,9,146 +1932472,14,LONG,68,16,6,320 +1932474,14,LONG,69,17,-15,544 +1932476,14,LONG,70,23,4,587 +1932478,14,LONG,71,2,15,234 +1932480,14,LONG,72,-5,34,1193 +1932482,14,LONG,73,22,5,530 +1932484,14,LONG,74,0,-9,98 +1932486,14,LONG,75,-24,-16,869 +1932488,14,LONG,76,5,-23,589 +1932490,14,LONG,77,-7,10,171 +1932492,14,LONG,78,5,1,32 +1932494,14,LONG,79,8,2,79 +1932496,14,LONG,80,-12,-2,153 +1932498,14,LONG,81,-19,-3,410 +1932500,14,LONG,82,-9,19,463 +1932502,14,LONG,83,24,12,737 +1932504,14,LONG,84,-8,10,182 +1932506,14,LONG,85,-10,3,131 +1932508,14,LONG,86,-18,13,497 +1932510,14,LONG,87,7,-4,75 +1932512,14,LONG,88,9,0,96 +1932514,14,LONG,89,-14,12,344 +1932516,14,LONG,90,10,-24,715 +1932518,14,LONG,91,-24,5,651 +1932520,14,LONG,92,4,-3,36 +1932522,14,LONG,93,0,0,0 +1932524,14,LONG,94,0,4,19 +1932526,14,LONG,95,-15,-13,431 +1932528,14,LONG,96,26,19,1100 +1932530,14,LONG,97,-1,15,249 +1932532,14,LONG,98,17,2,321 +1932534,14,LONG,99,5,-8,114 +1932536,14,LONG,100,0,0,1 +1932538,14,LONG,101,4,9,109 +1932540,14,LONG,102,-3,1,17 +1932542,14,LONG,103,-2,4,21 +1932544,14,LONG,104,-4,6,67 +1932546,14,LONG,105,-1,0,1 +1932548,14,LONG,106,2,1,9 +1932550,14,LONG,107,1,-4,25 +1932552,14,LONG,108,-4,1,20 +1932554,14,LONG,109,4,-5,48 +1932556,14,LONG,110,8,12,221 +1932558,14,LONG,111,3,8,82 +1932560,14,LONG,112,-2,0,5 +1932562,14,LONG,113,3,3,26 +1932564,14,LONG,114,5,9,134 +1932566,14,LONG,115,3,3,22 +1932568,14,LONG,116,0,-8,79 +1932570,14,LONG,117,-6,6,83 +1932572,14,LONG,118,0,5,27 +1932574,14,LONG,119,-2,8,80 +1932576,14,LONG,120,-2,-4,24 +1932578,14,LONG,121,0,11,136 +1932580,14,LONG,122,4,4,38 +1932582,14,LONG,123,-6,0,38 +1932584,14,LONG,124,2,-1,7 +1932586,14,LONG,125,-1,-3,13 +1932588,14,LONG,126,0,14,204 +1932590,14,LONG,127,0,6,45 +1932592,14,LONG,128,2,-7,55 +1932594,14,LONG,129,1,1,4 +1932596,14,LONG,130,1,0,2 +1932598,14,LONG,131,5,-11,157 +1932600,14,LONG,132,2,-1,8 +1932602,14,LONG,133,-2,2,9 +1932604,14,LONG,134,-1,10,109 +1932606,14,LONG,135,3,-10,131 +1932608,14,LONG,136,4,2,27 +1932610,14,LONG,137,4,10,118 +1932612,14,LONG,138,-6,-5,72 +1932614,14,LONG,139,-4,6,69 +1932616,14,LONG,140,4,-6,72 +1932618,14,LONG,141,-46,85,9424 +1932620,14,LONG,142,-57,80,9747 +1932622,14,LONG,143,-67,78,10701 +1932624,14,LONG,144,-80,68,11286 +1932626,14,LONG,145,-83,66,11310 +1932628,14,LONG,146,-91,43,10238 +1932630,14,LONG,147,-91,40,10029 +1932632,14,LONG,148,-87,20,8114 +1932634,14,LONG,149,-99,14,10164 +1932636,14,LONG,150,-102,3,10613 +1932638,14,LONG,151,-101,-14,10473 +1932640,14,LONG,152,-87,-24,8272 +1932642,14,LONG,153,-95,-37,10489 +1932644,14,LONG,154,-84,-40,8846 +1932646,14,LONG,155,-83,-61,10794 +1932648,14,LONG,156,-64,-67,8711 +1932650,14,LONG,157,-59,-85,10804 +1932652,14,LONG,158,-62,-88,11794 +1932654,14,LONG,159,-38,-87,9198 +1932656,14,LONG,160,-1,0,3 +1932658,14,LONG,161,0,5,32 +1932660,14,LONG,162,-2,-2,13 +1932662,14,LONG,163,3,0,12 +1932664,14,LONG,164,1,0,3 +1932666,14,LONG,165,2,2,16 +1932668,14,LONG,166,-2,-4,25 +1932670,14,LONG,167,0,-1,2 +1932672,14,LONG,168,1,3,12 +1932674,14,LONG,169,-3,-2,15 +1932676,14,LONG,170,2,12,156 +1932678,14,LONG,171,-2,0,7 +1932680,14,LONG,172,-3,0,11 +1932682,14,LONG,173,2,-2,10 +1932684,14,LONG,174,-7,8,125 +1932686,14,LONG,175,1,1,6 +1932688,14,LONG,176,-11,2,132 +1932690,14,LONG,177,-3,-6,55 +1932692,14,LONG,178,-6,3,53 +1932694,14,LONG,179,0,-5,27 +1932696,14,LONG,180,-1,-10,113 +1932698,14,LONG,181,-4,-1,17 +1932700,14,LONG,182,2,3,15 +1932702,14,LONG,183,5,0,30 +1932704,14,LONG,184,0,4,17 +1932706,14,LONG,185,2,-8,73 +1932708,14,LONG,186,0,4,21 +1932710,14,LONG,187,-1,0,4 +1932712,14,LONG,188,-4,4,44 +1932714,14,LONG,189,-1,-4,18 +1932716,14,LONG,190,3,4,28 +1932718,14,LONG,191,0,-7,52 +1932720,14,LONG,192,6,-6,95 +1932722,14,LONG,193,0,2,7 +1932724,14,LONG,194,-2,-3,15 +1932726,14,LONG,195,0,2,5 +1932728,14,LONG,196,-6,-4,68 +1932730,14,LONG,197,4,5,56 +1932732,14,LONG,198,0,-2,6 +1932734,14,LONG,199,2,-2,13 +1932736,14,LONG,200,-12,-8,220 +1932738,14,LONG,201,0,1,3 +1932740,14,LONG,202,-4,-5,47 +1932742,14,LONG,203,3,2,19 +1932744,14,LONG,204,-2,0,8 +1932746,14,LONG,205,-6,0,42 +1932748,14,LONG,206,-5,-5,60 +1932750,14,LONG,207,6,0,48 +1932752,14,LONG,208,-12,-3,171 +1932754,14,LONG,209,-5,-8,95 +1932756,14,LONG,210,-4,5,55 +1932758,14,LONG,211,1,-1,5 +1932760,14,LONG,212,8,0,72 +1932762,14,LONG,213,8,4,87 +1932764,14,LONG,214,0,5,30 +1932766,14,LONG,215,5,-5,63 +1932768,14,LONG,216,0,-2,6 +1932770,14,LONG,217,6,5,71 +1932772,14,LONG,218,-8,-1,71 +1932774,14,LONG,219,-7,6,105 +1932776,14,LONG,220,1,-3,13 +1932778,14,LONG,221,3,2,17 +1932780,14,LONG,222,-5,3,40 +1932782,14,LONG,223,4,10,143 +1932784,14,LONG,224,11,-5,158 +1932786,14,LONG,225,-7,2,64 +1932788,14,LONG,226,1,9,98 +1932790,14,LONG,227,-9,-4,110 +1932792,14,LONG,228,1,0,1 +1932794,14,LONG,229,-1,3,17 +1932796,14,LONG,230,-3,-7,61 +1932798,14,LONG,231,3,0,13 +1932800,14,LONG,232,-7,0,63 +1932802,14,LONG,233,-12,-2,172 +1932804,14,LONG,234,-8,-5,113 +1932806,14,LONG,235,2,5,38 +1932808,14,LONG,236,7,-5,93 +1932810,14,LONG,237,1,7,54 +1932812,14,LONG,238,6,8,123 +1932814,14,LONG,239,11,1,141 +1932816,14,LONG,240,12,0,153 +1932818,14,LONG,241,-7,-45,2127 +1932820,14,LONG,242,-1,-55,3045 +1932822,14,LONG,243,6,-43,1975 +1932824,14,LONG,244,14,-56,3392 +1932826,14,LONG,245,23,-48,2880 +1932828,14,LONG,246,31,-41,2755 +1932830,14,LONG,247,29,-44,2849 +1932832,14,LONG,248,25,-42,2438 +1932834,14,LONG,249,34,-39,2725 +1932836,14,LONG,250,40,-30,2578 +1932838,14,LONG,251,35,-17,1602 +1932840,14,LONG,252,56,-20,3639 +1932842,14,LONG,253,43,-6,1972 +1932844,14,LONG,254,47,-5,2253 +1932846,14,LONG,255,47,1,2249 +1932848,14,LONG,256,45,0,2025 +1932850,14,LONG,257,44,16,2275 +1932852,14,LONG,258,52,16,2981 +1932854,14,LONG,259,43,19,2290 +1932856,14,LONG,260,1,10,120 +1932858,14,LONG,261,-3,-4,31 +1932860,14,LONG,262,-7,-4,74 +1932862,14,LONG,263,3,3,26 +1932864,14,LONG,264,6,6,77 +1932866,14,LONG,265,-6,-2,47 +1932868,14,LONG,266,-3,0,14 +1932870,14,LONG,267,-4,-7,72 +1932872,14,LONG,268,1,4,21 +1932874,14,LONG,269,3,1,13 +1932876,14,LONG,270,3,-3,23 +1932878,14,LONG,271,1,3,18 +1932880,14,LONG,272,0,-2,7 +1932882,14,LONG,273,-1,0,1 +1932884,14,LONG,274,-2,-5,31 +1932886,14,LONG,275,3,-7,76 +1932888,14,LONG,276,3,8,86 +1932890,14,LONG,277,4,5,47 +1932892,14,LONG,278,-5,0,26 +1932894,14,LONG,279,0,-2,5 +1932896,14,LONG,280,-7,0,49 +1932898,14,LONG,281,1,0,1 +1932900,14,LONG,282,6,0,48 +1932902,14,LONG,283,0,0,0 +1932904,14,LONG,284,-7,-5,80 +1932906,14,LONG,285,2,4,25 +1932908,14,LONG,286,6,-2,53 +1932910,14,LONG,287,0,1,1 +1932912,14,LONG,288,7,-2,56 +1932914,14,LONG,289,-3,0,15 +1932916,14,LONG,290,-3,-3,23 +1932918,14,LONG,291,-2,3,17 +1932920,14,LONG,292,-9,-2,101 +1932922,14,LONG,293,-6,1,49 +1932924,14,LONG,294,-3,-6,51 +1932926,14,LONG,295,0,-2,6 +1932928,14,LONG,296,1,2,8 +1932930,14,LONG,297,8,1,83 +1932932,14,LONG,298,1,4,19 +1932934,14,LONG,299,-1,-6,49 +1932936,14,LONG,300,-7,-5,85 +1932938,14,LONG,301,-2,1,7 +1932940,14,LONG,302,2,2,12 +1932942,14,LONG,303,5,0,35 +1932944,14,LONG,304,-3,4,30 +1932946,14,LONG,305,1,-3,17 +1932948,14,LONG,306,-2,-4,22 +1932950,14,LONG,307,-5,-2,40 +1932952,14,LONG,308,3,2,15 +1932954,14,LONG,309,4,0,22 +1932956,14,LONG,310,8,6,114 +1932958,14,LONG,311,-2,6,50 +1932960,14,LONG,312,-3,1,17 +1932962,14,LONG,313,-6,-2,47 +1932964,14,LONG,314,0,0,1 +1932966,14,LONG,315,-1,2,6 +1932968,14,LONG,316,7,0,63 +1932970,14,LONG,317,-9,4,103 +1932972,14,LONG,318,4,2,24 +1932974,14,LONG,319,0,-8,69 +1932976,14,LONG,320,-2,-4,29 +1932978,14,LONG,321,-7,3,60 +1932980,14,LONG,322,-2,-4,27 +1932982,14,LONG,323,2,2,10 +1932984,14,LONG,324,-2,-9,105 +1932986,14,LONG,325,0,0,0 +1932988,14,LONG,326,-3,-2,17 +1932990,14,LONG,327,-9,-1,89 +1932992,14,LONG,328,0,5,34 +1932994,14,LONG,329,-7,0,57 +1932996,14,LONG,330,-1,6,42 +1932998,14,LONG,331,-5,9,126 +1933000,14,LONG,332,0,-6,42 +1933002,14,LONG,333,9,-4,107 +1933004,14,LONG,334,1,2,7 +1933006,14,LONG,335,2,0,5 +1933008,14,LONG,336,12,-3,160 +1933010,14,LONG,337,5,-5,60 +1933012,14,LONG,338,-3,3,25 +1933014,14,LONG,339,-8,5,106 +1933016,14,LONG,340,3,3,25 +1933018,14,LONG,341,-2,1,5 +1933020,14,LONG,342,-5,7,77 +1933022,14,LONG,343,1,5,32 +1933024,14,LONG,344,1,3,17 +1933026,14,LONG,345,2,0,5 +1933028,14,LONG,346,-6,2,43 +1933030,14,LONG,347,4,2,28 +1933032,14,LONG,348,-6,4,59 +1933034,14,LONG,349,9,1,84 +1933036,14,LONG,350,-2,-1,7 +1933038,14,LONG,351,2,2,13 +1933040,14,LONG,352,-7,-4,67 +1933042,14,LONG,353,0,2,5 +1933044,14,LONG,354,-1,-9,87 +1933046,14,LONG,355,4,-1,27 +1933048,14,LONG,356,7,-3,68 +1933050,14,LONG,357,-2,-2,13 +1933052,14,LONG,358,4,5,54 +1933054,14,LONG,359,5,-9,116 +1933056,14,LONG,360,0,-3,12 +1933058,14,LONG,361,-8,0,66 +1933060,14,LONG,362,5,3,38 +1933062,14,LONG,363,2,1,10 +1933064,14,LONG,364,0,3,15 +1933066,14,LONG,365,1,2,9 +1933068,14,LONG,366,-3,0,12 +1933070,14,LONG,367,8,0,79 +1933072,14,LONG,368,0,-4,25 +1933074,14,LONG,369,-7,7,102 +1933076,14,LONG,370,9,1,82 +1933078,14,LONG,371,8,-5,104 +1933080,14,LONG,372,-8,0,72 +1933082,14,LONG,373,1,6,48 +1933084,14,LONG,374,4,8,93 +1933086,14,LONG,375,7,-2,59 +1933088,14,LONG,376,-14,-5,251 +1933090,14,LONG,377,0,-3,11 +1933092,14,LONG,378,0,-1,3 +1933094,14,LONG,379,0,-4,21 +1933096,14,LONG,380,-8,5,96 +1933098,14,LONG,381,-3,-4,35 +1933100,14,LONG,382,-1,-9,89 +1933102,14,LONG,383,-6,-2,49 +1933104,14,LONG,384,1,-2,8 +1933106,14,LONG,385,-3,-1,11 +1933108,14,LONG,386,2,-10,107 +1933110,14,LONG,387,4,0,20 +1933112,14,LONG,388,-5,7,86 +1933114,14,LONG,389,8,2,81 +1933116,14,LONG,390,-1,4,18 +1933118,14,LONG,391,-20,-2,416 +1933120,14,LONG,392,-31,-4,1030 +1933122,14,LONG,393,-21,-14,675 +1933124,14,LONG,394,-30,-13,1121 +1933126,14,LONG,395,-24,-12,755 +1933128,14,LONG,396,-17,-25,958 +1933130,14,LONG,397,-11,-26,856 +1933132,14,LONG,398,-8,-22,597 +1933134,14,LONG,399,0,-12,168 +1933136,14,LONG,400,-6,-26,753 +1933138,14,LONG,401,0,-33,1129 +1933140,14,LONG,402,4,-32,1045 +1933142,14,LONG,403,2,-20,432 +1933144,14,LONG,404,7,-16,329 +1933146,14,LONG,405,14,-23,765 +1933148,14,LONG,406,7,-30,998 +1933150,14,LONG,407,16,-19,645 +1933152,14,LONG,408,18,-15,592 +1933154,14,LONG,409,22,-18,858 +1933156,14,LONG,410,0,8,71 +1933158,14,LONG,411,-1,8,67 +1933160,14,LONG,412,10,-2,121 +1933162,14,LONG,413,-1,-3,13 +1933164,14,LONG,414,-3,1,12 +1933166,14,LONG,415,-3,2,19 +1933168,14,LONG,416,-3,6,47 +1933170,14,LONG,417,-2,3,18 +1933172,14,LONG,418,-6,0,39 +1933174,14,LONG,419,-3,4,33 +1933176,14,LONG,420,-2,-2,16 +1933178,14,LONG,421,3,2,19 +1933180,14,LONG,422,-5,1,32 +1933182,14,LONG,423,0,-1,2 +1933184,14,LONG,424,-2,-3,18 +1933186,14,LONG,425,-2,5,33 +1933188,14,LONG,426,0,4,18 +1933190,14,LONG,427,-2,-7,65 +1933192,14,LONG,428,0,0,1 +1933194,14,LONG,429,-1,10,109 +1933196,14,LONG,430,6,-8,103 +1933198,14,LONG,431,4,4,40 +1933200,14,LONG,432,-3,2,15 +1933202,14,LONG,433,-1,-1,5 +1933204,14,LONG,434,-2,5,36 +1933206,14,LONG,435,-3,1,12 +1933208,14,LONG,436,1,5,33 +1933210,14,LONG,437,4,2,28 +1933212,14,LONG,438,1,2,8 +1933214,14,LONG,439,5,-2,40 +1933216,14,LONG,440,-5,0,32 +1933218,14,LONG,441,-3,13,194 +1933220,14,LONG,442,3,3,23 +1933222,14,LONG,443,4,-6,61 +1933224,14,LONG,444,2,0,7 +1933226,14,LONG,445,0,0,0 +1933228,14,LONG,446,5,10,140 +1933230,14,LONG,447,-4,1,26 +1933232,14,LONG,448,0,-7,58 +1933234,14,LONG,449,3,4,28 +1933236,14,LONG,450,0,0,0 +1933238,14,LONG,451,0,8,65 +1933240,14,LONG,452,-5,4,50 +1933242,14,LONG,453,0,4,20 +1933244,14,LONG,454,-4,-1,21 +1933246,14,LONG,455,0,-5,34 +1933248,14,LONG,456,4,-4,41 +1933250,14,LONG,457,1,7,51 +1933252,14,LONG,458,-2,-4,29 +1933254,14,LONG,459,1,0,2 +1933256,14,LONG,460,-4,7,80 +1933258,14,LONG,461,-3,4,35 +1933260,14,LONG,462,7,4,80 +1933262,14,LONG,463,0,0,0 +1933264,14,LONG,464,-5,3,39 +1933266,14,LONG,465,-5,5,62 +1933268,14,LONG,466,2,-10,123 +1933270,14,LONG,467,3,-5,41 +1933272,14,LONG,468,-3,7,74 +1933274,14,LONG,469,1,8,78 +1933276,14,LONG,470,0,2,5 +1933278,14,LONG,471,-2,7,60 +1933280,14,LONG,472,-6,13,218 +1933282,14,LONG,473,-5,2,32 +1933284,14,LONG,474,-2,0,7 +1933286,14,LONG,475,1,-6,50 +1933288,14,LONG,476,3,0,14 +1933290,14,LONG,477,5,-3,36 +1933292,14,LONG,478,-1,7,63 +1933294,14,LONG,479,-5,-1,32 +1933296,14,LONG,480,2,-2,14 +1933298,14,LONG,481,4,3,31 +1933300,14,LONG,482,-3,-2,19 +1933302,14,LONG,483,-4,6,55 +1933304,14,LONG,484,6,-5,67 +1933306,14,LONG,485,-6,0,45 +1933308,14,LONG,486,1,-1,5 +1933310,14,LONG,487,0,6,47 +1933312,14,LONG,488,-3,6,47 +1933314,14,LONG,489,-3,3,22 +1933316,14,LONG,490,6,-2,44 +1933318,14,LONG,491,-1,0,4 +1933320,14,LONG,492,4,0,18 +1933322,14,LONG,493,2,-3,23 +1933324,14,LONG,494,-6,0,48 +1933326,14,LONG,495,-3,5,43 +1933328,14,LONG,496,-5,-1,29 +1933330,14,LONG,497,0,4,16 +1933332,14,LONG,498,4,0,20 +1933334,14,LONG,499,-4,-1,18 +1933336,14,LONG,500,1,4,24 +1933338,14,LONG,501,-3,1,14 +1933340,14,LONG,502,5,-7,86 +1933342,14,LONG,503,0,5,25 +1933344,14,LONG,504,-2,6,56 +1933346,14,LONG,505,-3,6,56 +1933348,14,LONG,506,-7,0,56 +1933350,14,LONG,507,11,1,142 +1933352,14,LONG,508,-1,-2,9 +1933354,14,LONG,509,-3,-4,26 +1933356,14,LONG,510,3,7,72 +1933358,14,LONG,511,-3,2,18 +2070360,15,LONG,0,6,-1,39 +2070362,15,LONG,1,-1,12,146 +2070364,15,LONG,2,12,22,655 +2070366,15,LONG,3,-1,12,165 +2070368,15,LONG,4,-5,0,28 +2070370,15,LONG,5,5,7,89 +2070372,15,LONG,6,16,-10,394 +2070374,15,LONG,7,2,21,484 +2070376,15,LONG,8,2,6,51 +2070378,15,LONG,9,-6,-13,229 +2070380,15,LONG,10,0,24,611 +2070382,15,LONG,11,19,-1,374 +2070384,15,LONG,12,3,13,185 +2070386,15,LONG,13,2,-2,10 +2070388,15,LONG,14,0,2,8 +2070390,15,LONG,15,4,-5,53 +2070392,15,LONG,16,-4,10,124 +2070394,15,LONG,17,1,-10,121 +2070396,15,LONG,18,-2,-13,196 +2070398,15,LONG,19,-16,-14,482 +2070400,15,LONG,20,1,8,66 +2070402,15,LONG,21,3,-9,106 +2070404,15,LONG,22,-23,19,904 +2070406,15,LONG,23,16,-9,348 +2070408,15,LONG,24,-2,-9,90 +2070410,15,LONG,25,-13,7,240 +2070412,15,LONG,26,-15,0,226 +2070414,15,LONG,27,1,-1,6 +2070416,15,LONG,28,-13,8,260 +2070418,15,LONG,29,27,23,1300 +2070420,15,LONG,30,-3,0,9 +2070422,15,LONG,31,4,11,142 +2070424,15,LONG,32,4,4,36 +2070426,15,LONG,33,-3,-14,228 +2070428,15,LONG,34,-19,5,403 +2070430,15,LONG,35,-5,-3,39 +2070432,15,LONG,36,3,13,194 +2070434,15,LONG,37,8,-5,100 +2070436,15,LONG,38,12,15,376 +2070438,15,LONG,39,11,-12,278 +2070440,15,LONG,40,-16,0,258 +2070442,15,LONG,41,15,-5,272 +2070444,15,LONG,42,-1,-3,17 +2070446,15,LONG,43,-20,8,475 +2070448,15,LONG,44,14,-1,208 +2070450,15,LONG,45,-2,0,5 +2070452,15,LONG,46,-3,-16,289 +2070454,15,LONG,47,15,0,238 +2070456,15,LONG,48,-6,3,59 +2070458,15,LONG,49,1,-15,251 +2070460,15,LONG,50,13,4,203 +2070462,15,LONG,51,-19,-5,418 +2070464,15,LONG,52,-8,0,66 +2070466,15,LONG,53,8,3,94 +2070468,15,LONG,54,1,-4,25 +2070470,15,LONG,55,12,10,271 +2070472,15,LONG,56,-23,-7,589 +2070474,15,LONG,57,10,-4,126 +2070476,15,LONG,58,-9,-3,94 +2070478,15,LONG,59,-14,3,235 +2070480,15,LONG,60,16,-2,274 +2070482,15,LONG,61,-11,-1,130 +2070484,15,LONG,62,20,-13,619 +2070486,15,LONG,63,-17,2,320 +2070488,15,LONG,64,3,1,11 +2070490,15,LONG,65,5,-1,32 +2070492,15,LONG,66,8,0,71 +2070494,15,LONG,67,-2,15,248 +2070496,15,LONG,68,1,12,158 +2070498,15,LONG,69,11,10,250 +2070500,15,LONG,70,-15,-12,388 +2070502,15,LONG,71,14,-6,238 +2070504,15,LONG,72,4,6,64 +2070506,15,LONG,73,-13,-8,251 +2070508,15,LONG,74,-6,6,86 +2070510,15,LONG,75,-16,13,444 +2070512,15,LONG,76,8,-4,86 +2070514,15,LONG,77,13,-6,220 +2070516,15,LONG,78,-26,23,1229 +2070518,15,LONG,79,-1,12,154 +2070520,15,LONG,80,16,-5,311 +2070522,15,LONG,81,-3,-18,350 +2070524,15,LONG,82,10,-4,135 +2070526,15,LONG,83,7,-11,181 +2070528,15,LONG,84,11,-2,127 +2070530,15,LONG,85,8,-1,75 +2070532,15,LONG,86,12,-1,151 +2070534,15,LONG,87,25,7,691 +2070536,15,LONG,88,-19,11,500 +2070538,15,LONG,89,10,-18,465 +2070540,15,LONG,90,16,-4,298 +2070542,15,LONG,91,-23,0,560 +2070544,15,LONG,92,15,-4,262 +2070546,15,LONG,93,9,-35,1344 +2070548,15,LONG,94,-3,0,12 +2070550,15,LONG,95,-10,-6,142 +2070552,15,LONG,96,4,10,121 +2070554,15,LONG,97,-17,-8,390 +2070556,15,LONG,98,-1,-5,27 +2070558,15,LONG,99,-5,-6,68 +2070560,15,LONG,100,-1,-3,13 +2070562,15,LONG,101,0,7,57 +2070564,15,LONG,102,0,3,14 +2070566,15,LONG,103,0,-2,4 +2070568,15,LONG,104,8,0,69 +2070570,15,LONG,105,0,1,3 +2070572,15,LONG,106,-7,0,53 +2070574,15,LONG,107,2,7,68 +2070576,15,LONG,108,-1,-2,7 +2070578,15,LONG,109,3,1,13 +2070580,15,LONG,110,-2,3,20 +2070582,15,LONG,111,0,-2,8 +2070584,15,LONG,112,0,6,39 +2070586,15,LONG,113,7,4,75 +2070588,15,LONG,114,5,1,31 +2070590,15,LONG,115,3,0,14 +2070592,15,LONG,116,3,-1,10 +2070594,15,LONG,117,6,-1,43 +2070596,15,LONG,118,4,0,25 +2070598,15,LONG,119,-3,1,17 +2070600,15,LONG,120,4,1,23 +2070602,15,LONG,121,4,-5,50 +2070604,15,LONG,122,0,0,1 +2070606,15,LONG,123,1,-2,6 +2070608,15,LONG,124,-6,0,38 +2070610,15,LONG,125,4,0,19 +2070612,15,LONG,126,1,-9,84 +2070614,15,LONG,127,-4,0,18 +2070616,15,LONG,128,-14,5,243 +2070618,15,LONG,129,1,-1,4 +2070620,15,LONG,130,-5,6,72 +2070622,15,LONG,131,-2,2,13 +2070624,15,LONG,132,9,-3,110 +2070626,15,LONG,133,-3,11,153 +2070628,15,LONG,134,0,-6,40 +2070630,15,LONG,135,-1,9,84 +2070632,15,LONG,136,-3,3,23 +2070634,15,LONG,137,-7,-5,89 +2070636,15,LONG,138,-6,0,46 +2070638,15,LONG,139,0,-1,3 +2070640,15,LONG,140,3,1,16 +2070642,15,LONG,141,-92,-46,10607 +2070644,15,LONG,142,-78,-58,9602 +2070646,15,LONG,143,-84,-64,11182 +2070648,15,LONG,144,-67,-72,9812 +2070650,15,LONG,145,-56,-81,9919 +2070652,15,LONG,146,-50,-90,10833 +2070654,15,LONG,147,-39,-84,8630 +2070656,15,LONG,148,-23,-97,10109 +2070658,15,LONG,149,-2,-97,9464 +2070660,15,LONG,150,6,-98,9696 +2070662,15,LONG,151,13,-91,8552 +2070664,15,LONG,152,31,-100,11101 +2070666,15,LONG,153,42,-99,11687 +2070668,15,LONG,154,41,-92,10291 +2070670,15,LONG,155,57,-75,8962 +2070672,15,LONG,156,71,-78,11333 +2070674,15,LONG,157,77,-70,10991 +2070676,15,LONG,158,81,-49,8976 +2070678,15,LONG,159,95,-46,11412 +2070680,15,LONG,160,-5,-1,38 +2070682,15,LONG,161,0,-9,87 +2070684,15,LONG,162,-1,0,1 +2070686,15,LONG,163,-5,0,29 +2070688,15,LONG,164,-1,-1,6 +2070690,15,LONG,165,-1,6,46 +2070692,15,LONG,166,2,-2,16 +2070694,15,LONG,167,6,2,42 +2070696,15,LONG,168,-5,-1,35 +2070698,15,LONG,169,-7,1,54 +2070700,15,LONG,170,-5,8,106 +2070702,15,LONG,171,-3,-4,32 +2070704,15,LONG,172,0,4,23 +2070706,15,LONG,173,0,-3,14 +2070708,15,LONG,174,-3,-1,12 +2070710,15,LONG,175,7,9,155 +2070712,15,LONG,176,-1,4,18 +2070714,15,LONG,177,4,-2,27 +2070716,15,LONG,178,2,3,16 +2070718,15,LONG,179,-4,-1,20 +2070720,15,LONG,180,2,0,5 +2070722,15,LONG,181,-4,1,20 +2070724,15,LONG,182,0,-5,32 +2070726,15,LONG,183,7,0,51 +2070728,15,LONG,184,-1,0,3 +2070730,15,LONG,185,4,-16,281 +2070732,15,LONG,186,0,-1,3 +2070734,15,LONG,187,-2,-7,68 +2070736,15,LONG,188,-3,1,13 +2070738,15,LONG,189,9,2,90 +2070740,15,LONG,190,2,-7,61 +2070742,15,LONG,191,0,2,5 +2070744,15,LONG,192,-8,4,100 +2070746,15,LONG,193,1,-8,75 +2070748,15,LONG,194,-4,0,23 +2070750,15,LONG,195,0,0,0 +2070752,15,LONG,196,4,8,99 +2070754,15,LONG,197,0,9,98 +2070756,15,LONG,198,0,5,25 +2070758,15,LONG,199,2,11,139 +2070760,15,LONG,200,-3,0,10 +2070762,15,LONG,201,3,0,10 +2070764,15,LONG,202,0,1,1 +2070766,15,LONG,203,2,3,17 +2070768,15,LONG,204,0,0,0 +2070770,15,LONG,205,5,-4,50 +2070772,15,LONG,206,0,0,0 +2070774,15,LONG,207,-12,1,164 +2070776,15,LONG,208,-1,0,1 +2070778,15,LONG,209,1,-1,3 +2070780,15,LONG,210,-3,-1,15 +2070782,15,LONG,211,2,0,6 +2070784,15,LONG,212,8,-5,96 +2070786,15,LONG,213,1,5,29 +2070788,15,LONG,214,5,2,34 +2070790,15,LONG,215,1,4,26 +2070792,15,LONG,216,-4,0,17 +2070794,15,LONG,217,-3,3,21 +2070796,15,LONG,218,0,0,0 +2070798,15,LONG,219,7,-1,57 +2070800,15,LONG,220,-1,-2,6 +2070802,15,LONG,221,3,2,18 +2070804,15,LONG,222,-4,9,104 +2070806,15,LONG,223,-3,0,13 +2070808,15,LONG,224,5,14,245 +2070810,15,LONG,225,0,-6,38 +2070812,15,LONG,226,0,1,1 +2070814,15,LONG,227,1,5,28 +2070816,15,LONG,228,0,-5,27 +2070818,15,LONG,229,-5,-3,42 +2070820,15,LONG,230,-9,-5,107 +2070822,15,LONG,231,9,-3,105 +2070824,15,LONG,232,-4,-2,31 +2070826,15,LONG,233,-3,0,13 +2070828,15,LONG,234,-2,0,5 +2070830,15,LONG,235,-6,6,86 +2070832,15,LONG,236,-5,2,37 +2070834,15,LONG,237,-1,-3,13 +2070836,15,LONG,238,-6,3,59 +2070838,15,LONG,239,-1,-1,5 +2070840,15,LONG,240,0,3,13 +2070842,15,LONG,241,-40,-22,2121 +2070844,15,LONG,242,-44,-28,2784 +2070846,15,LONG,243,-38,-30,2437 +2070848,15,LONG,244,-33,-36,2419 +2070850,15,LONG,245,-26,-41,2408 +2070852,15,LONG,246,-20,-33,1505 +2070854,15,LONG,247,-17,-43,2215 +2070856,15,LONG,248,-8,-49,2534 +2070858,15,LONG,249,-6,-52,2802 +2070860,15,LONG,250,-7,-46,2243 +2070862,15,LONG,251,8,-50,2622 +2070864,15,LONG,252,19,-53,3219 +2070866,15,LONG,253,14,-51,2878 +2070868,15,LONG,254,23,-45,2607 +2070870,15,LONG,255,36,-37,2695 +2070872,15,LONG,256,34,-40,2761 +2070874,15,LONG,257,35,-39,2764 +2070876,15,LONG,258,40,-23,2167 +2070878,15,LONG,259,53,-14,3123 +2070880,15,LONG,260,5,-6,71 +2070882,15,LONG,261,3,0,15 +2070884,15,LONG,262,0,4,16 +2070886,15,LONG,263,1,0,1 +2070888,15,LONG,264,1,-1,3 +2070890,15,LONG,265,-4,14,240 +2070892,15,LONG,266,0,-7,55 +2070894,15,LONG,267,-3,0,11 +2070896,15,LONG,268,3,8,83 +2070898,15,LONG,269,-1,-4,21 +2070900,15,LONG,270,1,0,1 +2070902,15,LONG,271,15,4,261 +2070904,15,LONG,272,0,-2,8 +2070906,15,LONG,273,0,-7,51 +2070908,15,LONG,274,-5,0,33 +2070910,15,LONG,275,6,0,46 +2070912,15,LONG,276,1,5,37 +2070914,15,LONG,277,-4,-6,66 +2070916,15,LONG,278,-2,4,31 +2070918,15,LONG,279,-7,0,51 +2070920,15,LONG,280,2,-1,9 +2070922,15,LONG,281,-1,13,188 +2070924,15,LONG,282,7,-3,67 +2070926,15,LONG,283,-2,0,4 +2070928,15,LONG,284,1,-1,5 +2070930,15,LONG,285,0,-5,25 +2070932,15,LONG,286,5,-7,94 +2070934,15,LONG,287,9,-2,86 +2070936,15,LONG,288,-5,1,33 +2070938,15,LONG,289,1,4,26 +2070940,15,LONG,290,-2,-1,11 +2070942,15,LONG,291,8,1,66 +2070944,15,LONG,292,2,-4,25 +2070946,15,LONG,293,6,0,37 +2070948,15,LONG,294,0,2,7 +2070950,15,LONG,295,-6,5,81 +2070952,15,LONG,296,-4,-8,88 +2070954,15,LONG,297,-5,3,46 +2070956,15,LONG,298,-8,7,129 +2070958,15,LONG,299,1,0,1 +2070960,15,LONG,300,1,8,68 +2070962,15,LONG,301,3,-5,37 +2070964,15,LONG,302,-3,-2,22 +2070966,15,LONG,303,-1,3,13 +2070968,15,LONG,304,-8,3,81 +2070970,15,LONG,305,6,4,63 +2070972,15,LONG,306,-3,-6,57 +2070974,15,LONG,307,2,1,9 +2070976,15,LONG,308,0,-4,20 +2070978,15,LONG,309,4,-4,37 +2070980,15,LONG,310,0,8,75 +2070982,15,LONG,311,0,6,38 +2070984,15,LONG,312,0,-4,17 +2070986,15,LONG,313,9,0,93 +2070988,15,LONG,314,3,3,20 +2070990,15,LONG,315,-6,-1,46 +2070992,15,LONG,316,-6,-1,40 +2070994,15,LONG,317,8,-4,88 +2070996,15,LONG,318,5,-1,33 +2070998,15,LONG,319,0,0,0 +2071000,15,LONG,320,-6,5,68 +2071002,15,LONG,321,2,3,17 +2071004,15,LONG,322,-4,6,65 +2071006,15,LONG,323,0,-6,41 +2071008,15,LONG,324,-3,8,79 +2071010,15,LONG,325,3,-9,99 +2071012,15,LONG,326,2,-2,14 +2071014,15,LONG,327,1,0,3 +2071016,15,LONG,328,4,-1,20 +2071018,15,LONG,329,-4,3,33 +2071020,15,LONG,330,7,0,54 +2071022,15,LONG,331,1,6,43 +2071024,15,LONG,332,-6,-5,73 +2071026,15,LONG,333,6,1,41 +2071028,15,LONG,334,4,7,72 +2071030,15,LONG,335,5,-4,50 +2071032,15,LONG,336,5,-3,44 +2071034,15,LONG,337,2,-1,10 +2071036,15,LONG,338,-2,1,7 +2071038,15,LONG,339,-10,0,112 +2071040,15,LONG,340,4,6,57 +2071042,15,LONG,341,-6,1,38 +2071044,15,LONG,342,2,0,6 +2071046,15,LONG,343,-8,-5,111 +2071048,15,LONG,344,4,2,22 +2071050,15,LONG,345,-3,2,18 +2071052,15,LONG,346,5,-6,75 +2071054,15,LONG,347,-9,-4,106 +2071056,15,LONG,348,-7,-12,212 +2071058,15,LONG,349,-5,-1,33 +2071060,15,LONG,350,0,4,17 +2071062,15,LONG,351,0,5,29 +2071064,15,LONG,352,6,2,43 +2071066,15,LONG,353,11,0,133 +2071068,15,LONG,354,0,7,51 +2071070,15,LONG,355,-2,9,90 +2071072,15,LONG,356,7,-8,133 +2071074,15,LONG,357,-5,4,51 +2071076,15,LONG,358,-3,-9,105 +2071078,15,LONG,359,0,0,1 +2071080,15,LONG,360,-3,0,9 +2071082,15,LONG,361,3,2,17 +2071084,15,LONG,362,5,-1,32 +2071086,15,LONG,363,-1,0,1 +2071088,15,LONG,364,-9,2,102 +2071090,15,LONG,365,-5,11,179 +2071092,15,LONG,366,2,-4,26 +2071094,15,LONG,367,7,-1,55 +2071096,15,LONG,368,-6,-3,50 +2071098,15,LONG,369,0,3,11 +2071100,15,LONG,370,-9,-7,144 +2071102,15,LONG,371,-2,4,27 +2071104,15,LONG,372,7,1,51 +2071106,15,LONG,373,0,-2,6 +2071108,15,LONG,374,-5,0,28 +2071110,15,LONG,375,0,0,0 +2071112,15,LONG,376,1,0,2 +2071114,15,LONG,377,3,-2,15 +2071116,15,LONG,378,0,-9,86 +2071118,15,LONG,379,5,-4,46 +2071120,15,LONG,380,0,11,136 +2071122,15,LONG,381,3,4,36 +2071124,15,LONG,382,3,5,48 +2071126,15,LONG,383,-2,1,10 +2071128,15,LONG,384,0,6,37 +2071130,15,LONG,385,2,1,7 +2071132,15,LONG,386,-5,7,85 +2071134,15,LONG,387,-7,0,52 +2071136,15,LONG,388,-5,4,51 +2071138,15,LONG,389,0,5,32 +2071140,15,LONG,390,8,8,132 +2071142,15,LONG,391,-30,-8,999 +2071144,15,LONG,392,-22,-8,565 +2071146,15,LONG,393,-27,-18,1072 +2071148,15,LONG,394,-23,-13,736 +2071150,15,LONG,395,-14,-22,700 +2071152,15,LONG,396,-13,-30,1102 +2071154,15,LONG,397,-21,-29,1332 +2071156,15,LONG,398,-4,-25,655 +2071158,15,LONG,399,-13,-22,657 +2071160,15,LONG,400,-2,-16,270 +2071162,15,LONG,401,3,-28,799 +2071164,15,LONG,402,4,-26,735 +2071166,15,LONG,403,4,-18,372 +2071168,15,LONG,404,15,-28,1045 +2071170,15,LONG,405,17,-22,781 +2071172,15,LONG,406,21,-11,580 +2071174,15,LONG,407,25,-18,962 +2071176,15,LONG,408,18,-13,514 +2071178,15,LONG,409,21,-6,496 +2071180,15,LONG,410,-4,7,67 +2071182,15,LONG,411,-1,4,25 +2071184,15,LONG,412,5,-2,35 +2071186,15,LONG,413,6,-10,140 +2071188,15,LONG,414,4,-2,28 +2071190,15,LONG,415,-4,-11,151 +2071192,15,LONG,416,0,3,9 +2071194,15,LONG,417,3,0,15 +2071196,15,LONG,418,-1,-7,65 +2071198,15,LONG,419,-4,2,33 +2071200,15,LONG,420,5,10,129 +2071202,15,LONG,421,2,-4,24 +2071204,15,LONG,422,4,4,47 +2071206,15,LONG,423,0,-1,1 +2071208,15,LONG,424,0,-6,45 +2071210,15,LONG,425,-1,4,24 +2071212,15,LONG,426,-7,4,66 +2071214,15,LONG,427,4,4,34 +2071216,15,LONG,428,1,-8,68 +2071218,15,LONG,429,-2,-1,10 +2071220,15,LONG,430,-1,0,2 +2071222,15,LONG,431,-14,0,207 +2071224,15,LONG,432,-2,12,154 +2071226,15,LONG,433,3,2,16 +2071228,15,LONG,434,-8,9,174 +2071230,15,LONG,435,2,2,10 +2071232,15,LONG,436,2,6,52 +2071234,15,LONG,437,1,6,40 +2071236,15,LONG,438,0,-3,13 +2071238,15,LONG,439,3,-12,158 +2071240,15,LONG,440,1,-10,117 +2071242,15,LONG,441,-11,6,183 +2071244,15,LONG,442,-12,5,183 +2071246,15,LONG,443,8,-6,110 +2071248,15,LONG,444,8,3,79 +2071250,15,LONG,445,0,-9,87 +2071252,15,LONG,446,6,0,37 +2071254,15,LONG,447,-2,2,11 +2071256,15,LONG,448,3,0,13 +2071258,15,LONG,449,-1,-1,6 +2071260,15,LONG,450,-1,7,54 +2071262,15,LONG,451,-8,-6,123 +2071264,15,LONG,452,-2,1,10 +2071266,15,LONG,453,2,0,6 +2071268,15,LONG,454,3,-1,17 +2071270,15,LONG,455,1,-6,44 +2071272,15,LONG,456,-1,-1,3 +2071274,15,LONG,457,0,0,1 +2071276,15,LONG,458,-7,-1,65 +2071278,15,LONG,459,2,-1,7 +2071280,15,LONG,460,6,-2,53 +2071282,15,LONG,461,3,10,109 +2071284,15,LONG,462,0,-1,4 +2071286,15,LONG,463,1,5,33 +2071288,15,LONG,464,0,4,21 +2071290,15,LONG,465,5,2,31 +2071292,15,LONG,466,-2,-6,50 +2071294,15,LONG,467,-3,0,10 +2071296,15,LONG,468,1,3,13 +2071298,15,LONG,469,0,-2,9 +2071300,15,LONG,470,-1,-3,13 +2071302,15,LONG,471,6,0,43 +2071304,15,LONG,472,2,0,7 +2071306,15,LONG,473,0,0,0 +2071308,15,LONG,474,-1,-2,9 +2071310,15,LONG,475,3,-5,42 +2071312,15,LONG,476,3,-11,138 +2071314,15,LONG,477,5,-4,49 +2071316,15,LONG,478,-6,-5,80 +2071318,15,LONG,479,7,0,55 +2071320,15,LONG,480,7,3,66 +2071322,15,LONG,481,4,0,16 +2071324,15,LONG,482,-4,-7,83 +2071326,15,LONG,483,-3,-3,23 +2071328,15,LONG,484,0,3,13 +2071330,15,LONG,485,7,0,56 +2071332,15,LONG,486,-3,0,12 +2071334,15,LONG,487,-1,-5,32 +2071336,15,LONG,488,0,0,1 +2071338,15,LONG,489,7,3,67 +2071340,15,LONG,490,-9,-2,95 +2071342,15,LONG,491,1,-1,4 +2071344,15,LONG,492,-2,6,54 +2071346,15,LONG,493,-1,-3,17 +2071348,15,LONG,494,3,-9,100 +2071350,15,LONG,495,-8,-5,92 +2071352,15,LONG,496,6,-1,42 +2071354,15,LONG,497,4,-1,19 +2071356,15,LONG,498,-2,6,52 +2071358,15,LONG,499,5,1,35 +2071360,15,LONG,500,0,4,24 +2071362,15,LONG,501,0,1,3 +2071364,15,LONG,502,-8,4,97 +2071366,15,LONG,503,0,2,6 +2071368,15,LONG,504,-4,-1,21 +2071370,15,LONG,505,4,9,112 +2071372,15,LONG,506,1,10,110 +2071374,15,LONG,507,-3,-2,18 +2071376,15,LONG,508,0,-1,3 +2071378,15,LONG,509,-3,-4,36 +2071380,15,LONG,510,5,-4,58 +2071382,15,LONG,511,5,-5,54 +2383784,16,SHORT,0,-7,-3,73 +2383786,16,SHORT,1,3,1,13 +2383788,16,SHORT,2,-6,6,80 +2383790,16,SHORT,3,-10,10,222 +2383792,16,SHORT,4,-8,-2,80 +2383794,16,SHORT,5,-8,-10,168 +2383796,16,SHORT,6,5,0,35 +2383798,16,SHORT,7,9,-6,121 +2383800,16,SHORT,8,0,-11,122 +2383802,16,SHORT,9,-2,0,6 +2383804,16,SHORT,10,-1,1,3 +2383806,16,SHORT,11,-10,8,183 +2383808,16,SHORT,12,6,-4,62 +2383810,16,SHORT,13,2,-3,18 +2383812,16,SHORT,14,-5,13,224 +2383814,16,SHORT,15,-5,0,35 +2383816,16,SHORT,16,-8,6,108 +2383818,16,SHORT,17,8,9,157 +2383820,16,SHORT,18,1,1,4 +2383822,16,SHORT,19,-3,-6,54 +2383824,16,SHORT,20,-7,3,72 +2383826,16,SHORT,21,1,-1,2 +2383828,16,SHORT,22,0,-5,30 +2383830,16,SHORT,23,3,-6,49 +2383832,16,SHORT,24,1,7,55 +2383834,16,SHORT,25,5,-13,200 +2383836,16,SHORT,26,0,9,81 +2383838,16,SHORT,27,1,10,107 +2383840,16,SHORT,28,0,0,0 +2383842,16,SHORT,29,-6,4,65 +2383844,16,SHORT,30,1,0,2 +2383846,16,SHORT,31,-1,-8,66 +2383848,16,SHORT,32,-1,-12,158 +2383850,16,SHORT,33,-1,4,25 +2383852,16,SHORT,34,-8,0,69 +2383854,16,SHORT,35,2,-6,49 +2383856,16,SHORT,36,-5,-13,229 +2383858,16,SHORT,37,-15,13,415 +2383860,16,SHORT,38,1,0,2 +2383862,16,SHORT,39,8,0,70 +2383864,16,SHORT,40,-8,6,112 +2383866,16,SHORT,41,1,5,32 +2383868,16,SHORT,42,11,-7,184 +2383870,16,SHORT,43,11,14,333 +2383872,16,SHORT,44,-7,-1,58 +2383874,16,SHORT,45,-8,-13,259 +2383876,16,SHORT,46,-4,2,33 +2383878,16,SHORT,47,-1,8,83 +2383880,16,SHORT,48,0,-6,41 +2383882,16,SHORT,49,-8,2,73 +2383884,16,SHORT,50,-4,0,16 +2383886,16,SHORT,51,1,0,3 +2383888,16,SHORT,52,7,11,194 +2383890,16,SHORT,53,3,-1,16 +2383892,16,SHORT,54,-11,-9,210 +2383894,16,SHORT,55,5,8,111 +2383896,16,SHORT,56,-5,4,42 +2383898,16,SHORT,57,10,2,112 +2383900,16,SHORT,58,-3,-9,94 +2383902,16,SHORT,59,4,-4,42 +2383904,16,SHORT,60,-3,-1,10 +2383906,16,SHORT,61,-6,-4,56 +2383908,16,SHORT,62,2,-7,58 +2383910,16,SHORT,63,2,4,31 +2383912,16,SHORT,64,5,-3,47 +2383914,16,SHORT,65,0,0,0 +2383916,16,SHORT,66,2,-5,39 +2383918,16,SHORT,67,2,-9,104 +2383920,16,SHORT,68,20,-42,2217 +2383922,16,SHORT,69,42,-51,4476 +2383924,16,SHORT,70,44,-30,2920 +2383926,16,SHORT,71,46,-17,2487 +2383928,16,SHORT,72,57,-9,3425 +2383930,16,SHORT,73,57,11,3495 +2383932,16,SHORT,74,54,8,3023 +2383934,16,SHORT,75,59,25,4206 +2383936,16,SHORT,76,51,36,3952 +2383938,16,SHORT,77,28,37,2211 +2383940,16,SHORT,78,26,48,3026 +2383942,16,SHORT,79,17,57,3586 +2383944,16,SHORT,80,11,55,3209 +2383946,16,SHORT,81,-4,54,2985 +2383948,16,SHORT,82,-18,45,2439 +2383950,16,SHORT,83,1,4,20 +2383952,16,SHORT,84,9,0,89 +2383954,16,SHORT,85,8,-2,80 +2383956,16,SHORT,86,3,4,34 +2383958,16,SHORT,87,1,0,1 +2383960,16,SHORT,88,-7,-8,130 +2383962,16,SHORT,89,9,1,85 +2383964,16,SHORT,90,-2,-5,31 +2383966,16,SHORT,91,-5,-2,30 +2383968,16,SHORT,92,8,0,73 +2383970,16,SHORT,93,-3,-8,75 +2383972,16,SHORT,94,5,4,47 +2383974,16,SHORT,95,-6,-1,48 +2383976,16,SHORT,96,-8,-7,127 +2383978,16,SHORT,97,-8,-13,257 +2383980,16,SHORT,98,13,3,192 +2383982,16,SHORT,99,0,4,22 +2383984,16,SHORT,100,-4,-1,20 +2383986,16,SHORT,101,0,-10,116 +2383988,16,SHORT,102,8,-3,78 +2383990,16,SHORT,103,-5,2,39 +2383992,16,SHORT,104,-6,0,40 +2383994,16,SHORT,105,-2,-2,10 +2383996,16,SHORT,106,2,-6,45 +2383998,16,SHORT,107,6,0,47 +2384000,16,SHORT,108,5,3,37 +2384002,16,SHORT,109,-2,-1,6 +2384004,16,SHORT,110,0,-8,66 +2384006,16,SHORT,111,-4,-3,32 +2384008,16,SHORT,112,1,-4,21 +2384010,16,SHORT,113,6,-4,59 +2384012,16,SHORT,114,-2,2,13 +2384014,16,SHORT,115,5,-5,55 +2384016,16,SHORT,116,0,0,1 +2384018,16,SHORT,117,7,2,66 +2384020,16,SHORT,118,22,1,507 +2384022,16,SHORT,119,25,8,710 +2384024,16,SHORT,120,29,9,987 +2384026,16,SHORT,121,35,11,1378 +2384028,16,SHORT,122,15,18,606 +2384030,16,SHORT,123,14,25,871 +2384032,16,SHORT,124,9,25,728 +2384034,16,SHORT,125,1,30,922 +2384036,16,SHORT,126,7,19,418 +2384038,16,SHORT,127,-10,25,744 +2384040,16,SHORT,128,-20,20,857 +2384042,16,SHORT,129,-15,19,623 +2384044,16,SHORT,130,-29,12,999 +2384046,16,SHORT,131,-25,17,979 +2384048,16,SHORT,132,-31,9,1065 +2384050,16,SHORT,133,-2,0,5 +2384052,16,SHORT,134,-3,8,75 +2384054,16,SHORT,135,3,12,162 +2384056,16,SHORT,136,4,6,61 +2384058,16,SHORT,137,5,-4,52 +2384060,16,SHORT,138,2,-3,21 +2384062,16,SHORT,139,-3,0,9 +2384064,16,SHORT,140,3,-4,26 +2384066,16,SHORT,141,0,-4,17 +2384068,16,SHORT,142,1,0,3 +2384070,16,SHORT,143,6,2,53 +2384072,16,SHORT,144,6,1,46 +2384074,16,SHORT,145,7,-4,71 +2384076,16,SHORT,146,-6,9,132 +2384078,16,SHORT,147,4,0,16 +2384080,16,SHORT,148,3,0,11 +2384082,16,SHORT,149,0,2,7 +2384084,16,SHORT,150,-1,-1,3 +2384086,16,SHORT,151,-3,1,15 +2384088,16,SHORT,152,6,-1,38 +2384090,16,SHORT,153,-1,3,10 +2384092,16,SHORT,154,-4,2,28 +2384094,16,SHORT,155,9,-5,121 +2384096,16,SHORT,156,-1,-3,14 +2384098,16,SHORT,157,-6,-2,43 +2384100,16,SHORT,158,-7,0,62 +2384102,16,SHORT,159,3,8,94 +2384104,16,SHORT,160,-2,-1,7 +2384106,16,SHORT,161,2,-4,27 +2384108,16,SHORT,162,4,-4,48 +2384110,16,SHORT,163,5,-3,39 +2384112,16,SHORT,164,4,1,20 +2384114,16,SHORT,165,-1,0,2 +2384116,16,SHORT,166,-1,1,3 +2384118,16,SHORT,167,-3,-2,21 +2384120,16,SHORT,168,-1,2,9 +2384122,16,SHORT,169,1,3,15 +2384124,16,SHORT,170,-4,1,20 +2384126,16,SHORT,171,-2,-4,23 +2384128,16,SHORT,172,0,5,31 +2384130,16,SHORT,173,4,7,82 +2384132,16,SHORT,174,0,1,4 +2384134,16,SHORT,175,1,-1,2 +2384136,16,SHORT,176,-4,0,16 +2384138,16,SHORT,177,-3,-3,28 +2384140,16,SHORT,178,5,-6,74 +2384142,16,SHORT,179,5,0,28 +2384144,16,SHORT,180,-4,-1,23 +2384146,16,SHORT,181,8,2,79 +2384148,16,SHORT,182,-12,0,148 +2384150,16,SHORT,183,9,-2,102 +2384152,16,SHORT,184,-4,1,20 +2384154,16,SHORT,185,7,-1,62 +2384156,16,SHORT,186,8,0,78 +2384158,16,SHORT,187,2,-2,9 +2384160,16,SHORT,188,0,-1,3 +2384162,16,SHORT,189,3,-2,17 +2384164,16,SHORT,190,0,-9,84 +2384166,16,SHORT,191,-8,-4,82 +2384168,16,SHORT,192,0,-3,11 +2384170,16,SHORT,193,8,-21,543 +2384172,16,SHORT,194,6,-21,489 +2384174,16,SHORT,195,1,-13,188 +2384176,16,SHORT,196,6,-18,386 +2384178,16,SHORT,197,13,4,214 +2384180,16,SHORT,198,18,-9,431 +2384182,16,SHORT,199,12,5,198 +2384184,16,SHORT,200,16,-3,267 +2384186,16,SHORT,201,16,1,270 +2384188,16,SHORT,202,6,1,44 +2384190,16,SHORT,203,4,13,199 +2384192,16,SHORT,204,4,18,351 +2384194,16,SHORT,205,17,12,470 +2384196,16,SHORT,206,7,10,163 +2384198,16,SHORT,207,5,13,219 +2384200,16,SHORT,208,6,2,55 +2384202,16,SHORT,209,-2,2,12 +2384204,16,SHORT,210,-1,-2,8 +2384206,16,SHORT,211,-10,0,115 +2384208,16,SHORT,212,10,-3,121 +2384210,16,SHORT,213,0,10,107 +2384212,16,SHORT,214,5,5,65 +2384214,16,SHORT,215,-6,2,42 +2384216,16,SHORT,216,6,1,39 +2384218,16,SHORT,217,0,3,12 +2384220,16,SHORT,218,2,2,12 +2384222,16,SHORT,219,-5,9,114 +2384224,16,SHORT,220,2,8,78 +2384226,16,SHORT,221,-6,0,42 +2384228,16,SHORT,222,4,0,21 +2384230,16,SHORT,223,-2,-5,41 +2384232,16,SHORT,224,-1,-6,43 +2384234,16,SHORT,225,-5,-2,32 +2384236,16,SHORT,226,-6,3,53 +2384238,16,SHORT,227,2,-1,9 +2384240,16,SHORT,228,0,-7,56 +2384242,16,SHORT,229,3,3,20 +2384244,16,SHORT,230,0,0,0 +2384246,16,SHORT,231,0,0,1 +2384248,16,SHORT,232,3,-7,62 +2384250,16,SHORT,233,1,5,29 +2384252,16,SHORT,234,-8,-3,86 +2384254,16,SHORT,235,5,-2,39 +2384256,16,SHORT,236,-6,-1,48 +2384258,16,SHORT,237,5,6,74 +2384260,16,SHORT,238,-9,0,82 +2384262,16,SHORT,239,-11,0,122 +2384264,16,SHORT,240,5,-3,41 +2384266,16,SHORT,241,2,-2,9 +2384268,16,SHORT,242,2,-6,52 +2384270,16,SHORT,243,2,8,81 +2384272,16,SHORT,244,-3,0,15 +2384274,16,SHORT,245,6,-9,126 +2384276,16,SHORT,246,3,-3,23 +2384278,16,SHORT,247,0,2,8 +2384280,16,SHORT,248,3,9,109 +2384282,16,SHORT,249,-1,0,2 +2384284,16,SHORT,250,6,5,65 +2384286,16,SHORT,251,-7,3,61 +2384288,16,SHORT,252,2,0,4 +2384290,16,SHORT,253,0,1,4 +2384292,16,SHORT,254,-2,7,67 +2384294,16,SHORT,255,4,-2,23 +2384296,16,SHORT,256,0,5,30 +2384298,16,SHORT,257,0,-1,2 +2384300,16,SHORT,258,-9,5,129 +2384302,16,SHORT,259,-4,14,240 +2384304,16,SHORT,260,-6,3,52 +2384306,16,SHORT,261,-8,1,83 +2384308,16,SHORT,262,0,2,4 +2384310,16,SHORT,263,1,1,5 +2384312,16,SHORT,264,-2,1,10 +2384314,16,SHORT,265,0,4,16 +2384316,16,SHORT,266,3,-1,18 +2384318,16,SHORT,267,2,-4,24 +2384320,16,SHORT,268,4,-9,100 +2384322,16,SHORT,269,-3,5,40 +2384324,16,SHORT,270,6,-3,53 +2384326,16,SHORT,271,3,-1,14 +2384328,16,SHORT,272,7,11,176 +2384330,16,SHORT,273,-8,4,91 +2384332,16,SHORT,274,9,5,118 +2384334,16,SHORT,275,-4,1,22 +2384336,16,SHORT,276,4,2,25 +2384338,16,SHORT,277,1,0,2 +2384340,16,SHORT,278,4,-4,42 +2384342,16,SHORT,279,-4,2,20 +2384344,16,SHORT,280,3,1,15 +2384346,16,SHORT,281,-5,6,75 +2384348,16,SHORT,282,0,0,0 +2384350,16,SHORT,283,4,0,19 +2384352,16,SHORT,284,10,-1,118 +2384354,16,SHORT,285,-6,7,97 +2384356,16,SHORT,286,-3,0,15 +2384358,16,SHORT,287,-15,7,296 +2384360,16,SHORT,288,1,5,28 +2384362,16,SHORT,289,-5,3,50 +2384364,16,SHORT,290,1,-4,24 +2384366,16,SHORT,291,0,5,26 +2384368,16,SHORT,292,-7,-1,50 +2384370,16,SHORT,293,-6,14,265 +2384372,16,SHORT,294,-6,2,47 +2384374,16,SHORT,295,2,0,7 +2384376,16,SHORT,296,-4,5,52 +2384378,16,SHORT,297,-8,3,89 +2384380,16,SHORT,298,-6,10,146 +2384382,16,SHORT,299,-8,2,78 +2384384,16,SHORT,300,-7,2,66 +2384386,16,SHORT,301,-12,0,145 +2384388,16,SHORT,302,-2,0,7 +2384390,16,SHORT,303,-9,0,86 +2384392,16,SHORT,304,-5,-10,154 +2384394,16,SHORT,305,-11,-15,367 +2384396,16,SHORT,306,-3,-6,54 +2384398,16,SHORT,307,1,-9,95 +2384400,16,SHORT,308,1,-8,83 +2384402,16,SHORT,309,7,0,58 +2384404,16,SHORT,310,-12,-4,166 +2384406,16,SHORT,311,-6,-1,41 +2384408,16,SHORT,312,-4,11,153 +2384410,16,SHORT,313,-4,2,25 +2384412,16,SHORT,314,0,-3,12 +2384414,16,SHORT,315,-5,0,33 +2384416,16,SHORT,316,-2,-7,67 +2384418,16,SHORT,317,-4,-4,43 +2384420,16,SHORT,318,7,1,54 +2384422,16,SHORT,319,-1,-4,19 +2384424,16,SHORT,320,10,-3,118 +2384426,16,SHORT,321,-5,-7,78 +2384428,16,SHORT,322,-1,-9,89 +2384430,16,SHORT,323,4,4,43 +2384432,16,SHORT,324,1,0,1 +2384434,16,SHORT,325,-3,3,22 +2384436,16,SHORT,326,0,-2,4 +2384438,16,SHORT,327,-3,-3,22 +2384440,16,SHORT,328,-2,-5,33 +2384442,16,SHORT,329,2,6,43 +2384444,16,SHORT,330,-2,-4,21 +2384446,16,SHORT,331,-3,-10,111 +2384448,16,SHORT,332,2,-2,10 +2384450,16,SHORT,333,0,0,1 +2384452,16,SHORT,334,-3,-5,45 +2384454,16,SHORT,335,2,0,7 +2384456,16,SHORT,336,-5,6,74 +2384458,16,SHORT,337,5,-5,53 +2384460,16,SHORT,338,-5,0,26 +2384462,16,SHORT,339,-2,0,6 +2384464,16,SHORT,340,1,1,2 +2384466,16,SHORT,341,-1,6,40 +2384468,16,SHORT,342,0,-3,14 +2384470,16,SHORT,343,2,2,11 +2384472,16,SHORT,344,-1,-11,137 +2384474,16,SHORT,345,5,-4,46 +2384476,16,SHORT,346,-2,6,42 +2384478,16,SHORT,347,2,3,19 +2384480,16,SHORT,348,5,-1,36 +2384482,16,SHORT,349,-5,-4,50 +2384484,16,SHORT,350,-5,-8,103 +2384486,16,SHORT,351,-4,0,21 +2384488,16,SHORT,352,0,11,135 +2384490,16,SHORT,353,0,0,0 +2384492,16,SHORT,354,-1,-1,3 +2384494,16,SHORT,355,-6,-6,79 +2384496,16,SHORT,356,6,5,71 +2384498,16,SHORT,357,1,-4,21 +2384500,16,SHORT,358,0,2,7 +2384502,16,SHORT,359,0,4,18 +2384504,16,SHORT,360,0,3,9 +2384506,16,SHORT,361,9,4,107 +2384508,16,SHORT,362,-6,-4,54 +2384510,16,SHORT,363,3,8,77 +2384512,16,SHORT,364,2,-1,7 +2384514,16,SHORT,365,1,-8,68 +2384516,16,SHORT,366,0,-3,14 +2384518,16,SHORT,367,-4,-3,29 +2384520,16,SHORT,368,-4,-2,27 +2384522,16,SHORT,369,-5,-6,66 +2384524,16,SHORT,370,-3,4,31 +2384526,16,SHORT,371,-8,0,81 +2384528,16,SHORT,372,-2,-5,33 +2384530,16,SHORT,373,-2,-6,51 +2384532,16,SHORT,374,3,6,58 +2384534,16,SHORT,375,6,-1,44 +2384536,16,SHORT,376,0,-5,31 +2384538,16,SHORT,377,0,1,4 +2384540,16,SHORT,378,10,3,121 +2384542,16,SHORT,379,0,-2,6 +2384544,16,SHORT,380,4,6,64 +2384546,16,SHORT,381,8,5,102 +2384548,16,SHORT,382,3,-3,27 +2384550,16,SHORT,383,0,-2,6 +2384552,16,SHORT,384,-1,-1,3 +2384554,16,SHORT,385,0,4,18 +2384556,16,SHORT,386,3,8,83 +2384558,16,SHORT,387,9,7,140 +2384560,16,SHORT,388,-1,-7,51 +2384562,16,SHORT,389,2,3,18 +2384564,16,SHORT,390,5,4,47 +2384566,16,SHORT,391,-2,-4,21 +2384568,16,SHORT,392,1,1,3 +2384570,16,SHORT,393,0,-2,6 +2384572,16,SHORT,394,1,7,57 +2384574,16,SHORT,395,2,-5,39 +2384576,16,SHORT,396,0,-1,2 +2384578,16,SHORT,397,-2,2,16 +2384580,16,SHORT,398,-3,0,15 +2384582,16,SHORT,399,-3,3,22 +2384584,16,SHORT,400,-4,0,16 +2384586,16,SHORT,401,4,-5,54 +2384588,16,SHORT,402,-4,1,20 +2384590,16,SHORT,403,-6,0,42 +2384592,16,SHORT,404,4,10,126 +2384594,16,SHORT,405,5,-7,74 +2384596,16,SHORT,406,-3,6,54 +2384598,16,SHORT,407,-10,7,156 +2384600,16,SHORT,408,-6,-2,44 +2384602,16,SHORT,409,1,5,29 +2384604,16,SHORT,410,-1,0,2 +2384606,16,SHORT,411,4,-2,32 +2384608,16,SHORT,412,0,3,13 +2384610,16,SHORT,413,0,1,2 +2384612,16,SHORT,414,6,6,77 +2384614,16,SHORT,415,-8,1,81 +2384616,16,SHORT,416,-2,-5,42 +2384618,16,SHORT,417,-4,-11,146 +2384620,16,SHORT,418,-5,-2,35 +2384622,16,SHORT,419,3,2,19 +2384624,16,SHORT,420,4,2,27 +2384626,16,SHORT,421,7,-1,55 +2384628,16,SHORT,422,-1,4,21 +2384630,16,SHORT,423,-1,-1,5 +2384632,16,SHORT,424,-9,-4,102 +2384634,16,SHORT,425,2,0,5 +2384636,16,SHORT,426,0,-6,46 +2384638,16,SHORT,427,-1,-1,2 +2384640,16,SHORT,428,-7,5,89 +2384642,16,SHORT,429,-7,-10,168 +2384644,16,SHORT,430,1,4,22 +2384646,16,SHORT,431,9,3,108 +2384648,16,SHORT,432,1,-3,15 +2384650,16,SHORT,433,-4,-4,38 +2384652,16,SHORT,434,-2,-1,6 +2384654,16,SHORT,435,-5,2,31 +2384656,16,SHORT,436,7,1,55 +2384658,16,SHORT,437,0,-6,47 +2384660,16,SHORT,438,2,1,9 +2384662,16,SHORT,439,-12,-2,151 +2384664,16,SHORT,440,-2,2,9 +2384666,16,SHORT,441,0,0,0 +2384668,16,SHORT,442,1,-4,24 +2384670,16,SHORT,443,7,0,62 +2384672,16,SHORT,444,0,5,29 +2384674,16,SHORT,445,9,-4,113 +2384676,16,SHORT,446,4,8,95 +2384678,16,SHORT,447,-2,-2,11 +2384680,16,SHORT,448,3,-2,17 +2384682,16,SHORT,449,-12,-4,183 +2384684,16,SHORT,450,-3,-2,19 +2384686,16,SHORT,451,0,-6,46 +2384688,16,SHORT,452,5,-8,109 +2384690,16,SHORT,453,0,-6,46 +2384692,16,SHORT,454,-9,-5,122 +2384694,16,SHORT,455,-2,-2,10 +2384696,16,SHORT,456,6,4,55 +2384698,16,SHORT,457,2,1,8 +2384700,16,SHORT,458,-7,0,50 +2384702,16,SHORT,459,-10,-1,115 +2384704,16,SHORT,460,0,0,0 +2384706,16,SHORT,461,2,0,8 +2384708,16,SHORT,462,4,12,174 +2384710,16,SHORT,463,-3,-1,18 +2384712,16,SHORT,464,0,-7,50 +2384714,16,SHORT,465,4,-6,62 +2384716,16,SHORT,466,0,3,12 +2384718,16,SHORT,467,-6,6,86 +2384720,16,SHORT,468,-2,-2,10 +2384722,16,SHORT,469,1,4,22 +2384724,16,SHORT,470,-1,8,80 +2384726,16,SHORT,471,0,5,34 +2384728,16,SHORT,472,-3,0,12 +2384730,16,SHORT,473,0,0,0 +2384732,16,SHORT,474,7,-2,53 +2384734,16,SHORT,475,1,-1,4 +2384736,16,SHORT,476,4,5,52 +2384738,16,SHORT,477,-5,1,32 +2384740,16,SHORT,478,-2,-6,55 +2384742,16,SHORT,479,-7,-6,92 +2384744,16,SHORT,480,-1,2,9 +2384746,16,SHORT,481,-3,5,39 +2384748,16,SHORT,482,0,2,6 +2384750,16,SHORT,483,-1,2,12 +2384752,16,SHORT,484,-7,-4,70 +2384754,16,SHORT,485,2,0,5 +2384756,16,SHORT,486,-1,0,3 +2384758,16,SHORT,487,1,3,12 +2384760,16,SHORT,488,0,-1,1 +2384762,16,SHORT,489,-10,0,108 +2384764,16,SHORT,490,3,3,25 +2384766,16,SHORT,491,4,5,52 +2384768,16,SHORT,492,2,5,38 +2384770,16,SHORT,493,5,3,36 +2384772,16,SHORT,494,-2,-2,10 +2384774,16,SHORT,495,-6,-5,72 +2384776,16,SHORT,496,-5,-2,42 +2384778,16,SHORT,497,-3,0,13 +2384780,16,SHORT,498,-1,0,1 +2384782,16,SHORT,499,-4,0,20 +2384784,16,SHORT,500,3,4,27 +2384786,16,SHORT,501,-2,-1,5 +2384788,16,SHORT,502,7,-1,55 +2384790,16,SHORT,503,0,0,0 +2384792,16,SHORT,504,-5,-1,31 +2384794,16,SHORT,505,4,-2,27 +2384796,16,SHORT,506,0,14,203 +2384798,16,SHORT,507,-1,-6,49 +2384800,16,SHORT,508,4,1,25 +2384802,16,SHORT,509,0,12,154 +2384804,16,SHORT,510,0,-6,41 +2384806,16,SHORT,511,2,-2,9 +2559308,17,SHORT,0,-2,-19,389 +2559310,17,SHORT,1,-4,6,61 +2559312,17,SHORT,2,-8,-2,77 +2559314,17,SHORT,3,-3,1,11 +2559316,17,SHORT,4,4,0,19 +2559318,17,SHORT,5,-8,0,80 +2559320,17,SHORT,6,-10,-3,128 +2559322,17,SHORT,7,-12,9,248 +2559324,17,SHORT,8,-5,0,36 +2559326,17,SHORT,9,-8,-6,107 +2559328,17,SHORT,10,-12,0,166 +2559330,17,SHORT,11,14,0,212 +2559332,17,SHORT,12,-6,12,198 +2559334,17,SHORT,13,3,-4,32 +2559336,17,SHORT,14,0,4,19 +2559338,17,SHORT,15,-3,-8,81 +2559340,17,SHORT,16,2,0,4 +2559342,17,SHORT,17,-6,3,51 +2559344,17,SHORT,18,10,-6,142 +2559346,17,SHORT,19,8,4,85 +2559348,17,SHORT,20,7,-1,59 +2559350,17,SHORT,21,-7,-12,220 +2559352,17,SHORT,22,5,0,34 +2559354,17,SHORT,23,-4,-10,125 +2559356,17,SHORT,24,17,0,310 +2559358,17,SHORT,25,-7,5,89 +2559360,17,SHORT,26,-1,-11,144 +2559362,17,SHORT,27,0,8,64 +2559364,17,SHORT,28,-6,-9,144 +2559366,17,SHORT,29,14,-2,226 +2559368,17,SHORT,30,6,0,42 +2559370,17,SHORT,31,-2,6,42 +2559372,17,SHORT,32,-5,2,42 +2559374,17,SHORT,33,10,5,147 +2559376,17,SHORT,34,-5,-2,36 +2559378,17,SHORT,35,-1,1,3 +2559380,17,SHORT,36,7,1,52 +2559382,17,SHORT,37,16,-4,292 +2559384,17,SHORT,38,-16,-6,300 +2559386,17,SHORT,39,-9,1,97 +2559388,17,SHORT,40,4,-7,83 +2559390,17,SHORT,41,12,3,163 +2559392,17,SHORT,42,5,-4,49 +2559394,17,SHORT,43,-6,8,111 +2559396,17,SHORT,44,10,3,125 +2559398,17,SHORT,45,-1,3,15 +2559400,17,SHORT,46,10,-4,119 +2559402,17,SHORT,47,1,-1,6 +2559404,17,SHORT,48,7,-9,150 +2559406,17,SHORT,49,3,-1,15 +2559408,17,SHORT,50,6,10,161 +2559410,17,SHORT,51,2,-2,16 +2559412,17,SHORT,52,3,-1,17 +2559414,17,SHORT,53,5,0,33 +2559416,17,SHORT,54,7,-1,51 +2559418,17,SHORT,55,4,9,111 +2559420,17,SHORT,56,-1,9,90 +2559422,17,SHORT,57,-2,2,8 +2559424,17,SHORT,58,6,1,46 +2559426,17,SHORT,59,1,-9,92 +2559428,17,SHORT,60,7,-3,66 +2559430,17,SHORT,61,0,2,4 +2559432,17,SHORT,62,3,-1,18 +2559434,17,SHORT,63,-3,-3,23 +2559436,17,SHORT,64,-1,-14,224 +2559438,17,SHORT,65,-16,-9,374 +2559440,17,SHORT,66,-6,-2,47 +2559442,17,SHORT,67,7,-1,55 +2559444,17,SHORT,68,35,39,2866 +2559446,17,SHORT,69,27,43,2657 +2559448,17,SHORT,70,13,56,3317 +2559450,17,SHORT,71,14,53,3058 +2559452,17,SHORT,72,-8,57,3336 +2559454,17,SHORT,73,-25,54,3680 +2559456,17,SHORT,74,-34,42,3001 +2559458,17,SHORT,75,-38,40,3132 +2559460,17,SHORT,76,-56,30,4114 +2559462,17,SHORT,77,-54,21,3404 +2559464,17,SHORT,78,-54,9,3057 +2559466,17,SHORT,79,-56,-4,3246 +2559468,17,SHORT,80,-49,-9,2542 +2559470,17,SHORT,81,-55,-22,3535 +2559472,17,SHORT,82,-36,-36,2696 +2559474,17,SHORT,83,-7,-5,92 +2559476,17,SHORT,84,0,8,64 +2559478,17,SHORT,85,-1,3,13 +2559480,17,SHORT,86,0,5,30 +2559482,17,SHORT,87,7,-2,57 +2559484,17,SHORT,88,-9,1,87 +2559486,17,SHORT,89,2,10,112 +2559488,17,SHORT,90,0,-7,54 +2559490,17,SHORT,91,2,6,47 +2559492,17,SHORT,92,-5,2,34 +2559494,17,SHORT,93,3,1,16 +2559496,17,SHORT,94,5,3,39 +2559498,17,SHORT,95,-5,-3,36 +2559500,17,SHORT,96,-4,-2,28 +2559502,17,SHORT,97,-4,-2,27 +2559504,17,SHORT,98,-2,-6,54 +2559506,17,SHORT,99,2,2,12 +2559508,17,SHORT,100,2,-6,47 +2559510,17,SHORT,101,-4,6,60 +2559512,17,SHORT,102,2,1,9 +2559514,17,SHORT,103,9,-1,87 +2559516,17,SHORT,104,0,4,18 +2559518,17,SHORT,105,1,1,4 +2559520,17,SHORT,106,1,-10,119 +2559522,17,SHORT,107,-2,1,8 +2559524,17,SHORT,108,0,-2,7 +2559526,17,SHORT,109,6,8,109 +2559528,17,SHORT,110,7,-4,71 +2559530,17,SHORT,111,-4,-1,27 +2559532,17,SHORT,112,-1,4,18 +2559534,17,SHORT,113,3,0,12 +2559536,17,SHORT,114,-1,2,12 +2559538,17,SHORT,115,1,4,24 +2559540,17,SHORT,116,-2,-3,18 +2559542,17,SHORT,117,0,9,89 +2559544,17,SHORT,118,9,-25,719 +2559546,17,SHORT,119,8,-25,715 +2559548,17,SHORT,120,13,-17,497 +2559550,17,SHORT,121,22,-10,634 +2559552,17,SHORT,122,28,-11,963 +2559554,17,SHORT,123,25,1,674 +2559556,17,SHORT,124,30,-3,932 +2559558,17,SHORT,125,25,3,650 +2559560,17,SHORT,126,25,9,740 +2559562,17,SHORT,127,25,17,964 +2559564,17,SHORT,128,26,30,1633 +2559566,17,SHORT,129,14,27,1002 +2559568,17,SHORT,130,19,22,886 +2559570,17,SHORT,131,3,27,775 +2559572,17,SHORT,132,-9,20,515 +2559574,17,SHORT,133,0,2,9 +2559576,17,SHORT,134,0,-3,14 +2559578,17,SHORT,135,5,-6,76 +2559580,17,SHORT,136,0,-1,3 +2559582,17,SHORT,137,4,-2,27 +2559584,17,SHORT,138,-2,8,82 +2559586,17,SHORT,139,-1,-1,5 +2559588,17,SHORT,140,3,0,12 +2559590,17,SHORT,141,1,0,1 +2559592,17,SHORT,142,1,3,16 +2559594,17,SHORT,143,3,1,12 +2559596,17,SHORT,144,1,-3,17 +2559598,17,SHORT,145,-6,-2,54 +2559600,17,SHORT,146,5,1,32 +2559602,17,SHORT,147,0,-7,53 +2559604,17,SHORT,148,4,-5,50 +2559606,17,SHORT,149,0,0,1 +2559608,17,SHORT,150,4,0,23 +2559610,17,SHORT,151,0,1,2 +2559612,17,SHORT,152,6,0,43 +2559614,17,SHORT,153,2,0,9 +2559616,17,SHORT,154,9,-1,84 +2559618,17,SHORT,155,4,0,18 +2559620,17,SHORT,156,-4,9,115 +2559622,17,SHORT,157,-1,-5,32 +2559624,17,SHORT,158,-4,2,23 +2559626,17,SHORT,159,1,3,13 +2559628,17,SHORT,160,8,0,73 +2559630,17,SHORT,161,1,10,119 +2559632,17,SHORT,162,-1,0,4 +2559634,17,SHORT,163,0,-5,30 +2559636,17,SHORT,164,-1,2,9 +2559638,17,SHORT,165,2,-12,168 +2559640,17,SHORT,166,-4,1,20 +2559642,17,SHORT,167,-3,-2,16 +2559644,17,SHORT,168,0,1,2 +2559646,17,SHORT,169,3,1,14 +2559648,17,SHORT,170,0,-3,10 +2559650,17,SHORT,171,-6,-3,61 +2559652,17,SHORT,172,0,0,0 +2559654,17,SHORT,173,13,4,193 +2559656,17,SHORT,174,10,5,149 +2559658,17,SHORT,175,-1,0,3 +2559660,17,SHORT,176,-1,0,3 +2559662,17,SHORT,177,-4,-4,41 +2559664,17,SHORT,178,-11,0,133 +2559666,17,SHORT,179,1,-5,34 +2559668,17,SHORT,180,-7,-1,59 +2559670,17,SHORT,181,4,-6,67 +2559672,17,SHORT,182,0,4,24 +2559674,17,SHORT,183,0,0,0 +2559676,17,SHORT,184,-5,7,94 +2559678,17,SHORT,185,1,-4,20 +2559680,17,SHORT,186,3,2,20 +2559682,17,SHORT,187,2,6,46 +2559684,17,SHORT,188,9,2,107 +2559686,17,SHORT,189,1,1,4 +2559688,17,SHORT,190,6,2,45 +2559690,17,SHORT,191,-4,-1,24 +2559692,17,SHORT,192,1,-4,25 +2559694,17,SHORT,193,-1,-8,75 +2559696,17,SHORT,194,17,-8,386 +2559698,17,SHORT,195,2,-7,67 +2559700,17,SHORT,196,11,-6,186 +2559702,17,SHORT,197,20,-3,429 +2559704,17,SHORT,198,17,0,324 +2559706,17,SHORT,199,21,1,482 +2559708,17,SHORT,200,13,2,203 +2559710,17,SHORT,201,17,11,446 +2559712,17,SHORT,202,10,7,151 +2559714,17,SHORT,203,12,16,438 +2559716,17,SHORT,204,17,16,561 +2559718,17,SHORT,205,3,12,182 +2559720,17,SHORT,206,1,10,123 +2559722,17,SHORT,207,2,8,74 +2559724,17,SHORT,208,7,6,105 +2559726,17,SHORT,209,-2,-1,11 +2559728,17,SHORT,210,-2,3,15 +2559730,17,SHORT,211,7,-1,53 +2559732,17,SHORT,212,10,-7,166 +2559734,17,SHORT,213,7,2,66 +2559736,17,SHORT,214,4,-6,63 +2559738,17,SHORT,215,-10,8,180 +2559740,17,SHORT,216,6,-4,64 +2559742,17,SHORT,217,5,0,34 +2559744,17,SHORT,218,-7,2,58 +2559746,17,SHORT,219,-6,-3,60 +2559748,17,SHORT,220,-4,8,94 +2559750,17,SHORT,221,-4,16,303 +2559752,17,SHORT,222,4,3,35 +2559754,17,SHORT,223,-3,0,11 +2559756,17,SHORT,224,-6,4,55 +2559758,17,SHORT,225,-7,-4,72 +2559760,17,SHORT,226,1,5,27 +2559762,17,SHORT,227,-2,0,7 +2559764,17,SHORT,228,1,2,9 +2559766,17,SHORT,229,-5,3,44 +2559768,17,SHORT,230,-8,7,133 +2559770,17,SHORT,231,-3,0,12 +2559772,17,SHORT,232,-1,0,2 +2559774,17,SHORT,233,-5,-5,60 +2559776,17,SHORT,234,-2,-2,13 +2559778,17,SHORT,235,0,2,6 +2559780,17,SHORT,236,-4,1,22 +2559782,17,SHORT,237,0,-3,12 +2559784,17,SHORT,238,3,3,28 +2559786,17,SHORT,239,-5,-11,159 +2559788,17,SHORT,240,6,3,49 +2559790,17,SHORT,241,-5,0,32 +2559792,17,SHORT,242,-7,2,65 +2559794,17,SHORT,243,-2,7,57 +2559796,17,SHORT,244,-2,4,25 +2559798,17,SHORT,245,2,4,23 +2559800,17,SHORT,246,0,0,1 +2559802,17,SHORT,247,3,-2,15 +2559804,17,SHORT,248,-4,-10,132 +2559806,17,SHORT,249,7,-6,100 +2559808,17,SHORT,250,-2,-4,29 +2559810,17,SHORT,251,8,-5,104 +2559812,17,SHORT,252,2,-13,177 +2559814,17,SHORT,253,2,-1,7 +2559816,17,SHORT,254,-1,-6,45 +2559818,17,SHORT,255,-1,0,3 +2559820,17,SHORT,256,4,2,29 +2559822,17,SHORT,257,0,-12,150 +2559824,17,SHORT,258,-4,6,62 +2559826,17,SHORT,259,0,0,0 +2559828,17,SHORT,260,3,0,16 +2559830,17,SHORT,261,0,-7,52 +2559832,17,SHORT,262,-2,0,9 +2559834,17,SHORT,263,3,4,32 +2559836,17,SHORT,264,6,1,41 +2559838,17,SHORT,265,-7,-6,96 +2559840,17,SHORT,266,-5,0,36 +2559842,17,SHORT,267,-7,3,62 +2559844,17,SHORT,268,1,-8,72 +2559846,17,SHORT,269,0,1,2 +2559848,17,SHORT,270,-1,-7,53 +2559850,17,SHORT,271,1,6,38 +2559852,17,SHORT,272,-3,4,29 +2559854,17,SHORT,273,0,2,7 +2559856,17,SHORT,274,1,7,51 +2559858,17,SHORT,275,-12,-3,168 +2559860,17,SHORT,276,0,-5,31 +2559862,17,SHORT,277,5,-3,45 +2559864,17,SHORT,278,0,0,0 +2559866,17,SHORT,279,0,-3,11 +2559868,17,SHORT,280,2,3,19 +2559870,17,SHORT,281,-1,4,21 +2559872,17,SHORT,282,0,-1,1 +2559874,17,SHORT,283,0,3,15 +2559876,17,SHORT,284,10,-2,113 +2559878,17,SHORT,285,3,8,87 +2559880,17,SHORT,286,-3,0,11 +2559882,17,SHORT,287,9,-4,108 +2559884,17,SHORT,288,-4,0,21 +2559886,17,SHORT,289,3,7,73 +2559888,17,SHORT,290,5,-5,59 +2559890,17,SHORT,291,6,4,61 +2559892,17,SHORT,292,1,2,10 +2559894,17,SHORT,293,0,5,28 +2559896,17,SHORT,294,5,13,226 +2559898,17,SHORT,295,9,14,308 +2559900,17,SHORT,296,-6,6,81 +2559902,17,SHORT,297,2,4,28 +2559904,17,SHORT,298,-5,8,102 +2559906,17,SHORT,299,2,4,25 +2559908,17,SHORT,300,0,5,31 +2559910,17,SHORT,301,-4,11,149 +2559912,17,SHORT,302,-8,-6,114 +2559914,17,SHORT,303,-13,2,179 +2559916,17,SHORT,304,0,9,84 +2559918,17,SHORT,305,-7,-8,132 +2559920,17,SHORT,306,0,-3,11 +2559922,17,SHORT,307,-11,0,137 +2559924,17,SHORT,308,1,1,6 +2559926,17,SHORT,309,4,-3,27 +2559928,17,SHORT,310,8,0,70 +2559930,17,SHORT,311,-5,1,31 +2559932,17,SHORT,312,-8,3,85 +2559934,17,SHORT,313,0,3,15 +2559936,17,SHORT,314,-3,5,42 +2559938,17,SHORT,315,5,4,45 +2559940,17,SHORT,316,5,-2,38 +2559942,17,SHORT,317,0,3,11 +2559944,17,SHORT,318,0,0,0 +2559946,17,SHORT,319,1,2,11 +2559948,17,SHORT,320,-7,-1,54 +2559950,17,SHORT,321,-5,2,41 +2559952,17,SHORT,322,7,-3,60 +2559954,17,SHORT,323,-4,0,23 +2559956,17,SHORT,324,-2,9,103 +2559958,17,SHORT,325,0,7,52 +2559960,17,SHORT,326,3,1,15 +2559962,17,SHORT,327,4,0,20 +2559964,17,SHORT,328,-2,-5,36 +2559966,17,SHORT,329,8,0,68 +2559968,17,SHORT,330,-1,1,6 +2559970,17,SHORT,331,8,-2,77 +2559972,17,SHORT,332,1,1,3 +2559974,17,SHORT,333,0,8,79 +2559976,17,SHORT,334,5,2,40 +2559978,17,SHORT,335,0,-1,1 +2559980,17,SHORT,336,8,0,70 +2559982,17,SHORT,337,7,-1,52 +2559984,17,SHORT,338,3,-12,153 +2559986,17,SHORT,339,3,9,111 +2559988,17,SHORT,340,6,0,43 +2559990,17,SHORT,341,-3,5,46 +2559992,17,SHORT,342,5,-6,66 +2559994,17,SHORT,343,0,5,29 +2559996,17,SHORT,344,0,4,17 +2559998,17,SHORT,345,1,7,55 +2560000,17,SHORT,346,-2,4,29 +2560002,17,SHORT,347,4,6,63 +2560004,17,SHORT,348,-4,-8,80 +2560006,17,SHORT,349,-2,-4,27 +2560008,17,SHORT,350,8,-4,88 +2560010,17,SHORT,351,-7,-3,65 +2560012,17,SHORT,352,-1,0,2 +2560014,17,SHORT,353,-4,-6,58 +2560016,17,SHORT,354,-2,0,5 +2560018,17,SHORT,355,3,-3,22 +2560020,17,SHORT,356,-5,-1,31 +2560022,17,SHORT,357,2,5,35 +2560024,17,SHORT,358,4,2,24 +2560026,17,SHORT,359,-1,0,2 +2560028,17,SHORT,360,3,-7,77 +2560030,17,SHORT,361,-1,1,5 +2560032,17,SHORT,362,1,5,38 +2560034,17,SHORT,363,2,-3,16 +2560036,17,SHORT,364,-1,6,45 +2560038,17,SHORT,365,-3,6,47 +2560040,17,SHORT,366,0,-5,29 +2560042,17,SHORT,367,4,-7,81 +2560044,17,SHORT,368,12,-3,174 +2560046,17,SHORT,369,5,0,31 +2560048,17,SHORT,370,1,-3,17 +2560050,17,SHORT,371,-2,-7,61 +2560052,17,SHORT,372,0,-7,52 +2560054,17,SHORT,373,9,-5,129 +2560056,17,SHORT,374,-7,-5,84 +2560058,17,SHORT,375,-1,-3,14 +2560060,17,SHORT,376,-6,5,81 +2560062,17,SHORT,377,-5,-2,38 +2560064,17,SHORT,378,6,-2,44 +2560066,17,SHORT,379,-4,-2,24 +2560068,17,SHORT,380,-1,11,132 +2560070,17,SHORT,381,0,-3,14 +2560072,17,SHORT,382,5,-5,54 +2560074,17,SHORT,383,-6,-6,77 +2560076,17,SHORT,384,-2,6,44 +2560078,17,SHORT,385,6,0,39 +2560080,17,SHORT,386,-6,0,45 +2560082,17,SHORT,387,1,3,17 +2560084,17,SHORT,388,0,3,14 +2560086,17,SHORT,389,2,5,38 +2560088,17,SHORT,390,0,0,0 +2560090,17,SHORT,391,-1,7,50 +2560092,17,SHORT,392,6,2,42 +2560094,17,SHORT,393,0,-2,7 +2560096,17,SHORT,394,2,0,7 +2560098,17,SHORT,395,-5,0,28 +2560100,17,SHORT,396,0,2,6 +2560102,17,SHORT,397,2,0,5 +2560104,17,SHORT,398,-5,0,31 +2560106,17,SHORT,399,-4,-4,42 +2560108,17,SHORT,400,-5,0,28 +2560110,17,SHORT,401,-4,-5,42 +2560112,17,SHORT,402,-6,-2,54 +2560114,17,SHORT,403,0,-5,33 +2560116,17,SHORT,404,-6,5,68 +2560118,17,SHORT,405,0,0,0 +2560120,17,SHORT,406,8,-1,70 +2560122,17,SHORT,407,-6,-2,44 +2560124,17,SHORT,408,1,5,33 +2560126,17,SHORT,409,-4,-2,27 +2560128,17,SHORT,410,-7,-2,60 +2560130,17,SHORT,411,-3,-2,23 +2560132,17,SHORT,412,-1,-10,113 +2560134,17,SHORT,413,-6,3,52 +2560136,17,SHORT,414,-3,-6,64 +2560138,17,SHORT,415,1,1,5 +2560140,17,SHORT,416,0,-4,24 +2560142,17,SHORT,417,-2,2,11 +2560144,17,SHORT,418,9,4,105 +2560146,17,SHORT,419,-2,-8,72 +2560148,17,SHORT,420,1,3,14 +2560150,17,SHORT,421,-3,0,15 +2560152,17,SHORT,422,-11,0,130 +2560154,17,SHORT,423,-8,0,73 +2560156,17,SHORT,424,0,3,10 +2560158,17,SHORT,425,-3,0,14 +2560160,17,SHORT,426,0,0,0 +2560162,17,SHORT,427,-5,-11,174 +2560164,17,SHORT,428,-4,1,21 +2560166,17,SHORT,429,-2,6,44 +2560168,17,SHORT,430,-2,11,130 +2560170,17,SHORT,431,0,1,3 +2560172,17,SHORT,432,-8,3,79 +2560174,17,SHORT,433,0,1,3 +2560176,17,SHORT,434,4,8,95 +2560178,17,SHORT,435,1,1,4 +2560180,17,SHORT,436,7,2,58 +2560182,17,SHORT,437,-6,-1,41 +2560184,17,SHORT,438,0,3,15 +2560186,17,SHORT,439,0,0,0 +2560188,17,SHORT,440,3,10,111 +2560190,17,SHORT,441,-1,-4,20 +2560192,17,SHORT,442,-10,-5,144 +2560194,17,SHORT,443,-5,1,36 +2560196,17,SHORT,444,0,-6,44 +2560198,17,SHORT,445,0,2,7 +2560200,17,SHORT,446,-5,6,73 +2560202,17,SHORT,447,-6,4,62 +2560204,17,SHORT,448,-1,0,3 +2560206,17,SHORT,449,-2,1,9 +2560208,17,SHORT,450,-3,0,13 +2560210,17,SHORT,451,-3,-6,58 +2560212,17,SHORT,452,4,-13,216 +2560214,17,SHORT,453,0,4,16 +2560216,17,SHORT,454,-3,0,12 +2560218,17,SHORT,455,-3,6,51 +2560220,17,SHORT,456,-7,1,53 +2560222,17,SHORT,457,-1,4,26 +2560224,17,SHORT,458,9,-5,130 +2560226,17,SHORT,459,4,-2,22 +2560228,17,SHORT,460,-10,-3,116 +2560230,17,SHORT,461,-11,-6,163 +2560232,17,SHORT,462,1,10,112 +2560234,17,SHORT,463,2,-6,42 +2560236,17,SHORT,464,-4,2,26 +2560238,17,SHORT,465,1,0,1 +2560240,17,SHORT,466,-6,-1,43 +2560242,17,SHORT,467,3,-3,26 +2560244,17,SHORT,468,-3,-6,55 +2560246,17,SHORT,469,-1,0,2 +2560248,17,SHORT,470,0,-2,4 +2560250,17,SHORT,471,-7,3,69 +2560252,17,SHORT,472,-2,1,6 +2560254,17,SHORT,473,-3,4,34 +2560256,17,SHORT,474,1,1,7 +2560258,17,SHORT,475,-3,-7,61 +2560260,17,SHORT,476,-7,-4,74 +2560262,17,SHORT,477,-6,0,40 +2560264,17,SHORT,478,8,-8,144 +2560266,17,SHORT,479,6,-2,41 +2560268,17,SHORT,480,-7,2,56 +2560270,17,SHORT,481,-5,-1,32 +2560272,17,SHORT,482,-4,6,54 +2560274,17,SHORT,483,-8,0,72 +2560276,17,SHORT,484,0,0,1 +2560278,17,SHORT,485,5,0,29 +2560280,17,SHORT,486,1,-2,8 +2560282,17,SHORT,487,0,-1,2 +2560284,17,SHORT,488,9,2,89 +2560286,17,SHORT,489,2,-2,14 +2560288,17,SHORT,490,-3,1,14 +2560290,17,SHORT,491,-3,-2,21 +2560292,17,SHORT,492,-2,-5,33 +2560294,17,SHORT,493,-3,-17,311 +2560296,17,SHORT,494,-1,1,5 +2560298,17,SHORT,495,-1,0,2 +2560300,17,SHORT,496,1,3,10 +2560302,17,SHORT,497,3,-4,34 +2560304,17,SHORT,498,8,1,67 +2560306,17,SHORT,499,0,-5,28 +2560308,17,SHORT,500,-3,-1,13 +2560310,17,SHORT,501,12,3,158 +2560312,17,SHORT,502,0,-2,6 +2560314,17,SHORT,503,6,3,57 +2560316,17,SHORT,504,0,-4,24 +2560318,17,SHORT,505,0,-1,3 +2560320,17,SHORT,506,-9,-3,111 +2560322,17,SHORT,507,5,7,91 +2560324,17,SHORT,508,8,0,73 +2560326,17,SHORT,509,-2,-7,64 +2560328,17,SHORT,510,3,12,158 +2560330,17,SHORT,511,5,-2,34 +2734832,18,SHORT,0,11,-13,324 +2734834,18,SHORT,1,2,-1,9 +2734836,18,SHORT,2,4,-9,112 +2734838,18,SHORT,3,8,-1,79 +2734840,18,SHORT,4,-4,-1,20 +2734842,18,SHORT,5,9,3,108 +2734844,18,SHORT,6,0,-18,361 +2734846,18,SHORT,7,2,1,9 +2734848,18,SHORT,8,-14,2,214 +2734850,18,SHORT,9,-5,-8,100 +2734852,18,SHORT,10,10,1,113 +2734854,18,SHORT,11,4,-3,36 +2734856,18,SHORT,12,3,1,10 +2734858,18,SHORT,13,2,6,52 +2734860,18,SHORT,14,-13,11,317 +2734862,18,SHORT,15,5,4,49 +2734864,18,SHORT,16,2,-11,149 +2734866,18,SHORT,17,-1,-2,6 +2734868,18,SHORT,18,28,3,798 +2734870,18,SHORT,19,-8,-7,133 +2734872,18,SHORT,20,3,6,60 +2734874,18,SHORT,21,-1,-6,48 +2734876,18,SHORT,22,0,2,8 +2734878,18,SHORT,23,-8,-11,211 +2734880,18,SHORT,24,0,-5,28 +2734882,18,SHORT,25,-1,-5,35 +2734884,18,SHORT,26,3,5,41 +2734886,18,SHORT,27,6,-11,169 +2734888,18,SHORT,28,-4,-11,166 +2734890,18,SHORT,29,-12,-1,172 +2734892,18,SHORT,30,5,0,31 +2734894,18,SHORT,31,-7,-3,69 +2734896,18,SHORT,32,4,7,87 +2734898,18,SHORT,33,9,0,95 +2734900,18,SHORT,34,-8,9,156 +2734902,18,SHORT,35,-8,6,105 +2734904,18,SHORT,36,-5,-12,186 +2734906,18,SHORT,37,-11,7,188 +2734908,18,SHORT,38,-3,2,19 +2734910,18,SHORT,39,4,-4,34 +2734912,18,SHORT,40,0,-4,21 +2734914,18,SHORT,41,-11,5,149 +2734916,18,SHORT,42,-8,-7,120 +2734918,18,SHORT,43,-6,14,235 +2734920,18,SHORT,44,0,0,0 +2734922,18,SHORT,45,-12,-17,461 +2734924,18,SHORT,46,12,0,156 +2734926,18,SHORT,47,5,-13,203 +2734928,18,SHORT,48,6,7,105 +2734930,18,SHORT,49,11,9,216 +2734932,18,SHORT,50,2,0,9 +2734934,18,SHORT,51,0,-7,59 +2734936,18,SHORT,52,-4,-8,88 +2734938,18,SHORT,53,4,0,16 +2734940,18,SHORT,54,1,6,45 +2734942,18,SHORT,55,3,-5,39 +2734944,18,SHORT,56,-3,-7,60 +2734946,18,SHORT,57,4,-5,52 +2734948,18,SHORT,58,5,-7,92 +2734950,18,SHORT,59,-6,0,37 +2734952,18,SHORT,60,-4,0,16 +2734954,18,SHORT,61,1,1,4 +2734956,18,SHORT,62,-4,10,126 +2734958,18,SHORT,63,-3,1,16 +2734960,18,SHORT,64,-3,0,10 +2734962,18,SHORT,65,1,-9,91 +2734964,18,SHORT,66,2,10,115 +2734966,18,SHORT,67,-4,0,16 +2734968,18,SHORT,68,-57,24,3918 +2734970,18,SHORT,69,-51,5,2669 +2734972,18,SHORT,70,-49,-9,2508 +2734974,18,SHORT,71,-52,-17,3001 +2734976,18,SHORT,72,-44,-27,2739 +2734978,18,SHORT,73,-33,-45,3171 +2734980,18,SHORT,74,-32,-49,3455 +2734982,18,SHORT,75,-24,-45,2620 +2734984,18,SHORT,76,-11,-54,3051 +2734986,18,SHORT,77,0,-52,2751 +2734988,18,SHORT,78,18,-58,3796 +2734990,18,SHORT,79,29,-55,3924 +2734992,18,SHORT,80,38,-49,3951 +2734994,18,SHORT,81,39,-38,3050 +2734996,18,SHORT,82,54,-30,3953 +2734998,18,SHORT,83,6,-2,50 +2735000,18,SHORT,84,2,12,153 +2735002,18,SHORT,85,-1,-13,177 +2735004,18,SHORT,86,-1,5,36 +2735006,18,SHORT,87,1,5,35 +2735008,18,SHORT,88,3,0,15 +2735010,18,SHORT,89,-6,5,69 +2735012,18,SHORT,90,-2,-5,38 +2735014,18,SHORT,91,0,1,3 +2735016,18,SHORT,92,-4,-1,24 +2735018,18,SHORT,93,0,-7,53 +2735020,18,SHORT,94,-2,-2,11 +2735022,18,SHORT,95,-6,3,52 +2735024,18,SHORT,96,4,6,60 +2735026,18,SHORT,97,12,0,149 +2735028,18,SHORT,98,1,0,3 +2735030,18,SHORT,99,1,-1,6 +2735032,18,SHORT,100,8,0,77 +2735034,18,SHORT,101,2,7,69 +2735036,18,SHORT,102,-2,0,8 +2735038,18,SHORT,103,-8,-2,83 +2735040,18,SHORT,104,5,-9,119 +2735042,18,SHORT,105,-3,1,14 +2735044,18,SHORT,106,7,-1,62 +2735046,18,SHORT,107,5,0,32 +2735048,18,SHORT,108,3,0,12 +2735050,18,SHORT,109,4,9,124 +2735052,18,SHORT,110,-2,3,14 +2735054,18,SHORT,111,8,0,78 +2735056,18,SHORT,112,-11,-2,136 +2735058,18,SHORT,113,-1,2,8 +2735060,18,SHORT,114,7,8,129 +2735062,18,SHORT,115,2,4,28 +2735064,18,SHORT,116,0,-1,4 +2735066,18,SHORT,117,6,-4,56 +2735068,18,SHORT,118,-26,-24,1275 +2735070,18,SHORT,119,-18,-27,1107 +2735072,18,SHORT,120,-11,-13,312 +2735074,18,SHORT,121,-10,-28,913 +2735076,18,SHORT,122,-2,-30,945 +2735078,18,SHORT,123,6,-31,1021 +2735080,18,SHORT,124,15,-29,1123 +2735082,18,SHORT,125,16,-27,1019 +2735084,18,SHORT,126,24,-15,827 +2735086,18,SHORT,127,22,-13,671 +2735088,18,SHORT,128,21,-13,663 +2735090,18,SHORT,129,37,-8,1495 +2735092,18,SHORT,130,31,9,1087 +2735094,18,SHORT,131,25,9,737 +2735096,18,SHORT,132,16,26,962 +2735098,18,SHORT,133,0,13,173 +2735100,18,SHORT,134,1,0,1 +2735102,18,SHORT,135,4,-6,71 +2735104,18,SHORT,136,0,0,0 +2735106,18,SHORT,137,5,-1,33 +2735108,18,SHORT,138,-3,0,9 +2735110,18,SHORT,139,-2,1,10 +2735112,18,SHORT,140,-2,7,68 +2735114,18,SHORT,141,12,3,166 +2735116,18,SHORT,142,4,4,36 +2735118,18,SHORT,143,-3,-6,55 +2735120,18,SHORT,144,2,-4,31 +2735122,18,SHORT,145,-3,-3,25 +2735124,18,SHORT,146,1,5,36 +2735126,18,SHORT,147,-2,-3,16 +2735128,18,SHORT,148,10,0,109 +2735130,18,SHORT,149,7,1,57 +2735132,18,SHORT,150,-13,4,193 +2735134,18,SHORT,151,-2,8,87 +2735136,18,SHORT,152,1,11,124 +2735138,18,SHORT,153,-3,0,11 +2735140,18,SHORT,154,0,-1,1 +2735142,18,SHORT,155,0,4,19 +2735144,18,SHORT,156,-5,-5,53 +2735146,18,SHORT,157,9,2,99 +2735148,18,SHORT,158,0,1,1 +2735150,18,SHORT,159,1,2,7 +2735152,18,SHORT,160,-1,1,4 +2735154,18,SHORT,161,1,10,113 +2735156,18,SHORT,162,-7,9,156 +2735158,18,SHORT,163,0,4,20 +2735160,18,SHORT,164,1,7,53 +2735162,18,SHORT,165,3,-4,31 +2735164,18,SHORT,166,-3,-7,62 +2735166,18,SHORT,167,1,2,8 +2735168,18,SHORT,168,0,5,29 +2735170,18,SHORT,169,5,2,35 +2735172,18,SHORT,170,2,8,84 +2735174,18,SHORT,171,-14,0,212 +2735176,18,SHORT,172,4,1,24 +2735178,18,SHORT,173,11,4,143 +2735180,18,SHORT,174,-4,0,21 +2735182,18,SHORT,175,2,2,10 +2735184,18,SHORT,176,3,0,9 +2735186,18,SHORT,177,-1,1,6 +2735188,18,SHORT,178,1,6,39 +2735190,18,SHORT,179,3,5,39 +2735192,18,SHORT,180,-5,-2,36 +2735194,18,SHORT,181,0,-1,2 +2735196,18,SHORT,182,6,2,54 +2735198,18,SHORT,183,0,8,71 +2735200,18,SHORT,184,4,-1,21 +2735202,18,SHORT,185,-2,-4,29 +2735204,18,SHORT,186,-3,7,67 +2735206,18,SHORT,187,6,0,37 +2735208,18,SHORT,188,1,1,3 +2735210,18,SHORT,189,0,-1,3 +2735212,18,SHORT,190,0,1,1 +2735214,18,SHORT,191,1,0,4 +2735216,18,SHORT,192,5,0,30 +2735218,18,SHORT,193,4,-10,134 +2735220,18,SHORT,194,3,-19,403 +2735222,18,SHORT,195,14,-6,246 +2735224,18,SHORT,196,19,1,401 +2735226,18,SHORT,197,9,-2,101 +2735228,18,SHORT,198,12,-2,175 +2735230,18,SHORT,199,14,6,250 +2735232,18,SHORT,200,5,4,46 +2735234,18,SHORT,201,4,13,207 +2735236,18,SHORT,202,6,18,394 +2735238,18,SHORT,203,7,5,93 +2735240,18,SHORT,204,-1,10,103 +2735242,18,SHORT,205,0,18,346 +2735244,18,SHORT,206,-6,12,204 +2735246,18,SHORT,207,-2,18,338 +2735248,18,SHORT,208,-5,-4,53 +2735250,18,SHORT,209,-1,-2,8 +2735252,18,SHORT,210,-3,1,15 +2735254,18,SHORT,211,-4,2,28 +2735256,18,SHORT,212,-1,-4,18 +2735258,18,SHORT,213,-1,-7,51 +2735260,18,SHORT,214,-1,1,5 +2735262,18,SHORT,215,-10,-5,139 +2735264,18,SHORT,216,-1,3,15 +2735266,18,SHORT,217,9,0,94 +2735268,18,SHORT,218,-4,9,116 +2735270,18,SHORT,219,1,-1,4 +2735272,18,SHORT,220,-1,2,5 +2735274,18,SHORT,221,0,0,0 +2735276,18,SHORT,222,-4,1,26 +2735278,18,SHORT,223,-8,-7,125 +2735280,18,SHORT,224,4,5,47 +2735282,18,SHORT,225,-3,7,67 +2735284,18,SHORT,226,2,5,36 +2735286,18,SHORT,227,3,0,14 +2735288,18,SHORT,228,-2,-2,12 +2735290,18,SHORT,229,3,0,10 +2735292,18,SHORT,230,7,-3,69 +2735294,18,SHORT,231,0,-1,4 +2735296,18,SHORT,232,-3,1,15 +2735298,18,SHORT,233,5,-6,76 +2735300,18,SHORT,234,-4,-8,86 +2735302,18,SHORT,235,-8,0,66 +2735304,18,SHORT,236,-2,-8,74 +2735306,18,SHORT,237,2,-8,88 +2735308,18,SHORT,238,1,7,64 +2735310,18,SHORT,239,-6,6,83 +2735312,18,SHORT,240,3,-1,16 +2735314,18,SHORT,241,2,2,12 +2735316,18,SHORT,242,-6,2,48 +2735318,18,SHORT,243,-3,8,83 +2735320,18,SHORT,244,-2,11,128 +2735322,18,SHORT,245,6,9,137 +2735324,18,SHORT,246,-7,2,63 +2735326,18,SHORT,247,-5,-4,41 +2735328,18,SHORT,248,0,0,1 +2735330,18,SHORT,249,0,-3,10 +2735332,18,SHORT,250,0,3,9 +2735334,18,SHORT,251,0,-4,19 +2735336,18,SHORT,252,-2,3,19 +2735338,18,SHORT,253,-11,2,130 +2735340,18,SHORT,254,2,-4,22 +2735342,18,SHORT,255,0,0,0 +2735344,18,SHORT,256,-5,-9,118 +2735346,18,SHORT,257,1,-1,3 +2735348,18,SHORT,258,-9,0,99 +2735350,18,SHORT,259,0,-3,13 +2735352,18,SHORT,260,2,1,10 +2735354,18,SHORT,261,3,-7,60 +2735356,18,SHORT,262,2,0,5 +2735358,18,SHORT,263,-7,-5,99 +2735360,18,SHORT,264,-4,4,45 +2735362,18,SHORT,265,5,5,63 +2735364,18,SHORT,266,7,-4,74 +2735366,18,SHORT,267,3,1,12 +2735368,18,SHORT,268,7,3,70 +2735370,18,SHORT,269,1,-4,18 +2735372,18,SHORT,270,3,2,16 +2735374,18,SHORT,271,3,2,19 +2735376,18,SHORT,272,-8,8,130 +2735378,18,SHORT,273,5,5,58 +2735380,18,SHORT,274,3,-5,40 +2735382,18,SHORT,275,9,10,196 +2735384,18,SHORT,276,8,-2,71 +2735386,18,SHORT,277,0,-6,37 +2735388,18,SHORT,278,1,8,72 +2735390,18,SHORT,279,-3,1,17 +2735392,18,SHORT,280,2,-3,16 +2735394,18,SHORT,281,8,1,77 +2735396,18,SHORT,282,1,2,10 +2735398,18,SHORT,283,-1,-4,25 +2735400,18,SHORT,284,0,-1,1 +2735402,18,SHORT,285,0,8,76 +2735404,18,SHORT,286,-9,9,180 +2735406,18,SHORT,287,-2,-7,61 +2735408,18,SHORT,288,-2,-1,7 +2735410,18,SHORT,289,0,0,0 +2735412,18,SHORT,290,1,1,4 +2735414,18,SHORT,291,6,-6,86 +2735416,18,SHORT,292,3,3,18 +2735418,18,SHORT,293,4,5,46 +2735420,18,SHORT,294,3,2,22 +2735422,18,SHORT,295,11,-5,167 +2735424,18,SHORT,296,4,6,62 +2735426,18,SHORT,297,4,5,55 +2735428,18,SHORT,298,-3,5,43 +2735430,18,SHORT,299,2,10,108 +2735432,18,SHORT,300,0,0,0 +2735434,18,SHORT,301,-11,-4,147 +2735436,18,SHORT,302,-13,10,292 +2735438,18,SHORT,303,-8,11,193 +2735440,18,SHORT,304,-3,3,21 +2735442,18,SHORT,305,-7,-1,57 +2735444,18,SHORT,306,0,-1,2 +2735446,18,SHORT,307,-10,-1,114 +2735448,18,SHORT,308,0,-2,4 +2735450,18,SHORT,309,-8,2,82 +2735452,18,SHORT,310,-11,0,140 +2735454,18,SHORT,311,-3,-2,16 +2735456,18,SHORT,312,4,2,24 +2735458,18,SHORT,313,0,0,0 +2735460,18,SHORT,314,7,2,56 +2735462,18,SHORT,315,-10,2,108 +2735464,18,SHORT,316,5,5,52 +2735466,18,SHORT,317,9,3,105 +2735468,18,SHORT,318,-2,0,5 +2735470,18,SHORT,319,-11,2,136 +2735472,18,SHORT,320,3,-4,36 +2735474,18,SHORT,321,6,14,251 +2735476,18,SHORT,322,1,0,4 +2735478,18,SHORT,323,-4,-5,50 +2735480,18,SHORT,324,-3,-5,41 +2735482,18,SHORT,325,0,-2,5 +2735484,18,SHORT,326,-4,1,21 +2735486,18,SHORT,327,-3,-9,96 +2735488,18,SHORT,328,4,7,85 +2735490,18,SHORT,329,-5,4,43 +2735492,18,SHORT,330,-2,-6,47 +2735494,18,SHORT,331,0,0,0 +2735496,18,SHORT,332,5,-9,116 +2735498,18,SHORT,333,1,1,4 +2735500,18,SHORT,334,5,1,34 +2735502,18,SHORT,335,-3,5,39 +2735504,18,SHORT,336,-4,-1,22 +2735506,18,SHORT,337,0,3,16 +2735508,18,SHORT,338,0,1,2 +2735510,18,SHORT,339,0,-4,16 +2735512,18,SHORT,340,2,1,9 +2735514,18,SHORT,341,-4,-3,32 +2735516,18,SHORT,342,-2,-4,20 +2735518,18,SHORT,343,8,0,65 +2735520,18,SHORT,344,-2,-6,49 +2735522,18,SHORT,345,-7,-3,73 +2735524,18,SHORT,346,2,-5,31 +2735526,18,SHORT,347,8,-7,123 +2735528,18,SHORT,348,2,-10,113 +2735530,18,SHORT,349,-2,0,4 +2735532,18,SHORT,350,6,-6,92 +2735534,18,SHORT,351,10,0,108 +2735536,18,SHORT,352,6,1,47 +2735538,18,SHORT,353,0,0,0 +2735540,18,SHORT,354,3,0,10 +2735542,18,SHORT,355,-8,1,66 +2735544,18,SHORT,356,-2,-3,17 +2735546,18,SHORT,357,7,2,68 +2735548,18,SHORT,358,-1,4,20 +2735550,18,SHORT,359,-13,0,185 +2735552,18,SHORT,360,-3,2,19 +2735554,18,SHORT,361,4,2,31 +2735556,18,SHORT,362,-1,3,16 +2735558,18,SHORT,363,-1,1,6 +2735560,18,SHORT,364,-3,-9,92 +2735562,18,SHORT,365,2,1,9 +2735564,18,SHORT,366,6,-1,38 +2735566,18,SHORT,367,-4,2,30 +2735568,18,SHORT,368,-4,2,22 +2735570,18,SHORT,369,4,4,35 +2735572,18,SHORT,370,-2,-2,11 +2735574,18,SHORT,371,0,-3,15 +2735576,18,SHORT,372,-7,-3,65 +2735578,18,SHORT,373,-3,0,10 +2735580,18,SHORT,374,1,-1,4 +2735582,18,SHORT,375,-1,0,2 +2735584,18,SHORT,376,-10,2,129 +2735586,18,SHORT,377,-2,-6,48 +2735588,18,SHORT,378,4,-1,26 +2735590,18,SHORT,379,-7,5,85 +2735592,18,SHORT,380,-3,3,28 +2735594,18,SHORT,381,1,-2,6 +2735596,18,SHORT,382,3,10,128 +2735598,18,SHORT,383,-2,-1,9 +2735600,18,SHORT,384,0,5,28 +2735602,18,SHORT,385,-3,3,26 +2735604,18,SHORT,386,-3,5,41 +2735606,18,SHORT,387,4,-4,42 +2735608,18,SHORT,388,-5,-6,67 +2735610,18,SHORT,389,-3,-7,71 +2735612,18,SHORT,390,8,-2,82 +2735614,18,SHORT,391,-7,5,84 +2735616,18,SHORT,392,5,6,77 +2735618,18,SHORT,393,-1,-1,5 +2735620,18,SHORT,394,4,-2,27 +2735622,18,SHORT,395,-6,-4,57 +2735624,18,SHORT,396,-1,-3,14 +2735626,18,SHORT,397,3,0,12 +2735628,18,SHORT,398,0,7,60 +2735630,18,SHORT,399,-7,-1,56 +2735632,18,SHORT,400,0,3,12 +2735634,18,SHORT,401,1,0,3 +2735636,18,SHORT,402,-2,3,18 +2735638,18,SHORT,403,-7,2,72 +2735640,18,SHORT,404,-4,6,60 +2735642,18,SHORT,405,-5,1,28 +2735644,18,SHORT,406,0,0,0 +2735646,18,SHORT,407,4,0,16 +2735648,18,SHORT,408,-5,2,34 +2735650,18,SHORT,409,4,-5,51 +2735652,18,SHORT,410,-5,-1,39 +2735654,18,SHORT,411,9,3,106 +2735656,18,SHORT,412,3,0,12 +2735658,18,SHORT,413,1,2,7 +2735660,18,SHORT,414,6,1,49 +2735662,18,SHORT,415,-3,-6,55 +2735664,18,SHORT,416,3,-5,44 +2735666,18,SHORT,417,3,0,12 +2735668,18,SHORT,418,-1,3,11 +2735670,18,SHORT,419,3,8,75 +2735672,18,SHORT,420,-4,-3,33 +2735674,18,SHORT,421,-5,9,125 +2735676,18,SHORT,422,6,0,38 +2735678,18,SHORT,423,-8,5,100 +2735680,18,SHORT,424,6,-1,51 +2735682,18,SHORT,425,-2,3,17 +2735684,18,SHORT,426,0,4,21 +2735686,18,SHORT,427,-3,1,11 +2735688,18,SHORT,428,2,-3,14 +2735690,18,SHORT,429,6,3,55 +2735692,18,SHORT,430,-4,-2,24 +2735694,18,SHORT,431,-5,-1,32 +2735696,18,SHORT,432,2,0,7 +2735698,18,SHORT,433,-9,-3,98 +2735700,18,SHORT,434,7,-7,110 +2735702,18,SHORT,435,1,5,31 +2735704,18,SHORT,436,5,-4,43 +2735706,18,SHORT,437,-6,1,44 +2735708,18,SHORT,438,1,0,3 +2735710,18,SHORT,439,-6,0,39 +2735712,18,SHORT,440,-4,8,96 +2735714,18,SHORT,441,2,7,57 +2735716,18,SHORT,442,0,9,85 +2735718,18,SHORT,443,-1,-6,49 +2735720,18,SHORT,444,-3,-14,225 +2735722,18,SHORT,445,-2,-12,171 +2735724,18,SHORT,446,3,0,9 +2735726,18,SHORT,447,4,-9,111 +2735728,18,SHORT,448,5,-5,60 +2735730,18,SHORT,449,8,3,79 +2735732,18,SHORT,450,2,-1,8 +2735734,18,SHORT,451,3,-2,14 +2735736,18,SHORT,452,-7,-2,63 +2735738,18,SHORT,453,5,7,98 +2735740,18,SHORT,454,4,-4,34 +2735742,18,SHORT,455,5,2,37 +2735744,18,SHORT,456,-1,1,2 +2735746,18,SHORT,457,1,-3,12 +2735748,18,SHORT,458,6,0,46 +2735750,18,SHORT,459,0,0,0 +2735752,18,SHORT,460,-8,-7,117 +2735754,18,SHORT,461,-5,-1,33 +2735756,18,SHORT,462,-2,-5,39 +2735758,18,SHORT,463,3,-3,29 +2735760,18,SHORT,464,7,-3,67 +2735762,18,SHORT,465,3,2,23 +2735764,18,SHORT,466,0,3,16 +2735766,18,SHORT,467,-7,-4,78 +2735768,18,SHORT,468,-3,0,11 +2735770,18,SHORT,469,-1,-2,8 +2735772,18,SHORT,470,5,10,138 +2735774,18,SHORT,471,-3,-2,15 +2735776,18,SHORT,472,0,6,37 +2735778,18,SHORT,473,7,2,59 +2735780,18,SHORT,474,10,4,126 +2735782,18,SHORT,475,-9,6,123 +2735784,18,SHORT,476,-6,2,50 +2735786,18,SHORT,477,-1,-4,23 +2735788,18,SHORT,478,-5,-5,66 +2735790,18,SHORT,479,3,2,22 +2735792,18,SHORT,480,3,10,114 +2735794,18,SHORT,481,0,-6,40 +2735796,18,SHORT,482,3,-6,54 +2735798,18,SHORT,483,11,-8,201 +2735800,18,SHORT,484,9,0,84 +2735802,18,SHORT,485,3,-1,16 +2735804,18,SHORT,486,-14,-7,262 +2735806,18,SHORT,487,0,5,25 +2735808,18,SHORT,488,-1,5,34 +2735810,18,SHORT,489,2,-2,11 +2735812,18,SHORT,490,-3,9,94 +2735814,18,SHORT,491,3,-3,23 +2735816,18,SHORT,492,-1,-10,103 +2735818,18,SHORT,493,9,9,181 +2735820,18,SHORT,494,0,-1,2 +2735822,18,SHORT,495,3,-1,19 +2735824,18,SHORT,496,5,1,34 +2735826,18,SHORT,497,-14,3,226 +2735828,18,SHORT,498,5,2,39 +2735830,18,SHORT,499,2,7,66 +2735832,18,SHORT,500,1,-6,48 +2735834,18,SHORT,501,0,0,0 +2735836,18,SHORT,502,5,-1,30 +2735838,18,SHORT,503,-1,-3,12 +2735840,18,SHORT,504,7,0,63 +2735842,18,SHORT,505,-1,0,3 +2735844,18,SHORT,506,0,7,55 +2735846,18,SHORT,507,9,-2,98 +2735848,18,SHORT,508,2,3,22 +2735850,18,SHORT,509,0,0,0 +2735852,18,SHORT,510,2,4,27 +2735854,18,SHORT,511,10,-1,106 +2910356,19,SHORT,0,-2,14,222 +2910358,19,SHORT,1,-2,14,201 +2910360,19,SHORT,2,0,12,146 +2910362,19,SHORT,3,4,11,149 +2910364,19,SHORT,4,1,1,7 +2910366,19,SHORT,5,-3,-6,56 +2910368,19,SHORT,6,3,-6,59 +2910370,19,SHORT,7,7,-1,55 +2910372,19,SHORT,8,6,0,37 +2910374,19,SHORT,9,-15,-7,316 +2910376,19,SHORT,10,-4,0,22 +2910378,19,SHORT,11,-2,0,7 +2910380,19,SHORT,12,-6,-7,98 +2910382,19,SHORT,13,3,1,15 +2910384,19,SHORT,14,0,0,0 +2910386,19,SHORT,15,-4,0,17 +2910388,19,SHORT,16,2,0,6 +2910390,19,SHORT,17,-2,3,19 +2910392,19,SHORT,18,-14,-3,213 +2910394,19,SHORT,19,16,-2,281 +2910396,19,SHORT,20,-1,1,6 +2910398,19,SHORT,21,1,5,33 +2910400,19,SHORT,22,-5,1,34 +2910402,19,SHORT,23,-1,-4,24 +2910404,19,SHORT,24,3,-3,23 +2910406,19,SHORT,25,-13,1,174 +2910408,19,SHORT,26,0,3,10 +2910410,19,SHORT,27,6,3,59 +2910412,19,SHORT,28,2,4,30 +2910414,19,SHORT,29,2,4,24 +2910416,19,SHORT,30,14,6,261 +2910418,19,SHORT,31,2,5,36 +2910420,19,SHORT,32,0,7,62 +2910422,19,SHORT,33,-6,-5,79 +2910424,19,SHORT,34,4,1,23 +2910426,19,SHORT,35,4,9,110 +2910428,19,SHORT,36,7,2,55 +2910430,19,SHORT,37,-10,-12,262 +2910432,19,SHORT,38,-7,5,89 +2910434,19,SHORT,39,6,0,47 +2910436,19,SHORT,40,-8,10,174 +2910438,19,SHORT,41,-1,5,29 +2910440,19,SHORT,42,5,-6,69 +2910442,19,SHORT,43,-10,2,115 +2910444,19,SHORT,44,6,-10,142 +2910446,19,SHORT,45,13,2,176 +2910448,19,SHORT,46,8,8,138 +2910450,19,SHORT,47,-7,-12,228 +2910452,19,SHORT,48,-15,-3,240 +2910454,19,SHORT,49,0,0,0 +2910456,19,SHORT,50,0,-3,11 +2910458,19,SHORT,51,5,3,41 +2910460,19,SHORT,52,0,-7,54 +2910462,19,SHORT,53,5,6,71 +2910464,19,SHORT,54,0,3,10 +2910466,19,SHORT,55,-1,-8,82 +2910468,19,SHORT,56,-1,-5,37 +2910470,19,SHORT,57,-7,2,67 +2910472,19,SHORT,58,4,3,28 +2910474,19,SHORT,59,-5,0,26 +2910476,19,SHORT,60,0,-6,36 +2910478,19,SHORT,61,1,8,67 +2910480,19,SHORT,62,5,7,78 +2910482,19,SHORT,63,0,4,24 +2910484,19,SHORT,64,-1,6,37 +2910486,19,SHORT,65,0,0,0 +2910488,19,SHORT,66,-5,-5,55 +2910490,19,SHORT,67,-6,-1,43 +2910492,19,SHORT,68,9,-41,1843 +2910494,19,SHORT,69,14,-50,2720 +2910496,19,SHORT,70,22,-62,4412 +2910498,19,SHORT,71,44,-37,3396 +2910500,19,SHORT,72,51,-34,3904 +2910502,19,SHORT,73,50,-22,3083 +2910504,19,SHORT,74,57,-8,3346 +2910506,19,SHORT,75,49,2,2487 +2910508,19,SHORT,76,46,7,2212 +2910510,19,SHORT,77,52,24,3342 +2910512,19,SHORT,78,46,32,3260 +2910514,19,SHORT,79,40,43,3552 +2910516,19,SHORT,80,36,47,3529 +2910518,19,SHORT,81,23,65,4819 +2910520,19,SHORT,82,4,54,2936 +2910522,19,SHORT,83,2,2,15 +2910524,19,SHORT,84,-4,2,27 +2910526,19,SHORT,85,4,-2,27 +2910528,19,SHORT,86,1,0,2 +2910530,19,SHORT,87,9,8,161 +2910532,19,SHORT,88,-1,3,15 +2910534,19,SHORT,89,8,-7,125 +2910536,19,SHORT,90,6,0,42 +2910538,19,SHORT,91,-5,7,89 +2910540,19,SHORT,92,0,1,2 +2910542,19,SHORT,93,-1,-5,37 +2910544,19,SHORT,94,-3,3,28 +2910546,19,SHORT,95,0,-4,21 +2910548,19,SHORT,96,-2,-7,55 +2910550,19,SHORT,97,-1,2,9 +2910552,19,SHORT,98,-3,6,52 +2910554,19,SHORT,99,-3,2,17 +2910556,19,SHORT,100,-9,-5,119 +2910558,19,SHORT,101,10,0,120 +2910560,19,SHORT,102,-1,8,71 +2910562,19,SHORT,103,-5,-6,66 +2910564,19,SHORT,104,2,1,9 +2910566,19,SHORT,105,0,-1,3 +2910568,19,SHORT,106,6,-6,78 +2910570,19,SHORT,107,1,-5,30 +2910572,19,SHORT,108,-1,5,28 +2910574,19,SHORT,109,0,6,42 +2910576,19,SHORT,110,4,-4,38 +2910578,19,SHORT,111,8,0,65 +2910580,19,SHORT,112,-5,2,35 +2910582,19,SHORT,113,-4,4,40 +2910584,19,SHORT,114,4,4,45 +2910586,19,SHORT,115,-7,1,55 +2910588,19,SHORT,116,-2,2,11 +2910590,19,SHORT,117,-5,0,35 +2910592,19,SHORT,118,-33,6,1165 +2910594,19,SHORT,119,-28,-1,820 +2910596,19,SHORT,120,-31,-5,1035 +2910598,19,SHORT,121,-25,0,634 +2910600,19,SHORT,122,-24,-7,656 +2910602,19,SHORT,123,-26,-20,1145 +2910604,19,SHORT,124,-14,-17,528 +2910606,19,SHORT,125,-15,-25,885 +2910608,19,SHORT,126,-10,-33,1255 +2910610,19,SHORT,127,1,-23,564 +2910612,19,SHORT,128,-2,-21,473 +2910614,19,SHORT,129,4,-18,372 +2910616,19,SHORT,130,19,-31,1385 +2910618,19,SHORT,131,18,-16,634 +2910620,19,SHORT,132,21,-9,559 +2910622,19,SHORT,133,8,5,107 +2910624,19,SHORT,134,-4,0,19 +2910626,19,SHORT,135,0,0,0 +2910628,19,SHORT,136,-3,2,20 +2910630,19,SHORT,137,2,-2,11 +2910632,19,SHORT,138,0,-4,24 +2910634,19,SHORT,139,-2,0,5 +2910636,19,SHORT,140,5,-4,47 +2910638,19,SHORT,141,5,-1,32 +2910640,19,SHORT,142,-3,0,13 +2910642,19,SHORT,143,3,-3,26 +2910644,19,SHORT,144,9,-2,99 +2910646,19,SHORT,145,8,-8,145 +2910648,19,SHORT,146,-6,2,50 +2910650,19,SHORT,147,6,2,50 +2910652,19,SHORT,148,6,8,119 +2910654,19,SHORT,149,6,3,54 +2910656,19,SHORT,150,6,1,41 +2910658,19,SHORT,151,-4,2,27 +2910660,19,SHORT,152,0,5,32 +2910662,19,SHORT,153,1,-1,4 +2910664,19,SHORT,154,-1,4,20 +2910666,19,SHORT,155,-4,3,32 +2910668,19,SHORT,156,11,7,191 +2910670,19,SHORT,157,-1,-4,20 +2910672,19,SHORT,158,-2,-1,7 +2910674,19,SHORT,159,2,-2,12 +2910676,19,SHORT,160,4,7,67 +2910678,19,SHORT,161,-1,6,47 +2910680,19,SHORT,162,-1,-3,15 +2910682,19,SHORT,163,0,7,52 +2910684,19,SHORT,164,3,1,14 +2910686,19,SHORT,165,-4,-9,110 +2910688,19,SHORT,166,-6,-3,52 +2910690,19,SHORT,167,-4,-4,39 +2910692,19,SHORT,168,2,-8,74 +2910694,19,SHORT,169,12,0,167 +2910696,19,SHORT,170,5,3,42 +2910698,19,SHORT,171,-6,-3,49 +2910700,19,SHORT,172,0,0,0 +2910702,19,SHORT,173,3,-3,27 +2910704,19,SHORT,174,-1,5,36 +2910706,19,SHORT,175,5,8,114 +2910708,19,SHORT,176,9,3,111 +2910710,19,SHORT,177,-5,-6,71 +2910712,19,SHORT,178,-3,2,20 +2910714,19,SHORT,179,3,4,31 +2910716,19,SHORT,180,0,1,2 +2910718,19,SHORT,181,6,0,45 +2910720,19,SHORT,182,-3,3,20 +2910722,19,SHORT,183,4,3,32 +2910724,19,SHORT,184,3,2,18 +2910726,19,SHORT,185,3,4,31 +2910728,19,SHORT,186,5,-8,97 +2910730,19,SHORT,187,5,0,28 +2910732,19,SHORT,188,-2,-2,10 +2910734,19,SHORT,189,-4,4,34 +2910736,19,SHORT,190,0,-4,16 +2910738,19,SHORT,191,6,3,53 +2910740,19,SHORT,192,-1,0,1 +2910742,19,SHORT,193,16,-10,388 +2910744,19,SHORT,194,14,-10,298 +2910746,19,SHORT,195,8,0,68 +2910748,19,SHORT,196,7,2,56 +2910750,19,SHORT,197,23,-4,571 +2910752,19,SHORT,198,7,5,76 +2910754,19,SHORT,199,18,13,523 +2910756,19,SHORT,200,9,8,164 +2910758,19,SHORT,201,10,19,476 +2910760,19,SHORT,202,8,12,223 +2910762,19,SHORT,203,-11,18,469 +2910764,19,SHORT,204,8,16,361 +2910766,19,SHORT,205,2,7,65 +2910768,19,SHORT,206,-4,15,269 +2910770,19,SHORT,207,-17,-1,312 +2910772,19,SHORT,208,0,3,10 +2910774,19,SHORT,209,-3,4,39 +2910776,19,SHORT,210,-3,1,15 +2910778,19,SHORT,211,-2,-7,57 +2910780,19,SHORT,212,4,-1,20 +2910782,19,SHORT,213,3,-1,12 +2910784,19,SHORT,214,8,5,98 +2910786,19,SHORT,215,7,0,55 +2910788,19,SHORT,216,-1,1,2 +2910790,19,SHORT,217,10,2,116 +2910792,19,SHORT,218,-4,3,27 +2910794,19,SHORT,219,0,0,1 +2910796,19,SHORT,220,3,-8,80 +2910798,19,SHORT,221,-8,-5,101 +2910800,19,SHORT,222,-1,-8,68 +2910802,19,SHORT,223,-3,-2,16 +2910804,19,SHORT,224,-8,-4,99 +2910806,19,SHORT,225,-3,-6,59 +2910808,19,SHORT,226,5,0,30 +2910810,19,SHORT,227,-1,4,20 +2910812,19,SHORT,228,5,3,46 +2910814,19,SHORT,229,0,-3,14 +2910816,19,SHORT,230,4,-11,144 +2910818,19,SHORT,231,-3,-1,11 +2910820,19,SHORT,232,-5,0,34 +2910822,19,SHORT,233,-2,10,108 +2910824,19,SHORT,234,-3,-8,77 +2910826,19,SHORT,235,4,-2,26 +2910828,19,SHORT,236,5,1,30 +2910830,19,SHORT,237,2,-5,34 +2910832,19,SHORT,238,0,-10,111 +2910834,19,SHORT,239,0,0,0 +2910836,19,SHORT,240,8,5,100 +2910838,19,SHORT,241,-1,3,11 +2910840,19,SHORT,242,-3,-5,40 +2910842,19,SHORT,243,2,-4,29 +2910844,19,SHORT,244,3,10,122 +2910846,19,SHORT,245,0,-3,15 +2910848,19,SHORT,246,4,0,21 +2910850,19,SHORT,247,-2,-4,22 +2910852,19,SHORT,248,-5,-3,36 +2910854,19,SHORT,249,6,10,152 +2910856,19,SHORT,250,11,5,158 +2910858,19,SHORT,251,-7,1,54 +2910860,19,SHORT,252,-3,-3,26 +2910862,19,SHORT,253,-3,7,76 +2910864,19,SHORT,254,1,-8,69 +2910866,19,SHORT,255,3,-11,146 +2910868,19,SHORT,256,-2,1,7 +2910870,19,SHORT,257,-5,4,52 +2910872,19,SHORT,258,0,0,0 +2910874,19,SHORT,259,0,4,17 +2910876,19,SHORT,260,7,-1,55 +2910878,19,SHORT,261,1,-4,18 +2910880,19,SHORT,262,-1,-1,3 +2910882,19,SHORT,263,0,1,2 +2910884,19,SHORT,264,5,-4,43 +2910886,19,SHORT,265,-13,11,300 +2910888,19,SHORT,266,-2,3,19 +2910890,19,SHORT,267,2,-3,19 +2910892,19,SHORT,268,7,2,58 +2910894,19,SHORT,269,0,5,27 +2910896,19,SHORT,270,0,8,72 +2910898,19,SHORT,271,-1,-2,6 +2910900,19,SHORT,272,-2,-1,8 +2910902,19,SHORT,273,0,-2,7 +2910904,19,SHORT,274,2,-5,35 +2910906,19,SHORT,275,7,0,53 +2910908,19,SHORT,276,7,-7,111 +2910910,19,SHORT,277,2,-1,8 +2910912,19,SHORT,278,-2,3,19 +2910914,19,SHORT,279,0,-9,93 +2910916,19,SHORT,280,0,0,0 +2910918,19,SHORT,281,0,-1,2 +2910920,19,SHORT,282,6,-1,43 +2910922,19,SHORT,283,-3,0,9 +2910924,19,SHORT,284,-1,0,1 +2910926,19,SHORT,285,1,6,43 +2910928,19,SHORT,286,-3,-7,58 +2910930,19,SHORT,287,-1,0,2 +2910932,19,SHORT,288,1,6,45 +2910934,19,SHORT,289,1,1,6 +2910936,19,SHORT,290,-7,-2,66 +2910938,19,SHORT,291,-5,-6,63 +2910940,19,SHORT,292,7,5,83 +2910942,19,SHORT,293,14,-2,215 +2910944,19,SHORT,294,9,-2,95 +2910946,19,SHORT,295,3,0,9 +2910948,19,SHORT,296,2,13,186 +2910950,19,SHORT,297,6,0,37 +2910952,19,SHORT,298,5,10,149 +2910954,19,SHORT,299,6,-7,88 +2910956,19,SHORT,300,4,11,147 +2910958,19,SHORT,301,-5,7,89 +2910960,19,SHORT,302,5,-2,35 +2910962,19,SHORT,303,-8,9,157 +2910964,19,SHORT,304,-7,9,147 +2910966,19,SHORT,305,-8,4,100 +2910968,19,SHORT,306,-8,8,150 +2910970,19,SHORT,307,-1,5,31 +2910972,19,SHORT,308,-9,-4,111 +2910974,19,SHORT,309,-7,0,50 +2910976,19,SHORT,310,2,5,32 +2910978,19,SHORT,311,3,-3,24 +2910980,19,SHORT,312,-6,-3,47 +2910982,19,SHORT,313,2,6,41 +2910984,19,SHORT,314,0,-3,9 +2910986,19,SHORT,315,-5,-6,66 +2910988,19,SHORT,316,-4,4,46 +2910990,19,SHORT,317,0,2,5 +2910992,19,SHORT,318,2,2,10 +2910994,19,SHORT,319,5,-5,53 +2910996,19,SHORT,320,-9,-1,90 +2910998,19,SHORT,321,5,3,40 +2911000,19,SHORT,322,-6,-1,40 +2911002,19,SHORT,323,-8,-2,81 +2911004,19,SHORT,324,3,0,12 +2911006,19,SHORT,325,-6,-4,64 +2911008,19,SHORT,326,-11,5,158 +2911010,19,SHORT,327,8,-8,155 +2911012,19,SHORT,328,3,3,21 +2911014,19,SHORT,329,-3,-2,18 +2911016,19,SHORT,330,-4,-3,28 +2911018,19,SHORT,331,-2,0,8 +2911020,19,SHORT,332,-4,-5,54 +2911022,19,SHORT,333,3,-5,38 +2911024,19,SHORT,334,3,7,64 +2911026,19,SHORT,335,6,7,95 +2911028,19,SHORT,336,0,8,75 +2911030,19,SHORT,337,-11,1,139 +2911032,19,SHORT,338,-2,2,9 +2911034,19,SHORT,339,2,0,4 +2911036,19,SHORT,340,4,4,46 +2911038,19,SHORT,341,1,-3,12 +2911040,19,SHORT,342,-1,9,85 +2911042,19,SHORT,343,0,8,73 +2911044,19,SHORT,344,2,-5,36 +2911046,19,SHORT,345,1,1,5 +2911048,19,SHORT,346,0,3,12 +2911050,19,SHORT,347,2,-7,58 +2911052,19,SHORT,348,-1,-4,20 +2911054,19,SHORT,349,1,2,6 +2911056,19,SHORT,350,-2,-7,65 +2911058,19,SHORT,351,-2,-5,35 +2911060,19,SHORT,352,-5,3,43 +2911062,19,SHORT,353,0,0,0 +2911064,19,SHORT,354,6,-3,61 +2911066,19,SHORT,355,10,6,147 +2911068,19,SHORT,356,-8,1,69 +2911070,19,SHORT,357,-7,3,65 +2911072,19,SHORT,358,-5,0,31 +2911074,19,SHORT,359,-1,-4,19 +2911076,19,SHORT,360,0,8,80 +2911078,19,SHORT,361,-3,3,23 +2911080,19,SHORT,362,-3,7,74 +2911082,19,SHORT,363,-3,0,9 +2911084,19,SHORT,364,2,0,9 +2911086,19,SHORT,365,6,-1,47 +2911088,19,SHORT,366,-3,-2,15 +2911090,19,SHORT,367,-1,8,82 +2911092,19,SHORT,368,0,4,17 +2911094,19,SHORT,369,3,0,15 +2911096,19,SHORT,370,-1,-4,19 +2911098,19,SHORT,371,-4,3,31 +2911100,19,SHORT,372,5,-3,39 +2911102,19,SHORT,373,7,-7,115 +2911104,19,SHORT,374,-3,-4,33 +2911106,19,SHORT,375,-5,3,45 +2911108,19,SHORT,376,-2,5,38 +2911110,19,SHORT,377,0,4,16 +2911112,19,SHORT,378,4,0,16 +2911114,19,SHORT,379,4,0,20 +2911116,19,SHORT,380,1,-1,5 +2911118,19,SHORT,381,1,0,1 +2911120,19,SHORT,382,-10,-3,115 +2911122,19,SHORT,383,8,6,102 +2911124,19,SHORT,384,1,0,1 +2911126,19,SHORT,385,-1,0,2 +2911128,19,SHORT,386,5,-5,56 +2911130,19,SHORT,387,0,7,53 +2911132,19,SHORT,388,11,0,138 +2911134,19,SHORT,389,5,-11,157 +2911136,19,SHORT,390,0,0,0 +2911138,19,SHORT,391,0,-9,91 +2911140,19,SHORT,392,9,-5,114 +2911142,19,SHORT,393,0,12,165 +2911144,19,SHORT,394,1,6,42 +2911146,19,SHORT,395,0,-1,3 +2911148,19,SHORT,396,1,5,26 +2911150,19,SHORT,397,0,-3,10 +2911152,19,SHORT,398,7,0,61 +2911154,19,SHORT,399,0,-1,1 +2911156,19,SHORT,400,0,0,0 +2911158,19,SHORT,401,-4,0,20 +2911160,19,SHORT,402,1,-1,4 +2911162,19,SHORT,403,-6,-4,67 +2911164,19,SHORT,404,0,-2,5 +2911166,19,SHORT,405,4,-2,21 +2911168,19,SHORT,406,1,-1,6 +2911170,19,SHORT,407,-6,6,82 +2911172,19,SHORT,408,15,0,233 +2911174,19,SHORT,409,3,1,18 +2911176,19,SHORT,410,3,0,15 +2911178,19,SHORT,411,3,4,30 +2911180,19,SHORT,412,9,4,110 +2911182,19,SHORT,413,-5,-4,57 +2911184,19,SHORT,414,2,3,20 +2911186,19,SHORT,415,-1,4,20 +2911188,19,SHORT,416,1,-2,9 +2911190,19,SHORT,417,11,6,176 +2911192,19,SHORT,418,-2,4,28 +2911194,19,SHORT,419,0,-10,101 +2911196,19,SHORT,420,8,-5,111 +2911198,19,SHORT,421,-2,0,7 +2911200,19,SHORT,422,6,0,47 +2911202,19,SHORT,423,7,3,59 +2911204,19,SHORT,424,-1,-3,16 +2911206,19,SHORT,425,-7,-1,60 +2911208,19,SHORT,426,8,1,74 +2911210,19,SHORT,427,1,2,8 +2911212,19,SHORT,428,-1,3,13 +2911214,19,SHORT,429,-4,0,21 +2911216,19,SHORT,430,-4,0,16 +2911218,19,SHORT,431,2,2,10 +2911220,19,SHORT,432,1,-4,26 +2911222,19,SHORT,433,-4,-3,34 +2911224,19,SHORT,434,-1,-4,20 +2911226,19,SHORT,435,6,-8,114 +2911228,19,SHORT,436,5,0,29 +2911230,19,SHORT,437,3,-3,23 +2911232,19,SHORT,438,-5,8,100 +2911234,19,SHORT,439,-5,0,33 +2911236,19,SHORT,440,0,2,5 +2911238,19,SHORT,441,-7,-3,71 +2911240,19,SHORT,442,1,1,7 +2911242,19,SHORT,443,-7,1,50 +2911244,19,SHORT,444,0,-3,14 +2911246,19,SHORT,445,6,7,98 +2911248,19,SHORT,446,14,4,222 +2911250,19,SHORT,447,1,6,50 +2911252,19,SHORT,448,-3,2,16 +2911254,19,SHORT,449,-7,1,66 +2911256,19,SHORT,450,-5,-1,32 +2911258,19,SHORT,451,-5,-2,41 +2911260,19,SHORT,452,0,-4,21 +2911262,19,SHORT,453,3,9,96 +2911264,19,SHORT,454,7,-7,111 +2911266,19,SHORT,455,-8,-4,94 +2911268,19,SHORT,456,2,6,47 +2911270,19,SHORT,457,11,0,141 +2911272,19,SHORT,458,-2,4,22 +2911274,19,SHORT,459,1,3,12 +2911276,19,SHORT,460,2,0,6 +2911278,19,SHORT,461,2,0,5 +2911280,19,SHORT,462,0,-7,56 +2911282,19,SHORT,463,3,-5,42 +2911284,19,SHORT,464,3,1,14 +2911286,19,SHORT,465,-2,-1,8 +2911288,19,SHORT,466,0,-1,1 +2911290,19,SHORT,467,-4,3,33 +2911292,19,SHORT,468,0,5,28 +2911294,19,SHORT,469,-8,-13,245 +2911296,19,SHORT,470,2,-2,12 +2911298,19,SHORT,471,-4,-3,32 +2911300,19,SHORT,472,0,8,68 +2911302,19,SHORT,473,1,-5,30 +2911304,19,SHORT,474,4,5,51 +2911306,19,SHORT,475,4,-1,18 +2911308,19,SHORT,476,-4,9,105 +2911310,19,SHORT,477,2,0,5 +2911312,19,SHORT,478,-2,2,16 +2911314,19,SHORT,479,4,2,24 +2911316,19,SHORT,480,8,-4,94 +2911318,19,SHORT,481,0,-5,34 +2911320,19,SHORT,482,0,7,59 +2911322,19,SHORT,483,-2,-4,23 +2911324,19,SHORT,484,0,8,76 +2911326,19,SHORT,485,-3,0,14 +2911328,19,SHORT,486,2,6,47 +2911330,19,SHORT,487,-6,4,57 +2911332,19,SHORT,488,5,-2,36 +2911334,19,SHORT,489,-4,1,27 +2911336,19,SHORT,490,5,7,76 +2911338,19,SHORT,491,-4,11,152 +2911340,19,SHORT,492,0,-2,7 +2911342,19,SHORT,493,-2,0,6 +2911344,19,SHORT,494,1,-2,7 +2911346,19,SHORT,495,-3,-2,17 +2911348,19,SHORT,496,-4,-8,93 +2911350,19,SHORT,497,0,-1,3 +2911352,19,SHORT,498,2,-13,192 +2911354,19,SHORT,499,8,-3,86 +2911356,19,SHORT,500,-2,10,107 +2911358,19,SHORT,501,-2,8,79 +2911360,19,SHORT,502,-2,3,20 +2911362,19,SHORT,503,1,3,13 +2911364,19,SHORT,504,-5,0,32 +2911366,19,SHORT,505,-1,-2,11 +2911368,19,SHORT,506,-1,4,19 +2911370,19,SHORT,507,1,2,10 +2911372,19,SHORT,508,-15,0,229 +2911374,19,SHORT,509,-6,-3,58 +2911376,19,SHORT,510,0,10,108 +2911378,19,SHORT,511,1,-6,40 +3085880,20,SHORT,0,-1,2,6 +3085882,20,SHORT,1,-6,19,400 +3085884,20,SHORT,2,-5,9,122 +3085886,20,SHORT,3,7,13,245 +3085888,20,SHORT,4,-2,5,37 +3085890,20,SHORT,5,0,-1,3 +3085892,20,SHORT,6,2,-6,50 +3085894,20,SHORT,7,4,-1,23 +3085896,20,SHORT,8,-5,8,97 +3085898,20,SHORT,9,7,-4,75 +3085900,20,SHORT,10,-3,10,129 +3085902,20,SHORT,11,2,0,4 +3085904,20,SHORT,12,0,8,68 +3085906,20,SHORT,13,10,-1,106 +3085908,20,SHORT,14,3,0,14 +3085910,20,SHORT,15,-5,3,36 +3085912,20,SHORT,16,-7,-1,64 +3085914,20,SHORT,17,3,5,37 +3085916,20,SHORT,18,-4,-7,74 +3085918,20,SHORT,19,1,-5,29 +3085920,20,SHORT,20,16,5,287 +3085922,20,SHORT,21,-8,16,323 +3085924,20,SHORT,22,18,2,344 +3085926,20,SHORT,23,2,-3,16 +3085928,20,SHORT,24,-2,3,17 +3085930,20,SHORT,25,-10,-10,217 +3085932,20,SHORT,26,-1,-6,39 +3085934,20,SHORT,27,9,-20,503 +3085936,20,SHORT,28,-2,-11,139 +3085938,20,SHORT,29,7,0,58 +3085940,20,SHORT,30,-11,-7,191 +3085942,20,SHORT,31,-8,-16,329 +3085944,20,SHORT,32,8,9,156 +3085946,20,SHORT,33,-6,6,80 +3085948,20,SHORT,34,7,8,141 +3085950,20,SHORT,35,1,2,8 +3085952,20,SHORT,36,0,-7,56 +3085954,20,SHORT,37,-2,16,265 +3085956,20,SHORT,38,4,-3,40 +3085958,20,SHORT,39,7,-6,95 +3085960,20,SHORT,40,5,-5,59 +3085962,20,SHORT,41,2,-5,42 +3085964,20,SHORT,42,2,-2,12 +3085966,20,SHORT,43,1,2,6 +3085968,20,SHORT,44,4,5,48 +3085970,20,SHORT,45,-10,0,105 +3085972,20,SHORT,46,7,-7,102 +3085974,20,SHORT,47,-1,4,18 +3085976,20,SHORT,48,-10,1,112 +3085978,20,SHORT,49,0,3,14 +3085980,20,SHORT,50,4,0,22 +3085982,20,SHORT,51,3,0,14 +3085984,20,SHORT,52,-2,-2,13 +3085986,20,SHORT,53,-4,-6,63 +3085988,20,SHORT,54,-12,-4,164 +3085990,20,SHORT,55,-1,-1,3 +3085992,20,SHORT,56,-5,2,33 +3085994,20,SHORT,57,4,-5,54 +3085996,20,SHORT,58,0,-2,9 +3085998,20,SHORT,59,0,-10,107 +3086000,20,SHORT,60,-3,-5,36 +3086002,20,SHORT,61,-5,2,32 +3086004,20,SHORT,62,2,-2,12 +3086006,20,SHORT,63,0,-1,3 +3086008,20,SHORT,64,-2,3,14 +3086010,20,SHORT,65,-7,5,85 +3086012,20,SHORT,66,-1,11,126 +3086014,20,SHORT,67,0,-2,9 +3086016,20,SHORT,68,51,24,3200 +3086018,20,SHORT,69,33,28,1921 +3086020,20,SHORT,70,34,40,2806 +3086022,20,SHORT,71,23,53,3432 +3086024,20,SHORT,72,16,54,3209 +3086026,20,SHORT,73,1,62,3884 +3086028,20,SHORT,74,-6,57,3363 +3086030,20,SHORT,75,-13,44,2175 +3086032,20,SHORT,76,-24,42,2450 +3086034,20,SHORT,77,-44,33,3069 +3086036,20,SHORT,78,-49,29,3325 +3086038,20,SHORT,79,-53,11,2967 +3086040,20,SHORT,80,-59,1,3537 +3086042,20,SHORT,81,-63,-3,4102 +3086044,20,SHORT,82,-50,-18,2914 +3086046,20,SHORT,83,4,-1,17 +3086048,20,SHORT,84,-1,4,26 +3086050,20,SHORT,85,0,1,3 +3086052,20,SHORT,86,10,6,155 +3086054,20,SHORT,87,6,1,44 +3086056,20,SHORT,88,-2,-1,6 +3086058,20,SHORT,89,3,-2,14 +3086060,20,SHORT,90,0,-6,48 +3086062,20,SHORT,91,-7,-1,57 +3086064,20,SHORT,92,5,-1,37 +3086066,20,SHORT,93,5,-5,55 +3086068,20,SHORT,94,4,6,65 +3086070,20,SHORT,95,14,2,228 +3086072,20,SHORT,96,-6,5,68 +3086074,20,SHORT,97,2,-1,11 +3086076,20,SHORT,98,0,-4,20 +3086078,20,SHORT,99,-1,5,27 +3086080,20,SHORT,100,3,-1,12 +3086082,20,SHORT,101,-1,7,54 +3086084,20,SHORT,102,-3,-2,23 +3086086,20,SHORT,103,-1,0,3 +3086088,20,SHORT,104,0,0,0 +3086090,20,SHORT,105,4,-3,32 +3086092,20,SHORT,106,-5,3,41 +3086094,20,SHORT,107,4,-3,32 +3086096,20,SHORT,108,-6,5,62 +3086098,20,SHORT,109,-3,2,15 +3086100,20,SHORT,110,2,-1,8 +3086102,20,SHORT,111,-4,2,31 +3086104,20,SHORT,112,10,1,120 +3086106,20,SHORT,113,-6,0,46 +3086108,20,SHORT,114,-1,-4,21 +3086110,20,SHORT,115,-3,2,17 +3086112,20,SHORT,116,-2,0,6 +3086114,20,SHORT,117,3,3,21 +3086116,20,SHORT,118,4,30,942 +3086118,20,SHORT,119,0,34,1203 +3086120,20,SHORT,120,-15,24,856 +3086122,20,SHORT,121,-17,13,485 +3086124,20,SHORT,122,-25,17,933 +3086126,20,SHORT,123,-17,14,529 +3086128,20,SHORT,124,-28,8,905 +3086130,20,SHORT,125,-26,3,704 +3086132,20,SHORT,126,-30,-4,961 +3086134,20,SHORT,127,-23,-9,658 +3086136,20,SHORT,128,-25,-13,819 +3086138,20,SHORT,129,-13,-12,332 +3086140,20,SHORT,130,-20,-24,1031 +3086142,20,SHORT,131,-9,-25,739 +3086144,20,SHORT,132,-2,-20,428 +3086146,20,SHORT,133,0,-9,86 +3086148,20,SHORT,134,-2,0,5 +3086150,20,SHORT,135,-8,-1,66 +3086152,20,SHORT,136,5,0,28 +3086154,20,SHORT,137,-4,-8,95 +3086156,20,SHORT,138,7,2,62 +3086158,20,SHORT,139,1,2,7 +3086160,20,SHORT,140,2,6,43 +3086162,20,SHORT,141,-3,4,31 +3086164,20,SHORT,142,2,-13,200 +3086166,20,SHORT,143,7,0,54 +3086168,20,SHORT,144,-1,-1,6 +3086170,20,SHORT,145,1,0,1 +3086172,20,SHORT,146,1,3,17 +3086174,20,SHORT,147,3,-3,21 +3086176,20,SHORT,148,0,-3,14 +3086178,20,SHORT,149,6,6,82 +3086180,20,SHORT,150,-5,2,38 +3086182,20,SHORT,151,6,-1,39 +3086184,20,SHORT,152,7,2,63 +3086186,20,SHORT,153,-4,-1,21 +3086188,20,SHORT,154,-3,-1,17 +3086190,20,SHORT,155,3,2,19 +3086192,20,SHORT,156,2,-3,16 +3086194,20,SHORT,157,0,-3,13 +3086196,20,SHORT,158,-3,3,23 +3086198,20,SHORT,159,-4,9,108 +3086200,20,SHORT,160,3,6,50 +3086202,20,SHORT,161,-1,0,1 +3086204,20,SHORT,162,-5,-6,66 +3086206,20,SHORT,163,0,1,3 +3086208,20,SHORT,164,0,3,14 +3086210,20,SHORT,165,7,-2,65 +3086212,20,SHORT,166,2,1,8 +3086214,20,SHORT,167,5,-11,169 +3086216,20,SHORT,168,2,2,12 +3086218,20,SHORT,169,-9,-7,143 +3086220,20,SHORT,170,5,-11,162 +3086222,20,SHORT,171,-1,9,93 +3086224,20,SHORT,172,-5,1,29 +3086226,20,SHORT,173,2,-8,84 +3086228,20,SHORT,174,-5,0,25 +3086230,20,SHORT,175,3,0,12 +3086232,20,SHORT,176,-4,-6,60 +3086234,20,SHORT,177,2,0,7 +3086236,20,SHORT,178,11,3,131 +3086238,20,SHORT,179,-1,5,35 +3086240,20,SHORT,180,2,-13,180 +3086242,20,SHORT,181,-9,-2,104 +3086244,20,SHORT,182,-5,9,129 +3086246,20,SHORT,183,0,3,11 +3086248,20,SHORT,184,4,-10,127 +3086250,20,SHORT,185,-1,-8,73 +3086252,20,SHORT,186,-2,5,33 +3086254,20,SHORT,187,3,-1,13 +3086256,20,SHORT,188,0,-2,5 +3086258,20,SHORT,189,-4,-8,88 +3086260,20,SHORT,190,2,3,18 +3086262,20,SHORT,191,-3,0,10 +3086264,20,SHORT,192,-3,11,148 +3086266,20,SHORT,193,9,1,86 +3086268,20,SHORT,194,20,-6,473 +3086270,20,SHORT,195,12,10,268 +3086272,20,SHORT,196,10,9,216 +3086274,20,SHORT,197,8,8,158 +3086276,20,SHORT,198,10,15,344 +3086278,20,SHORT,199,-1,15,248 +3086280,20,SHORT,200,2,26,703 +3086282,20,SHORT,201,1,8,80 +3086284,20,SHORT,202,-1,18,330 +3086286,20,SHORT,203,-7,13,252 +3086288,20,SHORT,204,-5,15,264 +3086290,20,SHORT,205,-6,8,105 +3086292,20,SHORT,206,-8,0,69 +3086294,20,SHORT,207,-10,0,108 +3086296,20,SHORT,208,-2,4,22 +3086298,20,SHORT,209,-9,0,83 +3086300,20,SHORT,210,-6,0,46 +3086302,20,SHORT,211,8,0,64 +3086304,20,SHORT,212,-2,3,19 +3086306,20,SHORT,213,-6,-5,67 +3086308,20,SHORT,214,10,-2,109 +3086310,20,SHORT,215,8,-7,116 +3086312,20,SHORT,216,0,-7,57 +3086314,20,SHORT,217,3,14,219 +3086316,20,SHORT,218,9,-1,91 +3086318,20,SHORT,219,2,1,7 +3086320,20,SHORT,220,-5,2,32 +3086322,20,SHORT,221,0,5,29 +3086324,20,SHORT,222,2,4,31 +3086326,20,SHORT,223,0,2,8 +3086328,20,SHORT,224,10,-2,120 +3086330,20,SHORT,225,2,0,7 +3086332,20,SHORT,226,0,5,26 +3086334,20,SHORT,227,-4,3,36 +3086336,20,SHORT,228,-1,-1,5 +3086338,20,SHORT,229,-6,0,37 +3086340,20,SHORT,230,3,-1,13 +3086342,20,SHORT,231,6,2,45 +3086344,20,SHORT,232,-4,2,27 +3086346,20,SHORT,233,-1,-2,10 +3086348,20,SHORT,234,7,-2,63 +3086350,20,SHORT,235,7,-1,64 +3086352,20,SHORT,236,1,9,95 +3086354,20,SHORT,237,-2,-5,33 +3086356,20,SHORT,238,-7,3,60 +3086358,20,SHORT,239,0,-3,11 +3086360,20,SHORT,240,-2,-3,14 +3086362,20,SHORT,241,3,-2,20 +3086364,20,SHORT,242,-3,0,12 +3086366,20,SHORT,243,-6,6,77 +3086368,20,SHORT,244,-2,2,8 +3086370,20,SHORT,245,-4,-6,68 +3086372,20,SHORT,246,-1,-9,93 +3086374,20,SHORT,247,1,3,11 +3086376,20,SHORT,248,0,6,39 +3086378,20,SHORT,249,-3,-5,41 +3086380,20,SHORT,250,4,10,133 +3086382,20,SHORT,251,4,-7,78 +3086384,20,SHORT,252,4,9,100 +3086386,20,SHORT,253,-4,4,42 +3086388,20,SHORT,254,-4,-3,39 +3086390,20,SHORT,255,7,12,198 +3086392,20,SHORT,256,8,-4,96 +3086394,20,SHORT,257,4,4,40 +3086396,20,SHORT,258,-3,1,17 +3086398,20,SHORT,259,0,-7,64 +3086400,20,SHORT,260,5,3,39 +3086402,20,SHORT,261,-2,5,31 +3086404,20,SHORT,262,-4,-5,51 +3086406,20,SHORT,263,-3,5,43 +3086408,20,SHORT,264,-2,5,33 +3086410,20,SHORT,265,4,-4,38 +3086412,20,SHORT,266,0,-3,10 +3086414,20,SHORT,267,-1,-7,64 +3086416,20,SHORT,268,2,-1,6 +3086418,20,SHORT,269,-2,0,7 +3086420,20,SHORT,270,6,-4,54 +3086422,20,SHORT,271,-3,0,11 +3086424,20,SHORT,272,1,-1,3 +3086426,20,SHORT,273,-2,1,7 +3086428,20,SHORT,274,-15,4,260 +3086430,20,SHORT,275,-8,0,77 +3086432,20,SHORT,276,3,-3,25 +3086434,20,SHORT,277,0,6,46 +3086436,20,SHORT,278,5,3,38 +3086438,20,SHORT,279,2,0,8 +3086440,20,SHORT,280,-4,0,17 +3086442,20,SHORT,281,4,0,18 +3086444,20,SHORT,282,5,0,29 +3086446,20,SHORT,283,9,-7,148 +3086448,20,SHORT,284,-5,-3,41 +3086450,20,SHORT,285,-9,-5,121 +3086452,20,SHORT,286,-3,3,23 +3086454,20,SHORT,287,-5,3,41 +3086456,20,SHORT,288,1,-1,3 +3086458,20,SHORT,289,-6,0,36 +3086460,20,SHORT,290,0,-5,34 +3086462,20,SHORT,291,-6,-5,73 +3086464,20,SHORT,292,1,0,2 +3086466,20,SHORT,293,4,-9,107 +3086468,20,SHORT,294,12,-2,153 +3086470,20,SHORT,295,10,-10,220 +3086472,20,SHORT,296,4,-2,31 +3086474,20,SHORT,297,3,-9,98 +3086476,20,SHORT,298,5,5,63 +3086478,20,SHORT,299,6,2,47 +3086480,20,SHORT,300,10,8,180 +3086482,20,SHORT,301,-3,0,15 +3086484,20,SHORT,302,3,8,81 +3086486,20,SHORT,303,4,9,116 +3086488,20,SHORT,304,-3,8,83 +3086490,20,SHORT,305,-7,16,322 +3086492,20,SHORT,306,-8,12,232 +3086494,20,SHORT,307,1,11,134 +3086496,20,SHORT,308,2,9,101 +3086498,20,SHORT,309,-2,-4,27 +3086500,20,SHORT,310,-7,4,82 +3086502,20,SHORT,311,10,-10,222 +3086504,20,SHORT,312,4,-8,95 +3086506,20,SHORT,313,-2,2,16 +3086508,20,SHORT,314,4,-5,58 +3086510,20,SHORT,315,0,13,191 +3086512,20,SHORT,316,0,-3,10 +3086514,20,SHORT,317,6,4,57 +3086516,20,SHORT,318,-7,8,132 +3086518,20,SHORT,319,2,3,16 +3086520,20,SHORT,320,1,9,99 +3086522,20,SHORT,321,-3,4,32 +3086524,20,SHORT,322,3,-4,28 +3086526,20,SHORT,323,-6,-5,65 +3086528,20,SHORT,324,-2,-1,6 +3086530,20,SHORT,325,0,-2,7 +3086532,20,SHORT,326,-4,5,50 +3086534,20,SHORT,327,-4,2,27 +3086536,20,SHORT,328,-4,-1,19 +3086538,20,SHORT,329,3,3,18 +3086540,20,SHORT,330,0,7,51 +3086542,20,SHORT,331,-1,-3,11 +3086544,20,SHORT,332,5,0,28 +3086546,20,SHORT,333,0,-3,11 +3086548,20,SHORT,334,-3,-2,16 +3086550,20,SHORT,335,7,0,55 +3086552,20,SHORT,336,-3,-2,21 +3086554,20,SHORT,337,-13,-2,199 +3086556,20,SHORT,338,0,0,0 +3086558,20,SHORT,339,0,-1,1 +3086560,20,SHORT,340,-2,-1,7 +3086562,20,SHORT,341,-2,0,9 +3086564,20,SHORT,342,1,-7,60 +3086566,20,SHORT,343,0,-3,13 +3086568,20,SHORT,344,-6,7,87 +3086570,20,SHORT,345,-2,2,11 +3086572,20,SHORT,346,-1,0,3 +3086574,20,SHORT,347,-1,2,11 +3086576,20,SHORT,348,-3,-3,20 +3086578,20,SHORT,349,-2,-2,9 +3086580,20,SHORT,350,-1,-1,4 +3086582,20,SHORT,351,9,4,112 +3086584,20,SHORT,352,4,4,41 +3086586,20,SHORT,353,-1,8,76 +3086588,20,SHORT,354,-1,9,97 +3086590,20,SHORT,355,0,-1,2 +3086592,20,SHORT,356,0,-4,21 +3086594,20,SHORT,357,-9,1,85 +3086596,20,SHORT,358,2,-1,7 +3086598,20,SHORT,359,-1,4,24 +3086600,20,SHORT,360,-2,0,6 +3086602,20,SHORT,361,0,-5,34 +3086604,20,SHORT,362,5,-1,36 +3086606,20,SHORT,363,-2,0,6 +3086608,20,SHORT,364,2,0,6 +3086610,20,SHORT,365,0,6,42 +3086612,20,SHORT,366,-2,-9,99 +3086614,20,SHORT,367,-1,3,12 +3086616,20,SHORT,368,-2,3,18 +3086618,20,SHORT,369,2,-4,25 +3086620,20,SHORT,370,-6,-7,90 +3086622,20,SHORT,371,0,0,0 +3086624,20,SHORT,372,-2,3,18 +3086626,20,SHORT,373,3,-1,16 +3086628,20,SHORT,374,-4,7,72 +3086630,20,SHORT,375,-2,-1,8 +3086632,20,SHORT,376,-1,0,1 +3086634,20,SHORT,377,2,0,6 +3086636,20,SHORT,378,4,-9,107 +3086638,20,SHORT,379,-4,-1,28 +3086640,20,SHORT,380,-2,7,68 +3086642,20,SHORT,381,-2,-2,15 +3086644,20,SHORT,382,0,0,0 +3086646,20,SHORT,383,-4,3,32 +3086648,20,SHORT,384,3,2,14 +3086650,20,SHORT,385,1,-9,88 +3086652,20,SHORT,386,-2,0,5 +3086654,20,SHORT,387,7,1,65 +3086656,20,SHORT,388,-1,1,2 +3086658,20,SHORT,389,1,4,22 +3086660,20,SHORT,390,0,2,4 +3086662,20,SHORT,391,7,-2,58 +3086664,20,SHORT,392,-10,3,121 +3086666,20,SHORT,393,1,0,3 +3086668,20,SHORT,394,0,3,12 +3086670,20,SHORT,395,-6,6,81 +3086672,20,SHORT,396,3,7,62 +3086674,20,SHORT,397,-6,6,85 +3086676,20,SHORT,398,0,-9,86 +3086678,20,SHORT,399,6,2,50 +3086680,20,SHORT,400,-7,-9,143 +3086682,20,SHORT,401,-5,0,34 +3086684,20,SHORT,402,0,2,6 +3086686,20,SHORT,403,3,8,84 +3086688,20,SHORT,404,8,0,76 +3086690,20,SHORT,405,5,-5,52 +3086692,20,SHORT,406,0,4,19 +3086694,20,SHORT,407,-3,4,36 +3086696,20,SHORT,408,-1,3,18 +3086698,20,SHORT,409,-4,-6,67 +3086700,20,SHORT,410,3,-6,51 +3086702,20,SHORT,411,0,0,0 +3086704,20,SHORT,412,2,0,4 +3086706,20,SHORT,413,-1,-2,11 +3086708,20,SHORT,414,0,-2,8 +3086710,20,SHORT,415,0,-6,45 +3086712,20,SHORT,416,-5,0,35 +3086714,20,SHORT,417,-3,4,31 +3086716,20,SHORT,418,-3,-2,19 +3086718,20,SHORT,419,3,-9,103 +3086720,20,SHORT,420,3,-1,11 +3086722,20,SHORT,421,-10,11,233 +3086724,20,SHORT,422,1,-9,97 +3086726,20,SHORT,423,7,3,65 +3086728,20,SHORT,424,0,0,1 +3086730,20,SHORT,425,2,-4,29 +3086732,20,SHORT,426,3,1,16 +3086734,20,SHORT,427,2,-2,10 +3086736,20,SHORT,428,6,-2,50 +3086738,20,SHORT,429,4,3,35 +3086740,20,SHORT,430,0,2,6 +3086742,20,SHORT,431,-6,-5,77 +3086744,20,SHORT,432,0,-1,1 +3086746,20,SHORT,433,4,4,42 +3086748,20,SHORT,434,6,0,46 +3086750,20,SHORT,435,5,-4,49 +3086752,20,SHORT,436,5,-1,36 +3086754,20,SHORT,437,-4,1,21 +3086756,20,SHORT,438,5,-7,84 +3086758,20,SHORT,439,-9,2,94 +3086760,20,SHORT,440,0,-2,6 +3086762,20,SHORT,441,-3,-1,16 +3086764,20,SHORT,442,-2,9,101 +3086766,20,SHORT,443,-4,7,75 +3086768,20,SHORT,444,-6,4,64 +3086770,20,SHORT,445,3,-7,75 +3086772,20,SHORT,446,0,8,76 +3086774,20,SHORT,447,-5,7,79 +3086776,20,SHORT,448,-3,-4,39 +3086778,20,SHORT,449,-1,2,9 +3086780,20,SHORT,450,12,3,161 +3086782,20,SHORT,451,-1,0,2 +3086784,20,SHORT,452,0,2,8 +3086786,20,SHORT,453,8,0,68 +3086788,20,SHORT,454,1,1,3 +3086790,20,SHORT,455,0,2,5 +3086792,20,SHORT,456,-6,2,44 +3086794,20,SHORT,457,6,-1,51 +3086796,20,SHORT,458,6,4,68 +3086798,20,SHORT,459,-1,-3,14 +3086800,20,SHORT,460,3,0,9 +3086802,20,SHORT,461,-1,3,17 +3086804,20,SHORT,462,-5,-7,80 +3086806,20,SHORT,463,-3,4,33 +3086808,20,SHORT,464,9,-1,97 +3086810,20,SHORT,465,0,2,5 +3086812,20,SHORT,466,6,-5,78 +3086814,20,SHORT,467,-5,-7,87 +3086816,20,SHORT,468,0,-3,12 +3086818,20,SHORT,469,8,6,122 +3086820,20,SHORT,470,0,5,28 +3086822,20,SHORT,471,2,0,6 +3086824,20,SHORT,472,0,-3,10 +3086826,20,SHORT,473,-10,-2,116 +3086828,20,SHORT,474,0,-1,2 +3086830,20,SHORT,475,-10,-7,164 +3086832,20,SHORT,476,-1,-5,31 +3086834,20,SHORT,477,-2,-1,9 +3086836,20,SHORT,478,1,-3,13 +3086838,20,SHORT,479,5,-3,40 +3086840,20,SHORT,480,-3,3,26 +3086842,20,SHORT,481,-2,2,13 +3086844,20,SHORT,482,1,-7,51 +3086846,20,SHORT,483,0,1,1 +3086848,20,SHORT,484,0,-4,18 +3086850,20,SHORT,485,-4,-12,169 +3086852,20,SHORT,486,-2,0,5 +3086854,20,SHORT,487,0,-2,4 +3086856,20,SHORT,488,4,4,41 +3086858,20,SHORT,489,3,-6,58 +3086860,20,SHORT,490,-1,0,3 +3086862,20,SHORT,491,-4,-1,17 +3086864,20,SHORT,492,6,1,39 +3086866,20,SHORT,493,0,3,9 +3086868,20,SHORT,494,-3,-1,12 +3086870,20,SHORT,495,-8,-2,78 +3086872,20,SHORT,496,-1,-2,8 +3086874,20,SHORT,497,4,-1,20 +3086876,20,SHORT,498,0,6,39 +3086878,20,SHORT,499,0,-2,5 +3086880,20,SHORT,500,-1,6,44 +3086882,20,SHORT,501,-6,-3,57 +3086884,20,SHORT,502,0,6,38 +3086886,20,SHORT,503,6,-4,61 +3086888,20,SHORT,504,-4,-5,49 +3086890,20,SHORT,505,-1,-2,5 +3086892,20,SHORT,506,-4,1,22 +3086894,20,SHORT,507,7,6,104 +3086896,20,SHORT,508,-3,5,41 +3086898,20,SHORT,509,-3,1,17 +3086900,20,SHORT,510,6,0,39 +3086902,20,SHORT,511,-12,-12,323 +3261404,21,SHORT,0,12,-7,206 +3261406,21,SHORT,1,-2,-4,25 +3261408,21,SHORT,2,6,-2,45 +3261410,21,SHORT,3,20,1,439 +3261412,21,SHORT,4,-15,6,266 +3261414,21,SHORT,5,-6,-7,90 +3261416,21,SHORT,6,10,5,144 +3261418,21,SHORT,7,0,-6,41 +3261420,21,SHORT,8,0,11,141 +3261422,21,SHORT,9,0,6,41 +3261424,21,SHORT,10,-4,-7,80 +3261426,21,SHORT,11,-8,-5,101 +3261428,21,SHORT,12,6,-6,76 +3261430,21,SHORT,13,1,13,195 +3261432,21,SHORT,14,10,-5,144 +3261434,21,SHORT,15,5,-3,36 +3261436,21,SHORT,16,-1,-7,55 +3261438,21,SHORT,17,0,0,1 +3261440,21,SHORT,18,4,-3,33 +3261442,21,SHORT,19,0,-6,43 +3261444,21,SHORT,20,-7,17,351 +3261446,21,SHORT,21,2,9,104 +3261448,21,SHORT,22,-8,6,115 +3261450,21,SHORT,23,-19,-7,425 +3261452,21,SHORT,24,6,8,125 +3261454,21,SHORT,25,10,3,115 +3261456,21,SHORT,26,-2,-4,28 +3261458,21,SHORT,27,9,15,331 +3261460,21,SHORT,28,-6,-7,106 +3261462,21,SHORT,29,11,-2,142 +3261464,21,SHORT,30,-2,-6,45 +3261466,21,SHORT,31,7,-8,117 +3261468,21,SHORT,32,-10,0,117 +3261470,21,SHORT,33,-2,9,100 +3261472,21,SHORT,34,4,7,68 +3261474,21,SHORT,35,4,10,127 +3261476,21,SHORT,36,-7,2,58 +3261478,21,SHORT,37,-7,-7,112 +3261480,21,SHORT,38,-8,9,156 +3261482,21,SHORT,39,1,11,137 +3261484,21,SHORT,40,17,0,313 +3261486,21,SHORT,41,-4,0,22 +3261488,21,SHORT,42,9,-2,98 +3261490,21,SHORT,43,-12,3,160 +3261492,21,SHORT,44,-5,6,66 +3261494,21,SHORT,45,-4,-7,70 +3261496,21,SHORT,46,4,4,41 +3261498,21,SHORT,47,-8,2,87 +3261500,21,SHORT,48,18,8,412 +3261502,21,SHORT,49,0,8,69 +3261504,21,SHORT,50,0,2,6 +3261506,21,SHORT,51,-8,2,76 +3261508,21,SHORT,52,-8,-2,72 +3261510,21,SHORT,53,0,2,6 +3261512,21,SHORT,54,0,7,60 +3261514,21,SHORT,55,-1,1,4 +3261516,21,SHORT,56,5,0,33 +3261518,21,SHORT,57,2,-6,53 +3261520,21,SHORT,58,-3,-9,91 +3261522,21,SHORT,59,10,1,121 +3261524,21,SHORT,60,-1,0,3 +3261526,21,SHORT,61,-3,-1,13 +3261528,21,SHORT,62,4,-7,84 +3261530,21,SHORT,63,11,0,129 +3261532,21,SHORT,64,1,0,2 +3261534,21,SHORT,65,-1,-1,4 +3261536,21,SHORT,66,-2,-6,52 +3261538,21,SHORT,67,0,11,122 +3261540,21,SHORT,68,-44,38,3461 +3261542,21,SHORT,69,-44,29,2823 +3261544,21,SHORT,70,-42,25,2470 +3261546,21,SHORT,71,-55,-7,3078 +3261548,21,SHORT,72,-57,-8,3322 +3261550,21,SHORT,73,-55,-17,3421 +3261552,21,SHORT,74,-50,-34,3659 +3261554,21,SHORT,75,-40,-41,3400 +3261556,21,SHORT,76,-42,-41,3485 +3261558,21,SHORT,77,-25,-54,3647 +3261560,21,SHORT,78,-5,-64,4140 +3261562,21,SHORT,79,3,-57,3292 +3261564,21,SHORT,80,22,-54,3509 +3261566,21,SHORT,81,23,-47,2830 +3261568,21,SHORT,82,33,-42,2986 +3261570,21,SHORT,83,-2,5,40 +3261572,21,SHORT,84,3,-4,26 +3261574,21,SHORT,85,5,12,198 +3261576,21,SHORT,86,-3,0,13 +3261578,21,SHORT,87,0,0,0 +3261580,21,SHORT,88,-5,0,27 +3261582,21,SHORT,89,1,-2,9 +3261584,21,SHORT,90,-4,-1,24 +3261586,21,SHORT,91,3,-4,31 +3261588,21,SHORT,92,0,1,1 +3261590,21,SHORT,93,-3,-5,36 +3261592,21,SHORT,94,8,-4,82 +3261594,21,SHORT,95,-1,-5,30 +3261596,21,SHORT,96,0,0,0 +3261598,21,SHORT,97,-1,-8,82 +3261600,21,SHORT,98,0,4,22 +3261602,21,SHORT,99,-5,1,32 +3261604,21,SHORT,100,0,0,0 +3261606,21,SHORT,101,0,6,46 +3261608,21,SHORT,102,-7,0,55 +3261610,21,SHORT,103,5,-11,166 +3261612,21,SHORT,104,-6,7,98 +3261614,21,SHORT,105,0,-1,3 +3261616,21,SHORT,106,2,1,10 +3261618,21,SHORT,107,-5,3,46 +3261620,21,SHORT,108,-3,4,29 +3261622,21,SHORT,109,-3,1,17 +3261624,21,SHORT,110,4,-5,49 +3261626,21,SHORT,111,0,2,5 +3261628,21,SHORT,112,-2,-2,12 +3261630,21,SHORT,113,0,9,85 +3261632,21,SHORT,114,-1,1,3 +3261634,21,SHORT,115,2,-2,12 +3261636,21,SHORT,116,-9,-5,119 +3261638,21,SHORT,117,-6,6,93 +3261640,21,SHORT,118,27,6,772 +3261642,21,SHORT,119,20,19,801 +3261644,21,SHORT,120,9,13,272 +3261646,21,SHORT,121,20,25,1056 +3261648,21,SHORT,122,6,21,515 +3261650,21,SHORT,123,1,12,168 +3261652,21,SHORT,124,0,26,682 +3261654,21,SHORT,125,-6,28,846 +3261656,21,SHORT,126,-8,31,1091 +3261658,21,SHORT,127,-22,37,1927 +3261660,21,SHORT,128,-21,17,789 +3261662,21,SHORT,129,-28,9,924 +3261664,21,SHORT,130,-19,15,620 +3261666,21,SHORT,131,-26,3,737 +3261668,21,SHORT,132,-16,-4,291 +3261670,21,SHORT,133,-6,2,43 +3261672,21,SHORT,134,0,-3,13 +3261674,21,SHORT,135,8,0,77 +3261676,21,SHORT,136,-1,2,9 +3261678,21,SHORT,137,-4,1,25 +3261680,21,SHORT,138,-6,1,40 +3261682,21,SHORT,139,7,5,86 +3261684,21,SHORT,140,-3,5,37 +3261686,21,SHORT,141,-7,-3,73 +3261688,21,SHORT,142,-2,0,4 +3261690,21,SHORT,143,6,0,45 +3261692,21,SHORT,144,-4,-2,24 +3261694,21,SHORT,145,4,1,28 +3261696,21,SHORT,146,2,4,28 +3261698,21,SHORT,147,6,4,65 +3261700,21,SHORT,148,0,3,12 +3261702,21,SHORT,149,0,0,0 +3261704,21,SHORT,150,-9,-2,90 +3261706,21,SHORT,151,-1,-1,5 +3261708,21,SHORT,152,13,7,241 +3261710,21,SHORT,153,-7,11,195 +3261712,21,SHORT,154,-3,8,82 +3261714,21,SHORT,155,3,-3,23 +3261716,21,SHORT,156,3,-2,20 +3261718,21,SHORT,157,1,-2,8 +3261720,21,SHORT,158,-1,0,2 +3261722,21,SHORT,159,-4,-3,37 +3261724,21,SHORT,160,-1,-7,56 +3261726,21,SHORT,161,0,-5,32 +3261728,21,SHORT,162,0,-6,40 +3261730,21,SHORT,163,-3,-2,16 +3261732,21,SHORT,164,-10,-5,135 +3261734,21,SHORT,165,0,-2,8 +3261736,21,SHORT,166,1,1,3 +3261738,21,SHORT,167,3,-5,45 +3261740,21,SHORT,168,9,-7,155 +3261742,21,SHORT,169,-6,0,37 +3261744,21,SHORT,170,-5,1,37 +3261746,21,SHORT,171,-1,1,4 +3261748,21,SHORT,172,-12,7,223 +3261750,21,SHORT,173,0,-5,28 +3261752,21,SHORT,174,0,3,11 +3261754,21,SHORT,175,-1,-1,4 +3261756,21,SHORT,176,-2,11,146 +3261758,21,SHORT,177,-2,4,28 +3261760,21,SHORT,178,-1,3,16 +3261762,21,SHORT,179,-11,6,161 +3261764,21,SHORT,180,-3,3,25 +3261766,21,SHORT,181,0,-1,2 +3261768,21,SHORT,182,0,3,14 +3261770,21,SHORT,183,-1,-3,13 +3261772,21,SHORT,184,2,-9,105 +3261774,21,SHORT,185,1,8,77 +3261776,21,SHORT,186,3,3,28 +3261778,21,SHORT,187,4,-3,32 +3261780,21,SHORT,188,2,-5,39 +3261782,21,SHORT,189,2,-8,86 +3261784,21,SHORT,190,1,5,27 +3261786,21,SHORT,191,3,10,130 +3261788,21,SHORT,192,3,-4,34 +3261790,21,SHORT,193,16,2,292 +3261792,21,SHORT,194,12,11,293 +3261794,21,SHORT,195,6,2,44 +3261796,21,SHORT,196,11,12,281 +3261798,21,SHORT,197,5,20,456 +3261800,21,SHORT,198,1,12,148 +3261802,21,SHORT,199,1,20,438 +3261804,21,SHORT,200,-4,11,156 +3261806,21,SHORT,201,-5,17,344 +3261808,21,SHORT,202,-13,8,247 +3261810,21,SHORT,203,-3,15,251 +3261812,21,SHORT,204,-18,10,429 +3261814,21,SHORT,205,-5,8,98 +3261816,21,SHORT,206,-11,-3,147 +3261818,21,SHORT,207,-17,-6,345 +3261820,21,SHORT,208,-3,-4,31 +3261822,21,SHORT,209,-1,-11,127 +3261824,21,SHORT,210,-1,2,6 +3261826,21,SHORT,211,-6,-7,95 +3261828,21,SHORT,212,0,1,1 +3261830,21,SHORT,213,3,4,34 +3261832,21,SHORT,214,-4,-2,26 +3261834,21,SHORT,215,5,7,93 +3261836,21,SHORT,216,-4,-5,53 +3261838,21,SHORT,217,-8,-3,78 +3261840,21,SHORT,218,4,-2,25 +3261842,21,SHORT,219,1,6,42 +3261844,21,SHORT,220,3,-1,13 +3261846,21,SHORT,221,5,7,93 +3261848,21,SHORT,222,9,-4,113 +3261850,21,SHORT,223,9,-3,99 +3261852,21,SHORT,224,-1,5,33 +3261854,21,SHORT,225,2,3,13 +3261856,21,SHORT,226,-3,-2,18 +3261858,21,SHORT,227,3,-1,14 +3261860,21,SHORT,228,2,-1,11 +3261862,21,SHORT,229,0,3,12 +3261864,21,SHORT,230,10,-3,127 +3261866,21,SHORT,231,-5,2,38 +3261868,21,SHORT,232,5,-7,92 +3261870,21,SHORT,233,0,-4,22 +3261872,21,SHORT,234,-3,-6,46 +3261874,21,SHORT,235,8,10,181 +3261876,21,SHORT,236,-2,2,12 +3261878,21,SHORT,237,-3,3,28 +3261880,21,SHORT,238,-2,-4,22 +3261882,21,SHORT,239,-9,-4,100 +3261884,21,SHORT,240,-4,4,40 +3261886,21,SHORT,241,3,7,67 +3261888,21,SHORT,242,1,2,7 +3261890,21,SHORT,243,5,1,33 +3261892,21,SHORT,244,0,-14,199 +3261894,21,SHORT,245,5,5,60 +3261896,21,SHORT,246,8,2,70 +3261898,21,SHORT,247,-10,3,114 +3261900,21,SHORT,248,-3,0,15 +3261902,21,SHORT,249,-3,3,25 +3261904,21,SHORT,250,5,-2,39 +3261906,21,SHORT,251,3,0,11 +3261908,21,SHORT,252,-8,0,77 +3261910,21,SHORT,253,7,-2,62 +3261912,21,SHORT,254,1,-3,16 +3261914,21,SHORT,255,-3,-5,37 +3261916,21,SHORT,256,1,-5,34 +3261918,21,SHORT,257,-2,2,11 +3261920,21,SHORT,258,6,-1,39 +3261922,21,SHORT,259,-3,-4,28 +3261924,21,SHORT,260,-4,1,19 +3261926,21,SHORT,261,2,6,44 +3261928,21,SHORT,262,4,-1,24 +3261930,21,SHORT,263,7,5,87 +3261932,21,SHORT,264,4,0,23 +3261934,21,SHORT,265,-4,-1,20 +3261936,21,SHORT,266,1,7,60 +3261938,21,SHORT,267,9,2,101 +3261940,21,SHORT,268,0,5,29 +3261942,21,SHORT,269,-8,-1,77 +3261944,21,SHORT,270,3,-5,45 +3261946,21,SHORT,271,2,-3,18 +3261948,21,SHORT,272,-7,7,117 +3261950,21,SHORT,273,0,0,0 +3261952,21,SHORT,274,-2,0,8 +3261954,21,SHORT,275,0,2,5 +3261956,21,SHORT,276,4,3,30 +3261958,21,SHORT,277,-5,0,29 +3261960,21,SHORT,278,-5,-2,37 +3261962,21,SHORT,279,-4,0,17 +3261964,21,SHORT,280,-4,-12,177 +3261966,21,SHORT,281,4,3,31 +3261968,21,SHORT,282,-6,0,44 +3261970,21,SHORT,283,0,3,9 +3261972,21,SHORT,284,5,-1,36 +3261974,21,SHORT,285,6,-4,56 +3261976,21,SHORT,286,9,-4,107 +3261978,21,SHORT,287,3,-3,25 +3261980,21,SHORT,288,0,-1,1 +3261982,21,SHORT,289,0,-7,61 +3261984,21,SHORT,290,-2,-2,11 +3261986,21,SHORT,291,9,10,192 +3261988,21,SHORT,292,0,-5,35 +3261990,21,SHORT,293,0,-1,2 +3261992,21,SHORT,294,3,-5,39 +3261994,21,SHORT,295,4,0,22 +3261996,21,SHORT,296,8,-3,78 +3261998,21,SHORT,297,10,-6,156 +3262000,21,SHORT,298,5,-3,39 +3262002,21,SHORT,299,10,0,103 +3262004,21,SHORT,300,3,9,101 +3262006,21,SHORT,301,17,1,296 +3262008,21,SHORT,302,6,-6,92 +3262010,21,SHORT,303,0,-3,12 +3262012,21,SHORT,304,11,5,165 +3262014,21,SHORT,305,3,8,83 +3262016,21,SHORT,306,2,10,126 +3262018,21,SHORT,307,0,10,108 +3262020,21,SHORT,308,8,-2,74 +3262022,21,SHORT,309,-3,-3,21 +3262024,21,SHORT,310,0,-2,4 +3262026,21,SHORT,311,2,-2,12 +3262028,21,SHORT,312,-1,10,103 +3262030,21,SHORT,313,3,0,9 +3262032,21,SHORT,314,11,3,142 +3262034,21,SHORT,315,6,5,80 +3262036,21,SHORT,316,-3,-1,17 +3262038,21,SHORT,317,0,6,40 +3262040,21,SHORT,318,-8,-1,70 +3262042,21,SHORT,319,10,-7,160 +3262044,21,SHORT,320,-8,8,148 +3262046,21,SHORT,321,0,8,73 +3262048,21,SHORT,322,5,-8,106 +3262050,21,SHORT,323,0,0,0 +3262052,21,SHORT,324,-3,3,30 +3262054,21,SHORT,325,12,-3,179 +3262056,21,SHORT,326,0,2,7 +3262058,21,SHORT,327,-1,3,16 +3262060,21,SHORT,328,0,-3,14 +3262062,21,SHORT,329,-3,4,34 +3262064,21,SHORT,330,-2,0,8 +3262066,21,SHORT,331,-8,-4,101 +3262068,21,SHORT,332,5,-4,45 +3262070,21,SHORT,333,-6,5,72 +3262072,21,SHORT,334,-4,1,19 +3262074,21,SHORT,335,-10,3,123 +3262076,21,SHORT,336,5,5,60 +3262078,21,SHORT,337,-4,3,32 +3262080,21,SHORT,338,-10,7,181 +3262082,21,SHORT,339,-5,-5,58 +3262084,21,SHORT,340,-2,3,22 +3262086,21,SHORT,341,-3,2,19 +3262088,21,SHORT,342,10,1,109 +3262090,21,SHORT,343,-2,-3,19 +3262092,21,SHORT,344,7,3,60 +3262094,21,SHORT,345,5,8,96 +3262096,21,SHORT,346,-1,4,22 +3262098,21,SHORT,347,-1,2,10 +3262100,21,SHORT,348,-2,0,4 +3262102,21,SHORT,349,-3,-3,23 +3262104,21,SHORT,350,-4,-4,45 +3262106,21,SHORT,351,0,0,0 +3262108,21,SHORT,352,3,1,10 +3262110,21,SHORT,353,3,1,13 +3262112,21,SHORT,354,0,3,9 +3262114,21,SHORT,355,-1,0,1 +3262116,21,SHORT,356,4,-5,45 +3262118,21,SHORT,357,9,-2,96 +3262120,21,SHORT,358,3,-7,65 +3262122,21,SHORT,359,-7,0,55 +3262124,21,SHORT,360,-7,-9,147 +3262126,21,SHORT,361,-2,0,8 +3262128,21,SHORT,362,-1,3,15 +3262130,21,SHORT,363,-1,-5,33 +3262132,21,SHORT,364,-7,4,70 +3262134,21,SHORT,365,-4,-1,22 +3262136,21,SHORT,366,-4,0,19 +3262138,21,SHORT,367,2,0,8 +3262140,21,SHORT,368,3,-8,94 +3262142,21,SHORT,369,0,5,33 +3262144,21,SHORT,370,-9,-1,95 +3262146,21,SHORT,371,-6,0,46 +3262148,21,SHORT,372,-1,-5,30 +3262150,21,SHORT,373,-1,5,33 +3262152,21,SHORT,374,1,-10,104 +3262154,21,SHORT,375,5,4,55 +3262156,21,SHORT,376,0,10,116 +3262158,21,SHORT,377,-1,-10,115 +3262160,21,SHORT,378,0,-7,60 +3262162,21,SHORT,379,0,-1,2 +3262164,21,SHORT,380,1,-2,5 +3262166,21,SHORT,381,0,-8,77 +3262168,21,SHORT,382,-8,-10,174 +3262170,21,SHORT,383,3,-3,21 +3262172,21,SHORT,384,-2,-2,13 +3262174,21,SHORT,385,-1,2,10 +3262176,21,SHORT,386,0,-9,93 +3262178,21,SHORT,387,0,0,0 +3262180,21,SHORT,388,-11,3,133 +3262182,21,SHORT,389,0,-8,66 +3262184,21,SHORT,390,9,0,83 +3262186,21,SHORT,391,-7,-9,136 +3262188,21,SHORT,392,2,-2,12 +3262190,21,SHORT,393,0,7,54 +3262192,21,SHORT,394,3,6,59 +3262194,21,SHORT,395,6,7,92 +3262196,21,SHORT,396,-2,3,17 +3262198,21,SHORT,397,-8,-8,134 +3262200,21,SHORT,398,3,-2,17 +3262202,21,SHORT,399,-2,-2,12 +3262204,21,SHORT,400,0,-3,11 +3262206,21,SHORT,401,-7,-2,61 +3262208,21,SHORT,402,-1,-3,12 +3262210,21,SHORT,403,-3,0,10 +3262212,21,SHORT,404,5,5,56 +3262214,21,SHORT,405,3,0,14 +3262216,21,SHORT,406,-7,2,64 +3262218,21,SHORT,407,8,-1,67 +3262220,21,SHORT,408,5,-5,55 +3262222,21,SHORT,409,-9,1,84 +3262224,21,SHORT,410,-3,0,12 +3262226,21,SHORT,411,4,-12,173 +3262228,21,SHORT,412,-3,-1,15 +3262230,21,SHORT,413,3,5,41 +3262232,21,SHORT,414,-8,2,76 +3262234,21,SHORT,415,7,-3,65 +3262236,21,SHORT,416,1,10,117 +3262238,21,SHORT,417,0,2,7 +3262240,21,SHORT,418,6,0,39 +3262242,21,SHORT,419,2,-1,7 +3262244,21,SHORT,420,3,-2,18 +3262246,21,SHORT,421,-2,0,7 +3262248,21,SHORT,422,6,-3,56 +3262250,21,SHORT,423,0,3,15 +3262252,21,SHORT,424,-1,3,15 +3262254,21,SHORT,425,8,-8,151 +3262256,21,SHORT,426,-2,-2,13 +3262258,21,SHORT,427,-1,-1,5 +3262260,21,SHORT,428,0,12,152 +3262262,21,SHORT,429,-3,2,14 +3262264,21,SHORT,430,-9,-4,104 +3262266,21,SHORT,431,4,4,38 +3262268,21,SHORT,432,6,9,122 +3262270,21,SHORT,433,-1,3,16 +3262272,21,SHORT,434,0,5,25 +3262274,21,SHORT,435,-1,13,190 +3262276,21,SHORT,436,-1,5,34 +3262278,21,SHORT,437,-9,-7,142 +3262280,21,SHORT,438,-1,-1,3 +3262282,21,SHORT,439,3,-3,27 +3262284,21,SHORT,440,-1,-4,23 +3262286,21,SHORT,441,-7,-3,72 +3262288,21,SHORT,442,-2,11,138 +3262290,21,SHORT,443,9,-7,142 +3262292,21,SHORT,444,0,0,0 +3262294,21,SHORT,445,-3,5,42 +3262296,21,SHORT,446,1,11,125 +3262298,21,SHORT,447,4,-4,43 +3262300,21,SHORT,448,-4,-2,31 +3262302,21,SHORT,449,-1,-7,53 +3262304,21,SHORT,450,1,0,3 +3262306,21,SHORT,451,4,-3,32 +3262308,21,SHORT,452,-3,0,10 +3262310,21,SHORT,453,0,3,10 +3262312,21,SHORT,454,-2,-3,16 +3262314,21,SHORT,455,-2,-2,14 +3262316,21,SHORT,456,0,-6,36 +3262318,21,SHORT,457,8,7,132 +3262320,21,SHORT,458,3,-8,83 +3262322,21,SHORT,459,-2,3,14 +3262324,21,SHORT,460,2,8,87 +3262326,21,SHORT,461,13,-10,292 +3262328,21,SHORT,462,2,-5,33 +3262330,21,SHORT,463,1,5,26 +3262332,21,SHORT,464,-4,12,171 +3262334,21,SHORT,465,-2,1,7 +3262336,21,SHORT,466,3,-10,120 +3262338,21,SHORT,467,9,-2,101 +3262340,21,SHORT,468,7,0,61 +3262342,21,SHORT,469,8,-2,86 +3262344,21,SHORT,470,0,1,2 +3262346,21,SHORT,471,4,-4,41 +3262348,21,SHORT,472,0,3,14 +3262350,21,SHORT,473,5,-2,37 +3262352,21,SHORT,474,-11,7,176 +3262354,21,SHORT,475,-3,-1,15 +3262356,21,SHORT,476,9,2,98 +3262358,21,SHORT,477,-1,7,52 +3262360,21,SHORT,478,-1,8,72 +3262362,21,SHORT,479,0,8,80 +3262364,21,SHORT,480,-1,-4,22 +3262366,21,SHORT,481,-1,-3,16 +3262368,21,SHORT,482,6,0,44 +3262370,21,SHORT,483,-3,-4,31 +3262372,21,SHORT,484,-1,3,11 +3262374,21,SHORT,485,1,2,10 +3262376,21,SHORT,486,-3,3,28 +3262378,21,SHORT,487,0,7,53 +3262380,21,SHORT,488,-3,0,11 +3262382,21,SHORT,489,0,0,0 +3262384,21,SHORT,490,3,0,13 +3262386,21,SHORT,491,3,0,14 +3262388,21,SHORT,492,2,-2,12 +3262390,21,SHORT,493,-1,-1,5 +3262392,21,SHORT,494,-4,0,17 +3262394,21,SHORT,495,-4,2,26 +3262396,21,SHORT,496,-1,0,2 +3262398,21,SHORT,497,-2,0,4 +3262400,21,SHORT,498,-5,-3,47 +3262402,21,SHORT,499,-2,0,6 +3262404,21,SHORT,500,3,0,12 +3262406,21,SHORT,501,0,4,20 +3262408,21,SHORT,502,-3,-2,22 +3262410,21,SHORT,503,-5,-3,41 +3262412,21,SHORT,504,6,-4,63 +3262414,21,SHORT,505,-1,-3,13 +3262416,21,SHORT,506,0,0,0 +3262418,21,SHORT,507,-2,0,8 +3262420,21,SHORT,508,1,6,45 +3262422,21,SHORT,509,0,-1,3 +3262424,21,SHORT,510,6,0,43 +3262426,21,SHORT,511,3,-4,32 +3436928,22,SHORT,0,-6,-9,142 +3436930,22,SHORT,1,4,9,117 +3436932,22,SHORT,2,0,6,38 +3436934,22,SHORT,3,3,0,14 +3436936,22,SHORT,4,-11,2,128 +3436938,22,SHORT,5,-7,-7,109 +3436940,22,SHORT,6,0,9,95 +3436942,22,SHORT,7,0,-5,33 +3436944,22,SHORT,8,-5,5,64 +3436946,22,SHORT,9,10,-6,154 +3436948,22,SHORT,10,-5,1,34 +3436950,22,SHORT,11,6,1,42 +3436952,22,SHORT,12,10,6,146 +3436954,22,SHORT,13,-4,0,21 +3436956,22,SHORT,14,-7,6,90 +3436958,22,SHORT,15,-4,0,20 +3436960,22,SHORT,16,0,-9,90 +3436962,22,SHORT,17,2,2,9 +3436964,22,SHORT,18,-3,-10,132 +3436966,22,SHORT,19,11,9,230 +3436968,22,SHORT,20,7,6,111 +3436970,22,SHORT,21,2,6,55 +3436972,22,SHORT,22,-13,-13,372 +3436974,22,SHORT,23,-2,2,11 +3436976,22,SHORT,24,1,5,36 +3436978,22,SHORT,25,-5,-1,35 +3436980,22,SHORT,26,17,-7,367 +3436982,22,SHORT,27,0,6,37 +3436984,22,SHORT,28,7,-2,65 +3436986,22,SHORT,29,5,-5,54 +3436988,22,SHORT,30,-4,6,66 +3436990,22,SHORT,31,-3,-14,235 +3436992,22,SHORT,32,0,4,19 +3436994,22,SHORT,33,-4,1,24 +3436996,22,SHORT,34,-6,18,374 +3436998,22,SHORT,35,3,2,18 +3437000,22,SHORT,36,8,-2,77 +3437002,22,SHORT,37,0,5,28 +3437004,22,SHORT,38,1,-8,71 +3437006,22,SHORT,39,-1,9,100 +3437008,22,SHORT,40,9,-9,181 +3437010,22,SHORT,41,1,-8,67 +3437012,22,SHORT,42,-4,2,32 +3437014,22,SHORT,43,1,-4,27 +3437016,22,SHORT,44,-4,-2,25 +3437018,22,SHORT,45,-1,6,44 +3437020,22,SHORT,46,6,5,70 +3437022,22,SHORT,47,4,7,78 +3437024,22,SHORT,48,-1,0,2 +3437026,22,SHORT,49,-9,-1,89 +3437028,22,SHORT,50,9,-3,100 +3437030,22,SHORT,51,3,-1,13 +3437032,22,SHORT,52,-6,0,46 +3437034,22,SHORT,53,0,-6,48 +3437036,22,SHORT,54,-9,-2,100 +3437038,22,SHORT,55,9,-4,105 +3437040,22,SHORT,56,-7,-2,61 +3437042,22,SHORT,57,0,-1,2 +3437044,22,SHORT,58,3,-9,91 +3437046,22,SHORT,59,-1,0,3 +3437048,22,SHORT,60,2,-1,10 +3437050,22,SHORT,61,2,5,34 +3437052,22,SHORT,62,-10,-2,110 +3437054,22,SHORT,63,-3,2,21 +3437056,22,SHORT,64,-2,-1,8 +3437058,22,SHORT,65,4,-3,29 +3437060,22,SHORT,66,-3,-2,17 +3437062,22,SHORT,67,-2,3,18 +3437064,22,SHORT,68,-18,-53,3227 +3437066,22,SHORT,69,-7,-51,2664 +3437068,22,SHORT,70,10,-56,3257 +3437070,22,SHORT,71,12,-48,2541 +3437072,22,SHORT,72,32,-50,3617 +3437074,22,SHORT,73,29,-41,2638 +3437076,22,SHORT,74,56,-36,4490 +3437078,22,SHORT,75,59,-16,3820 +3437080,22,SHORT,76,50,-11,2711 +3437082,22,SHORT,77,51,4,2666 +3437084,22,SHORT,78,55,19,3399 +3437086,22,SHORT,79,54,26,3701 +3437088,22,SHORT,80,47,27,3000 +3437090,22,SHORT,81,34,37,2615 +3437092,22,SHORT,82,16,46,2463 +3437094,22,SHORT,83,-5,-4,49 +3437096,22,SHORT,84,-9,-4,101 +3437098,22,SHORT,85,-7,-2,55 +3437100,22,SHORT,86,1,1,6 +3437102,22,SHORT,87,-2,0,7 +3437104,22,SHORT,88,9,-1,98 +3437106,22,SHORT,89,0,-1,4 +3437108,22,SHORT,90,8,10,191 +3437110,22,SHORT,91,1,-8,70 +3437112,22,SHORT,92,-1,-3,11 +3437114,22,SHORT,93,4,5,44 +3437116,22,SHORT,94,5,5,65 +3437118,22,SHORT,95,0,-3,15 +3437120,22,SHORT,96,-5,0,30 +3437122,22,SHORT,97,-2,-8,77 +3437124,22,SHORT,98,4,0,19 +3437126,22,SHORT,99,2,-3,16 +3437128,22,SHORT,100,3,0,11 +3437130,22,SHORT,101,-5,-6,72 +3437132,22,SHORT,102,2,-1,9 +3437134,22,SHORT,103,5,-10,140 +3437136,22,SHORT,104,6,3,55 +3437138,22,SHORT,105,3,4,30 +3437140,22,SHORT,106,-6,6,80 +3437142,22,SHORT,107,0,0,0 +3437144,22,SHORT,108,-2,2,13 +3437146,22,SHORT,109,9,3,91 +3437148,22,SHORT,110,-4,4,38 +3437150,22,SHORT,111,-1,0,1 +3437152,22,SHORT,112,10,1,114 +3437154,22,SHORT,113,-2,0,6 +3437156,22,SHORT,114,-9,-3,102 +3437158,22,SHORT,115,9,-6,129 +3437160,22,SHORT,116,-7,1,61 +3437162,22,SHORT,117,-1,-6,38 +3437164,22,SHORT,118,25,-22,1164 +3437166,22,SHORT,119,17,-19,690 +3437168,22,SHORT,120,20,-12,589 +3437170,22,SHORT,121,28,-5,870 +3437172,22,SHORT,122,34,-13,1389 +3437174,22,SHORT,123,21,13,624 +3437176,22,SHORT,124,17,5,327 +3437178,22,SHORT,125,23,8,633 +3437180,22,SHORT,126,19,23,939 +3437182,22,SHORT,127,14,23,751 +3437184,22,SHORT,128,20,25,1099 +3437186,22,SHORT,129,-3,29,906 +3437188,22,SHORT,130,-3,28,838 +3437190,22,SHORT,131,-4,31,1000 +3437192,22,SHORT,132,-16,26,934 +3437194,22,SHORT,133,11,-3,135 +3437196,22,SHORT,134,12,8,212 +3437198,22,SHORT,135,3,2,16 +3437200,22,SHORT,136,6,5,72 +3437202,22,SHORT,137,3,9,94 +3437204,22,SHORT,138,-5,4,48 +3437206,22,SHORT,139,4,4,35 +3437208,22,SHORT,140,-2,-2,10 +3437210,22,SHORT,141,1,2,6 +3437212,22,SHORT,142,-1,0,3 +3437214,22,SHORT,143,-8,-7,133 +3437216,22,SHORT,144,1,-2,9 +3437218,22,SHORT,145,-4,0,16 +3437220,22,SHORT,146,0,-7,53 +3437222,22,SHORT,147,-7,-3,68 +3437224,22,SHORT,148,6,0,40 +3437226,22,SHORT,149,-5,-4,54 +3437228,22,SHORT,150,0,5,31 +3437230,22,SHORT,151,4,9,107 +3437232,22,SHORT,152,-1,-3,14 +3437234,22,SHORT,153,7,-7,115 +3437236,22,SHORT,154,4,6,65 +3437238,22,SHORT,155,1,-2,8 +3437240,22,SHORT,156,7,2,58 +3437242,22,SHORT,157,0,-1,2 +3437244,22,SHORT,158,-5,-3,43 +3437246,22,SHORT,159,-4,8,85 +3437248,22,SHORT,160,1,-3,18 +3437250,22,SHORT,161,0,2,4 +3437252,22,SHORT,162,1,-1,2 +3437254,22,SHORT,163,4,4,39 +3437256,22,SHORT,164,0,3,9 +3437258,22,SHORT,165,7,10,177 +3437260,22,SHORT,166,-8,0,71 +3437262,22,SHORT,167,2,-6,43 +3437264,22,SHORT,168,0,-5,27 +3437266,22,SHORT,169,-6,3,54 +3437268,22,SHORT,170,4,-6,67 +3437270,22,SHORT,171,-13,1,181 +3437272,22,SHORT,172,3,0,13 +3437274,22,SHORT,173,0,-6,46 +3437276,22,SHORT,174,-2,-5,30 +3437278,22,SHORT,175,-2,-3,20 +3437280,22,SHORT,176,10,-1,110 +3437282,22,SHORT,177,-4,3,33 +3437284,22,SHORT,178,2,-2,11 +3437286,22,SHORT,179,-2,-3,21 +3437288,22,SHORT,180,4,4,39 +3437290,22,SHORT,181,0,1,1 +3437292,22,SHORT,182,-5,4,48 +3437294,22,SHORT,183,0,-4,22 +3437296,22,SHORT,184,3,2,18 +3437298,22,SHORT,185,-4,4,39 +3437300,22,SHORT,186,-3,0,15 +3437302,22,SHORT,187,-3,-1,14 +3437304,22,SHORT,188,0,4,17 +3437306,22,SHORT,189,-1,-2,6 +3437308,22,SHORT,190,-3,4,29 +3437310,22,SHORT,191,0,0,0 +3437312,22,SHORT,192,5,-1,36 +3437314,22,SHORT,193,15,1,229 +3437316,22,SHORT,194,4,13,213 +3437318,22,SHORT,195,5,19,396 +3437320,22,SHORT,196,2,15,234 +3437322,22,SHORT,197,-1,12,153 +3437324,22,SHORT,198,-8,10,198 +3437326,22,SHORT,199,-5,12,170 +3437328,22,SHORT,200,-10,17,406 +3437330,22,SHORT,201,-1,12,161 +3437332,22,SHORT,202,-8,-3,85 +3437334,22,SHORT,203,-11,8,206 +3437336,22,SHORT,204,-28,7,879 +3437338,22,SHORT,205,-13,0,170 +3437340,22,SHORT,206,-15,-6,278 +3437342,22,SHORT,207,-8,-9,158 +3437344,22,SHORT,208,-6,-4,63 +3437346,22,SHORT,209,-1,1,4 +3437348,22,SHORT,210,-5,2,38 +3437350,22,SHORT,211,-8,-2,76 +3437352,22,SHORT,212,-5,-3,42 +3437354,22,SHORT,213,1,0,1 +3437356,22,SHORT,214,5,-2,38 +3437358,22,SHORT,215,4,-4,45 +3437360,22,SHORT,216,-1,1,6 +3437362,22,SHORT,217,7,1,51 +3437364,22,SHORT,218,0,5,35 +3437366,22,SHORT,219,1,5,36 +3437368,22,SHORT,220,3,0,12 +3437370,22,SHORT,221,-8,0,74 +3437372,22,SHORT,222,5,-7,82 +3437374,22,SHORT,223,-1,3,12 +3437376,22,SHORT,224,-4,-2,23 +3437378,22,SHORT,225,-7,-2,59 +3437380,22,SHORT,226,-1,2,8 +3437382,22,SHORT,227,-4,10,130 +3437384,22,SHORT,228,-2,-11,145 +3437386,22,SHORT,229,1,-4,25 +3437388,22,SHORT,230,6,-4,72 +3437390,22,SHORT,231,0,6,42 +3437392,22,SHORT,232,4,-1,22 +3437394,22,SHORT,233,-2,2,9 +3437396,22,SHORT,234,2,3,17 +3437398,22,SHORT,235,8,0,73 +3437400,22,SHORT,236,-11,5,161 +3437402,22,SHORT,237,0,2,5 +3437404,22,SHORT,238,-8,-2,79 +3437406,22,SHORT,239,0,-2,5 +3437408,22,SHORT,240,-4,7,79 +3437410,22,SHORT,241,0,-4,22 +3437412,22,SHORT,242,2,-7,70 +3437414,22,SHORT,243,2,0,8 +3437416,22,SHORT,244,-2,5,33 +3437418,22,SHORT,245,7,-1,62 +3437420,22,SHORT,246,-5,-1,27 +3437422,22,SHORT,247,-5,10,133 +3437424,22,SHORT,248,-2,7,66 +3437426,22,SHORT,249,0,-1,3 +3437428,22,SHORT,250,-2,-4,21 +3437430,22,SHORT,251,-2,5,36 +3437432,22,SHORT,252,-5,2,31 +3437434,22,SHORT,253,0,1,4 +3437436,22,SHORT,254,-3,0,15 +3437438,22,SHORT,255,-3,-2,21 +3437440,22,SHORT,256,0,-2,6 +3437442,22,SHORT,257,-12,6,204 +3437444,22,SHORT,258,5,-7,82 +3437446,22,SHORT,259,5,-11,155 +3437448,22,SHORT,260,-1,7,66 +3437450,22,SHORT,261,0,2,6 +3437452,22,SHORT,262,-5,-5,58 +3437454,22,SHORT,263,6,-2,51 +3437456,22,SHORT,264,0,-4,20 +3437458,22,SHORT,265,1,2,7 +3437460,22,SHORT,266,0,6,40 +3437462,22,SHORT,267,-10,5,129 +3437464,22,SHORT,268,4,-3,35 +3437466,22,SHORT,269,3,1,16 +3437468,22,SHORT,270,0,0,0 +3437470,22,SHORT,271,0,-1,3 +3437472,22,SHORT,272,-3,1,17 +3437474,22,SHORT,273,3,0,10 +3437476,22,SHORT,274,6,0,42 +3437478,22,SHORT,275,0,-6,42 +3437480,22,SHORT,276,-4,-1,23 +3437482,22,SHORT,277,-2,-8,85 +3437484,22,SHORT,278,0,3,10 +3437486,22,SHORT,279,-13,-4,216 +3437488,22,SHORT,280,0,1,1 +3437490,22,SHORT,281,-9,-4,112 +3437492,22,SHORT,282,6,0,46 +3437494,22,SHORT,283,-4,-7,80 +3437496,22,SHORT,284,-4,-3,31 +3437498,22,SHORT,285,-6,1,45 +3437500,22,SHORT,286,7,0,62 +3437502,22,SHORT,287,-2,10,122 +3437504,22,SHORT,288,-7,6,102 +3437506,22,SHORT,289,3,8,83 +3437508,22,SHORT,290,12,1,157 +3437510,22,SHORT,291,-5,-4,54 +3437512,22,SHORT,292,9,-8,176 +3437514,22,SHORT,293,-4,-7,82 +3437516,22,SHORT,294,-5,-11,153 +3437518,22,SHORT,295,2,-8,68 +3437520,22,SHORT,296,-2,-3,13 +3437522,22,SHORT,297,1,-10,116 +3437524,22,SHORT,298,0,-5,26 +3437526,22,SHORT,299,5,-3,44 +3437528,22,SHORT,300,2,-4,33 +3437530,22,SHORT,301,5,-3,36 +3437532,22,SHORT,302,8,4,86 +3437534,22,SHORT,303,5,2,42 +3437536,22,SHORT,304,4,-2,25 +3437538,22,SHORT,305,17,12,461 +3437540,22,SHORT,306,0,3,12 +3437542,22,SHORT,307,7,2,58 +3437544,22,SHORT,308,4,4,42 +3437546,22,SHORT,309,2,-1,9 +3437548,22,SHORT,310,1,-6,44 +3437550,22,SHORT,311,4,-5,54 +3437552,22,SHORT,312,-1,-1,3 +3437554,22,SHORT,313,5,6,76 +3437556,22,SHORT,314,-2,1,11 +3437558,22,SHORT,315,1,-10,103 +3437560,22,SHORT,316,-13,-7,246 +3437562,22,SHORT,317,-7,-5,79 +3437564,22,SHORT,318,0,-2,8 +3437566,22,SHORT,319,-3,-3,28 +3437568,22,SHORT,320,2,4,30 +3437570,22,SHORT,321,6,0,42 +3437572,22,SHORT,322,7,0,57 +3437574,22,SHORT,323,4,-6,54 +3437576,22,SHORT,324,-8,-1,71 +3437578,22,SHORT,325,5,3,44 +3437580,22,SHORT,326,-4,4,37 +3437582,22,SHORT,327,-2,0,5 +3437584,22,SHORT,328,-3,0,10 +3437586,22,SHORT,329,0,-1,3 +3437588,22,SHORT,330,6,-3,53 +3437590,22,SHORT,331,1,-2,11 +3437592,22,SHORT,332,1,4,21 +3437594,22,SHORT,333,1,-3,13 +3437596,22,SHORT,334,-2,1,9 +3437598,22,SHORT,335,0,-1,1 +3437600,22,SHORT,336,-6,2,51 +3437602,22,SHORT,337,-3,-2,17 +3437604,22,SHORT,338,5,9,122 +3437606,22,SHORT,339,-2,9,99 +3437608,22,SHORT,340,3,-5,44 +3437610,22,SHORT,341,-12,-5,174 +3437612,22,SHORT,342,-4,-3,27 +3437614,22,SHORT,343,4,-6,58 +3437616,22,SHORT,344,1,-8,78 +3437618,22,SHORT,345,0,-4,20 +3437620,22,SHORT,346,2,-12,169 +3437622,22,SHORT,347,2,7,64 +3437624,22,SHORT,348,-4,-4,34 +3437626,22,SHORT,349,0,5,30 +3437628,22,SHORT,350,0,-7,51 +3437630,22,SHORT,351,-1,-4,28 +3437632,22,SHORT,352,-6,-4,60 +3437634,22,SHORT,353,1,-11,134 +3437636,22,SHORT,354,-4,3,35 +3437638,22,SHORT,355,-11,3,143 +3437640,22,SHORT,356,2,0,4 +3437642,22,SHORT,357,-5,-3,48 +3437644,22,SHORT,358,6,-1,40 +3437646,22,SHORT,359,-9,-6,122 +3437648,22,SHORT,360,7,3,62 +3437650,22,SHORT,361,-3,-1,13 +3437652,22,SHORT,362,-1,-2,7 +3437654,22,SHORT,363,4,2,31 +3437656,22,SHORT,364,0,-3,11 +3437658,22,SHORT,365,3,0,11 +3437660,22,SHORT,366,5,-7,87 +3437662,22,SHORT,367,-6,4,59 +3437664,22,SHORT,368,-1,-13,181 +3437666,22,SHORT,369,-4,-1,18 +3437668,22,SHORT,370,1,4,23 +3437670,22,SHORT,371,2,-5,36 +3437672,22,SHORT,372,8,-1,80 +3437674,22,SHORT,373,3,0,12 +3437676,22,SHORT,374,0,3,12 +3437678,22,SHORT,375,2,9,91 +3437680,22,SHORT,376,-3,-1,16 +3437682,22,SHORT,377,8,1,69 +3437684,22,SHORT,378,-4,1,22 +3437686,22,SHORT,379,1,3,17 +3437688,22,SHORT,380,0,-3,15 +3437690,22,SHORT,381,0,0,0 +3437692,22,SHORT,382,4,0,16 +3437694,22,SHORT,383,-8,-6,114 +3437696,22,SHORT,384,4,10,122 +3437698,22,SHORT,385,0,6,45 +3437700,22,SHORT,386,-6,1,51 +3437702,22,SHORT,387,-7,8,142 +3437704,22,SHORT,388,2,-6,41 +3437706,22,SHORT,389,-2,7,54 +3437708,22,SHORT,390,-3,-4,34 +3437710,22,SHORT,391,-1,0,4 +3437712,22,SHORT,392,-2,3,18 +3437714,22,SHORT,393,11,-1,142 +3437716,22,SHORT,394,-4,6,69 +3437718,22,SHORT,395,-2,10,113 +3437720,22,SHORT,396,-5,-7,95 +3437722,22,SHORT,397,1,2,9 +3437724,22,SHORT,398,2,-1,9 +3437726,22,SHORT,399,3,-11,136 +3437728,22,SHORT,400,0,10,103 +3437730,22,SHORT,401,2,-3,16 +3437732,22,SHORT,402,5,2,40 +3437734,22,SHORT,403,-5,6,77 +3437736,22,SHORT,404,-7,1,62 +3437738,22,SHORT,405,1,5,33 +3437740,22,SHORT,406,-4,-3,37 +3437742,22,SHORT,407,6,-1,40 +3437744,22,SHORT,408,4,-2,32 +3437746,22,SHORT,409,-1,1,5 +3437748,22,SHORT,410,9,-1,96 +3437750,22,SHORT,411,5,3,35 +3437752,22,SHORT,412,-4,-4,40 +3437754,22,SHORT,413,5,-3,46 +3437756,22,SHORT,414,-1,-6,42 +3437758,22,SHORT,415,-5,5,60 +3437760,22,SHORT,416,-6,-2,52 +3437762,22,SHORT,417,2,4,27 +3437764,22,SHORT,418,-3,3,23 +3437766,22,SHORT,419,6,-11,169 +3437768,22,SHORT,420,-1,15,238 +3437770,22,SHORT,421,0,-1,1 +3437772,22,SHORT,422,8,7,129 +3437774,22,SHORT,423,-3,-6,60 +3437776,22,SHORT,424,2,14,207 +3437778,22,SHORT,425,1,6,45 +3437780,22,SHORT,426,2,4,26 +3437782,22,SHORT,427,4,0,20 +3437784,22,SHORT,428,3,-2,18 +3437786,22,SHORT,429,-7,-5,85 +3437788,22,SHORT,430,0,-4,17 +3437790,22,SHORT,431,15,-5,280 +3437792,22,SHORT,432,-8,3,95 +3437794,22,SHORT,433,-6,2,51 +3437796,22,SHORT,434,0,3,12 +3437798,22,SHORT,435,0,-1,4 +3437800,22,SHORT,436,4,0,24 +3437802,22,SHORT,437,0,1,2 +3437804,22,SHORT,438,-3,1,15 +3437806,22,SHORT,439,0,-5,34 +3437808,22,SHORT,440,-3,-2,13 +3437810,22,SHORT,441,-1,0,1 +3437812,22,SHORT,442,-6,-8,122 +3437814,22,SHORT,443,-5,1,39 +3437816,22,SHORT,444,0,8,72 +3437818,22,SHORT,445,5,9,116 +3437820,22,SHORT,446,1,3,14 +3437822,22,SHORT,447,-10,2,108 +3437824,22,SHORT,448,-3,2,18 +3437826,22,SHORT,449,-1,-4,25 +3437828,22,SHORT,450,-2,10,125 +3437830,22,SHORT,451,-8,3,77 +3437832,22,SHORT,452,2,-3,20 +3437834,22,SHORT,453,-3,8,92 +3437836,22,SHORT,454,0,-2,9 +3437838,22,SHORT,455,7,-4,76 +3437840,22,SHORT,456,-2,0,6 +3437842,22,SHORT,457,-4,0,23 +3437844,22,SHORT,458,2,3,18 +3437846,22,SHORT,459,4,13,192 +3437848,22,SHORT,460,0,8,81 +3437850,22,SHORT,461,-2,0,7 +3437852,22,SHORT,462,3,-3,22 +3437854,22,SHORT,463,-6,3,50 +3437856,22,SHORT,464,-5,0,36 +3437858,22,SHORT,465,-1,6,37 +3437860,22,SHORT,466,-5,-5,56 +3437862,22,SHORT,467,0,-4,21 +3437864,22,SHORT,468,-4,1,19 +3437866,22,SHORT,469,-1,-10,102 +3437868,22,SHORT,470,6,5,75 +3437870,22,SHORT,471,-2,3,18 +3437872,22,SHORT,472,6,2,49 +3437874,22,SHORT,473,-5,3,42 +3437876,22,SHORT,474,-3,-11,147 +3437878,22,SHORT,475,-2,-3,18 +3437880,22,SHORT,476,3,3,28 +3437882,22,SHORT,477,1,-7,63 +3437884,22,SHORT,478,0,1,3 +3437886,22,SHORT,479,8,3,81 +3437888,22,SHORT,480,-3,0,14 +3437890,22,SHORT,481,1,-5,30 +3437892,22,SHORT,482,9,0,93 +3437894,22,SHORT,483,-6,0,44 +3437896,22,SHORT,484,0,2,8 +3437898,22,SHORT,485,3,1,16 +3437900,22,SHORT,486,0,1,3 +3437902,22,SHORT,487,-5,3,40 +3437904,22,SHORT,488,-10,3,117 +3437906,22,SHORT,489,-1,15,240 +3437908,22,SHORT,490,5,0,33 +3437910,22,SHORT,491,7,0,57 +3437912,22,SHORT,492,4,-3,35 +3437914,22,SHORT,493,-3,-5,46 +3437916,22,SHORT,494,2,-2,13 +3437918,22,SHORT,495,-5,1,29 +3437920,22,SHORT,496,4,1,22 +3437922,22,SHORT,497,5,0,27 +3437924,22,SHORT,498,-4,0,17 +3437926,22,SHORT,499,7,9,149 +3437928,22,SHORT,500,5,1,27 +3437930,22,SHORT,501,5,-5,65 +3437932,22,SHORT,502,-3,0,13 +3437934,22,SHORT,503,-1,-1,4 +3437936,22,SHORT,504,3,4,32 +3437938,22,SHORT,505,6,-3,52 +3437940,22,SHORT,506,-3,-2,21 +3437942,22,SHORT,507,-2,1,5 +3437944,22,SHORT,508,-2,-6,51 +3437946,22,SHORT,509,2,0,4 +3437948,22,SHORT,510,0,0,0 +3437950,22,SHORT,511,-2,-4,22 +3612452,23,SHORT,0,1,3,15 +3612454,23,SHORT,1,-10,12,259 +3612456,23,SHORT,2,0,-1,1 +3612458,23,SHORT,3,-9,-3,95 +3612460,23,SHORT,4,3,-1,17 +3612462,23,SHORT,5,-6,-1,41 +3612464,23,SHORT,6,-3,14,220 +3612466,23,SHORT,7,0,9,89 +3612468,23,SHORT,8,-4,-7,72 +3612470,23,SHORT,9,2,-3,21 +3612472,23,SHORT,10,-1,0,2 +3612474,23,SHORT,11,6,0,39 +3612476,23,SHORT,12,-12,2,154 +3612478,23,SHORT,13,7,3,69 +3612480,23,SHORT,14,-1,4,24 +3612482,23,SHORT,15,3,4,33 +3612484,23,SHORT,16,-1,-1,7 +3612486,23,SHORT,17,0,0,0 +3612488,23,SHORT,18,0,1,2 +3612490,23,SHORT,19,-1,-1,2 +3612492,23,SHORT,20,-7,1,56 +3612494,23,SHORT,21,0,-2,5 +3612496,23,SHORT,22,13,0,193 +3612498,23,SHORT,23,-8,15,316 +3612500,23,SHORT,24,8,-1,68 +3612502,23,SHORT,25,0,0,0 +3612504,23,SHORT,26,4,-1,24 +3612506,23,SHORT,27,-1,0,2 +3612508,23,SHORT,28,2,-1,7 +3612510,23,SHORT,29,5,-1,27 +3612512,23,SHORT,30,4,-11,164 +3612514,23,SHORT,31,-5,3,39 +3612516,23,SHORT,32,-8,4,82 +3612518,23,SHORT,33,4,3,35 +3612520,23,SHORT,34,-9,0,91 +3612522,23,SHORT,35,6,3,58 +3612524,23,SHORT,36,6,2,46 +3612526,23,SHORT,37,5,-2,32 +3612528,23,SHORT,38,4,-6,66 +3612530,23,SHORT,39,3,0,12 +3612532,23,SHORT,40,5,-1,33 +3612534,23,SHORT,41,0,7,60 +3612536,23,SHORT,42,7,4,76 +3612538,23,SHORT,43,7,-11,174 +3612540,23,SHORT,44,-11,-5,153 +3612542,23,SHORT,45,-8,8,133 +3612544,23,SHORT,46,-3,0,12 +3612546,23,SHORT,47,0,-5,27 +3612548,23,SHORT,48,-3,-13,205 +3612550,23,SHORT,49,-1,-5,37 +3612552,23,SHORT,50,0,-4,16 +3612554,23,SHORT,51,2,2,15 +3612556,23,SHORT,52,4,1,22 +3612558,23,SHORT,53,0,1,1 +3612560,23,SHORT,54,4,4,37 +3612562,23,SHORT,55,-4,0,21 +3612564,23,SHORT,56,0,12,149 +3612566,23,SHORT,57,0,0,0 +3612568,23,SHORT,58,2,1,12 +3612570,23,SHORT,59,-6,0,47 +3612572,23,SHORT,60,-1,2,10 +3612574,23,SHORT,61,6,-3,53 +3612576,23,SHORT,62,-4,0,17 +3612578,23,SHORT,63,3,0,10 +3612580,23,SHORT,64,0,1,3 +3612582,23,SHORT,65,-6,6,87 +3612584,23,SHORT,66,2,1,8 +3612586,23,SHORT,67,-2,-6,52 +3612588,23,SHORT,68,54,1,2995 +3612590,23,SHORT,69,52,19,3121 +3612592,23,SHORT,70,61,30,4756 +3612594,23,SHORT,71,49,37,3823 +3612596,23,SHORT,72,26,47,2950 +3612598,23,SHORT,73,21,57,3835 +3612600,23,SHORT,74,20,52,3138 +3612602,23,SHORT,75,-2,54,3017 +3612604,23,SHORT,76,-11,60,3804 +3612606,23,SHORT,77,-23,48,2876 +3612608,23,SHORT,78,-30,52,3643 +3612610,23,SHORT,79,-41,33,2843 +3612612,23,SHORT,80,-40,24,2260 +3612614,23,SHORT,81,-62,21,4400 +3612616,23,SHORT,82,-49,7,2467 +3612618,23,SHORT,83,3,0,10 +3612620,23,SHORT,84,-7,-12,211 +3612622,23,SHORT,85,-3,-1,15 +3612624,23,SHORT,86,-1,2,7 +3612626,23,SHORT,87,-9,3,105 +3612628,23,SHORT,88,-7,-1,55 +3612630,23,SHORT,89,0,5,30 +3612632,23,SHORT,90,6,0,39 +3612634,23,SHORT,91,4,-4,37 +3612636,23,SHORT,92,2,-2,16 +3612638,23,SHORT,93,-3,0,15 +3612640,23,SHORT,94,-3,2,15 +3612642,23,SHORT,95,0,0,1 +3612644,23,SHORT,96,3,3,25 +3612646,23,SHORT,97,3,-1,17 +3612648,23,SHORT,98,3,-2,18 +3612650,23,SHORT,99,-4,2,28 +3612652,23,SHORT,100,5,7,88 +3612654,23,SHORT,101,0,-2,6 +3612656,23,SHORT,102,2,4,27 +3612658,23,SHORT,103,5,3,51 +3612660,23,SHORT,104,-4,3,30 +3612662,23,SHORT,105,7,-6,95 +3612664,23,SHORT,106,-5,0,26 +3612666,23,SHORT,107,-2,1,8 +3612668,23,SHORT,108,-2,3,18 +3612670,23,SHORT,109,0,-2,7 +3612672,23,SHORT,110,5,1,35 +3612674,23,SHORT,111,2,-6,53 +3612676,23,SHORT,112,0,6,43 +3612678,23,SHORT,113,0,-5,28 +3612680,23,SHORT,114,3,0,15 +3612682,23,SHORT,115,3,-3,20 +3612684,23,SHORT,116,3,-4,30 +3612686,23,SHORT,117,1,-7,52 +3612688,23,SHORT,118,-18,-27,1100 +3612690,23,SHORT,119,-7,-25,731 +3612692,23,SHORT,120,-2,-28,799 +3612694,23,SHORT,121,7,-16,318 +3612696,23,SHORT,122,9,-22,579 +3612698,23,SHORT,123,15,-23,792 +3612700,23,SHORT,124,19,-17,667 +3612702,23,SHORT,125,27,-10,832 +3612704,23,SHORT,126,24,-8,689 +3612706,23,SHORT,127,25,3,656 +3612708,23,SHORT,128,20,-6,444 +3612710,23,SHORT,129,26,13,893 +3612712,23,SHORT,130,23,10,674 +3612714,23,SHORT,131,33,15,1375 +3612716,23,SHORT,132,17,15,538 +3612718,23,SHORT,133,-1,0,3 +3612720,23,SHORT,134,-3,-3,24 +3612722,23,SHORT,135,-5,0,32 +3612724,23,SHORT,136,5,-4,49 +3612726,23,SHORT,137,-8,-1,69 +3612728,23,SHORT,138,3,2,18 +3612730,23,SHORT,139,2,0,5 +3612732,23,SHORT,140,1,8,75 +3612734,23,SHORT,141,-5,1,37 +3612736,23,SHORT,142,8,2,75 +3612738,23,SHORT,143,3,-3,29 +3612740,23,SHORT,144,0,0,1 +3612742,23,SHORT,145,0,3,14 +3612744,23,SHORT,146,15,0,232 +3612746,23,SHORT,147,2,2,10 +3612748,23,SHORT,148,-4,2,23 +3612750,23,SHORT,149,9,-3,97 +3612752,23,SHORT,150,-5,2,34 +3612754,23,SHORT,151,3,4,34 +3612756,23,SHORT,152,9,0,96 +3612758,23,SHORT,153,0,3,13 +3612760,23,SHORT,154,8,9,161 +3612762,23,SHORT,155,1,2,11 +3612764,23,SHORT,156,5,-11,166 +3612766,23,SHORT,157,-11,7,179 +3612768,23,SHORT,158,9,-2,100 +3612770,23,SHORT,159,14,2,206 +3612772,23,SHORT,160,4,0,21 +3612774,23,SHORT,161,1,-8,75 +3612776,23,SHORT,162,-3,4,34 +3612778,23,SHORT,163,-11,-5,155 +3612780,23,SHORT,164,-5,0,34 +3612782,23,SHORT,165,-5,0,26 +3612784,23,SHORT,166,0,-2,5 +3612786,23,SHORT,167,-2,0,7 +3612788,23,SHORT,168,-6,0,45 +3612790,23,SHORT,169,3,2,18 +3612792,23,SHORT,170,0,-1,2 +3612794,23,SHORT,171,9,-3,98 +3612796,23,SHORT,172,8,-1,68 +3612798,23,SHORT,173,-3,0,16 +3612800,23,SHORT,174,-5,4,47 +3612802,23,SHORT,175,-4,-3,32 +3612804,23,SHORT,176,-6,-1,48 +3612806,23,SHORT,177,0,-2,6 +3612808,23,SHORT,178,11,-7,185 +3612810,23,SHORT,179,-2,1,10 +3612812,23,SHORT,180,0,2,8 +3612814,23,SHORT,181,5,0,36 +3612816,23,SHORT,182,4,-1,20 +3612818,23,SHORT,183,-6,-1,47 +3612820,23,SHORT,184,4,-7,78 +3612822,23,SHORT,185,0,-7,56 +3612824,23,SHORT,186,-6,4,72 +3612826,23,SHORT,187,6,-5,72 +3612828,23,SHORT,188,3,-3,26 +3612830,23,SHORT,189,2,-7,60 +3612832,23,SHORT,190,-2,-3,15 +3612834,23,SHORT,191,0,3,14 +3612836,23,SHORT,192,-1,1,4 +3612838,23,SHORT,193,15,8,312 +3612840,23,SHORT,194,0,13,195 +3612842,23,SHORT,195,0,15,231 +3612844,23,SHORT,196,-6,6,87 +3612846,23,SHORT,197,-5,19,392 +3612848,23,SHORT,198,-20,11,553 +3612850,23,SHORT,199,-8,12,233 +3612852,23,SHORT,200,-12,9,264 +3612854,23,SHORT,201,-17,4,314 +3612856,23,SHORT,202,-18,0,353 +3612858,23,SHORT,203,-15,1,233 +3612860,23,SHORT,204,-21,-2,462 +3612862,23,SHORT,205,-16,-1,266 +3612864,23,SHORT,206,-14,-7,278 +3612866,23,SHORT,207,-10,-2,112 +3612868,23,SHORT,208,-3,8,82 +3612870,23,SHORT,209,-1,2,10 +3612872,23,SHORT,210,0,-1,2 +3612874,23,SHORT,211,-3,-10,117 +3612876,23,SHORT,212,7,0,53 +3612878,23,SHORT,213,5,0,27 +3612880,23,SHORT,214,-3,0,15 +3612882,23,SHORT,215,5,-4,55 +3612884,23,SHORT,216,1,-2,12 +3612886,23,SHORT,217,4,1,20 +3612888,23,SHORT,218,1,0,2 +3612890,23,SHORT,219,-3,-6,50 +3612892,23,SHORT,220,-1,0,2 +3612894,23,SHORT,221,2,0,5 +3612896,23,SHORT,222,0,-10,102 +3612898,23,SHORT,223,-3,-1,10 +3612900,23,SHORT,224,3,3,24 +3612902,23,SHORT,225,3,4,35 +3612904,23,SHORT,226,-3,0,11 +3612906,23,SHORT,227,0,7,62 +3612908,23,SHORT,228,0,-6,39 +3612910,23,SHORT,229,1,1,6 +3612912,23,SHORT,230,1,6,51 +3612914,23,SHORT,231,1,-1,3 +3612916,23,SHORT,232,-2,-5,30 +3612918,23,SHORT,233,-2,5,35 +3612920,23,SHORT,234,7,0,63 +3612922,23,SHORT,235,6,4,66 +3612924,23,SHORT,236,0,-2,7 +3612926,23,SHORT,237,-6,-2,45 +3612928,23,SHORT,238,3,-8,87 +3612930,23,SHORT,239,-1,0,3 +3612932,23,SHORT,240,3,2,22 +3612934,23,SHORT,241,0,0,1 +3612936,23,SHORT,242,1,5,38 +3612938,23,SHORT,243,0,-1,3 +3612940,23,SHORT,244,8,0,66 +3612942,23,SHORT,245,7,-2,62 +3612944,23,SHORT,246,5,-7,87 +3612946,23,SHORT,247,-4,0,19 +3612948,23,SHORT,248,5,6,64 +3612950,23,SHORT,249,1,3,13 +3612952,23,SHORT,250,0,0,0 +3612954,23,SHORT,251,-7,-4,81 +3612956,23,SHORT,252,0,2,6 +3612958,23,SHORT,253,0,-10,113 +3612960,23,SHORT,254,4,1,27 +3612962,23,SHORT,255,0,9,84 +3612964,23,SHORT,256,3,0,15 +3612966,23,SHORT,257,8,2,85 +3612968,23,SHORT,258,2,1,6 +3612970,23,SHORT,259,5,-4,53 +3612972,23,SHORT,260,-10,-12,265 +3612974,23,SHORT,261,0,-3,13 +3612976,23,SHORT,262,-3,-4,35 +3612978,23,SHORT,263,0,4,24 +3612980,23,SHORT,264,-3,-5,39 +3612982,23,SHORT,265,-1,0,1 +3612984,23,SHORT,266,5,-9,121 +3612986,23,SHORT,267,-2,-3,14 +3612988,23,SHORT,268,4,-4,41 +3612990,23,SHORT,269,7,-4,73 +3612992,23,SHORT,270,-9,-4,110 +3612994,23,SHORT,271,2,-2,14 +3612996,23,SHORT,272,0,-4,21 +3612998,23,SHORT,273,2,6,48 +3613000,23,SHORT,274,0,0,1 +3613002,23,SHORT,275,-1,-2,9 +3613004,23,SHORT,276,6,4,57 +3613006,23,SHORT,277,-1,4,24 +3613008,23,SHORT,278,-1,0,2 +3613010,23,SHORT,279,-6,5,71 +3613012,23,SHORT,280,1,-6,45 +3613014,23,SHORT,281,-2,3,17 +3613016,23,SHORT,282,4,0,25 +3613018,23,SHORT,283,-4,-2,24 +3613020,23,SHORT,284,5,-11,158 +3613022,23,SHORT,285,1,-6,51 +3613024,23,SHORT,286,3,-4,37 +3613026,23,SHORT,287,0,-4,22 +3613028,23,SHORT,288,-11,-3,147 +3613030,23,SHORT,289,4,0,19 +3613032,23,SHORT,290,5,-8,105 +3613034,23,SHORT,291,-3,-1,13 +3613036,23,SHORT,292,-8,1,69 +3613038,23,SHORT,293,-8,0,67 +3613040,23,SHORT,294,-9,-4,109 +3613042,23,SHORT,295,-9,-7,133 +3613044,23,SHORT,296,-8,-7,137 +3613046,23,SHORT,297,-8,-3,76 +3613048,23,SHORT,298,-2,-3,18 +3613050,23,SHORT,299,-7,-10,167 +3613052,23,SHORT,300,8,-8,137 +3613054,23,SHORT,301,2,-4,28 +3613056,23,SHORT,302,-1,-7,59 +3613058,23,SHORT,303,3,-7,73 +3613060,23,SHORT,304,3,-5,48 +3613062,23,SHORT,305,12,-6,193 +3613064,23,SHORT,306,3,3,26 +3613066,23,SHORT,307,8,1,77 +3613068,23,SHORT,308,4,11,163 +3613070,23,SHORT,309,0,-5,27 +3613072,23,SHORT,310,2,-1,7 +3613074,23,SHORT,311,1,-3,14 +3613076,23,SHORT,312,2,-1,9 +3613078,23,SHORT,313,6,0,39 +3613080,23,SHORT,314,2,0,8 +3613082,23,SHORT,315,-1,6,47 +3613084,23,SHORT,316,1,-9,84 +3613086,23,SHORT,317,-3,2,19 +3613088,23,SHORT,318,-1,5,30 +3613090,23,SHORT,319,5,9,135 +3613092,23,SHORT,320,-1,0,2 +3613094,23,SHORT,321,4,-3,31 +3613096,23,SHORT,322,-3,3,26 +3613098,23,SHORT,323,-6,-8,107 +3613100,23,SHORT,324,2,-1,10 +3613102,23,SHORT,325,-4,-4,39 +3613104,23,SHORT,326,2,-2,9 +3613106,23,SHORT,327,-1,9,97 +3613108,23,SHORT,328,0,2,8 +3613110,23,SHORT,329,0,3,12 +3613112,23,SHORT,330,1,1,5 +3613114,23,SHORT,331,-3,-2,20 +3613116,23,SHORT,332,13,-1,176 +3613118,23,SHORT,333,0,0,0 +3613120,23,SHORT,334,0,3,12 +3613122,23,SHORT,335,-4,-2,25 +3613124,23,SHORT,336,0,2,5 +3613126,23,SHORT,337,3,-7,63 +3613128,23,SHORT,338,-1,-7,54 +3613130,23,SHORT,339,0,-2,6 +3613132,23,SHORT,340,-7,9,151 +3613134,23,SHORT,341,-4,2,22 +3613136,23,SHORT,342,-2,0,6 +3613138,23,SHORT,343,0,-2,7 +3613140,23,SHORT,344,1,5,31 +3613142,23,SHORT,345,-5,5,60 +3613144,23,SHORT,346,8,-8,137 +3613146,23,SHORT,347,-1,7,62 +3613148,23,SHORT,348,-2,-7,63 +3613150,23,SHORT,349,0,-1,2 +3613152,23,SHORT,350,4,-2,26 +3613154,23,SHORT,351,5,-4,51 +3613156,23,SHORT,352,5,-2,35 +3613158,23,SHORT,353,-8,-1,79 +3613160,23,SHORT,354,-4,0,21 +3613162,23,SHORT,355,-6,7,99 +3613164,23,SHORT,356,-1,4,26 +3613166,23,SHORT,357,-2,7,62 +3613168,23,SHORT,358,-3,-9,97 +3613170,23,SHORT,359,9,6,135 +3613172,23,SHORT,360,-6,1,46 +3613174,23,SHORT,361,2,-5,30 +3613176,23,SHORT,362,1,6,47 +3613178,23,SHORT,363,2,0,8 +3613180,23,SHORT,364,-1,-6,45 +3613182,23,SHORT,365,2,0,5 +3613184,23,SHORT,366,7,-9,143 +3613186,23,SHORT,367,7,-1,58 +3613188,23,SHORT,368,-1,0,2 +3613190,23,SHORT,369,-4,-5,58 +3613192,23,SHORT,370,3,-2,16 +3613194,23,SHORT,371,-1,0,1 +3613196,23,SHORT,372,0,-9,88 +3613198,23,SHORT,373,0,0,0 +3613200,23,SHORT,374,2,-3,22 +3613202,23,SHORT,375,-2,0,8 +3613204,23,SHORT,376,-4,-3,31 +3613206,23,SHORT,377,7,-5,94 +3613208,23,SHORT,378,-1,3,15 +3613210,23,SHORT,379,-6,6,87 +3613212,23,SHORT,380,-4,-2,31 +3613214,23,SHORT,381,2,0,6 +3613216,23,SHORT,382,1,0,1 +3613218,23,SHORT,383,5,3,42 +3613220,23,SHORT,384,-8,-4,81 +3613222,23,SHORT,385,1,-3,15 +3613224,23,SHORT,386,7,-6,90 +3613226,23,SHORT,387,-2,7,59 +3613228,23,SHORT,388,-9,0,89 +3613230,23,SHORT,389,-4,-8,88 +3613232,23,SHORT,390,-9,4,115 +3613234,23,SHORT,391,2,1,7 +3613236,23,SHORT,392,0,-2,4 +3613238,23,SHORT,393,2,3,16 +3613240,23,SHORT,394,0,-4,20 +3613242,23,SHORT,395,0,5,34 +3613244,23,SHORT,396,6,-4,60 +3613246,23,SHORT,397,0,-1,1 +3613248,23,SHORT,398,-1,4,19 +3613250,23,SHORT,399,0,6,46 +3613252,23,SHORT,400,1,0,2 +3613254,23,SHORT,401,-1,0,3 +3613256,23,SHORT,402,-4,8,86 +3613258,23,SHORT,403,0,4,20 +3613260,23,SHORT,404,3,3,21 +3613262,23,SHORT,405,0,-5,29 +3613264,23,SHORT,406,-4,8,97 +3613266,23,SHORT,407,-2,-9,92 +3613268,23,SHORT,408,-4,0,19 +3613270,23,SHORT,409,-3,-7,73 +3613272,23,SHORT,410,4,6,58 +3613274,23,SHORT,411,-3,0,15 +3613276,23,SHORT,412,7,3,68 +3613278,23,SHORT,413,0,5,26 +3613280,23,SHORT,414,-8,-1,71 +3613282,23,SHORT,415,0,-4,24 +3613284,23,SHORT,416,2,5,36 +3613286,23,SHORT,417,1,0,2 +3613288,23,SHORT,418,2,0,8 +3613290,23,SHORT,419,2,5,37 +3613292,23,SHORT,420,3,5,48 +3613294,23,SHORT,421,0,-6,39 +3613296,23,SHORT,422,0,-7,59 +3613298,23,SHORT,423,1,3,16 +3613300,23,SHORT,424,1,-2,11 +3613302,23,SHORT,425,0,8,68 +3613304,23,SHORT,426,-4,9,106 +3613306,23,SHORT,427,2,-1,9 +3613308,23,SHORT,428,-8,3,80 +3613310,23,SHORT,429,-6,0,48 +3613312,23,SHORT,430,10,0,112 +3613314,23,SHORT,431,7,2,59 +3613316,23,SHORT,432,-3,-1,16 +3613318,23,SHORT,433,-5,3,48 +3613320,23,SHORT,434,-5,-11,170 +3613322,23,SHORT,435,-1,-4,20 +3613324,23,SHORT,436,4,8,90 +3613326,23,SHORT,437,-6,-2,45 +3613328,23,SHORT,438,10,-8,198 +3613330,23,SHORT,439,8,5,91 +3613332,23,SHORT,440,-2,9,104 +3613334,23,SHORT,441,4,0,23 +3613336,23,SHORT,442,6,11,168 +3613338,23,SHORT,443,3,-4,30 +3613340,23,SHORT,444,2,6,52 +3613342,23,SHORT,445,2,0,6 +3613344,23,SHORT,446,-3,-5,46 +3613346,23,SHORT,447,2,-7,56 +3613348,23,SHORT,448,5,-2,34 +3613350,23,SHORT,449,-1,0,3 +3613352,23,SHORT,450,4,-13,201 +3613354,23,SHORT,451,0,-7,51 +3613356,23,SHORT,452,-2,-6,45 +3613358,23,SHORT,453,-2,5,30 +3613360,23,SHORT,454,-1,2,11 +3613362,23,SHORT,455,3,0,9 +3613364,23,SHORT,456,0,-1,2 +3613366,23,SHORT,457,5,-1,32 +3613368,23,SHORT,458,-6,-2,46 +3613370,23,SHORT,459,0,9,84 +3613372,23,SHORT,460,4,-6,61 +3613374,23,SHORT,461,5,2,37 +3613376,23,SHORT,462,2,2,13 +3613378,23,SHORT,463,0,-6,39 +3613380,23,SHORT,464,-6,-8,117 +3613382,23,SHORT,465,0,1,2 +3613384,23,SHORT,466,0,-1,3 +3613386,23,SHORT,467,5,-4,46 +3613388,23,SHORT,468,-2,-5,36 +3613390,23,SHORT,469,2,0,5 +3613392,23,SHORT,470,6,5,76 +3613394,23,SHORT,471,-2,6,44 +3613396,23,SHORT,472,-4,-3,33 +3613398,23,SHORT,473,3,5,36 +3613400,23,SHORT,474,0,0,0 +3613402,23,SHORT,475,-5,-6,71 +3613404,23,SHORT,476,-8,-3,95 +3613406,23,SHORT,477,1,5,34 +3613408,23,SHORT,478,0,-3,16 +3613410,23,SHORT,479,0,3,15 +3613412,23,SHORT,480,1,0,2 +3613414,23,SHORT,481,-3,1,12 +3613416,23,SHORT,482,11,-2,138 +3613418,23,SHORT,483,0,-10,107 +3613420,23,SHORT,484,0,-4,18 +3613422,23,SHORT,485,4,8,101 +3613424,23,SHORT,486,7,0,62 +3613426,23,SHORT,487,2,0,6 +3613428,23,SHORT,488,0,2,8 +3613430,23,SHORT,489,-1,-2,9 +3613432,23,SHORT,490,-2,-1,10 +3613434,23,SHORT,491,-1,7,54 +3613436,23,SHORT,492,0,5,29 +3613438,23,SHORT,493,-2,4,30 +3613440,23,SHORT,494,1,8,79 +3613442,23,SHORT,495,0,-5,32 +3613444,23,SHORT,496,-2,0,8 +3613446,23,SHORT,497,7,0,52 +3613448,23,SHORT,498,3,11,134 +3613450,23,SHORT,499,11,-2,133 +3613452,23,SHORT,500,-3,5,44 +3613454,23,SHORT,501,6,-1,49 +3613456,23,SHORT,502,1,1,4 +3613458,23,SHORT,503,-4,2,26 +3613460,23,SHORT,504,8,2,85 +3613462,23,SHORT,505,-7,1,59 +3613464,23,SHORT,506,4,0,17 +3613466,23,SHORT,507,0,1,1 +3613468,23,SHORT,508,12,0,161 +3613470,23,SHORT,509,-3,8,85 +3613472,23,SHORT,510,3,4,31 +3613474,23,SHORT,511,8,11,196 +3787976,24,SHORT,0,-6,-7,95 +3787978,24,SHORT,1,-3,-1,17 +3787980,24,SHORT,2,4,3,35 +3787982,24,SHORT,3,2,16,284 +3787984,24,SHORT,4,-8,0,68 +3787986,24,SHORT,5,-4,1,20 +3787988,24,SHORT,6,11,-9,223 +3787990,24,SHORT,7,-2,10,123 +3787992,24,SHORT,8,8,1,69 +3787994,24,SHORT,9,6,-13,215 +3787996,24,SHORT,10,-2,-7,58 +3787998,24,SHORT,11,7,12,217 +3788000,24,SHORT,12,-6,3,55 +3788002,24,SHORT,13,5,0,30 +3788004,24,SHORT,14,-10,0,104 +3788006,24,SHORT,15,0,11,128 +3788008,24,SHORT,16,5,0,36 +3788010,24,SHORT,17,7,-3,66 +3788012,24,SHORT,18,3,7,62 +3788014,24,SHORT,19,1,7,50 +3788016,24,SHORT,20,-4,-2,23 +3788018,24,SHORT,21,-4,4,38 +3788020,24,SHORT,22,11,4,157 +3788022,24,SHORT,23,0,2,5 +3788024,24,SHORT,24,9,0,93 +3788026,24,SHORT,25,0,1,1 +3788028,24,SHORT,26,-2,-4,24 +3788030,24,SHORT,27,-14,0,208 +3788032,24,SHORT,28,11,0,144 +3788034,24,SHORT,29,-1,-2,7 +3788036,24,SHORT,30,-14,-9,288 +3788038,24,SHORT,31,0,-6,49 +3788040,24,SHORT,32,-6,-6,87 +3788042,24,SHORT,33,0,-5,33 +3788044,24,SHORT,34,3,-1,13 +3788046,24,SHORT,35,17,3,308 +3788048,24,SHORT,36,1,7,58 +3788050,24,SHORT,37,7,-5,81 +3788052,24,SHORT,38,-3,-3,22 +3788054,24,SHORT,39,0,19,365 +3788056,24,SHORT,40,14,-8,289 +3788058,24,SHORT,41,-8,3,92 +3788060,24,SHORT,42,0,-6,46 +3788062,24,SHORT,43,-2,4,31 +3788064,24,SHORT,44,-10,-1,102 +3788066,24,SHORT,45,-9,0,86 +3788068,24,SHORT,46,0,-3,13 +3788070,24,SHORT,47,5,-7,90 +3788072,24,SHORT,48,-1,-11,131 +3788074,24,SHORT,49,-3,-7,73 +3788076,24,SHORT,50,0,-1,1 +3788078,24,SHORT,51,-5,-2,32 +3788080,24,SHORT,52,0,7,49 +3788082,24,SHORT,53,-1,4,23 +3788084,24,SHORT,54,-12,8,236 +3788086,24,SHORT,55,-2,6,54 +3788088,24,SHORT,56,4,0,21 +3788090,24,SHORT,57,-2,0,5 +3788092,24,SHORT,58,0,6,41 +3788094,24,SHORT,59,0,1,3 +3788096,24,SHORT,60,-4,-8,95 +3788098,24,SHORT,61,0,12,145 +3788100,24,SHORT,62,-3,-3,22 +3788102,24,SHORT,63,7,0,50 +3788104,24,SHORT,64,-2,-4,28 +3788106,24,SHORT,65,1,-2,9 +3788108,24,SHORT,66,0,4,19 +3788110,24,SHORT,67,1,6,48 +3788112,24,SHORT,68,-28,53,3682 +3788114,24,SHORT,69,-41,52,4470 +3788116,24,SHORT,70,-31,43,2855 +3788118,24,SHORT,71,-49,31,3480 +3788120,24,SHORT,72,-55,9,3224 +3788122,24,SHORT,73,-62,5,3963 +3788124,24,SHORT,74,-50,-18,2951 +3788126,24,SHORT,75,-49,-13,2610 +3788128,24,SHORT,76,-42,-28,2647 +3788130,24,SHORT,77,-33,-47,3322 +3788132,24,SHORT,78,-16,-49,2709 +3788134,24,SHORT,79,-24,-45,2655 +3788136,24,SHORT,80,-9,-63,4143 +3788138,24,SHORT,81,9,-48,2418 +3788140,24,SHORT,82,11,-52,2855 +3788142,24,SHORT,83,-1,5,35 +3788144,24,SHORT,84,4,6,67 +3788146,24,SHORT,85,-9,0,93 +3788148,24,SHORT,86,2,1,9 +3788150,24,SHORT,87,0,3,10 +3788152,24,SHORT,88,-5,-7,77 +3788154,24,SHORT,89,-5,2,40 +3788156,24,SHORT,90,1,0,2 +3788158,24,SHORT,91,1,10,110 +3788160,24,SHORT,92,0,2,5 +3788162,24,SHORT,93,-3,3,25 +3788164,24,SHORT,94,2,3,17 +3788166,24,SHORT,95,-2,-4,27 +3788168,24,SHORT,96,9,0,94 +3788170,24,SHORT,97,4,0,18 +3788172,24,SHORT,98,-1,0,3 +3788174,24,SHORT,99,-8,6,109 +3788176,24,SHORT,100,1,0,1 +3788178,24,SHORT,101,1,10,104 +3788180,24,SHORT,102,1,2,8 +3788182,24,SHORT,103,3,-2,17 +3788184,24,SHORT,104,0,3,11 +3788186,24,SHORT,105,-2,0,7 +3788188,24,SHORT,106,-6,-2,46 +3788190,24,SHORT,107,-2,0,8 +3788192,24,SHORT,108,7,-7,110 +3788194,24,SHORT,109,2,-2,14 +3788196,24,SHORT,110,8,0,77 +3788198,24,SHORT,111,-3,-4,27 +3788200,24,SHORT,112,9,1,99 +3788202,24,SHORT,113,10,5,144 +3788204,24,SHORT,114,4,-4,42 +3788206,24,SHORT,115,2,-2,10 +3788208,24,SHORT,116,0,0,0 +3788210,24,SHORT,117,-3,3,30 +3788212,24,SHORT,118,-38,-1,1473 +3788214,24,SHORT,119,-34,-1,1210 +3788216,24,SHORT,120,-22,-17,791 +3788218,24,SHORT,121,-32,-8,1149 +3788220,24,SHORT,122,-22,-18,845 +3788222,24,SHORT,123,-13,-31,1173 +3788224,24,SHORT,124,-9,-26,807 +3788226,24,SHORT,125,-3,-29,887 +3788228,24,SHORT,126,-4,-35,1277 +3788230,24,SHORT,127,10,-33,1227 +3788232,24,SHORT,128,13,-22,700 +3788234,24,SHORT,129,10,-15,363 +3788236,24,SHORT,130,17,-18,637 +3788238,24,SHORT,131,24,-12,737 +3788240,24,SHORT,132,24,-7,681 +3788242,24,SHORT,133,-5,0,27 +3788244,24,SHORT,134,5,-5,60 +3788246,24,SHORT,135,-3,6,51 +3788248,24,SHORT,136,10,-5,142 +3788250,24,SHORT,137,2,-5,37 +3788252,24,SHORT,138,1,-8,76 +3788254,24,SHORT,139,0,-5,30 +3788256,24,SHORT,140,2,0,7 +3788258,24,SHORT,141,0,10,116 +3788260,24,SHORT,142,0,2,7 +3788262,24,SHORT,143,0,5,32 +3788264,24,SHORT,144,0,16,286 +3788266,24,SHORT,145,6,-2,48 +3788268,24,SHORT,146,3,2,15 +3788270,24,SHORT,147,0,6,42 +3788272,24,SHORT,148,-3,-3,21 +3788274,24,SHORT,149,0,7,51 +3788276,24,SHORT,150,0,0,0 +3788278,24,SHORT,151,0,-1,3 +3788280,24,SHORT,152,1,10,103 +3788282,24,SHORT,153,8,3,85 +3788284,24,SHORT,154,1,-11,123 +3788286,24,SHORT,155,-10,0,115 +3788288,24,SHORT,156,0,-7,50 +3788290,24,SHORT,157,4,-4,34 +3788292,24,SHORT,158,0,1,1 +3788294,24,SHORT,159,0,-1,3 +3788296,24,SHORT,160,0,-7,53 +3788298,24,SHORT,161,-1,-2,6 +3788300,24,SHORT,162,-3,1,14 +3788302,24,SHORT,163,-1,0,2 +3788304,24,SHORT,164,4,-6,57 +3788306,24,SHORT,165,-1,2,5 +3788308,24,SHORT,166,0,-12,149 +3788310,24,SHORT,167,5,-5,61 +3788312,24,SHORT,168,0,-5,29 +3788314,24,SHORT,169,-6,2,48 +3788316,24,SHORT,170,-3,-1,14 +3788318,24,SHORT,171,-3,-1,14 +3788320,24,SHORT,172,5,-6,77 +3788322,24,SHORT,173,1,-2,6 +3788324,24,SHORT,174,-6,0,48 +3788326,24,SHORT,175,-3,6,54 +3788328,24,SHORT,176,3,1,15 +3788330,24,SHORT,177,0,-1,3 +3788332,24,SHORT,178,5,3,42 +3788334,24,SHORT,179,1,-1,7 +3788336,24,SHORT,180,-1,1,4 +3788338,24,SHORT,181,2,4,26 +3788340,24,SHORT,182,8,0,74 +3788342,24,SHORT,183,-6,2,51 +3788344,24,SHORT,184,3,4,30 +3788346,24,SHORT,185,0,-1,1 +3788348,24,SHORT,186,4,-3,32 +3788350,24,SHORT,187,8,3,85 +3788352,24,SHORT,188,5,5,60 +3788354,24,SHORT,189,2,11,136 +3788356,24,SHORT,190,2,12,161 +3788358,24,SHORT,191,-1,1,3 +3788360,24,SHORT,192,3,5,41 +3788362,24,SHORT,193,5,12,191 +3788364,24,SHORT,194,-1,2,6 +3788366,24,SHORT,195,0,11,131 +3788368,24,SHORT,196,-12,11,287 +3788370,24,SHORT,197,-6,11,167 +3788372,24,SHORT,198,-9,7,146 +3788374,24,SHORT,199,-4,3,35 +3788376,24,SHORT,200,-15,9,336 +3788378,24,SHORT,201,-13,3,181 +3788380,24,SHORT,202,-17,-1,303 +3788382,24,SHORT,203,-9,-2,95 +3788384,24,SHORT,204,-16,-7,329 +3788386,24,SHORT,205,-6,-15,281 +3788388,24,SHORT,206,-15,-8,333 +3788390,24,SHORT,207,-3,-21,454 +3788392,24,SHORT,208,4,1,21 +3788394,24,SHORT,209,1,6,39 +3788396,24,SHORT,210,0,-5,33 +3788398,24,SHORT,211,-4,6,67 +3788400,24,SHORT,212,-3,-6,56 +3788402,24,SHORT,213,-1,1,4 +3788404,24,SHORT,214,-5,-7,81 +3788406,24,SHORT,215,2,5,41 +3788408,24,SHORT,216,4,-5,53 +3788410,24,SHORT,217,3,0,16 +3788412,24,SHORT,218,-4,-2,27 +3788414,24,SHORT,219,-2,0,6 +3788416,24,SHORT,220,3,5,39 +3788418,24,SHORT,221,-8,0,78 +3788420,24,SHORT,222,8,-1,72 +3788422,24,SHORT,223,-4,-3,33 +3788424,24,SHORT,224,11,-3,142 +3788426,24,SHORT,225,-2,-2,9 +3788428,24,SHORT,226,-5,-2,33 +3788430,24,SHORT,227,6,0,41 +3788432,24,SHORT,228,-5,1,35 +3788434,24,SHORT,229,-6,5,70 +3788436,24,SHORT,230,8,4,102 +3788438,24,SHORT,231,0,1,3 +3788440,24,SHORT,232,-2,6,49 +3788442,24,SHORT,233,4,-2,24 +3788444,24,SHORT,234,0,2,5 +3788446,24,SHORT,235,7,0,60 +3788448,24,SHORT,236,5,1,34 +3788450,24,SHORT,237,6,5,72 +3788452,24,SHORT,238,-2,-5,37 +3788454,24,SHORT,239,-2,0,4 +3788456,24,SHORT,240,0,0,0 +3788458,24,SHORT,241,-2,3,23 +3788460,24,SHORT,242,2,1,5 +3788462,24,SHORT,243,-1,0,4 +3788464,24,SHORT,244,-2,0,5 +3788466,24,SHORT,245,3,0,13 +3788468,24,SHORT,246,9,-5,120 +3788470,24,SHORT,247,1,3,15 +3788472,24,SHORT,248,4,-12,185 +3788474,24,SHORT,249,4,0,22 +3788476,24,SHORT,250,1,0,1 +3788478,24,SHORT,251,0,-11,127 +3788480,24,SHORT,252,1,-1,7 +3788482,24,SHORT,253,-1,-7,56 +3788484,24,SHORT,254,-2,-5,37 +3788486,24,SHORT,255,-3,-3,27 +3788488,24,SHORT,256,0,3,14 +3788490,24,SHORT,257,-1,-2,9 +3788492,24,SHORT,258,-4,-2,30 +3788494,24,SHORT,259,-7,-4,72 +3788496,24,SHORT,260,-5,5,63 +3788498,24,SHORT,261,-1,-3,12 +3788500,24,SHORT,262,-6,7,101 +3788502,24,SHORT,263,-4,-7,70 +3788504,24,SHORT,264,-2,-3,15 +3788506,24,SHORT,265,2,-4,25 +3788508,24,SHORT,266,-1,8,67 +3788510,24,SHORT,267,4,0,19 +3788512,24,SHORT,268,1,1,3 +3788514,24,SHORT,269,-4,-4,37 +3788516,24,SHORT,270,7,6,99 +3788518,24,SHORT,271,3,-8,88 +3788520,24,SHORT,272,3,-9,96 +3788522,24,SHORT,273,0,10,104 +3788524,24,SHORT,274,-2,3,19 +3788526,24,SHORT,275,6,2,45 +3788528,24,SHORT,276,-3,0,15 +3788530,24,SHORT,277,4,-8,93 +3788532,24,SHORT,278,-7,-2,70 +3788534,24,SHORT,279,-6,0,42 +3788536,24,SHORT,280,0,-1,3 +3788538,24,SHORT,281,-2,0,9 +3788540,24,SHORT,282,2,-2,14 +3788542,24,SHORT,283,0,0,1 +3788544,24,SHORT,284,0,1,1 +3788546,24,SHORT,285,3,0,12 +3788548,24,SHORT,286,1,9,85 +3788550,24,SHORT,287,-2,5,36 +3788552,24,SHORT,288,-14,7,266 +3788554,24,SHORT,289,0,2,7 +3788556,24,SHORT,290,-4,0,16 +3788558,24,SHORT,291,-7,-5,84 +3788560,24,SHORT,292,1,-10,110 +3788562,24,SHORT,293,-6,6,77 +3788564,24,SHORT,294,-7,-3,76 +3788566,24,SHORT,295,-14,-14,419 +3788568,24,SHORT,296,-14,1,218 +3788570,24,SHORT,297,-6,5,68 +3788572,24,SHORT,298,-13,2,195 +3788574,24,SHORT,299,-2,-14,229 +3788576,24,SHORT,300,-6,-3,48 +3788578,24,SHORT,301,-5,-10,141 +3788580,24,SHORT,302,2,-10,118 +3788582,24,SHORT,303,-3,-8,86 +3788584,24,SHORT,304,8,-5,108 +3788586,24,SHORT,305,-3,-10,131 +3788588,24,SHORT,306,5,-1,35 +3788590,24,SHORT,307,9,-7,141 +3788592,24,SHORT,308,-1,-2,8 +3788594,24,SHORT,309,-5,9,113 +3788596,24,SHORT,310,0,2,6 +3788598,24,SHORT,311,-1,-8,71 +3788600,24,SHORT,312,-2,-7,55 +3788602,24,SHORT,313,-4,-4,44 +3788604,24,SHORT,314,2,0,7 +3788606,24,SHORT,315,13,2,178 +3788608,24,SHORT,316,6,-11,166 +3788610,24,SHORT,317,-4,-2,26 +3788612,24,SHORT,318,0,-4,18 +3788614,24,SHORT,319,-1,5,31 +3788616,24,SHORT,320,2,-6,55 +3788618,24,SHORT,321,-1,-3,14 +3788620,24,SHORT,322,2,1,11 +3788622,24,SHORT,323,-7,-6,105 +3788624,24,SHORT,324,7,-8,122 +3788626,24,SHORT,325,4,4,37 +3788628,24,SHORT,326,5,0,31 +3788630,24,SHORT,327,1,0,3 +3788632,24,SHORT,328,1,2,6 +3788634,24,SHORT,329,6,2,43 +3788636,24,SHORT,330,2,1,6 +3788638,24,SHORT,331,-6,3,52 +3788640,24,SHORT,332,0,-1,2 +3788642,24,SHORT,333,1,3,16 +3788644,24,SHORT,334,2,5,30 +3788646,24,SHORT,335,-3,3,24 +3788648,24,SHORT,336,7,-3,78 +3788650,24,SHORT,337,-1,-2,6 +3788652,24,SHORT,338,1,3,14 +3788654,24,SHORT,339,7,-4,77 +3788656,24,SHORT,340,-3,0,15 +3788658,24,SHORT,341,0,7,53 +3788660,24,SHORT,342,-1,1,4 +3788662,24,SHORT,343,0,4,21 +3788664,24,SHORT,344,-6,2,46 +3788666,24,SHORT,345,-5,6,72 +3788668,24,SHORT,346,4,-3,27 +3788670,24,SHORT,347,-3,2,19 +3788672,24,SHORT,348,-3,3,22 +3788674,24,SHORT,349,-9,0,97 +3788676,24,SHORT,350,4,-3,37 +3788678,24,SHORT,351,-2,-4,23 +3788680,24,SHORT,352,1,0,2 +3788682,24,SHORT,353,-4,3,35 +3788684,24,SHORT,354,-5,5,68 +3788686,24,SHORT,355,-3,3,27 +3788688,24,SHORT,356,-3,3,20 +3788690,24,SHORT,357,7,-3,72 +3788692,24,SHORT,358,7,0,56 +3788694,24,SHORT,359,-3,-3,25 +3788696,24,SHORT,360,-1,2,8 +3788698,24,SHORT,361,6,-5,65 +3788700,24,SHORT,362,-9,4,120 +3788702,24,SHORT,363,7,-2,65 +3788704,24,SHORT,364,0,-3,11 +3788706,24,SHORT,365,-4,-6,67 +3788708,24,SHORT,366,-1,4,25 +3788710,24,SHORT,367,-5,5,57 +3788712,24,SHORT,368,-2,-1,7 +3788714,24,SHORT,369,0,9,97 +3788716,24,SHORT,370,4,6,61 +3788718,24,SHORT,371,4,-2,23 +3788720,24,SHORT,372,-2,5,43 +3788722,24,SHORT,373,0,-1,2 +3788724,24,SHORT,374,12,-1,157 +3788726,24,SHORT,375,3,-2,17 +3788728,24,SHORT,376,1,12,156 +3788730,24,SHORT,377,-4,-8,89 +3788732,24,SHORT,378,4,4,33 +3788734,24,SHORT,379,-7,3,76 +3788736,24,SHORT,380,4,1,18 +3788738,24,SHORT,381,-2,-1,8 +3788740,24,SHORT,382,-6,-4,64 +3788742,24,SHORT,383,0,-4,18 +3788744,24,SHORT,384,-3,0,10 +3788746,24,SHORT,385,3,0,9 +3788748,24,SHORT,386,-2,-1,10 +3788750,24,SHORT,387,-1,-1,6 +3788752,24,SHORT,388,-4,-1,25 +3788754,24,SHORT,389,7,-3,76 +3788756,24,SHORT,390,-9,4,117 +3788758,24,SHORT,391,-5,-1,33 +3788760,24,SHORT,392,-7,-8,131 +3788762,24,SHORT,393,5,6,76 +3788764,24,SHORT,394,-5,3,43 +3788766,24,SHORT,395,-12,8,215 +3788768,24,SHORT,396,-3,-7,63 +3788770,24,SHORT,397,-1,-2,7 +3788772,24,SHORT,398,5,-3,46 +3788774,24,SHORT,399,7,-3,60 +3788776,24,SHORT,400,0,5,27 +3788778,24,SHORT,401,-3,-4,37 +3788780,24,SHORT,402,-4,4,41 +3788782,24,SHORT,403,-1,-1,5 +3788784,24,SHORT,404,0,11,142 +3788786,24,SHORT,405,-12,-1,160 +3788788,24,SHORT,406,-9,-1,101 +3788790,24,SHORT,407,-6,11,169 +3788792,24,SHORT,408,5,2,32 +3788794,24,SHORT,409,5,-2,36 +3788796,24,SHORT,410,-1,1,3 +3788798,24,SHORT,411,-1,7,56 +3788800,24,SHORT,412,1,5,34 +3788802,24,SHORT,413,7,0,56 +3788804,24,SHORT,414,-8,2,77 +3788806,24,SHORT,415,8,-7,123 +3788808,24,SHORT,416,3,-9,104 +3788810,24,SHORT,417,-6,0,41 +3788812,24,SHORT,418,7,1,65 +3788814,24,SHORT,419,-2,10,115 +3788816,24,SHORT,420,-3,0,13 +3788818,24,SHORT,421,-6,-5,73 +3788820,24,SHORT,422,-6,5,65 +3788822,24,SHORT,423,-1,6,44 +3788824,24,SHORT,424,7,-1,52 +3788826,24,SHORT,425,-7,-2,53 +3788828,24,SHORT,426,3,-3,24 +3788830,24,SHORT,427,3,0,15 +3788832,24,SHORT,428,0,-3,11 +3788834,24,SHORT,429,-3,6,55 +3788836,24,SHORT,430,-4,12,164 +3788838,24,SHORT,431,1,4,24 +3788840,24,SHORT,432,-4,-1,23 +3788842,24,SHORT,433,8,-2,86 +3788844,24,SHORT,434,-1,2,9 +3788846,24,SHORT,435,2,1,10 +3788848,24,SHORT,436,8,-2,77 +3788850,24,SHORT,437,2,13,173 +3788852,24,SHORT,438,-4,2,33 +3788854,24,SHORT,439,1,0,3 +3788856,24,SHORT,440,9,5,112 +3788858,24,SHORT,441,-6,-3,58 +3788860,24,SHORT,442,-9,8,166 +3788862,24,SHORT,443,13,-1,189 +3788864,24,SHORT,444,-3,0,9 +3788866,24,SHORT,445,8,3,82 +3788868,24,SHORT,446,-3,-5,42 +3788870,24,SHORT,447,0,0,0 +3788872,24,SHORT,448,-13,8,240 +3788874,24,SHORT,449,7,4,75 +3788876,24,SHORT,450,-5,-8,111 +3788878,24,SHORT,451,5,5,55 +3788880,24,SHORT,452,6,-4,56 +3788882,24,SHORT,453,-8,-5,96 +3788884,24,SHORT,454,2,-9,94 +3788886,24,SHORT,455,-10,7,157 +3788888,24,SHORT,456,5,-2,41 +3788890,24,SHORT,457,0,1,2 +3788892,24,SHORT,458,-1,0,1 +3788894,24,SHORT,459,0,-3,15 +3788896,24,SHORT,460,-7,3,63 +3788898,24,SHORT,461,8,3,86 +3788900,24,SHORT,462,0,3,11 +3788902,24,SHORT,463,-1,2,10 +3788904,24,SHORT,464,4,0,17 +3788906,24,SHORT,465,0,7,50 +3788908,24,SHORT,466,6,1,49 +3788910,24,SHORT,467,7,-1,56 +3788912,24,SHORT,468,0,-5,29 +3788914,24,SHORT,469,-5,-4,49 +3788916,24,SHORT,470,-9,-4,117 +3788918,24,SHORT,471,-6,-10,154 +3788920,24,SHORT,472,-5,0,35 +3788922,24,SHORT,473,-5,3,38 +3788924,24,SHORT,474,-1,-5,34 +3788926,24,SHORT,475,0,10,115 +3788928,24,SHORT,476,0,6,38 +3788930,24,SHORT,477,0,4,21 +3788932,24,SHORT,478,10,1,104 +3788934,24,SHORT,479,-2,-5,33 +3788936,24,SHORT,480,2,0,6 +3788938,24,SHORT,481,4,2,23 +3788940,24,SHORT,482,-4,1,19 +3788942,24,SHORT,483,0,0,0 +3788944,24,SHORT,484,1,-1,3 +3788946,24,SHORT,485,0,8,75 +3788948,24,SHORT,486,1,3,17 +3788950,24,SHORT,487,-2,1,6 +3788952,24,SHORT,488,-1,6,39 +3788954,24,SHORT,489,0,6,45 +3788956,24,SHORT,490,-4,5,47 +3788958,24,SHORT,491,6,-3,50 +3788960,24,SHORT,492,6,0,37 +3788962,24,SHORT,493,0,12,156 +3788964,24,SHORT,494,-1,3,14 +3788966,24,SHORT,495,-10,-4,122 +3788968,24,SHORT,496,-4,3,31 +3788970,24,SHORT,497,0,-5,26 +3788972,24,SHORT,498,11,-4,155 +3788974,24,SHORT,499,3,9,103 +3788976,24,SHORT,500,0,-1,1 +3788978,24,SHORT,501,-2,0,7 +3788980,24,SHORT,502,-4,5,54 +3788982,24,SHORT,503,-4,1,26 +3788984,24,SHORT,504,0,5,29 +3788986,24,SHORT,505,-1,-2,7 +3788988,24,SHORT,506,-1,0,1 +3788990,24,SHORT,507,-9,-3,107 +3788992,24,SHORT,508,6,2,51 +3788994,24,SHORT,509,-2,1,8 +3788996,24,SHORT,510,4,-3,28 +3788998,24,SHORT,511,0,-5,34 +3963500,25,SHORT,0,4,9,113 +3963502,25,SHORT,1,2,-2,13 +3963504,25,SHORT,2,6,-12,191 +3963506,25,SHORT,3,-1,3,18 +3963508,25,SHORT,4,-1,-3,14 +3963510,25,SHORT,5,-4,-12,178 +3963512,25,SHORT,6,0,0,0 +3963514,25,SHORT,7,-7,-10,158 +3963516,25,SHORT,8,0,-8,66 +3963518,25,SHORT,9,-7,-5,82 +3963520,25,SHORT,10,-3,0,12 +3963522,25,SHORT,11,-1,12,160 +3963524,25,SHORT,12,-8,-3,88 +3963526,25,SHORT,13,0,8,67 +3963528,25,SHORT,14,-3,7,66 +3963530,25,SHORT,15,-1,11,143 +3963532,25,SHORT,16,0,-1,3 +3963534,25,SHORT,17,-15,-8,301 +3963536,25,SHORT,18,0,10,101 +3963538,25,SHORT,19,10,3,126 +3963540,25,SHORT,20,-2,-1,7 +3963542,25,SHORT,21,0,-1,1 +3963544,25,SHORT,22,1,0,4 +3963546,25,SHORT,23,2,-2,13 +3963548,25,SHORT,24,13,-5,200 +3963550,25,SHORT,25,11,4,155 +3963552,25,SHORT,26,-1,4,19 +3963554,25,SHORT,27,-5,-5,61 +3963556,25,SHORT,28,4,4,42 +3963558,25,SHORT,29,7,5,87 +3963560,25,SHORT,30,0,-10,108 +3963562,25,SHORT,31,12,-2,159 +3963564,25,SHORT,32,-9,-8,150 +3963566,25,SHORT,33,-1,0,4 +3963568,25,SHORT,34,0,-9,87 +3963570,25,SHORT,35,-1,2,9 +3963572,25,SHORT,36,0,6,48 +3963574,25,SHORT,37,7,-6,101 +3963576,25,SHORT,38,8,-6,116 +3963578,25,SHORT,39,0,3,12 +3963580,25,SHORT,40,-11,0,125 +3963582,25,SHORT,41,-3,0,14 +3963584,25,SHORT,42,-4,-1,20 +3963586,25,SHORT,43,-11,-11,265 +3963588,25,SHORT,44,-5,3,46 +3963590,25,SHORT,45,-3,0,9 +3963592,25,SHORT,46,7,0,56 +3963594,25,SHORT,47,12,6,204 +3963596,25,SHORT,48,-12,5,184 +3963598,25,SHORT,49,2,8,71 +3963600,25,SHORT,50,-3,5,45 +3963602,25,SHORT,51,0,1,4 +3963604,25,SHORT,52,2,3,16 +3963606,25,SHORT,53,-1,-9,87 +3963608,25,SHORT,54,4,-7,72 +3963610,25,SHORT,55,7,-5,85 +3963612,25,SHORT,56,1,-1,7 +3963614,25,SHORT,57,-12,3,166 +3963616,25,SHORT,58,-4,3,34 +3963618,25,SHORT,59,-2,0,5 +3963620,25,SHORT,60,-12,1,166 +3963622,25,SHORT,61,-4,0,17 +3963624,25,SHORT,62,-4,-3,35 +3963626,25,SHORT,63,2,6,53 +3963628,25,SHORT,64,-5,-4,47 +3963630,25,SHORT,65,2,-6,43 +3963632,25,SHORT,66,-1,5,36 +3963634,25,SHORT,67,-2,6,52 +3963636,25,SHORT,68,-40,-42,3422 +3963638,25,SHORT,69,-27,-46,2901 +3963640,25,SHORT,70,-13,-51,2856 +3963642,25,SHORT,71,-1,-56,3244 +3963644,25,SHORT,72,7,-63,4104 +3963646,25,SHORT,73,27,-55,3888 +3963648,25,SHORT,74,25,-47,2962 +3963650,25,SHORT,75,44,-46,4190 +3963652,25,SHORT,76,42,-35,3073 +3963654,25,SHORT,77,53,-20,3259 +3963656,25,SHORT,78,56,-8,3241 +3963658,25,SHORT,79,54,-2,2996 +3963660,25,SHORT,80,54,9,3033 +3963662,25,SHORT,81,50,21,3020 +3963664,25,SHORT,82,46,30,3068 +3963666,25,SHORT,83,2,4,25 +3963668,25,SHORT,84,0,10,112 +3963670,25,SHORT,85,2,2,11 +3963672,25,SHORT,86,11,2,126 +3963674,25,SHORT,87,2,3,18 +3963676,25,SHORT,88,-1,1,4 +3963678,25,SHORT,89,-6,4,67 +3963680,25,SHORT,90,0,-4,23 +3963682,25,SHORT,91,-6,2,42 +3963684,25,SHORT,92,-9,-3,99 +3963686,25,SHORT,93,5,-10,137 +3963688,25,SHORT,94,9,0,96 +3963690,25,SHORT,95,-1,1,6 +3963692,25,SHORT,96,-2,0,7 +3963694,25,SHORT,97,3,-3,24 +3963696,25,SHORT,98,6,2,48 +3963698,25,SHORT,99,4,0,20 +3963700,25,SHORT,100,-8,6,116 +3963702,25,SHORT,101,-2,1,7 +3963704,25,SHORT,102,5,-1,37 +3963706,25,SHORT,103,0,0,0 +3963708,25,SHORT,104,-2,8,71 +3963710,25,SHORT,105,0,-1,3 +3963712,25,SHORT,106,1,3,11 +3963714,25,SHORT,107,3,0,15 +3963716,25,SHORT,108,2,0,5 +3963718,25,SHORT,109,1,3,16 +3963720,25,SHORT,110,-5,0,26 +3963722,25,SHORT,111,0,2,5 +3963724,25,SHORT,112,-7,-5,80 +3963726,25,SHORT,113,2,-1,8 +3963728,25,SHORT,114,-4,-1,21 +3963730,25,SHORT,115,7,5,85 +3963732,25,SHORT,116,1,6,45 +3963734,25,SHORT,117,-1,9,96 +3963736,25,SHORT,118,-9,21,559 +3963738,25,SHORT,119,-23,27,1334 +3963740,25,SHORT,120,-8,16,354 +3963742,25,SHORT,121,-23,22,1066 +3963744,25,SHORT,122,-28,11,920 +3963746,25,SHORT,123,-26,0,687 +3963748,25,SHORT,124,-36,5,1331 +3963750,25,SHORT,125,-28,-13,975 +3963752,25,SHORT,126,-26,-18,1045 +3963754,25,SHORT,127,-18,-23,896 +3963756,25,SHORT,128,-12,-22,658 +3963758,25,SHORT,129,-21,-24,1080 +3963760,25,SHORT,130,-10,-28,916 +3963762,25,SHORT,131,0,-29,883 +3963764,25,SHORT,132,1,-24,618 +3963766,25,SHORT,133,3,3,20 +3963768,25,SHORT,134,2,3,14 +3963770,25,SHORT,135,-8,-2,72 +3963772,25,SHORT,136,-2,-1,9 +3963774,25,SHORT,137,3,-4,26 +3963776,25,SHORT,138,0,8,77 +3963778,25,SHORT,139,-3,-2,21 +3963780,25,SHORT,140,-2,3,20 +3963782,25,SHORT,141,-1,4,18 +3963784,25,SHORT,142,-1,0,2 +3963786,25,SHORT,143,0,0,0 +3963788,25,SHORT,144,4,8,87 +3963790,25,SHORT,145,2,1,9 +3963792,25,SHORT,146,5,-8,94 +3963794,25,SHORT,147,7,-6,95 +3963796,25,SHORT,148,0,3,13 +3963798,25,SHORT,149,0,1,2 +3963800,25,SHORT,150,-1,-4,22 +3963802,25,SHORT,151,5,0,32 +3963804,25,SHORT,152,-4,6,62 +3963806,25,SHORT,153,1,-2,5 +3963808,25,SHORT,154,-7,1,67 +3963810,25,SHORT,155,-1,-3,13 +3963812,25,SHORT,156,0,5,26 +3963814,25,SHORT,157,2,-3,22 +3963816,25,SHORT,158,-2,-6,46 +3963818,25,SHORT,159,5,-1,27 +3963820,25,SHORT,160,-10,2,116 +3963822,25,SHORT,161,5,0,33 +3963824,25,SHORT,162,-8,1,66 +3963826,25,SHORT,163,2,-2,11 +3963828,25,SHORT,164,0,3,13 +3963830,25,SHORT,165,0,0,0 +3963832,25,SHORT,166,3,3,24 +3963834,25,SHORT,167,-3,-3,24 +3963836,25,SHORT,168,1,1,3 +3963838,25,SHORT,169,-10,0,118 +3963840,25,SHORT,170,-2,11,131 +3963842,25,SHORT,171,4,0,17 +3963844,25,SHORT,172,3,3,27 +3963846,25,SHORT,173,-1,-8,72 +3963848,25,SHORT,174,-10,9,188 +3963850,25,SHORT,175,0,8,71 +3963852,25,SHORT,176,-7,-5,77 +3963854,25,SHORT,177,3,3,20 +3963856,25,SHORT,178,-9,4,109 +3963858,25,SHORT,179,-7,-2,64 +3963860,25,SHORT,180,4,-7,75 +3963862,25,SHORT,181,6,1,45 +3963864,25,SHORT,182,9,-5,122 +3963866,25,SHORT,183,-2,-5,36 +3963868,25,SHORT,184,-4,-6,71 +3963870,25,SHORT,185,1,6,39 +3963872,25,SHORT,186,0,-8,76 +3963874,25,SHORT,187,0,-1,4 +3963876,25,SHORT,188,-12,1,156 +3963878,25,SHORT,189,-8,-1,70 +3963880,25,SHORT,190,9,-1,87 +3963882,25,SHORT,191,0,-4,21 +3963884,25,SHORT,192,0,-6,41 +3963886,25,SHORT,193,8,15,312 +3963888,25,SHORT,194,-3,3,23 +3963890,25,SHORT,195,3,9,105 +3963892,25,SHORT,196,-10,1,103 +3963894,25,SHORT,197,-12,9,246 +3963896,25,SHORT,198,-12,6,206 +3963898,25,SHORT,199,-17,-8,366 +3963900,25,SHORT,200,-6,0,42 +3963902,25,SHORT,201,-4,-10,144 +3963904,25,SHORT,202,-6,-10,156 +3963906,25,SHORT,203,-4,-15,279 +3963908,25,SHORT,204,4,-25,660 +3963910,25,SHORT,205,-12,-17,443 +3963912,25,SHORT,206,-3,-5,41 +3963914,25,SHORT,207,4,-15,270 +3963916,25,SHORT,208,-3,2,17 +3963918,25,SHORT,209,2,-8,75 +3963920,25,SHORT,210,2,-11,133 +3963922,25,SHORT,211,-2,-2,9 +3963924,25,SHORT,212,6,-2,43 +3963926,25,SHORT,213,4,2,32 +3963928,25,SHORT,214,-4,6,59 +3963930,25,SHORT,215,-6,-6,75 +3963932,25,SHORT,216,-5,4,55 +3963934,25,SHORT,217,6,0,36 +3963936,25,SHORT,218,-2,-3,19 +3963938,25,SHORT,219,-6,2,54 +3963940,25,SHORT,220,-1,3,15 +3963942,25,SHORT,221,-15,1,240 +3963944,25,SHORT,222,2,-6,52 +3963946,25,SHORT,223,-4,3,35 +3963948,25,SHORT,224,0,-1,4 +3963950,25,SHORT,225,-8,6,119 +3963952,25,SHORT,226,4,0,21 +3963954,25,SHORT,227,-12,-1,164 +3963956,25,SHORT,228,-6,0,41 +3963958,25,SHORT,229,-2,-2,13 +3963960,25,SHORT,230,-2,5,30 +3963962,25,SHORT,231,0,2,8 +3963964,25,SHORT,232,0,5,29 +3963966,25,SHORT,233,4,1,17 +3963968,25,SHORT,234,5,0,30 +3963970,25,SHORT,235,-1,-8,79 +3963972,25,SHORT,236,6,7,104 +3963974,25,SHORT,237,4,0,18 +3963976,25,SHORT,238,1,-1,4 +3963978,25,SHORT,239,-14,-3,237 +3963980,25,SHORT,240,5,-3,47 +3963982,25,SHORT,241,-5,-5,59 +3963984,25,SHORT,242,9,4,104 +3963986,25,SHORT,243,-14,-5,233 +3963988,25,SHORT,244,-2,-6,52 +3963990,25,SHORT,245,-4,4,44 +3963992,25,SHORT,246,-2,2,13 +3963994,25,SHORT,247,1,7,63 +3963996,25,SHORT,248,-10,-2,113 +3963998,25,SHORT,249,-3,-4,37 +3964000,25,SHORT,250,-3,10,126 +3964002,25,SHORT,251,-1,-6,41 +3964004,25,SHORT,252,1,2,11 +3964006,25,SHORT,253,-2,-2,14 +3964008,25,SHORT,254,2,-5,37 +3964010,25,SHORT,255,1,1,3 +3964012,25,SHORT,256,11,-7,206 +3964014,25,SHORT,257,-3,1,17 +3964016,25,SHORT,258,3,3,20 +3964018,25,SHORT,259,2,2,14 +3964020,25,SHORT,260,-1,0,3 +3964022,25,SHORT,261,-10,-2,126 +3964024,25,SHORT,262,-7,-12,217 +3964026,25,SHORT,263,3,1,16 +3964028,25,SHORT,264,3,-3,24 +3964030,25,SHORT,265,-9,-11,208 +3964032,25,SHORT,266,4,0,25 +3964034,25,SHORT,267,0,-5,26 +3964036,25,SHORT,268,-5,2,34 +3964038,25,SHORT,269,-6,0,45 +3964040,25,SHORT,270,0,3,11 +3964042,25,SHORT,271,4,1,23 +3964044,25,SHORT,272,4,1,21 +3964046,25,SHORT,273,2,8,74 +3964048,25,SHORT,274,0,-3,11 +3964050,25,SHORT,275,3,-2,19 +3964052,25,SHORT,276,2,-9,102 +3964054,25,SHORT,277,0,3,12 +3964056,25,SHORT,278,0,-4,20 +3964058,25,SHORT,279,0,-2,4 +3964060,25,SHORT,280,-1,4,25 +3964062,25,SHORT,281,1,-8,76 +3964064,25,SHORT,282,1,-5,38 +3964066,25,SHORT,283,0,5,35 +3964068,25,SHORT,284,0,4,17 +3964070,25,SHORT,285,8,6,114 +3964072,25,SHORT,286,-2,0,4 +3964074,25,SHORT,287,1,2,6 +3964076,25,SHORT,288,6,-4,65 +3964078,25,SHORT,289,2,2,14 +3964080,25,SHORT,290,1,-7,58 +3964082,25,SHORT,291,-2,2,14 +3964084,25,SHORT,292,-2,2,9 +3964086,25,SHORT,293,-10,8,173 +3964088,25,SHORT,294,-8,1,70 +3964090,25,SHORT,295,-6,-1,47 +3964092,25,SHORT,296,-8,-3,74 +3964094,25,SHORT,297,-14,0,213 +3964096,25,SHORT,298,-10,-4,136 +3964098,25,SHORT,299,-8,-7,131 +3964100,25,SHORT,300,-5,0,27 +3964102,25,SHORT,301,-6,0,40 +3964104,25,SHORT,302,0,-3,13 +3964106,25,SHORT,303,-1,-8,68 +3964108,25,SHORT,304,-1,0,3 +3964110,25,SHORT,305,-1,-8,74 +3964112,25,SHORT,306,2,-14,210 +3964114,25,SHORT,307,4,0,18 +3964116,25,SHORT,308,0,2,8 +3964118,25,SHORT,309,2,-1,8 +3964120,25,SHORT,310,0,-14,199 +3964122,25,SHORT,311,-4,-3,29 +3964124,25,SHORT,312,-6,-2,53 +3964126,25,SHORT,313,6,1,45 +3964128,25,SHORT,314,4,-2,24 +3964130,25,SHORT,315,3,-2,19 +3964132,25,SHORT,316,-2,0,7 +3964134,25,SHORT,317,0,12,146 +3964136,25,SHORT,318,4,2,29 +3964138,25,SHORT,319,1,-6,45 +3964140,25,SHORT,320,11,6,172 +3964142,25,SHORT,321,6,8,122 +3964144,25,SHORT,322,0,3,10 +3964146,25,SHORT,323,-6,-4,62 +3964148,25,SHORT,324,5,3,40 +3964150,25,SHORT,325,0,-9,100 +3964152,25,SHORT,326,0,-2,7 +3964154,25,SHORT,327,11,0,132 +3964156,25,SHORT,328,1,0,2 +3964158,25,SHORT,329,1,7,63 +3964160,25,SHORT,330,-2,3,20 +3964162,25,SHORT,331,2,-2,11 +3964164,25,SHORT,332,0,6,42 +3964166,25,SHORT,333,-3,3,18 +3964168,25,SHORT,334,-5,-8,99 +3964170,25,SHORT,335,-2,2,13 +3964172,25,SHORT,336,-6,6,82 +3964174,25,SHORT,337,-2,-5,32 +3964176,25,SHORT,338,5,-4,46 +3964178,25,SHORT,339,0,-2,6 +3964180,25,SHORT,340,4,2,25 +3964182,25,SHORT,341,-1,4,24 +3964184,25,SHORT,342,0,7,53 +3964186,25,SHORT,343,-10,-3,118 +3964188,25,SHORT,344,5,8,96 +3964190,25,SHORT,345,-2,10,120 +3964192,25,SHORT,346,7,1,58 +3964194,25,SHORT,347,-1,4,26 +3964196,25,SHORT,348,1,1,7 +3964198,25,SHORT,349,-3,-9,91 +3964200,25,SHORT,350,-3,-2,17 +3964202,25,SHORT,351,-3,1,16 +3964204,25,SHORT,352,-5,-4,55 +3964206,25,SHORT,353,-3,0,9 +3964208,25,SHORT,354,0,-5,32 +3964210,25,SHORT,355,-1,-6,43 +3964212,25,SHORT,356,-6,-8,102 +3964214,25,SHORT,357,-1,1,6 +3964216,25,SHORT,358,5,2,38 +3964218,25,SHORT,359,4,-1,22 +3964220,25,SHORT,360,0,3,13 +3964222,25,SHORT,361,5,-4,49 +3964224,25,SHORT,362,-2,4,27 +3964226,25,SHORT,363,-3,0,12 +3964228,25,SHORT,364,0,10,112 +3964230,25,SHORT,365,-10,-3,125 +3964232,25,SHORT,366,0,3,9 +3964234,25,SHORT,367,0,-1,2 +3964236,25,SHORT,368,3,-3,30 +3964238,25,SHORT,369,3,-7,67 +3964240,25,SHORT,370,-1,1,2 +3964242,25,SHORT,371,-4,-1,20 +3964244,25,SHORT,372,-8,-1,69 +3964246,25,SHORT,373,2,9,92 +3964248,25,SHORT,374,-2,1,10 +3964250,25,SHORT,375,-1,3,12 +3964252,25,SHORT,376,-1,0,1 +3964254,25,SHORT,377,-3,-12,159 +3964256,25,SHORT,378,3,-2,17 +3964258,25,SHORT,379,-1,-1,5 +3964260,25,SHORT,380,-5,0,30 +3964262,25,SHORT,381,0,-3,12 +3964264,25,SHORT,382,7,2,63 +3964266,25,SHORT,383,-9,4,110 +3964268,25,SHORT,384,-2,1,8 +3964270,25,SHORT,385,3,-2,18 +3964272,25,SHORT,386,-9,-3,93 +3964274,25,SHORT,387,-5,8,106 +3964276,25,SHORT,388,0,11,122 +3964278,25,SHORT,389,-6,1,40 +3964280,25,SHORT,390,0,-8,69 +3964282,25,SHORT,391,9,3,97 +3964284,25,SHORT,392,6,-4,72 +3964286,25,SHORT,393,0,0,0 +3964288,25,SHORT,394,0,-3,13 +3964290,25,SHORT,395,0,0,0 +3964292,25,SHORT,396,0,-6,38 +3964294,25,SHORT,397,1,6,41 +3964296,25,SHORT,398,3,1,11 +3964298,25,SHORT,399,10,0,101 +3964300,25,SHORT,400,4,2,22 +3964302,25,SHORT,401,-1,5,32 +3964304,25,SHORT,402,-3,-3,28 +3964306,25,SHORT,403,5,0,33 +3964308,25,SHORT,404,8,-3,80 +3964310,25,SHORT,405,0,-5,28 +3964312,25,SHORT,406,-7,1,51 +3964314,25,SHORT,407,6,-6,88 +3964316,25,SHORT,408,0,1,2 +3964318,25,SHORT,409,-4,1,21 +3964320,25,SHORT,410,6,-1,47 +3964322,25,SHORT,411,-4,4,40 +3964324,25,SHORT,412,-7,3,63 +3964326,25,SHORT,413,-7,7,110 +3964328,25,SHORT,414,10,3,119 +3964330,25,SHORT,415,2,-2,12 +3964332,25,SHORT,416,0,4,22 +3964334,25,SHORT,417,9,1,102 +3964336,25,SHORT,418,-6,-3,59 +3964338,25,SHORT,419,-8,-5,107 +3964340,25,SHORT,420,-3,-8,84 +3964342,25,SHORT,421,-3,-1,14 +3964344,25,SHORT,422,2,0,6 +3964346,25,SHORT,423,-2,-5,36 +3964348,25,SHORT,424,-3,0,10 +3964350,25,SHORT,425,0,7,52 +3964352,25,SHORT,426,7,-3,65 +3964354,25,SHORT,427,-2,-1,9 +3964356,25,SHORT,428,-3,-5,35 +3964358,25,SHORT,429,4,-4,37 +3964360,25,SHORT,430,7,0,52 +3964362,25,SHORT,431,-5,-3,41 +3964364,25,SHORT,432,0,6,38 +3964366,25,SHORT,433,1,-3,11 +3964368,25,SHORT,434,-1,3,15 +3964370,25,SHORT,435,0,3,13 +3964372,25,SHORT,436,1,-3,13 +3964374,25,SHORT,437,5,0,33 +3964376,25,SHORT,438,0,5,30 +3964378,25,SHORT,439,2,11,127 +3964380,25,SHORT,440,7,2,58 +3964382,25,SHORT,441,1,-8,71 +3964384,25,SHORT,442,-5,5,57 +3964386,25,SHORT,443,8,-3,75 +3964388,25,SHORT,444,0,4,24 +3964390,25,SHORT,445,-8,2,79 +3964392,25,SHORT,446,3,-1,11 +3964394,25,SHORT,447,-5,2,34 +3964396,25,SHORT,448,3,2,17 +3964398,25,SHORT,449,0,1,3 +3964400,25,SHORT,450,4,1,23 +3964402,25,SHORT,451,8,0,71 +3964404,25,SHORT,452,9,-3,104 +3964406,25,SHORT,453,5,5,64 +3964408,25,SHORT,454,4,9,114 +3964410,25,SHORT,455,7,-4,79 +3964412,25,SHORT,456,5,6,71 +3964414,25,SHORT,457,-1,5,26 +3964416,25,SHORT,458,1,-6,41 +3964418,25,SHORT,459,1,2,9 +3964420,25,SHORT,460,-5,5,58 +3964422,25,SHORT,461,3,5,36 +3964424,25,SHORT,462,0,1,2 +3964426,25,SHORT,463,0,-2,7 +3964428,25,SHORT,464,8,0,65 +3964430,25,SHORT,465,-5,2,33 +3964432,25,SHORT,466,-5,0,25 +3964434,25,SHORT,467,8,7,117 +3964436,25,SHORT,468,-9,10,188 +3964438,25,SHORT,469,2,-1,8 +3964440,25,SHORT,470,0,-4,24 +3964442,25,SHORT,471,-2,-5,37 +3964444,25,SHORT,472,-11,6,187 +3964446,25,SHORT,473,1,-8,72 +3964448,25,SHORT,474,-3,1,12 +3964450,25,SHORT,475,2,7,59 +3964452,25,SHORT,476,-1,0,3 +3964454,25,SHORT,477,-12,-3,183 +3964456,25,SHORT,478,4,-8,93 +3964458,25,SHORT,479,2,-3,18 +3964460,25,SHORT,480,5,0,29 +3964462,25,SHORT,481,1,-3,13 +3964464,25,SHORT,482,8,2,70 +3964466,25,SHORT,483,-3,-1,14 +3964468,25,SHORT,484,-6,-4,57 +3964470,25,SHORT,485,8,-6,112 +3964472,25,SHORT,486,2,-2,13 +3964474,25,SHORT,487,12,3,164 +3964476,25,SHORT,488,-8,4,87 +3964478,25,SHORT,489,-7,7,107 +3964480,25,SHORT,490,3,-4,36 +3964482,25,SHORT,491,0,-6,37 +3964484,25,SHORT,492,4,3,28 +3964486,25,SHORT,493,1,-4,20 +3964488,25,SHORT,494,-6,2,45 +3964490,25,SHORT,495,-2,0,5 +3964492,25,SHORT,496,1,-5,37 +3964494,25,SHORT,497,1,8,80 +3964496,25,SHORT,498,3,0,13 +3964498,25,SHORT,499,2,6,45 +3964500,25,SHORT,500,3,0,14 +3964502,25,SHORT,501,4,-1,19 +3964504,25,SHORT,502,-4,6,55 +3964506,25,SHORT,503,-4,0,17 +3964508,25,SHORT,504,0,-2,5 +3964510,25,SHORT,505,8,0,74 +3964512,25,SHORT,506,-1,7,51 +3964514,25,SHORT,507,0,3,13 +3964516,25,SHORT,508,2,0,7 +3964518,25,SHORT,509,-6,2,46 +3964520,25,SHORT,510,-1,0,1 +3964522,25,SHORT,511,0,4,24 +4139024,26,SHORT,0,5,-11,176 +4139026,26,SHORT,1,-1,-5,33 +4139028,26,SHORT,2,-2,-8,84 +4139030,26,SHORT,3,1,-6,44 +4139032,26,SHORT,4,0,-2,5 +4139034,26,SHORT,5,7,-4,70 +4139036,26,SHORT,6,5,-6,67 +4139038,26,SHORT,7,-5,-9,126 +4139040,26,SHORT,8,-3,-4,32 +4139042,26,SHORT,9,3,-2,18 +4139044,26,SHORT,10,-4,8,93 +4139046,26,SHORT,11,-14,-4,230 +4139048,26,SHORT,12,0,0,0 +4139050,26,SHORT,13,-1,8,77 +4139052,26,SHORT,14,-1,8,71 +4139054,26,SHORT,15,6,6,80 +4139056,26,SHORT,16,-4,2,24 +4139058,26,SHORT,17,0,-13,181 +4139060,26,SHORT,18,-1,1,7 +4139062,26,SHORT,19,7,2,56 +4139064,26,SHORT,20,8,-1,68 +4139066,26,SHORT,21,-16,5,304 +4139068,26,SHORT,22,-14,4,228 +4139070,26,SHORT,23,8,5,104 +4139072,26,SHORT,24,3,-4,30 +4139074,26,SHORT,25,-10,-10,218 +4139076,26,SHORT,26,-3,9,112 +4139078,26,SHORT,27,-7,12,211 +4139080,26,SHORT,28,-11,-1,134 +4139082,26,SHORT,29,16,-10,372 +4139084,26,SHORT,30,8,6,124 +4139086,26,SHORT,31,-19,-4,415 +4139088,26,SHORT,32,-11,-1,123 +4139090,26,SHORT,33,-11,-6,160 +4139092,26,SHORT,34,-3,2,17 +4139094,26,SHORT,35,-6,7,97 +4139096,26,SHORT,36,-2,-12,157 +4139098,26,SHORT,37,7,-8,136 +4139100,26,SHORT,38,0,7,62 +4139102,26,SHORT,39,1,-5,34 +4139104,26,SHORT,40,12,2,157 +4139106,26,SHORT,41,0,-9,96 +4139108,26,SHORT,42,-1,6,47 +4139110,26,SHORT,43,0,-10,114 +4139112,26,SHORT,44,-4,0,17 +4139114,26,SHORT,45,-2,0,4 +4139116,26,SHORT,46,1,1,3 +4139118,26,SHORT,47,1,-7,55 +4139120,26,SHORT,48,6,0,47 +4139122,26,SHORT,49,1,-7,63 +4139124,26,SHORT,50,0,-2,8 +4139126,26,SHORT,51,3,-4,30 +4139128,26,SHORT,52,4,1,26 +4139130,26,SHORT,53,-1,3,11 +4139132,26,SHORT,54,-1,-4,21 +4139134,26,SHORT,55,7,-2,55 +4139136,26,SHORT,56,3,1,19 +4139138,26,SHORT,57,-4,-5,44 +4139140,26,SHORT,58,-3,0,11 +4139142,26,SHORT,59,5,-1,33 +4139144,26,SHORT,60,-1,0,3 +4139146,26,SHORT,61,-3,-10,113 +4139148,26,SHORT,62,1,2,9 +4139150,26,SHORT,63,0,0,0 +4139152,26,SHORT,64,-5,3,40 +4139154,26,SHORT,65,-3,4,31 +4139156,26,SHORT,66,-1,0,2 +4139158,26,SHORT,67,-9,8,157 +4139160,26,SHORT,68,50,-9,2617 +4139162,26,SHORT,69,52,-6,2829 +4139164,26,SHORT,70,61,2,3784 +4139166,26,SHORT,71,50,17,2907 +4139168,26,SHORT,72,48,19,2714 +4139170,26,SHORT,73,33,40,2730 +4139172,26,SHORT,74,29,41,2566 +4139174,26,SHORT,75,19,56,3611 +4139176,26,SHORT,76,16,58,3661 +4139178,26,SHORT,77,-13,49,2589 +4139180,26,SHORT,78,-8,53,2915 +4139182,26,SHORT,79,-22,48,2839 +4139184,26,SHORT,80,-37,43,3229 +4139186,26,SHORT,81,-34,37,2589 +4139188,26,SHORT,82,-51,32,3771 +4139190,26,SHORT,83,-3,0,15 +4139192,26,SHORT,84,11,-3,135 +4139194,26,SHORT,85,4,-2,31 +4139196,26,SHORT,86,2,0,6 +4139198,26,SHORT,87,0,0,1 +4139200,26,SHORT,88,2,7,57 +4139202,26,SHORT,89,-4,-3,38 +4139204,26,SHORT,90,0,0,1 +4139206,26,SHORT,91,-5,6,66 +4139208,26,SHORT,92,0,-5,28 +4139210,26,SHORT,93,-1,-3,12 +4139212,26,SHORT,94,-2,10,117 +4139214,26,SHORT,95,5,8,96 +4139216,26,SHORT,96,-2,0,5 +4139218,26,SHORT,97,5,-1,35 +4139220,26,SHORT,98,-4,1,22 +4139222,26,SHORT,99,1,4,18 +4139224,26,SHORT,100,-3,-6,50 +4139226,26,SHORT,101,-15,-1,245 +4139228,26,SHORT,102,4,1,20 +4139230,26,SHORT,103,0,0,1 +4139232,26,SHORT,104,-5,-6,71 +4139234,26,SHORT,105,6,-2,52 +4139236,26,SHORT,106,0,3,11 +4139238,26,SHORT,107,5,5,58 +4139240,26,SHORT,108,1,-12,154 +4139242,26,SHORT,109,-3,1,16 +4139244,26,SHORT,110,-4,2,31 +4139246,26,SHORT,111,3,0,11 +4139248,26,SHORT,112,7,-5,95 +4139250,26,SHORT,113,0,-3,13 +4139252,26,SHORT,114,2,-6,48 +4139254,26,SHORT,115,2,2,10 +4139256,26,SHORT,116,1,-13,177 +4139258,26,SHORT,117,4,0,22 +4139260,26,SHORT,118,15,21,706 +4139262,26,SHORT,119,16,28,1076 +4139264,26,SHORT,120,9,29,961 +4139266,26,SHORT,121,-2,15,234 +4139268,26,SHORT,122,-4,25,674 +4139270,26,SHORT,123,-11,34,1323 +4139272,26,SHORT,124,-17,16,567 +4139274,26,SHORT,125,-13,20,601 +4139276,26,SHORT,126,-15,20,670 +4139278,26,SHORT,127,-21,9,554 +4139280,26,SHORT,128,-32,4,1072 +4139282,26,SHORT,129,-23,-3,577 +4139284,26,SHORT,130,-28,-7,885 +4139286,26,SHORT,131,-28,-3,826 +4139288,26,SHORT,132,-14,-17,503 +4139290,26,SHORT,133,5,-8,95 +4139292,26,SHORT,134,2,1,7 +4139294,26,SHORT,135,0,0,0 +4139296,26,SHORT,136,-4,5,56 +4139298,26,SHORT,137,5,-5,65 +4139300,26,SHORT,138,-2,7,59 +4139302,26,SHORT,139,0,-13,170 +4139304,26,SHORT,140,6,1,42 +4139306,26,SHORT,141,7,-1,61 +4139308,26,SHORT,142,-4,1,23 +4139310,26,SHORT,143,9,8,171 +4139312,26,SHORT,144,0,1,2 +4139314,26,SHORT,145,5,0,34 +4139316,26,SHORT,146,2,3,16 +4139318,26,SHORT,147,-2,-3,21 +4139320,26,SHORT,148,4,-3,30 +4139322,26,SHORT,149,7,2,64 +4139324,26,SHORT,150,-3,-6,62 +4139326,26,SHORT,151,-4,-4,37 +4139328,26,SHORT,152,3,2,18 +4139330,26,SHORT,153,4,-3,31 +4139332,26,SHORT,154,2,7,62 +4139334,26,SHORT,155,-6,5,79 +4139336,26,SHORT,156,8,-4,93 +4139338,26,SHORT,157,3,4,35 +4139340,26,SHORT,158,2,1,8 +4139342,26,SHORT,159,3,3,24 +4139344,26,SHORT,160,-4,-6,64 +4139346,26,SHORT,161,0,6,45 +4139348,26,SHORT,162,-5,13,217 +4139350,26,SHORT,163,3,3,25 +4139352,26,SHORT,164,-2,2,12 +4139354,26,SHORT,165,-1,5,28 +4139356,26,SHORT,166,0,-7,58 +4139358,26,SHORT,167,-5,6,73 +4139360,26,SHORT,168,3,0,10 +4139362,26,SHORT,169,7,3,64 +4139364,26,SHORT,170,0,-3,15 +4139366,26,SHORT,171,2,-8,75 +4139368,26,SHORT,172,-1,5,32 +4139370,26,SHORT,173,5,-9,122 +4139372,26,SHORT,174,4,0,18 +4139374,26,SHORT,175,-3,3,23 +4139376,26,SHORT,176,-6,-7,96 +4139378,26,SHORT,177,-7,-12,199 +4139380,26,SHORT,178,1,-2,10 +4139382,26,SHORT,179,-5,-7,87 +4139384,26,SHORT,180,0,-3,12 +4139386,26,SHORT,181,-4,3,32 +4139388,26,SHORT,182,4,7,70 +4139390,26,SHORT,183,-8,1,79 +4139392,26,SHORT,184,-5,7,77 +4139394,26,SHORT,185,-4,-9,117 +4139396,26,SHORT,186,0,6,46 +4139398,26,SHORT,187,-6,0,42 +4139400,26,SHORT,188,7,0,64 +4139402,26,SHORT,189,0,-2,6 +4139404,26,SHORT,190,-3,-1,12 +4139406,26,SHORT,191,-2,-3,16 +4139408,26,SHORT,192,-3,-9,97 +4139410,26,SHORT,193,-7,10,164 +4139412,26,SHORT,194,-12,11,291 +4139414,26,SHORT,195,-14,8,283 +4139416,26,SHORT,196,-17,3,314 +4139418,26,SHORT,197,-9,0,83 +4139420,26,SHORT,198,-15,-5,272 +4139422,26,SHORT,199,-2,-5,43 +4139424,26,SHORT,200,-14,-11,350 +4139426,26,SHORT,201,-5,-6,74 +4139428,26,SHORT,202,-10,-21,568 +4139430,26,SHORT,203,-10,-15,345 +4139432,26,SHORT,204,2,-2,17 +4139434,26,SHORT,205,0,-13,178 +4139436,26,SHORT,206,9,-14,298 +4139438,26,SHORT,207,14,-17,507 +4139440,26,SHORT,208,6,0,45 +4139442,26,SHORT,209,-1,-1,5 +4139444,26,SHORT,210,-2,-8,72 +4139446,26,SHORT,211,0,-2,5 +4139448,26,SHORT,212,5,0,29 +4139450,26,SHORT,213,-1,1,3 +4139452,26,SHORT,214,-6,-1,48 +4139454,26,SHORT,215,-4,-4,35 +4139456,26,SHORT,216,0,-2,4 +4139458,26,SHORT,217,-1,2,6 +4139460,26,SHORT,218,-8,0,64 +4139462,26,SHORT,219,4,-1,24 +4139464,26,SHORT,220,2,1,7 +4139466,26,SHORT,221,0,3,14 +4139468,26,SHORT,222,-6,0,39 +4139470,26,SHORT,223,0,3,11 +4139472,26,SHORT,224,0,3,14 +4139474,26,SHORT,225,-7,-2,61 +4139476,26,SHORT,226,-5,0,32 +4139478,26,SHORT,227,-6,0,40 +4139480,26,SHORT,228,2,-3,13 +4139482,26,SHORT,229,-12,0,152 +4139484,26,SHORT,230,5,-4,49 +4139486,26,SHORT,231,7,1,52 +4139488,26,SHORT,232,7,-4,79 +4139490,26,SHORT,233,-3,5,39 +4139492,26,SHORT,234,-2,8,80 +4139494,26,SHORT,235,0,1,4 +4139496,26,SHORT,236,-3,0,15 +4139498,26,SHORT,237,-7,-5,95 +4139500,26,SHORT,238,3,-3,28 +4139502,26,SHORT,239,3,0,11 +4139504,26,SHORT,240,-1,-6,39 +4139506,26,SHORT,241,0,-6,40 +4139508,26,SHORT,242,0,4,23 +4139510,26,SHORT,243,-2,3,17 +4139512,26,SHORT,244,-1,2,7 +4139514,26,SHORT,245,-6,1,39 +4139516,26,SHORT,246,-1,4,23 +4139518,26,SHORT,247,-1,-4,20 +4139520,26,SHORT,248,5,-10,137 +4139522,26,SHORT,249,-6,-1,44 +4139524,26,SHORT,250,-1,2,10 +4139526,26,SHORT,251,-3,0,14 +4139528,26,SHORT,252,-13,8,255 +4139530,26,SHORT,253,-8,0,73 +4139532,26,SHORT,254,15,3,246 +4139534,26,SHORT,255,-2,8,80 +4139536,26,SHORT,256,-8,-8,160 +4139538,26,SHORT,257,0,0,0 +4139540,26,SHORT,258,0,-9,90 +4139542,26,SHORT,259,-7,16,335 +4139544,26,SHORT,260,-7,0,50 +4139546,26,SHORT,261,0,6,44 +4139548,26,SHORT,262,3,-6,59 +4139550,26,SHORT,263,3,0,11 +4139552,26,SHORT,264,3,0,14 +4139554,26,SHORT,265,3,-4,32 +4139556,26,SHORT,266,3,6,60 +4139558,26,SHORT,267,-4,-1,17 +4139560,26,SHORT,268,-10,1,114 +4139562,26,SHORT,269,-1,0,2 +4139564,26,SHORT,270,6,1,48 +4139566,26,SHORT,271,1,1,5 +4139568,26,SHORT,272,-4,-6,69 +4139570,26,SHORT,273,-1,10,110 +4139572,26,SHORT,274,-5,-3,38 +4139574,26,SHORT,275,1,-5,34 +4139576,26,SHORT,276,2,5,37 +4139578,26,SHORT,277,4,-8,96 +4139580,26,SHORT,278,-1,-1,5 +4139582,26,SHORT,279,-3,5,36 +4139584,26,SHORT,280,0,0,0 +4139586,26,SHORT,281,-5,-1,38 +4139588,26,SHORT,282,4,1,23 +4139590,26,SHORT,283,-11,-2,137 +4139592,26,SHORT,284,11,0,128 +4139594,26,SHORT,285,-3,-5,41 +4139596,26,SHORT,286,10,-1,114 +4139598,26,SHORT,287,-1,-2,7 +4139600,26,SHORT,288,2,-3,18 +4139602,26,SHORT,289,-13,4,194 +4139604,26,SHORT,290,1,-6,38 +4139606,26,SHORT,291,-2,-6,49 +4139608,26,SHORT,292,-2,1,6 +4139610,26,SHORT,293,-2,14,229 +4139612,26,SHORT,294,3,5,41 +4139614,26,SHORT,295,-17,11,452 +4139616,26,SHORT,296,-9,0,93 +4139618,26,SHORT,297,-4,-1,26 +4139620,26,SHORT,298,-16,13,449 +4139622,26,SHORT,299,-3,0,14 +4139624,26,SHORT,300,-6,-2,52 +4139626,26,SHORT,301,-5,-14,228 +4139628,26,SHORT,302,-11,-1,132 +4139630,26,SHORT,303,-4,-14,224 +4139632,26,SHORT,304,-1,-11,133 +4139634,26,SHORT,305,-5,-5,63 +4139636,26,SHORT,306,-6,-8,114 +4139638,26,SHORT,307,-8,-10,189 +4139640,26,SHORT,308,2,-4,31 +4139642,26,SHORT,309,0,0,0 +4139644,26,SHORT,310,-2,4,23 +4139646,26,SHORT,311,-3,-11,146 +4139648,26,SHORT,312,-4,-6,62 +4139650,26,SHORT,313,0,1,3 +4139652,26,SHORT,314,-7,4,73 +4139654,26,SHORT,315,5,-2,40 +4139656,26,SHORT,316,0,3,15 +4139658,26,SHORT,317,3,-2,19 +4139660,26,SHORT,318,0,4,17 +4139662,26,SHORT,319,2,0,6 +4139664,26,SHORT,320,0,2,4 +4139666,26,SHORT,321,2,7,60 +4139668,26,SHORT,322,-6,4,60 +4139670,26,SHORT,323,0,-6,36 +4139672,26,SHORT,324,-2,-2,14 +4139674,26,SHORT,325,-1,1,3 +4139676,26,SHORT,326,-8,8,140 +4139678,26,SHORT,327,6,2,53 +4139680,26,SHORT,328,-1,-3,14 +4139682,26,SHORT,329,-1,-9,86 +4139684,26,SHORT,330,6,1,48 +4139686,26,SHORT,331,1,1,2 +4139688,26,SHORT,332,2,-4,25 +4139690,26,SHORT,333,-3,-8,89 +4139692,26,SHORT,334,-3,7,63 +4139694,26,SHORT,335,-1,4,27 +4139696,26,SHORT,336,2,-4,32 +4139698,26,SHORT,337,0,-4,16 +4139700,26,SHORT,338,-3,9,98 +4139702,26,SHORT,339,-1,-1,4 +4139704,26,SHORT,340,1,1,6 +4139706,26,SHORT,341,0,-4,18 +4139708,26,SHORT,342,0,7,55 +4139710,26,SHORT,343,7,3,62 +4139712,26,SHORT,344,1,0,4 +4139714,26,SHORT,345,-6,4,61 +4139716,26,SHORT,346,2,0,8 +4139718,26,SHORT,347,1,1,3 +4139720,26,SHORT,348,0,-4,17 +4139722,26,SHORT,349,-9,-3,97 +4139724,26,SHORT,350,-1,2,8 +4139726,26,SHORT,351,-1,7,60 +4139728,26,SHORT,352,0,-8,67 +4139730,26,SHORT,353,-1,-3,18 +4139732,26,SHORT,354,0,-1,2 +4139734,26,SHORT,355,5,6,73 +4139736,26,SHORT,356,9,1,95 +4139738,26,SHORT,357,0,-3,12 +4139740,26,SHORT,358,0,-2,5 +4139742,26,SHORT,359,-1,6,41 +4139744,26,SHORT,360,-4,-4,44 +4139746,26,SHORT,361,1,5,31 +4139748,26,SHORT,362,-1,1,6 +4139750,26,SHORT,363,-10,-7,173 +4139752,26,SHORT,364,-5,5,58 +4139754,26,SHORT,365,-7,0,50 +4139756,26,SHORT,366,5,-3,40 +4139758,26,SHORT,367,-3,-5,42 +4139760,26,SHORT,368,0,0,0 +4139762,26,SHORT,369,-7,-12,204 +4139764,26,SHORT,370,6,7,102 +4139766,26,SHORT,371,8,3,85 +4139768,26,SHORT,372,-7,0,52 +4139770,26,SHORT,373,-2,7,63 +4139772,26,SHORT,374,2,-5,37 +4139774,26,SHORT,375,1,4,25 +4139776,26,SHORT,376,6,-1,40 +4139778,26,SHORT,377,1,1,4 +4139780,26,SHORT,378,-8,0,79 +4139782,26,SHORT,379,4,1,21 +4139784,26,SHORT,380,2,16,288 +4139786,26,SHORT,381,1,12,148 +4139788,26,SHORT,382,0,6,39 +4139790,26,SHORT,383,2,10,119 +4139792,26,SHORT,384,-3,1,12 +4139794,26,SHORT,385,4,4,39 +4139796,26,SHORT,386,6,2,50 +4139798,26,SHORT,387,5,-2,38 +4139800,26,SHORT,388,-4,-3,35 +4139802,26,SHORT,389,4,0,16 +4139804,26,SHORT,390,-1,2,6 +4139806,26,SHORT,391,0,0,0 +4139808,26,SHORT,392,4,-1,18 +4139810,26,SHORT,393,5,-2,30 +4139812,26,SHORT,394,-5,0,32 +4139814,26,SHORT,395,-1,6,49 +4139816,26,SHORT,396,9,0,96 +4139818,26,SHORT,397,0,3,15 +4139820,26,SHORT,398,0,-3,11 +4139822,26,SHORT,399,4,0,17 +4139824,26,SHORT,400,-4,7,80 +4139826,26,SHORT,401,-1,2,6 +4139828,26,SHORT,402,1,2,10 +4139830,26,SHORT,403,2,0,4 +4139832,26,SHORT,404,-3,-1,13 +4139834,26,SHORT,405,3,-2,21 +4139836,26,SHORT,406,0,-7,61 +4139838,26,SHORT,407,0,5,28 +4139840,26,SHORT,408,5,0,36 +4139842,26,SHORT,409,0,3,9 +4139844,26,SHORT,410,0,-7,62 +4139846,26,SHORT,411,-2,-2,13 +4139848,26,SHORT,412,0,1,2 +4139850,26,SHORT,413,0,2,5 +4139852,26,SHORT,414,6,17,330 +4139854,26,SHORT,415,0,-8,71 +4139856,26,SHORT,416,1,5,30 +4139858,26,SHORT,417,-5,8,93 +4139860,26,SHORT,418,-2,-5,31 +4139862,26,SHORT,419,3,4,35 +4139864,26,SHORT,420,-2,1,9 +4139866,26,SHORT,421,3,-1,13 +4139868,26,SHORT,422,4,8,98 +4139870,26,SHORT,423,3,5,43 +4139872,26,SHORT,424,-3,-4,34 +4139874,26,SHORT,425,-4,-1,19 +4139876,26,SHORT,426,-6,9,131 +4139878,26,SHORT,427,1,2,9 +4139880,26,SHORT,428,6,12,194 +4139882,26,SHORT,429,0,7,52 +4139884,26,SHORT,430,0,-4,22 +4139886,26,SHORT,431,4,-7,80 +4139888,26,SHORT,432,2,-2,13 +4139890,26,SHORT,433,-3,2,17 +4139892,26,SHORT,434,-7,2,57 +4139894,26,SHORT,435,-8,7,124 +4139896,26,SHORT,436,0,4,17 +4139898,26,SHORT,437,1,1,2 +4139900,26,SHORT,438,1,2,6 +4139902,26,SHORT,439,6,0,37 +4139904,26,SHORT,440,-4,-4,37 +4139906,26,SHORT,441,-4,0,16 +4139908,26,SHORT,442,-1,-1,2 +4139910,26,SHORT,443,5,1,33 +4139912,26,SHORT,444,3,-1,18 +4139914,26,SHORT,445,3,4,32 +4139916,26,SHORT,446,0,1,2 +4139918,26,SHORT,447,13,-11,315 +4139920,26,SHORT,448,1,8,67 +4139922,26,SHORT,449,-3,3,21 +4139924,26,SHORT,450,-9,-4,121 +4139926,26,SHORT,451,5,4,47 +4139928,26,SHORT,452,10,3,120 +4139930,26,SHORT,453,3,-1,12 +4139932,26,SHORT,454,1,-1,6 +4139934,26,SHORT,455,10,0,100 +4139936,26,SHORT,456,-1,-5,29 +4139938,26,SHORT,457,-2,5,35 +4139940,26,SHORT,458,-6,6,73 +4139942,26,SHORT,459,-7,7,119 +4139944,26,SHORT,460,-2,2,11 +4139946,26,SHORT,461,8,2,73 +4139948,26,SHORT,462,-3,5,36 +4139950,26,SHORT,463,5,-4,45 +4139952,26,SHORT,464,4,0,19 +4139954,26,SHORT,465,4,-2,23 +4139956,26,SHORT,466,-4,3,32 +4139958,26,SHORT,467,-6,-11,174 +4139960,26,SHORT,468,0,1,1 +4139962,26,SHORT,469,2,-4,25 +4139964,26,SHORT,470,0,-1,3 +4139966,26,SHORT,471,-3,-2,15 +4139968,26,SHORT,472,7,7,111 +4139970,26,SHORT,473,-2,3,21 +4139972,26,SHORT,474,13,-3,189 +4139974,26,SHORT,475,8,-2,85 +4139976,26,SHORT,476,2,-1,6 +4139978,26,SHORT,477,5,6,67 +4139980,26,SHORT,478,0,3,14 +4139982,26,SHORT,479,-1,-3,11 +4139984,26,SHORT,480,3,0,15 +4139986,26,SHORT,481,-2,0,7 +4139988,26,SHORT,482,0,1,3 +4139990,26,SHORT,483,-3,2,18 +4139992,26,SHORT,484,-3,2,18 +4139994,26,SHORT,485,6,6,74 +4139996,26,SHORT,486,2,-5,35 +4139998,26,SHORT,487,-5,3,47 +4140000,26,SHORT,488,-5,4,57 +4140002,26,SHORT,489,6,1,46 +4140004,26,SHORT,490,-1,0,1 +4140006,26,SHORT,491,-5,-1,35 +4140008,26,SHORT,492,-9,0,94 +4140010,26,SHORT,493,3,-3,21 +4140012,26,SHORT,494,-2,-1,7 +4140014,26,SHORT,495,0,4,23 +4140016,26,SHORT,496,-5,0,29 +4140018,26,SHORT,497,1,1,4 +4140020,26,SHORT,498,1,-7,57 +4140022,26,SHORT,499,-1,0,1 +4140024,26,SHORT,500,0,2,8 +4140026,26,SHORT,501,2,3,17 +4140028,26,SHORT,502,3,-3,27 +4140030,26,SHORT,503,-11,0,133 +4140032,26,SHORT,504,-1,4,18 +4140034,26,SHORT,505,3,3,25 +4140036,26,SHORT,506,-1,4,19 +4140038,26,SHORT,507,1,-1,5 +4140040,26,SHORT,508,-4,7,84 +4140042,26,SHORT,509,-14,-8,291 +4140044,26,SHORT,510,-4,9,105 +4140046,26,SHORT,511,-5,-8,93 +4314548,27,SHORT,0,13,1,185 +4314550,27,SHORT,1,-15,-1,251 +4314552,27,SHORT,2,6,-12,210 +4314554,27,SHORT,3,2,-10,119 +4314556,27,SHORT,4,9,3,99 +4314558,27,SHORT,5,8,0,70 +4314560,27,SHORT,6,-9,2,89 +4314562,27,SHORT,7,4,4,43 +4314564,27,SHORT,8,-12,0,145 +4314566,27,SHORT,9,9,4,101 +4314568,27,SHORT,10,11,24,752 +4314570,27,SHORT,11,-7,1,54 +4314572,27,SHORT,12,-11,3,141 +4314574,27,SHORT,13,5,-7,81 +4314576,27,SHORT,14,-16,16,549 +4314578,27,SHORT,15,9,9,184 +4314580,27,SHORT,16,7,5,75 +4314582,27,SHORT,17,-5,-3,42 +4314584,27,SHORT,18,-6,0,36 +4314586,27,SHORT,19,-5,4,45 +4314588,27,SHORT,20,-11,-5,172 +4314590,27,SHORT,21,8,0,79 +4314592,27,SHORT,22,-1,-3,14 +4314594,27,SHORT,23,2,7,55 +4314596,27,SHORT,24,-7,11,190 +4314598,27,SHORT,25,0,3,13 +4314600,27,SHORT,26,6,-7,108 +4314602,27,SHORT,27,8,-13,238 +4314604,27,SHORT,28,1,-2,5 +4314606,27,SHORT,29,-6,14,237 +4314608,27,SHORT,30,-9,4,108 +4314610,27,SHORT,31,0,5,35 +4314612,27,SHORT,32,5,-1,29 +4314614,27,SHORT,33,0,7,60 +4314616,27,SHORT,34,2,-9,105 +4314618,27,SHORT,35,-2,9,108 +4314620,27,SHORT,36,7,-3,70 +4314622,27,SHORT,37,10,-4,128 +4314624,27,SHORT,38,10,4,139 +4314626,27,SHORT,39,3,6,59 +4314628,27,SHORT,40,-1,3,13 +4314630,27,SHORT,41,7,-2,64 +4314632,27,SHORT,42,-12,-13,354 +4314634,27,SHORT,43,-2,0,7 +4314636,27,SHORT,44,-16,0,257 +4314638,27,SHORT,45,-8,10,187 +4314640,27,SHORT,46,-14,-3,236 +4314642,27,SHORT,47,8,-5,95 +4314644,27,SHORT,48,-1,-4,21 +4314646,27,SHORT,49,9,1,97 +4314648,27,SHORT,50,-6,3,59 +4314650,27,SHORT,51,-1,6,41 +4314652,27,SHORT,52,-5,0,26 +4314654,27,SHORT,53,10,0,102 +4314656,27,SHORT,54,-9,6,129 +4314658,27,SHORT,55,-2,0,9 +4314660,27,SHORT,56,11,4,166 +4314662,27,SHORT,57,5,-3,39 +4314664,27,SHORT,58,-7,-7,112 +4314666,27,SHORT,59,0,2,4 +4314668,27,SHORT,60,0,-1,3 +4314670,27,SHORT,61,0,1,3 +4314672,27,SHORT,62,-10,5,133 +4314674,27,SHORT,63,3,5,41 +4314676,27,SHORT,64,5,-4,53 +4314678,27,SHORT,65,-2,-2,12 +4314680,27,SHORT,66,10,-2,123 +4314682,27,SHORT,67,2,0,6 +4314684,27,SHORT,68,-5,57,3308 +4314686,27,SHORT,69,-11,60,3827 +4314688,27,SHORT,70,-23,48,2894 +4314690,27,SHORT,71,-39,47,3785 +4314692,27,SHORT,72,-44,26,2708 +4314694,27,SHORT,73,-52,24,3403 +4314696,27,SHORT,74,-66,1,4460 +4314698,27,SHORT,75,-56,10,3317 +4314700,27,SHORT,76,-58,-19,3859 +4314702,27,SHORT,77,-50,-25,3180 +4314704,27,SHORT,78,-48,-32,3415 +4314706,27,SHORT,79,-40,-36,2976 +4314708,27,SHORT,80,-21,-44,2497 +4314710,27,SHORT,81,-18,-60,4053 +4314712,27,SHORT,82,0,-56,3148 +4314714,27,SHORT,83,-5,5,55 +4314716,27,SHORT,84,8,8,146 +4314718,27,SHORT,85,7,3,72 +4314720,27,SHORT,86,-3,-5,50 +4314722,27,SHORT,87,-2,0,4 +4314724,27,SHORT,88,-2,0,9 +4314726,27,SHORT,89,2,5,34 +4314728,27,SHORT,90,0,-3,9 +4314730,27,SHORT,91,0,-4,21 +4314732,27,SHORT,92,0,4,18 +4314734,27,SHORT,93,1,-1,2 +4314736,27,SHORT,94,2,2,16 +4314738,27,SHORT,95,1,-3,17 +4314740,27,SHORT,96,-5,-1,31 +4314742,27,SHORT,97,-3,0,9 +4314744,27,SHORT,98,-9,0,90 +4314746,27,SHORT,99,14,4,218 +4314748,27,SHORT,100,2,-1,9 +4314750,27,SHORT,101,2,0,8 +4314752,27,SHORT,102,-13,4,191 +4314754,27,SHORT,103,0,0,0 +4314756,27,SHORT,104,9,-2,99 +4314758,27,SHORT,105,-4,-6,67 +4314760,27,SHORT,106,2,3,16 +4314762,27,SHORT,107,3,4,36 +4314764,27,SHORT,108,-4,0,22 +4314766,27,SHORT,109,0,-2,4 +4314768,27,SHORT,110,3,5,46 +4314770,27,SHORT,111,2,9,97 +4314772,27,SHORT,112,3,4,35 +4314774,27,SHORT,113,-3,-1,12 +4314776,27,SHORT,114,0,2,9 +4314778,27,SHORT,115,-5,0,34 +4314780,27,SHORT,116,-2,7,58 +4314782,27,SHORT,117,17,0,289 +4314784,27,SHORT,118,24,-10,700 +4314786,27,SHORT,119,38,6,1499 +4314788,27,SHORT,120,24,2,611 +4314790,27,SHORT,121,25,7,700 +4314792,27,SHORT,122,24,18,942 +4314794,27,SHORT,123,22,12,656 +4314796,27,SHORT,124,21,23,1039 +4314798,27,SHORT,125,16,17,582 +4314800,27,SHORT,126,6,36,1370 +4314802,27,SHORT,127,2,30,952 +4314804,27,SHORT,128,-4,28,810 +4314806,27,SHORT,129,-13,27,966 +4314808,27,SHORT,130,-11,25,785 +4314810,27,SHORT,131,-16,18,632 +4314812,27,SHORT,132,-16,7,322 +4314814,27,SHORT,133,0,-12,145 +4314816,27,SHORT,134,0,4,16 +4314818,27,SHORT,135,-3,2,19 +4314820,27,SHORT,136,-1,-2,8 +4314822,27,SHORT,137,1,-8,74 +4314824,27,SHORT,138,-1,0,1 +4314826,27,SHORT,139,9,-5,127 +4314828,27,SHORT,140,1,0,2 +4314830,27,SHORT,141,-2,4,29 +4314832,27,SHORT,142,9,-8,164 +4314834,27,SHORT,143,0,11,128 +4314836,27,SHORT,144,-3,2,16 +4314838,27,SHORT,145,0,-5,29 +4314840,27,SHORT,146,-4,0,22 +4314842,27,SHORT,147,0,2,4 +4314844,27,SHORT,148,0,-2,6 +4314846,27,SHORT,149,-12,-2,163 +4314848,27,SHORT,150,6,-3,52 +4314850,27,SHORT,151,3,0,11 +4314852,27,SHORT,152,0,-3,11 +4314854,27,SHORT,153,0,12,168 +4314856,27,SHORT,154,-1,3,17 +4314858,27,SHORT,155,-1,3,15 +4314860,27,SHORT,156,11,11,278 +4314862,27,SHORT,157,-3,0,11 +4314864,27,SHORT,158,0,-2,8 +4314866,27,SHORT,159,-5,-6,77 +4314868,27,SHORT,160,-8,2,75 +4314870,27,SHORT,161,9,-8,163 +4314872,27,SHORT,162,2,-1,11 +4314874,27,SHORT,163,10,5,140 +4314876,27,SHORT,164,0,10,101 +4314878,27,SHORT,165,2,4,24 +4314880,27,SHORT,166,-2,0,4 +4314882,27,SHORT,167,-6,0,46 +4314884,27,SHORT,168,3,0,11 +4314886,27,SHORT,169,10,-8,193 +4314888,27,SHORT,170,1,-1,4 +4314890,27,SHORT,171,6,5,65 +4314892,27,SHORT,172,-12,0,146 +4314894,27,SHORT,173,6,-1,51 +4314896,27,SHORT,174,-2,-4,22 +4314898,27,SHORT,175,-4,0,16 +4314900,27,SHORT,176,6,0,41 +4314902,27,SHORT,177,-2,5,34 +4314904,27,SHORT,178,2,13,195 +4314906,27,SHORT,179,0,5,28 +4314908,27,SHORT,180,-4,5,54 +4314910,27,SHORT,181,7,-1,67 +4314912,27,SHORT,182,0,10,104 +4314914,27,SHORT,183,4,-5,51 +4314916,27,SHORT,184,0,0,0 +4314918,27,SHORT,185,-6,-1,41 +4314920,27,SHORT,186,-1,-1,4 +4314922,27,SHORT,187,-1,11,138 +4314924,27,SHORT,188,4,-1,21 +4314926,27,SHORT,189,-10,0,117 +4314928,27,SHORT,190,-2,6,45 +4314930,27,SHORT,191,1,5,33 +4314932,27,SHORT,192,-7,1,56 +4314934,27,SHORT,193,-8,3,93 +4314936,27,SHORT,194,-13,2,178 +4314938,27,SHORT,195,-11,3,137 +4314940,27,SHORT,196,-20,-10,529 +4314942,27,SHORT,197,-10,0,118 +4314944,27,SHORT,198,-12,-6,204 +4314946,27,SHORT,199,-8,-10,185 +4314948,27,SHORT,200,-12,-20,558 +4314950,27,SHORT,201,-16,-10,384 +4314952,27,SHORT,202,6,-18,390 +4314954,27,SHORT,203,-4,-23,565 +4314956,27,SHORT,204,2,-13,180 +4314958,27,SHORT,205,7,-12,220 +4314960,27,SHORT,206,11,-4,143 +4314962,27,SHORT,207,6,-18,392 +4314964,27,SHORT,208,7,0,60 +4314966,27,SHORT,209,7,5,91 +4314968,27,SHORT,210,3,0,9 +4314970,27,SHORT,211,-5,0,29 +4314972,27,SHORT,212,-3,0,10 +4314974,27,SHORT,213,3,9,95 +4314976,27,SHORT,214,-5,3,35 +4314978,27,SHORT,215,-3,4,31 +4314980,27,SHORT,216,3,-1,14 +4314982,27,SHORT,217,1,2,11 +4314984,27,SHORT,218,-4,4,44 +4314986,27,SHORT,219,12,4,174 +4314988,27,SHORT,220,-5,3,50 +4314990,27,SHORT,221,-2,0,6 +4314992,27,SHORT,222,-1,7,53 +4314994,27,SHORT,223,-1,-1,3 +4314996,27,SHORT,224,11,-2,134 +4314998,27,SHORT,225,-3,-7,70 +4315000,27,SHORT,226,6,1,49 +4315002,27,SHORT,227,3,-9,111 +4315004,27,SHORT,228,-3,2,19 +4315006,27,SHORT,229,0,2,6 +4315008,27,SHORT,230,-7,1,59 +4315010,27,SHORT,231,5,6,71 +4315012,27,SHORT,232,0,0,0 +4315014,27,SHORT,233,3,0,15 +4315016,27,SHORT,234,0,1,1 +4315018,27,SHORT,235,-4,0,19 +4315020,27,SHORT,236,-2,2,14 +4315022,27,SHORT,237,-3,-8,80 +4315024,27,SHORT,238,1,-5,32 +4315026,27,SHORT,239,1,-2,5 +4315028,27,SHORT,240,0,0,1 +4315030,27,SHORT,241,5,0,28 +4315032,27,SHORT,242,4,-2,31 +4315034,27,SHORT,243,3,1,12 +4315036,27,SHORT,244,1,3,13 +4315038,27,SHORT,245,-10,0,115 +4315040,27,SHORT,246,3,-3,31 +4315042,27,SHORT,247,6,1,43 +4315044,27,SHORT,248,-1,0,1 +4315046,27,SHORT,249,0,-10,104 +4315048,27,SHORT,250,6,0,37 +4315050,27,SHORT,251,-1,0,2 +4315052,27,SHORT,252,-4,8,88 +4315054,27,SHORT,253,-7,3,64 +4315056,27,SHORT,254,0,0,0 +4315058,27,SHORT,255,-7,-2,66 +4315060,27,SHORT,256,3,-9,106 +4315062,27,SHORT,257,-3,2,15 +4315064,27,SHORT,258,-3,-2,15 +4315066,27,SHORT,259,3,1,13 +4315068,27,SHORT,260,0,-1,2 +4315070,27,SHORT,261,-4,7,80 +4315072,27,SHORT,262,13,0,182 +4315074,27,SHORT,263,-5,6,65 +4315076,27,SHORT,264,-8,0,73 +4315078,27,SHORT,265,-4,-2,22 +4315080,27,SHORT,266,2,3,16 +4315082,27,SHORT,267,-6,-5,74 +4315084,27,SHORT,268,-1,0,3 +4315086,27,SHORT,269,1,5,32 +4315088,27,SHORT,270,3,-4,30 +4315090,27,SHORT,271,5,-1,32 +4315092,27,SHORT,272,6,5,71 +4315094,27,SHORT,273,8,0,64 +4315096,27,SHORT,274,-1,-5,29 +4315098,27,SHORT,275,1,-4,22 +4315100,27,SHORT,276,0,1,2 +4315102,27,SHORT,277,-4,2,28 +4315104,27,SHORT,278,0,4,16 +4315106,27,SHORT,279,1,5,26 +4315108,27,SHORT,280,-3,0,12 +4315110,27,SHORT,281,3,-3,25 +4315112,27,SHORT,282,-9,-4,99 +4315114,27,SHORT,283,1,-5,32 +4315116,27,SHORT,284,0,2,6 +4315118,27,SHORT,285,-1,3,16 +4315120,27,SHORT,286,6,2,43 +4315122,27,SHORT,287,6,0,43 +4315124,27,SHORT,288,5,-2,41 +4315126,27,SHORT,289,4,3,31 +4315128,27,SHORT,290,-5,0,27 +4315130,27,SHORT,291,-9,4,112 +4315132,27,SHORT,292,-2,-2,12 +4315134,27,SHORT,293,1,-4,21 +4315136,27,SHORT,294,-5,12,183 +4315138,27,SHORT,295,0,11,121 +4315140,27,SHORT,296,-3,4,34 +4315142,27,SHORT,297,-1,9,96 +4315144,27,SHORT,298,0,1,3 +4315146,27,SHORT,299,2,11,147 +4315148,27,SHORT,300,-9,6,129 +4315150,27,SHORT,301,-10,0,101 +4315152,27,SHORT,302,-7,6,95 +4315154,27,SHORT,303,-4,3,30 +4315156,27,SHORT,304,-2,-2,10 +4315158,27,SHORT,305,-7,1,52 +4315160,27,SHORT,306,-4,4,46 +4315162,27,SHORT,307,-4,-2,26 +4315164,27,SHORT,308,6,0,44 +4315166,27,SHORT,309,0,-3,10 +4315168,27,SHORT,310,0,0,1 +4315170,27,SHORT,311,-2,-1,6 +4315172,27,SHORT,312,-4,-3,26 +4315174,27,SHORT,313,-5,-3,45 +4315176,27,SHORT,314,-11,10,228 +4315178,27,SHORT,315,4,4,41 +4315180,27,SHORT,316,-2,-8,79 +4315182,27,SHORT,317,7,4,70 +4315184,27,SHORT,318,0,7,53 +4315186,27,SHORT,319,4,-2,29 +4315188,27,SHORT,320,2,2,12 +4315190,27,SHORT,321,-5,1,38 +4315192,27,SHORT,322,2,2,15 +4315194,27,SHORT,323,-4,1,17 +4315196,27,SHORT,324,-6,2,41 +4315198,27,SHORT,325,-4,1,27 +4315200,27,SHORT,326,0,-1,1 +4315202,27,SHORT,327,-7,11,193 +4315204,27,SHORT,328,-1,0,3 +4315206,27,SHORT,329,1,1,2 +4315208,27,SHORT,330,4,1,26 +4315210,27,SHORT,331,-4,8,92 +4315212,27,SHORT,332,-7,11,183 +4315214,27,SHORT,333,-9,4,100 +4315216,27,SHORT,334,-2,3,16 +4315218,27,SHORT,335,-4,0,16 +4315220,27,SHORT,336,7,2,63 +4315222,27,SHORT,337,-1,-2,10 +4315224,27,SHORT,338,7,0,58 +4315226,27,SHORT,339,0,3,15 +4315228,27,SHORT,340,1,9,94 +4315230,27,SHORT,341,8,-3,86 +4315232,27,SHORT,342,1,-4,20 +4315234,27,SHORT,343,4,-2,24 +4315236,27,SHORT,344,7,0,57 +4315238,27,SHORT,345,4,1,24 +4315240,27,SHORT,346,0,0,0 +4315242,27,SHORT,347,5,-7,94 +4315244,27,SHORT,348,6,3,55 +4315246,27,SHORT,349,-3,0,11 +4315248,27,SHORT,350,0,-2,5 +4315250,27,SHORT,351,4,0,18 +4315252,27,SHORT,352,-2,-2,13 +4315254,27,SHORT,353,1,-6,49 +4315256,27,SHORT,354,-2,0,4 +4315258,27,SHORT,355,12,0,147 +4315260,27,SHORT,356,1,-5,33 +4315262,27,SHORT,357,-1,-5,36 +4315264,27,SHORT,358,1,0,2 +4315266,27,SHORT,359,0,-4,21 +4315268,27,SHORT,360,-7,2,62 +4315270,27,SHORT,361,-1,-5,34 +4315272,27,SHORT,362,5,2,30 +4315274,27,SHORT,363,4,4,39 +4315276,27,SHORT,364,-4,1,26 +4315278,27,SHORT,365,-6,16,306 +4315280,27,SHORT,366,-1,5,34 +4315282,27,SHORT,367,10,9,204 +4315284,27,SHORT,368,6,-2,41 +4315286,27,SHORT,369,0,-3,12 +4315288,27,SHORT,370,-7,-4,73 +4315290,27,SHORT,371,-3,4,35 +4315292,27,SHORT,372,6,0,37 +4315294,27,SHORT,373,6,-4,66 +4315296,27,SHORT,374,9,4,107 +4315298,27,SHORT,375,0,-2,8 +4315300,27,SHORT,376,0,-3,11 +4315302,27,SHORT,377,4,8,93 +4315304,27,SHORT,378,0,10,104 +4315306,27,SHORT,379,-12,-2,170 +4315308,27,SHORT,380,3,8,90 +4315310,27,SHORT,381,11,-2,143 +4315312,27,SHORT,382,4,6,60 +4315314,27,SHORT,383,0,4,24 +4315316,27,SHORT,384,2,0,5 +4315318,27,SHORT,385,-1,2,8 +4315320,27,SHORT,386,-4,0,19 +4315322,27,SHORT,387,6,-5,78 +4315324,27,SHORT,388,4,-11,153 +4315326,27,SHORT,389,-2,0,6 +4315328,27,SHORT,390,13,-6,216 +4315330,27,SHORT,391,-4,-2,22 +4315332,27,SHORT,392,9,3,96 +4315334,27,SHORT,393,11,3,135 +4315336,27,SHORT,394,1,-3,17 +4315338,27,SHORT,395,-8,-8,136 +4315340,27,SHORT,396,-4,-1,27 +4315342,27,SHORT,397,8,-1,67 +4315344,27,SHORT,398,-3,11,147 +4315346,27,SHORT,399,4,-6,65 +4315348,27,SHORT,400,-5,-2,38 +4315350,27,SHORT,401,-5,0,26 +4315352,27,SHORT,402,-2,-6,42 +4315354,27,SHORT,403,-7,0,53 +4315356,27,SHORT,404,0,3,10 +4315358,27,SHORT,405,-4,4,46 +4315360,27,SHORT,406,0,4,19 +4315362,27,SHORT,407,-5,0,32 +4315364,27,SHORT,408,-2,-1,7 +4315366,27,SHORT,409,1,-1,4 +4315368,27,SHORT,410,-8,12,229 +4315370,27,SHORT,411,-3,2,21 +4315372,27,SHORT,412,-2,-7,64 +4315374,27,SHORT,413,1,1,3 +4315376,27,SHORT,414,-8,-6,121 +4315378,27,SHORT,415,1,0,3 +4315380,27,SHORT,416,-13,3,194 +4315382,27,SHORT,417,3,-5,43 +4315384,27,SHORT,418,2,0,4 +4315386,27,SHORT,419,-2,-3,17 +4315388,27,SHORT,420,-1,-4,24 +4315390,27,SHORT,421,-3,-3,24 +4315392,27,SHORT,422,1,-4,24 +4315394,27,SHORT,423,1,2,9 +4315396,27,SHORT,424,-4,1,21 +4315398,27,SHORT,425,5,-3,40 +4315400,27,SHORT,426,-3,3,25 +4315402,27,SHORT,427,-2,-3,22 +4315404,27,SHORT,428,1,5,37 +4315406,27,SHORT,429,-5,-1,33 +4315408,27,SHORT,430,5,0,27 +4315410,27,SHORT,431,1,-2,11 +4315412,27,SHORT,432,-2,0,5 +4315414,27,SHORT,433,3,1,19 +4315416,27,SHORT,434,-1,-1,3 +4315418,27,SHORT,435,-2,-4,26 +4315420,27,SHORT,436,0,0,1 +4315422,27,SHORT,437,-3,0,9 +4315424,27,SHORT,438,0,-7,56 +4315426,27,SHORT,439,0,2,5 +4315428,27,SHORT,440,1,0,1 +4315430,27,SHORT,441,0,0,0 +4315432,27,SHORT,442,0,1,2 +4315434,27,SHORT,443,4,2,32 +4315436,27,SHORT,444,11,4,151 +4315438,27,SHORT,445,-3,5,41 +4315440,27,SHORT,446,2,-4,29 +4315442,27,SHORT,447,-10,0,105 +4315444,27,SHORT,448,-7,-2,55 +4315446,27,SHORT,449,6,3,53 +4315448,27,SHORT,450,9,2,96 +4315450,27,SHORT,451,0,2,7 +4315452,27,SHORT,452,1,3,15 +4315454,27,SHORT,453,-2,1,8 +4315456,27,SHORT,454,1,-2,8 +4315458,27,SHORT,455,4,6,70 +4315460,27,SHORT,456,0,0,0 +4315462,27,SHORT,457,3,8,76 +4315464,27,SHORT,458,0,-1,2 +4315466,27,SHORT,459,0,0,0 +4315468,27,SHORT,460,-1,-12,162 +4315470,27,SHORT,461,10,-1,105 +4315472,27,SHORT,462,5,0,31 +4315474,27,SHORT,463,-3,-1,11 +4315476,27,SHORT,464,-6,-3,58 +4315478,27,SHORT,465,8,6,116 +4315480,27,SHORT,466,6,0,41 +4315482,27,SHORT,467,-1,-1,5 +4315484,27,SHORT,468,2,0,6 +4315486,27,SHORT,469,3,2,17 +4315488,27,SHORT,470,0,-4,20 +4315490,27,SHORT,471,-5,-3,44 +4315492,27,SHORT,472,11,-4,145 +4315494,27,SHORT,473,0,2,6 +4315496,27,SHORT,474,0,2,7 +4315498,27,SHORT,475,-8,2,76 +4315500,27,SHORT,476,0,9,92 +4315502,27,SHORT,477,1,-8,81 +4315504,27,SHORT,478,8,-6,124 +4315506,27,SHORT,479,2,-2,13 +4315508,27,SHORT,480,-2,3,13 +4315510,27,SHORT,481,0,-1,3 +4315512,27,SHORT,482,0,0,0 +4315514,27,SHORT,483,-3,3,21 +4315516,27,SHORT,484,-2,8,79 +4315518,27,SHORT,485,-1,-7,61 +4315520,27,SHORT,486,6,-1,44 +4315522,27,SHORT,487,0,2,5 +4315524,27,SHORT,488,-7,-2,59 +4315526,27,SHORT,489,-3,1,15 +4315528,27,SHORT,490,-2,6,44 +4315530,27,SHORT,491,-9,-8,169 +4315532,27,SHORT,492,-5,1,32 +4315534,27,SHORT,493,-6,5,78 +4315536,27,SHORT,494,-2,0,6 +4315538,27,SHORT,495,2,0,7 +4315540,27,SHORT,496,-2,-9,94 +4315542,27,SHORT,497,0,6,46 +4315544,27,SHORT,498,9,2,94 +4315546,27,SHORT,499,0,-2,7 +4315548,27,SHORT,500,2,-2,13 +4315550,27,SHORT,501,4,-5,53 +4315552,27,SHORT,502,-2,0,7 +4315554,27,SHORT,503,-1,-7,57 +4315556,27,SHORT,504,5,-8,97 +4315558,27,SHORT,505,2,-11,145 +4315560,27,SHORT,506,6,1,45 +4315562,27,SHORT,507,0,0,1 +4315564,27,SHORT,508,7,1,51 +4315566,27,SHORT,509,0,-4,20 +4315568,27,SHORT,510,7,4,73 +4315570,27,SHORT,511,3,-8,79 +4490072,28,SHORT,0,1,-2,9 +4490074,28,SHORT,1,5,5,59 +4490076,28,SHORT,2,-4,4,37 +4490078,28,SHORT,3,-5,1,31 +4490080,28,SHORT,4,-2,5,33 +4490082,28,SHORT,5,-13,-3,206 +4490084,28,SHORT,6,-1,-9,94 +4490086,28,SHORT,7,-1,-7,66 +4490088,28,SHORT,8,-12,0,149 +4490090,28,SHORT,9,-7,-13,234 +4490092,28,SHORT,10,0,0,0 +4490094,28,SHORT,11,8,0,76 +4490096,28,SHORT,12,-3,-1,18 +4490098,28,SHORT,13,4,6,66 +4490100,28,SHORT,14,5,7,83 +4490102,28,SHORT,15,-9,8,153 +4490104,28,SHORT,16,13,-1,174 +4490106,28,SHORT,17,0,1,3 +4490108,28,SHORT,18,-8,-1,80 +4490110,28,SHORT,19,9,2,100 +4490112,28,SHORT,20,4,0,17 +4490114,28,SHORT,21,-5,-9,123 +4490116,28,SHORT,22,-17,-2,329 +4490118,28,SHORT,23,0,-9,95 +4490120,28,SHORT,24,-4,15,259 +4490122,28,SHORT,25,-2,3,19 +4490124,28,SHORT,26,5,-9,108 +4490126,28,SHORT,27,0,4,23 +4490128,28,SHORT,28,-5,3,47 +4490130,28,SHORT,29,5,13,199 +4490132,28,SHORT,30,-9,3,90 +4490134,28,SHORT,31,0,7,62 +4490136,28,SHORT,32,-13,-1,182 +4490138,28,SHORT,33,9,-11,211 +4490140,28,SHORT,34,0,8,65 +4490142,28,SHORT,35,-5,-3,42 +4490144,28,SHORT,36,9,0,87 +4490146,28,SHORT,37,0,1,2 +4490148,28,SHORT,38,0,-5,26 +4490150,28,SHORT,39,-1,2,12 +4490152,28,SHORT,40,3,-7,64 +4490154,28,SHORT,41,4,0,23 +4490156,28,SHORT,42,-4,0,25 +4490158,28,SHORT,43,-5,8,109 +4490160,28,SHORT,44,-6,0,38 +4490162,28,SHORT,45,3,-2,16 +4490164,28,SHORT,46,-16,0,262 +4490166,28,SHORT,47,-3,5,40 +4490168,28,SHORT,48,5,0,28 +4490170,28,SHORT,49,0,-5,26 +4490172,28,SHORT,50,3,0,10 +4490174,28,SHORT,51,-3,0,15 +4490176,28,SHORT,52,0,7,55 +4490178,28,SHORT,53,-9,-2,95 +4490180,28,SHORT,54,4,-7,69 +4490182,28,SHORT,55,-2,5,36 +4490184,28,SHORT,56,1,1,5 +4490186,28,SHORT,57,-9,-3,99 +4490188,28,SHORT,58,-3,0,15 +4490190,28,SHORT,59,3,-1,15 +4490192,28,SHORT,60,12,6,199 +4490194,28,SHORT,61,-4,-1,20 +4490196,28,SHORT,62,1,0,3 +4490198,28,SHORT,63,11,8,192 +4490200,28,SHORT,64,0,0,1 +4490202,28,SHORT,65,1,3,15 +4490204,28,SHORT,66,1,2,10 +4490206,28,SHORT,67,-1,3,12 +4490208,28,SHORT,68,-47,-28,3034 +4490210,28,SHORT,69,-39,-37,2947 +4490212,28,SHORT,70,-33,-50,3697 +4490214,28,SHORT,71,-19,-47,2623 +4490216,28,SHORT,72,-4,-65,4261 +4490218,28,SHORT,73,-5,-60,3662 +4490220,28,SHORT,74,16,-49,2754 +4490222,28,SHORT,75,33,-40,2766 +4490224,28,SHORT,76,27,-38,2291 +4490226,28,SHORT,77,41,-43,3633 +4490228,28,SHORT,78,39,-27,2289 +4490230,28,SHORT,79,49,-15,2711 +4490232,28,SHORT,80,52,-4,2797 +4490234,28,SHORT,81,53,5,2865 +4490236,28,SHORT,82,54,17,3288 +4490238,28,SHORT,83,-1,-1,3 +4490240,28,SHORT,84,-1,0,1 +4490242,28,SHORT,85,2,5,34 +4490244,28,SHORT,86,5,-2,40 +4490246,28,SHORT,87,0,8,66 +4490248,28,SHORT,88,-3,2,18 +4490250,28,SHORT,89,0,3,12 +4490252,28,SHORT,90,-7,0,50 +4490254,28,SHORT,91,3,6,54 +4490256,28,SHORT,92,3,-15,249 +4490258,28,SHORT,93,3,-1,17 +4490260,28,SHORT,94,0,-3,15 +4490262,28,SHORT,95,0,9,89 +4490264,28,SHORT,96,-1,-3,12 +4490266,28,SHORT,97,-4,0,19 +4490268,28,SHORT,98,5,2,32 +4490270,28,SHORT,99,-9,-2,95 +4490272,28,SHORT,100,-5,0,33 +4490274,28,SHORT,101,-3,-4,28 +4490276,28,SHORT,102,-7,-7,101 +4490278,28,SHORT,103,-7,6,106 +4490280,28,SHORT,104,-4,2,25 +4490282,28,SHORT,105,4,8,98 +4490284,28,SHORT,106,6,4,66 +4490286,28,SHORT,107,-2,-3,14 +4490288,28,SHORT,108,4,3,25 +4490290,28,SHORT,109,4,0,23 +4490292,28,SHORT,110,1,11,123 +4490294,28,SHORT,111,3,3,25 +4490296,28,SHORT,112,0,-1,2 +4490298,28,SHORT,113,7,4,73 +4490300,28,SHORT,114,6,-4,59 +4490302,28,SHORT,115,0,-4,24 +4490304,28,SHORT,116,0,3,12 +4490306,28,SHORT,117,2,1,5 +4490308,28,SHORT,118,1,-31,1000 +4490310,28,SHORT,119,3,-37,1426 +4490312,28,SHORT,120,23,-19,921 +4490314,28,SHORT,121,20,-20,842 +4490316,28,SHORT,122,20,-22,939 +4490318,28,SHORT,123,18,-18,715 +4490320,28,SHORT,124,26,-8,784 +4490322,28,SHORT,125,32,-7,1112 +4490324,28,SHORT,126,33,4,1172 +4490326,28,SHORT,127,34,11,1317 +4490328,28,SHORT,128,35,18,1579 +4490330,28,SHORT,129,19,19,738 +4490332,28,SHORT,130,14,22,715 +4490334,28,SHORT,131,16,24,898 +4490336,28,SHORT,132,11,24,756 +4490338,28,SHORT,133,1,0,4 +4490340,28,SHORT,134,0,1,3 +4490342,28,SHORT,135,-3,-4,29 +4490344,28,SHORT,136,-3,1,12 +4490346,28,SHORT,137,3,2,19 +4490348,28,SHORT,138,-7,2,55 +4490350,28,SHORT,139,-4,0,16 +4490352,28,SHORT,140,-3,0,12 +4490354,28,SHORT,141,-6,-2,51 +4490356,28,SHORT,142,2,-8,73 +4490358,28,SHORT,143,7,-1,55 +4490360,28,SHORT,144,8,5,101 +4490362,28,SHORT,145,-12,2,152 +4490364,28,SHORT,146,0,-5,29 +4490366,28,SHORT,147,-6,0,48 +4490368,28,SHORT,148,1,0,2 +4490370,28,SHORT,149,-5,0,26 +4490372,28,SHORT,150,8,6,122 +4490374,28,SHORT,151,-1,-1,4 +4490376,28,SHORT,152,2,6,54 +4490378,28,SHORT,153,-6,4,65 +4490380,28,SHORT,154,9,-5,111 +4490382,28,SHORT,155,-1,1,3 +4490384,28,SHORT,156,0,-5,29 +4490386,28,SHORT,157,-7,-2,59 +4490388,28,SHORT,158,-8,0,70 +4490390,28,SHORT,159,-2,-4,22 +4490392,28,SHORT,160,-4,8,92 +4490394,28,SHORT,161,-4,0,16 +4490396,28,SHORT,162,-1,-2,5 +4490398,28,SHORT,163,1,1,6 +4490400,28,SHORT,164,-5,0,36 +4490402,28,SHORT,165,1,-4,23 +4490404,28,SHORT,166,4,0,24 +4490406,28,SHORT,167,0,-3,10 +4490408,28,SHORT,168,-3,-3,24 +4490410,28,SHORT,169,-1,-7,61 +4490412,28,SHORT,170,0,5,27 +4490414,28,SHORT,171,-1,-2,9 +4490416,28,SHORT,172,-5,-5,52 +4490418,28,SHORT,173,4,-3,28 +4490420,28,SHORT,174,-3,-3,20 +4490422,28,SHORT,175,13,6,224 +4490424,28,SHORT,176,-8,-3,92 +4490426,28,SHORT,177,-7,3,60 +4490428,28,SHORT,178,-2,-1,7 +4490430,28,SHORT,179,-6,0,37 +4490432,28,SHORT,180,-1,1,6 +4490434,28,SHORT,181,6,0,45 +4490436,28,SHORT,182,2,-8,74 +4490438,28,SHORT,183,-1,3,16 +4490440,28,SHORT,184,-3,-5,43 +4490442,28,SHORT,185,0,-2,8 +4490444,28,SHORT,186,6,6,92 +4490446,28,SHORT,187,-9,-7,159 +4490448,28,SHORT,188,5,-1,31 +4490450,28,SHORT,189,4,0,17 +4490452,28,SHORT,190,-6,0,37 +4490454,28,SHORT,191,0,4,16 +4490456,28,SHORT,192,-2,5,40 +4490458,28,SHORT,193,-17,9,376 +4490460,28,SHORT,194,-10,-7,157 +4490462,28,SHORT,195,-14,-8,269 +4490464,28,SHORT,196,-2,-8,75 +4490466,28,SHORT,197,-5,-15,253 +4490468,28,SHORT,198,1,-14,222 +4490470,28,SHORT,199,-5,-10,154 +4490472,28,SHORT,200,8,-15,299 +4490474,28,SHORT,201,5,-24,604 +4490476,28,SHORT,202,6,-10,154 +4490478,28,SHORT,203,12,-4,175 +4490480,28,SHORT,204,2,-14,219 +4490482,28,SHORT,205,9,-6,125 +4490484,28,SHORT,206,9,-12,264 +4490486,28,SHORT,207,10,-17,433 +4490488,28,SHORT,208,-3,5,48 +4490490,28,SHORT,209,-6,5,68 +4490492,28,SHORT,210,7,3,68 +4490494,28,SHORT,211,-8,2,75 +4490496,28,SHORT,212,-1,7,52 +4490498,28,SHORT,213,10,1,101 +4490500,28,SHORT,214,-7,-2,66 +4490502,28,SHORT,215,-7,-6,96 +4490504,28,SHORT,216,2,0,7 +4490506,28,SHORT,217,-6,2,46 +4490508,28,SHORT,218,1,3,12 +4490510,28,SHORT,219,-11,0,127 +4490512,28,SHORT,220,4,-1,19 +4490514,28,SHORT,221,-4,-4,45 +4490516,28,SHORT,222,2,3,20 +4490518,28,SHORT,223,0,-4,19 +4490520,28,SHORT,224,-2,-1,7 +4490522,28,SHORT,225,0,4,20 +4490524,28,SHORT,226,2,-4,21 +4490526,28,SHORT,227,1,8,71 +4490528,28,SHORT,228,0,-4,22 +4490530,28,SHORT,229,-5,0,26 +4490532,28,SHORT,230,2,1,10 +4490534,28,SHORT,231,3,0,11 +4490536,28,SHORT,232,-1,0,3 +4490538,28,SHORT,233,-1,1,4 +4490540,28,SHORT,234,2,3,22 +4490542,28,SHORT,235,-7,-4,70 +4490544,28,SHORT,236,1,-1,4 +4490546,28,SHORT,237,1,-6,41 +4490548,28,SHORT,238,0,-6,39 +4490550,28,SHORT,239,-1,-7,60 +4490552,28,SHORT,240,-4,-7,79 +4490554,28,SHORT,241,1,-4,24 +4490556,28,SHORT,242,-3,6,53 +4490558,28,SHORT,243,3,-1,16 +4490560,28,SHORT,244,0,0,0 +4490562,28,SHORT,245,1,-2,5 +4490564,28,SHORT,246,-1,0,2 +4490566,28,SHORT,247,2,3,23 +4490568,28,SHORT,248,4,2,23 +4490570,28,SHORT,249,-10,7,165 +4490572,28,SHORT,250,2,1,10 +4490574,28,SHORT,251,4,-1,23 +4490576,28,SHORT,252,1,-7,57 +4490578,28,SHORT,253,3,-3,23 +4490580,28,SHORT,254,4,2,32 +4490582,28,SHORT,255,-7,0,58 +4490584,28,SHORT,256,4,0,20 +4490586,28,SHORT,257,0,0,0 +4490588,28,SHORT,258,-1,4,19 +4490590,28,SHORT,259,0,-3,12 +4490592,28,SHORT,260,-4,-2,23 +4490594,28,SHORT,261,2,3,19 +4490596,28,SHORT,262,1,-7,58 +4490598,28,SHORT,263,4,-8,88 +4490600,28,SHORT,264,5,-11,163 +4490602,28,SHORT,265,4,-1,18 +4490604,28,SHORT,266,0,0,1 +4490606,28,SHORT,267,-3,1,12 +4490608,28,SHORT,268,0,5,28 +4490610,28,SHORT,269,-4,-1,18 +4490612,28,SHORT,270,2,1,9 +4490614,28,SHORT,271,0,6,38 +4490616,28,SHORT,272,4,-2,22 +4490618,28,SHORT,273,0,10,118 +4490620,28,SHORT,274,-2,-2,11 +4490622,28,SHORT,275,13,9,259 +4490624,28,SHORT,276,7,-2,65 +4490626,28,SHORT,277,-7,8,129 +4490628,28,SHORT,278,1,-3,16 +4490630,28,SHORT,279,0,2,5 +4490632,28,SHORT,280,-6,-3,53 +4490634,28,SHORT,281,4,-5,47 +4490636,28,SHORT,282,6,-4,70 +4490638,28,SHORT,283,-4,-4,34 +4490640,28,SHORT,284,-10,-4,132 +4490642,28,SHORT,285,9,-1,99 +4490644,28,SHORT,286,4,-2,26 +4490646,28,SHORT,287,-6,-10,147 +4490648,28,SHORT,288,5,0,32 +4490650,28,SHORT,289,-6,-6,77 +4490652,28,SHORT,290,2,-2,13 +4490654,28,SHORT,291,0,-2,8 +4490656,28,SHORT,292,-1,3,17 +4490658,28,SHORT,293,7,-1,66 +4490660,28,SHORT,294,10,5,142 +4490662,28,SHORT,295,8,7,134 +4490664,28,SHORT,296,5,13,199 +4490666,28,SHORT,297,10,4,130 +4490668,28,SHORT,298,-3,5,49 +4490670,28,SHORT,299,0,0,0 +4490672,28,SHORT,300,3,18,341 +4490674,28,SHORT,301,-4,7,84 +4490676,28,SHORT,302,-5,4,50 +4490678,28,SHORT,303,-12,6,199 +4490680,28,SHORT,304,-8,12,218 +4490682,28,SHORT,305,-3,3,20 +4490684,28,SHORT,306,-2,2,12 +4490686,28,SHORT,307,-5,1,31 +4490688,28,SHORT,308,-1,0,1 +4490690,28,SHORT,309,5,-1,29 +4490692,28,SHORT,310,-3,0,11 +4490694,28,SHORT,311,6,-2,43 +4490696,28,SHORT,312,-7,-6,96 +4490698,28,SHORT,313,-8,-1,81 +4490700,28,SHORT,314,1,0,2 +4490702,28,SHORT,315,7,-6,90 +4490704,28,SHORT,316,4,-5,49 +4490706,28,SHORT,317,0,-12,145 +4490708,28,SHORT,318,-4,0,23 +4490710,28,SHORT,319,0,0,1 +4490712,28,SHORT,320,1,-3,16 +4490714,28,SHORT,321,-7,-13,249 +4490716,28,SHORT,322,-7,3,63 +4490718,28,SHORT,323,5,0,26 +4490720,28,SHORT,324,-3,-2,21 +4490722,28,SHORT,325,-4,-1,18 +4490724,28,SHORT,326,-2,10,124 +4490726,28,SHORT,327,-4,-2,30 +4490728,28,SHORT,328,5,6,65 +4490730,28,SHORT,329,0,3,13 +4490732,28,SHORT,330,1,0,3 +4490734,28,SHORT,331,-2,4,23 +4490736,28,SHORT,332,2,-7,55 +4490738,28,SHORT,333,-3,-5,38 +4490740,28,SHORT,334,-2,9,92 +4490742,28,SHORT,335,1,-1,5 +4490744,28,SHORT,336,-3,-6,52 +4490746,28,SHORT,337,2,-8,80 +4490748,28,SHORT,338,-5,0,32 +4490750,28,SHORT,339,-4,4,45 +4490752,28,SHORT,340,6,1,38 +4490754,28,SHORT,341,3,-4,33 +4490756,28,SHORT,342,2,-2,11 +4490758,28,SHORT,343,-2,0,6 +4490760,28,SHORT,344,4,2,24 +4490762,28,SHORT,345,1,-9,100 +4490764,28,SHORT,346,-3,-2,19 +4490766,28,SHORT,347,-1,0,3 +4490768,28,SHORT,348,0,6,49 +4490770,28,SHORT,349,-1,-1,3 +4490772,28,SHORT,350,5,10,148 +4490774,28,SHORT,351,1,6,46 +4490776,28,SHORT,352,6,4,54 +4490778,28,SHORT,353,0,-2,4 +4490780,28,SHORT,354,4,-12,184 +4490782,28,SHORT,355,-3,1,15 +4490784,28,SHORT,356,0,5,28 +4490786,28,SHORT,357,-3,5,41 +4490788,28,SHORT,358,7,0,62 +4490790,28,SHORT,359,-5,-1,30 +4490792,28,SHORT,360,-2,0,4 +4490794,28,SHORT,361,1,-2,8 +4490796,28,SHORT,362,1,7,54 +4490798,28,SHORT,363,1,-1,5 +4490800,28,SHORT,364,3,7,60 +4490802,28,SHORT,365,-6,3,49 +4490804,28,SHORT,366,5,-1,35 +4490806,28,SHORT,367,-1,-6,49 +4490808,28,SHORT,368,-3,-5,45 +4490810,28,SHORT,369,-4,6,62 +4490812,28,SHORT,370,1,0,1 +4490814,28,SHORT,371,2,0,4 +4490816,28,SHORT,372,4,-2,26 +4490818,28,SHORT,373,-3,-7,63 +4490820,28,SHORT,374,3,5,37 +4490822,28,SHORT,375,12,5,183 +4490824,28,SHORT,376,3,10,129 +4490826,28,SHORT,377,0,2,6 +4490828,28,SHORT,378,6,1,37 +4490830,28,SHORT,379,-9,2,104 +4490832,28,SHORT,380,-12,9,245 +4490834,28,SHORT,381,4,8,91 +4490836,28,SHORT,382,-2,-12,157 +4490838,28,SHORT,383,-4,-5,47 +4490840,28,SHORT,384,-6,-6,86 +4490842,28,SHORT,385,-6,4,56 +4490844,28,SHORT,386,3,3,24 +4490846,28,SHORT,387,0,3,10 +4490848,28,SHORT,388,-5,-1,27 +4490850,28,SHORT,389,-8,0,72 +4490852,28,SHORT,390,0,-8,73 +4490854,28,SHORT,391,-5,0,29 +4490856,28,SHORT,392,0,1,3 +4490858,28,SHORT,393,4,9,116 +4490860,28,SHORT,394,-2,13,177 +4490862,28,SHORT,395,7,1,58 +4490864,28,SHORT,396,3,2,13 +4490866,28,SHORT,397,-2,-2,8 +4490868,28,SHORT,398,-1,6,44 +4490870,28,SHORT,399,-6,4,62 +4490872,28,SHORT,400,6,0,37 +4490874,28,SHORT,401,3,0,12 +4490876,28,SHORT,402,0,0,0 +4490878,28,SHORT,403,-6,4,68 +4490880,28,SHORT,404,-2,0,6 +4490882,28,SHORT,405,0,6,37 +4490884,28,SHORT,406,-10,2,119 +4490886,28,SHORT,407,0,-2,9 +4490888,28,SHORT,408,3,-6,52 +4490890,28,SHORT,409,-2,3,19 +4490892,28,SHORT,410,-5,7,89 +4490894,28,SHORT,411,1,5,34 +4490896,28,SHORT,412,0,8,68 +4490898,28,SHORT,413,2,3,20 +4490900,28,SHORT,414,-8,0,68 +4490902,28,SHORT,415,-5,2,30 +4490904,28,SHORT,416,3,-3,28 +4490906,28,SHORT,417,2,5,31 +4490908,28,SHORT,418,-1,6,49 +4490910,28,SHORT,419,1,-6,41 +4490912,28,SHORT,420,3,0,16 +4490914,28,SHORT,421,2,-1,8 +4490916,28,SHORT,422,-3,-8,76 +4490918,28,SHORT,423,0,-8,80 +4490920,28,SHORT,424,11,-1,140 +4490922,28,SHORT,425,2,3,16 +4490924,28,SHORT,426,-4,-5,54 +4490926,28,SHORT,427,-1,-11,144 +4490928,28,SHORT,428,3,-1,10 +4490930,28,SHORT,429,-1,4,26 +4490932,28,SHORT,430,0,0,0 +4490934,28,SHORT,431,-7,-9,155 +4490936,28,SHORT,432,0,-4,19 +4490938,28,SHORT,433,2,-5,34 +4490940,28,SHORT,434,0,0,0 +4490942,28,SHORT,435,-3,0,11 +4490944,28,SHORT,436,-3,-1,11 +4490946,28,SHORT,437,5,-2,43 +4490948,28,SHORT,438,0,2,7 +4490950,28,SHORT,439,5,1,29 +4490952,28,SHORT,440,-8,-1,72 +4490954,28,SHORT,441,3,0,11 +4490956,28,SHORT,442,-2,3,19 +4490958,28,SHORT,443,0,-4,18 +4490960,28,SHORT,444,2,-6,40 +4490962,28,SHORT,445,-11,6,166 +4490964,28,SHORT,446,8,6,118 +4490966,28,SHORT,447,7,-1,54 +4490968,28,SHORT,448,2,-1,10 +4490970,28,SHORT,449,7,-1,61 +4490972,28,SHORT,450,-1,-5,28 +4490974,28,SHORT,451,5,-7,90 +4490976,28,SHORT,452,1,-1,3 +4490978,28,SHORT,453,2,9,94 +4490980,28,SHORT,454,3,0,11 +4490982,28,SHORT,455,-1,-1,5 +4490984,28,SHORT,456,-1,0,4 +4490986,28,SHORT,457,-6,3,63 +4490988,28,SHORT,458,5,-4,47 +4490990,28,SHORT,459,0,3,10 +4490992,28,SHORT,460,-9,-4,112 +4490994,28,SHORT,461,0,0,0 +4490996,28,SHORT,462,-9,9,183 +4490998,28,SHORT,463,5,0,34 +4491000,28,SHORT,464,1,1,4 +4491002,28,SHORT,465,2,-1,9 +4491004,28,SHORT,466,-4,0,22 +4491006,28,SHORT,467,0,-1,2 +4491008,28,SHORT,468,0,2,8 +4491010,28,SHORT,469,-2,0,7 +4491012,28,SHORT,470,4,10,121 +4491014,28,SHORT,471,1,-4,23 +4491016,28,SHORT,472,1,2,8 +4491018,28,SHORT,473,0,0,0 +4491020,28,SHORT,474,0,0,0 +4491022,28,SHORT,475,-4,-8,86 +4491024,28,SHORT,476,6,-10,146 +4491026,28,SHORT,477,-1,-2,6 +4491028,28,SHORT,478,1,-4,18 +4491030,28,SHORT,479,2,-5,34 +4491032,28,SHORT,480,0,6,38 +4491034,28,SHORT,481,0,8,70 +4491036,28,SHORT,482,-2,3,21 +4491038,28,SHORT,483,6,0,44 +4491040,28,SHORT,484,-2,-7,69 +4491042,28,SHORT,485,-1,1,4 +4491044,28,SHORT,486,6,-7,97 +4491046,28,SHORT,487,0,-3,12 +4491048,28,SHORT,488,7,-1,57 +4491050,28,SHORT,489,3,1,11 +4491052,28,SHORT,490,-3,2,22 +4491054,28,SHORT,491,0,4,16 +4491056,28,SHORT,492,-4,0,16 +4491058,28,SHORT,493,0,0,0 +4491060,28,SHORT,494,6,8,112 +4491062,28,SHORT,495,-2,-1,10 +4491064,28,SHORT,496,0,2,5 +4491066,28,SHORT,497,2,4,27 +4491068,28,SHORT,498,-7,3,73 +4491070,28,SHORT,499,-4,6,58 +4491072,28,SHORT,500,2,3,21 +4491074,28,SHORT,501,1,8,75 +4491076,28,SHORT,502,6,-3,58 +4491078,28,SHORT,503,1,7,54 +4491080,28,SHORT,504,-2,10,127 +4491082,28,SHORT,505,-10,6,144 +4491084,28,SHORT,506,3,6,48 +4491086,28,SHORT,507,4,4,38 +4491088,28,SHORT,508,4,-4,42 +4491090,28,SHORT,509,0,3,11 +4491092,28,SHORT,510,-5,1,30 +4491094,28,SHORT,511,1,-6,43 +4665596,29,SHORT,0,5,0,28 +4665598,29,SHORT,1,-2,1,7 +4665600,29,SHORT,2,1,0,4 +4665602,29,SHORT,3,4,0,20 +4665604,29,SHORT,4,1,-2,10 +4665606,29,SHORT,5,-3,10,124 +4665608,29,SHORT,6,12,-3,176 +4665610,29,SHORT,7,7,0,57 +4665612,29,SHORT,8,8,4,83 +4665614,29,SHORT,9,0,5,31 +4665616,29,SHORT,10,1,9,83 +4665618,29,SHORT,11,12,3,176 +4665620,29,SHORT,12,-2,7,62 +4665622,29,SHORT,13,-2,-5,31 +4665624,29,SHORT,14,-13,-2,179 +4665626,29,SHORT,15,1,-7,53 +4665628,29,SHORT,16,4,14,241 +4665630,29,SHORT,17,7,4,68 +4665632,29,SHORT,18,3,0,12 +4665634,29,SHORT,19,3,-6,48 +4665636,29,SHORT,20,0,-15,234 +4665638,29,SHORT,21,5,0,25 +4665640,29,SHORT,22,-4,-1,25 +4665642,29,SHORT,23,2,6,43 +4665644,29,SHORT,24,0,7,51 +4665646,29,SHORT,25,0,6,39 +4665648,29,SHORT,26,-5,12,176 +4665650,29,SHORT,27,8,0,73 +4665652,29,SHORT,28,2,12,162 +4665654,29,SHORT,29,0,-7,51 +4665656,29,SHORT,30,0,-9,87 +4665658,29,SHORT,31,0,3,16 +4665660,29,SHORT,32,7,-16,331 +4665662,29,SHORT,33,4,-11,146 +4665664,29,SHORT,34,-3,-6,47 +4665666,29,SHORT,35,6,-3,60 +4665668,29,SHORT,36,4,13,212 +4665670,29,SHORT,37,-5,-10,135 +4665672,29,SHORT,38,0,-2,7 +4665674,29,SHORT,39,0,11,133 +4665676,29,SHORT,40,-1,6,50 +4665678,29,SHORT,41,-8,-1,76 +4665680,29,SHORT,42,5,-15,281 +4665682,29,SHORT,43,0,-10,108 +4665684,29,SHORT,44,-14,1,216 +4665686,29,SHORT,45,6,-2,44 +4665688,29,SHORT,46,-2,-11,140 +4665690,29,SHORT,47,-2,-4,22 +4665692,29,SHORT,48,3,-10,126 +4665694,29,SHORT,49,-4,-9,121 +4665696,29,SHORT,50,4,5,52 +4665698,29,SHORT,51,9,-3,101 +4665700,29,SHORT,52,1,1,3 +4665702,29,SHORT,53,-8,0,72 +4665704,29,SHORT,54,4,0,17 +4665706,29,SHORT,55,1,2,6 +4665708,29,SHORT,56,4,-2,29 +4665710,29,SHORT,57,3,0,12 +4665712,29,SHORT,58,-3,-1,14 +4665714,29,SHORT,59,6,-2,45 +4665716,29,SHORT,60,-9,3,101 +4665718,29,SHORT,61,0,2,5 +4665720,29,SHORT,62,-7,2,60 +4665722,29,SHORT,63,-6,-1,46 +4665724,29,SHORT,64,7,1,56 +4665726,29,SHORT,65,4,-1,18 +4665728,29,SHORT,66,-4,-4,40 +4665730,29,SHORT,67,1,4,25 +4665732,29,SHORT,68,48,-39,3897 +4665734,29,SHORT,69,44,-16,2220 +4665736,29,SHORT,70,53,-16,3195 +4665738,29,SHORT,71,50,0,2555 +4665740,29,SHORT,72,57,8,3420 +4665742,29,SHORT,73,48,18,2727 +4665744,29,SHORT,74,44,30,2892 +4665746,29,SHORT,75,34,42,3009 +4665748,29,SHORT,76,28,45,2904 +4665750,29,SHORT,77,21,53,3365 +4665752,29,SHORT,78,9,51,2723 +4665754,29,SHORT,79,-3,51,2661 +4665756,29,SHORT,80,-14,61,3954 +4665758,29,SHORT,81,-32,47,3350 +4665760,29,SHORT,82,-34,45,3279 +4665762,29,SHORT,83,0,1,3 +4665764,29,SHORT,84,-11,3,149 +4665766,29,SHORT,85,6,0,49 +4665768,29,SHORT,86,0,-5,26 +4665770,29,SHORT,87,6,4,63 +4665772,29,SHORT,88,5,-5,66 +4665774,29,SHORT,89,1,-2,7 +4665776,29,SHORT,90,-7,3,73 +4665778,29,SHORT,91,0,7,51 +4665780,29,SHORT,92,7,0,63 +4665782,29,SHORT,93,6,-2,52 +4665784,29,SHORT,94,5,6,76 +4665786,29,SHORT,95,-1,-1,6 +4665788,29,SHORT,96,7,0,54 +4665790,29,SHORT,97,-5,1,27 +4665792,29,SHORT,98,-2,11,125 +4665794,29,SHORT,99,-7,2,56 +4665796,29,SHORT,100,-2,6,45 +4665798,29,SHORT,101,2,0,5 +4665800,29,SHORT,102,8,-4,95 +4665802,29,SHORT,103,-5,-3,37 +4665804,29,SHORT,104,1,-3,13 +4665806,29,SHORT,105,-7,-1,58 +4665808,29,SHORT,106,1,4,26 +4665810,29,SHORT,107,4,8,83 +4665812,29,SHORT,108,-6,0,39 +4665814,29,SHORT,109,-3,7,66 +4665816,29,SHORT,110,0,1,1 +4665818,29,SHORT,111,0,-2,5 +4665820,29,SHORT,112,2,2,12 +4665822,29,SHORT,113,0,0,0 +4665824,29,SHORT,114,-2,-1,10 +4665826,29,SHORT,115,-3,-1,17 +4665828,29,SHORT,116,-4,0,24 +4665830,29,SHORT,117,-2,-3,15 +4665832,29,SHORT,118,-28,-14,1018 +4665834,29,SHORT,119,-15,-17,572 +4665836,29,SHORT,120,-21,-18,782 +4665838,29,SHORT,121,-14,-14,414 +4665840,29,SHORT,122,-9,-36,1413 +4665842,29,SHORT,123,-6,-22,574 +4665844,29,SHORT,124,6,-30,997 +4665846,29,SHORT,125,14,-23,773 +4665848,29,SHORT,126,16,-21,739 +4665850,29,SHORT,127,20,-22,935 +4665852,29,SHORT,128,20,-12,558 +4665854,29,SHORT,129,27,-12,902 +4665856,29,SHORT,130,28,-8,855 +4665858,29,SHORT,131,21,-1,479 +4665860,29,SHORT,132,28,6,867 +4665862,29,SHORT,133,6,1,50 +4665864,29,SHORT,134,0,0,0 +4665866,29,SHORT,135,0,5,28 +4665868,29,SHORT,136,0,-2,7 +4665870,29,SHORT,137,4,-5,46 +4665872,29,SHORT,138,0,-1,3 +4665874,29,SHORT,139,1,3,14 +4665876,29,SHORT,140,0,-7,54 +4665878,29,SHORT,141,-3,7,72 +4665880,29,SHORT,142,1,-6,40 +4665882,29,SHORT,143,-8,17,366 +4665884,29,SHORT,144,-12,-16,414 +4665886,29,SHORT,145,2,0,7 +4665888,29,SHORT,146,0,-3,11 +4665890,29,SHORT,147,-2,-2,14 +4665892,29,SHORT,148,-3,-3,21 +4665894,29,SHORT,149,-7,0,56 +4665896,29,SHORT,150,-2,-8,81 +4665898,29,SHORT,151,-12,-7,220 +4665900,29,SHORT,152,5,-6,78 +4665902,29,SHORT,153,-1,0,3 +4665904,29,SHORT,154,3,0,9 +4665906,29,SHORT,155,-2,-4,31 +4665908,29,SHORT,156,-3,-9,110 +4665910,29,SHORT,157,1,7,52 +4665912,29,SHORT,158,2,9,106 +4665914,29,SHORT,159,5,1,36 +4665916,29,SHORT,160,5,-1,35 +4665918,29,SHORT,161,0,5,29 +4665920,29,SHORT,162,0,-4,21 +4665922,29,SHORT,163,-3,0,14 +4665924,29,SHORT,164,-2,1,8 +4665926,29,SHORT,165,0,1,1 +4665928,29,SHORT,166,0,0,0 +4665930,29,SHORT,167,-2,0,7 +4665932,29,SHORT,168,0,-2,8 +4665934,29,SHORT,169,-6,-5,72 +4665936,29,SHORT,170,6,-5,67 +4665938,29,SHORT,171,0,-2,5 +4665940,29,SHORT,172,1,6,42 +4665942,29,SHORT,173,-8,1,78 +4665944,29,SHORT,174,5,3,39 +4665946,29,SHORT,175,-9,5,123 +4665948,29,SHORT,176,2,-9,91 +4665950,29,SHORT,177,0,-3,9 +4665952,29,SHORT,178,-6,1,49 +4665954,29,SHORT,179,2,2,15 +4665956,29,SHORT,180,-6,1,47 +4665958,29,SHORT,181,7,-4,75 +4665960,29,SHORT,182,9,0,86 +4665962,29,SHORT,183,4,6,67 +4665964,29,SHORT,184,4,8,88 +4665966,29,SHORT,185,-5,-6,79 +4665968,29,SHORT,186,-9,-1,85 +4665970,29,SHORT,187,-1,0,3 +4665972,29,SHORT,188,-1,2,7 +4665974,29,SHORT,189,2,-3,19 +4665976,29,SHORT,190,2,-3,20 +4665978,29,SHORT,191,-7,-1,59 +4665980,29,SHORT,192,3,-10,119 +4665982,29,SHORT,193,-8,0,80 +4665984,29,SHORT,194,-14,-12,369 +4665986,29,SHORT,195,-8,1,80 +4665988,29,SHORT,196,-14,-11,333 +4665990,29,SHORT,197,-3,-11,143 +4665992,29,SHORT,198,6,-15,287 +4665994,29,SHORT,199,6,-13,216 +4665996,29,SHORT,200,3,-11,149 +4665998,29,SHORT,201,3,-14,213 +4666000,29,SHORT,202,6,1,46 +4666002,29,SHORT,203,15,-23,816 +4666004,29,SHORT,204,23,-11,662 +4666006,29,SHORT,205,-4,-6,53 +4666008,29,SHORT,206,9,0,86 +4666010,29,SHORT,207,14,3,217 +4666012,29,SHORT,208,-3,-5,42 +4666014,29,SHORT,209,7,-2,69 +4666016,29,SHORT,210,-7,-6,104 +4666018,29,SHORT,211,-1,2,7 +4666020,29,SHORT,212,0,2,5 +4666022,29,SHORT,213,0,5,32 +4666024,29,SHORT,214,0,-6,43 +4666026,29,SHORT,215,-5,-1,31 +4666028,29,SHORT,216,10,-6,145 +4666030,29,SHORT,217,1,7,55 +4666032,29,SHORT,218,-8,5,107 +4666034,29,SHORT,219,4,0,22 +4666036,29,SHORT,220,1,-5,30 +4666038,29,SHORT,221,-3,4,27 +4666040,29,SHORT,222,0,0,0 +4666042,29,SHORT,223,-3,5,44 +4666044,29,SHORT,224,5,1,37 +4666046,29,SHORT,225,-3,0,11 +4666048,29,SHORT,226,4,0,17 +4666050,29,SHORT,227,4,6,63 +4666052,29,SHORT,228,8,0,79 +4666054,29,SHORT,229,-3,-5,37 +4666056,29,SHORT,230,-4,-9,101 +4666058,29,SHORT,231,0,3,14 +4666060,29,SHORT,232,5,0,30 +4666062,29,SHORT,233,2,9,98 +4666064,29,SHORT,234,0,-2,5 +4666066,29,SHORT,235,9,5,123 +4666068,29,SHORT,236,0,-1,3 +4666070,29,SHORT,237,1,-1,2 +4666072,29,SHORT,238,4,1,20 +4666074,29,SHORT,239,4,1,22 +4666076,29,SHORT,240,-2,0,5 +4666078,29,SHORT,241,0,-3,15 +4666080,29,SHORT,242,-1,3,17 +4666082,29,SHORT,243,2,-1,7 +4666084,29,SHORT,244,-8,0,65 +4666086,29,SHORT,245,8,10,180 +4666088,29,SHORT,246,4,1,22 +4666090,29,SHORT,247,0,-7,55 +4666092,29,SHORT,248,7,5,82 +4666094,29,SHORT,249,1,1,4 +4666096,29,SHORT,250,-4,0,20 +4666098,29,SHORT,251,-3,4,32 +4666100,29,SHORT,252,5,-8,103 +4666102,29,SHORT,253,0,1,1 +4666104,29,SHORT,254,-3,1,16 +4666106,29,SHORT,255,4,-1,21 +4666108,29,SHORT,256,5,-1,36 +4666110,29,SHORT,257,-2,5,33 +4666112,29,SHORT,258,4,-7,76 +4666114,29,SHORT,259,-6,10,150 +4666116,29,SHORT,260,-3,4,37 +4666118,29,SHORT,261,-7,2,66 +4666120,29,SHORT,262,-2,1,10 +4666122,29,SHORT,263,0,3,14 +4666124,29,SHORT,264,5,6,68 +4666126,29,SHORT,265,-2,7,64 +4666128,29,SHORT,266,4,0,16 +4666130,29,SHORT,267,1,5,28 +4666132,29,SHORT,268,-3,0,12 +4666134,29,SHORT,269,-1,10,114 +4666136,29,SHORT,270,5,0,33 +4666138,29,SHORT,271,0,0,0 +4666140,29,SHORT,272,6,1,45 +4666142,29,SHORT,273,0,6,43 +4666144,29,SHORT,274,6,5,67 +4666146,29,SHORT,275,2,9,98 +4666148,29,SHORT,276,4,11,153 +4666150,29,SHORT,277,3,5,50 +4666152,29,SHORT,278,0,-1,3 +4666154,29,SHORT,279,11,0,141 +4666156,29,SHORT,280,2,7,55 +4666158,29,SHORT,281,6,-2,51 +4666160,29,SHORT,282,11,-2,138 +4666162,29,SHORT,283,5,-2,39 +4666164,29,SHORT,284,5,3,44 +4666166,29,SHORT,285,-3,-3,24 +4666168,29,SHORT,286,2,2,10 +4666170,29,SHORT,287,5,10,136 +4666172,29,SHORT,288,-4,1,20 +4666174,29,SHORT,289,-5,-1,31 +4666176,29,SHORT,290,-2,0,6 +4666178,29,SHORT,291,-1,5,37 +4666180,29,SHORT,292,-1,0,3 +4666182,29,SHORT,293,12,-2,167 +4666184,29,SHORT,294,9,5,122 +4666186,29,SHORT,295,9,-7,143 +4666188,29,SHORT,296,19,3,407 +4666190,29,SHORT,297,2,-8,77 +4666192,29,SHORT,298,3,7,71 +4666194,29,SHORT,299,0,9,86 +4666196,29,SHORT,300,-3,12,162 +4666198,29,SHORT,301,3,2,19 +4666200,29,SHORT,302,1,13,175 +4666202,29,SHORT,303,4,0,17 +4666204,29,SHORT,304,6,5,67 +4666206,29,SHORT,305,-19,7,442 +4666208,29,SHORT,306,-9,0,97 +4666210,29,SHORT,307,-8,-2,82 +4666212,29,SHORT,308,5,-6,73 +4666214,29,SHORT,309,-4,8,84 +4666216,29,SHORT,310,-3,-7,60 +4666218,29,SHORT,311,2,1,8 +4666220,29,SHORT,312,7,0,61 +4666222,29,SHORT,313,1,8,73 +4666224,29,SHORT,314,-1,5,28 +4666226,29,SHORT,315,-3,1,12 +4666228,29,SHORT,316,-2,-5,39 +4666230,29,SHORT,317,6,-2,41 +4666232,29,SHORT,318,3,-5,41 +4666234,29,SHORT,319,-1,3,15 +4666236,29,SHORT,320,-7,-4,78 +4666238,29,SHORT,321,-4,5,47 +4666240,29,SHORT,322,-2,0,5 +4666242,29,SHORT,323,-7,2,58 +4666244,29,SHORT,324,-3,-4,29 +4666246,29,SHORT,325,1,-6,39 +4666248,29,SHORT,326,-2,-4,27 +4666250,29,SHORT,327,1,-2,8 +4666252,29,SHORT,328,-2,1,10 +4666254,29,SHORT,329,0,6,46 +4666256,29,SHORT,330,1,-4,20 +4666258,29,SHORT,331,-3,3,21 +4666260,29,SHORT,332,6,0,37 +4666262,29,SHORT,333,6,8,112 +4666264,29,SHORT,334,-4,0,23 +4666266,29,SHORT,335,1,2,10 +4666268,29,SHORT,336,-5,-4,52 +4666270,29,SHORT,337,4,-7,82 +4666272,29,SHORT,338,-4,4,39 +4666274,29,SHORT,339,8,3,93 +4666276,29,SHORT,340,-5,-3,47 +4666278,29,SHORT,341,7,3,64 +4666280,29,SHORT,342,4,-2,29 +4666282,29,SHORT,343,1,-4,18 +4666284,29,SHORT,344,3,-4,33 +4666286,29,SHORT,345,-2,0,5 +4666288,29,SHORT,346,1,-3,18 +4666290,29,SHORT,347,7,1,60 +4666292,29,SHORT,348,1,-2,5 +4666294,29,SHORT,349,0,-2,6 +4666296,29,SHORT,350,0,-1,2 +4666298,29,SHORT,351,-1,0,1 +4666300,29,SHORT,352,-7,-1,55 +4666302,29,SHORT,353,9,-2,97 +4666304,29,SHORT,354,-2,-4,24 +4666306,29,SHORT,355,0,1,3 +4666308,29,SHORT,356,1,3,13 +4666310,29,SHORT,357,-9,-13,261 +4666312,29,SHORT,358,12,2,162 +4666314,29,SHORT,359,0,2,9 +4666316,29,SHORT,360,6,5,79 +4666318,29,SHORT,361,-6,-1,41 +4666320,29,SHORT,362,4,-4,39 +4666322,29,SHORT,363,3,7,69 +4666324,29,SHORT,364,1,-3,12 +4666326,29,SHORT,365,-2,7,62 +4666328,29,SHORT,366,-2,-1,9 +4666330,29,SHORT,367,-7,0,62 +4666332,29,SHORT,368,5,-9,126 +4666334,29,SHORT,369,4,0,21 +4666336,29,SHORT,370,-2,-1,5 +4666338,29,SHORT,371,9,4,113 +4666340,29,SHORT,372,4,-5,56 +4666342,29,SHORT,373,2,1,6 +4666344,29,SHORT,374,0,2,9 +4666346,29,SHORT,375,1,0,3 +4666348,29,SHORT,376,4,7,78 +4666350,29,SHORT,377,2,-8,74 +4666352,29,SHORT,378,6,-6,78 +4666354,29,SHORT,379,-1,-7,66 +4666356,29,SHORT,380,-1,5,27 +4666358,29,SHORT,381,0,-2,8 +4666360,29,SHORT,382,4,1,24 +4666362,29,SHORT,383,-1,-3,13 +4666364,29,SHORT,384,3,1,16 +4666366,29,SHORT,385,2,-1,10 +4666368,29,SHORT,386,-4,8,85 +4666370,29,SHORT,387,-1,0,3 +4666372,29,SHORT,388,0,5,28 +4666374,29,SHORT,389,3,-7,67 +4666376,29,SHORT,390,2,-7,61 +4666378,29,SHORT,391,3,0,11 +4666380,29,SHORT,392,5,-3,50 +4666382,29,SHORT,393,-2,5,36 +4666384,29,SHORT,394,2,-4,25 +4666386,29,SHORT,395,-5,4,49 +4666388,29,SHORT,396,-5,4,44 +4666390,29,SHORT,397,3,-1,16 +4666392,29,SHORT,398,-6,2,40 +4666394,29,SHORT,399,-7,-3,63 +4666396,29,SHORT,400,1,-2,10 +4666398,29,SHORT,401,9,1,97 +4666400,29,SHORT,402,4,2,25 +4666402,29,SHORT,403,0,1,3 +4666404,29,SHORT,404,-1,7,64 +4666406,29,SHORT,405,3,1,18 +4666408,29,SHORT,406,0,-7,57 +4666410,29,SHORT,407,6,-5,70 +4666412,29,SHORT,408,-4,8,97 +4666414,29,SHORT,409,-2,1,11 +4666416,29,SHORT,410,-1,3,16 +4666418,29,SHORT,411,-9,0,89 +4666420,29,SHORT,412,-5,-4,52 +4666422,29,SHORT,413,7,-5,89 +4666424,29,SHORT,414,0,4,22 +4666426,29,SHORT,415,-1,4,21 +4666428,29,SHORT,416,6,-2,48 +4666430,29,SHORT,417,-5,6,76 +4666432,29,SHORT,418,5,-5,52 +4666434,29,SHORT,419,2,2,12 +4666436,29,SHORT,420,4,0,17 +4666438,29,SHORT,421,-4,1,18 +4666440,29,SHORT,422,0,-6,48 +4666442,29,SHORT,423,-5,-3,46 +4666444,29,SHORT,424,0,2,5 +4666446,29,SHORT,425,5,-8,104 +4666448,29,SHORT,426,3,-4,33 +4666450,29,SHORT,427,0,-3,15 +4666452,29,SHORT,428,0,1,1 +4666454,29,SHORT,429,-3,1,16 +4666456,29,SHORT,430,-4,8,89 +4666458,29,SHORT,431,-2,-4,30 +4666460,29,SHORT,432,2,3,16 +4666462,29,SHORT,433,-7,-2,58 +4666464,29,SHORT,434,0,3,11 +4666466,29,SHORT,435,-6,7,100 +4666468,29,SHORT,436,1,4,25 +4666470,29,SHORT,437,2,4,31 +4666472,29,SHORT,438,1,0,3 +4666474,29,SHORT,439,0,-4,23 +4666476,29,SHORT,440,-13,4,191 +4666478,29,SHORT,441,-1,5,31 +4666480,29,SHORT,442,1,4,22 +4666482,29,SHORT,443,0,7,60 +4666484,29,SHORT,444,3,13,203 +4666486,29,SHORT,445,0,-1,2 +4666488,29,SHORT,446,4,-4,48 +4666490,29,SHORT,447,-2,-2,8 +4666492,29,SHORT,448,7,1,59 +4666494,29,SHORT,449,-2,-3,20 +4666496,29,SHORT,450,-9,2,87 +4666498,29,SHORT,451,5,-3,40 +4666500,29,SHORT,452,-8,0,67 +4666502,29,SHORT,453,4,7,83 +4666504,29,SHORT,454,5,-3,42 +4666506,29,SHORT,455,-13,2,193 +4666508,29,SHORT,456,-4,4,43 +4666510,29,SHORT,457,8,-7,127 +4666512,29,SHORT,458,-3,-3,26 +4666514,29,SHORT,459,2,0,9 +4666516,29,SHORT,460,-3,9,99 +4666518,29,SHORT,461,3,2,17 +4666520,29,SHORT,462,-1,4,20 +4666522,29,SHORT,463,-3,-11,158 +4666524,29,SHORT,464,6,0,46 +4666526,29,SHORT,465,-1,2,9 +4666528,29,SHORT,466,3,3,18 +4666530,29,SHORT,467,-2,4,29 +4666532,29,SHORT,468,3,-2,16 +4666534,29,SHORT,469,0,-1,2 +4666536,29,SHORT,470,1,7,60 +4666538,29,SHORT,471,6,7,98 +4666540,29,SHORT,472,1,3,11 +4666542,29,SHORT,473,2,-3,18 +4666544,29,SHORT,474,3,-4,27 +4666546,29,SHORT,475,0,-11,131 +4666548,29,SHORT,476,5,0,35 +4666550,29,SHORT,477,0,4,21 +4666552,29,SHORT,478,-7,-5,82 +4666554,29,SHORT,479,-2,4,29 +4666556,29,SHORT,480,5,0,35 +4666558,29,SHORT,481,-5,2,31 +4666560,29,SHORT,482,0,6,37 +4666562,29,SHORT,483,-7,2,56 +4666564,29,SHORT,484,5,10,128 +4666566,29,SHORT,485,-5,2,38 +4666568,29,SHORT,486,8,6,105 +4666570,29,SHORT,487,0,-6,41 +4666572,29,SHORT,488,-1,-8,67 +4666574,29,SHORT,489,-1,1,4 +4666576,29,SHORT,490,-4,4,39 +4666578,29,SHORT,491,-2,-7,59 +4666580,29,SHORT,492,9,2,90 +4666582,29,SHORT,493,0,8,67 +4666584,29,SHORT,494,2,-10,114 +4666586,29,SHORT,495,1,-3,13 +4666588,29,SHORT,496,-6,-2,43 +4666590,29,SHORT,497,-2,0,6 +4666592,29,SHORT,498,3,0,13 +4666594,29,SHORT,499,-1,-4,26 +4666596,29,SHORT,500,5,6,69 +4666598,29,SHORT,501,7,-6,96 +4666600,29,SHORT,502,-3,2,17 +4666602,29,SHORT,503,-1,-2,7 +4666604,29,SHORT,504,7,5,91 +4666606,29,SHORT,505,-2,-1,7 +4666608,29,SHORT,506,6,0,44 +4666610,29,SHORT,507,3,0,11 +4666612,29,SHORT,508,-1,-1,4 +4666614,29,SHORT,509,-6,1,52 +4666616,29,SHORT,510,-3,5,44 +4666618,29,SHORT,511,-7,0,53 +4841120,30,SHORT,0,13,6,230 +4841122,30,SHORT,1,1,4,28 +4841124,30,SHORT,2,-6,-5,74 +4841126,30,SHORT,3,2,-1,7 +4841128,30,SHORT,4,-8,5,106 +4841130,30,SHORT,5,9,10,204 +4841132,30,SHORT,6,-2,-1,8 +4841134,30,SHORT,7,-4,11,148 +4841136,30,SHORT,8,-3,-4,29 +4841138,30,SHORT,9,-6,0,43 +4841140,30,SHORT,10,-9,-4,109 +4841142,30,SHORT,11,6,-1,48 +4841144,30,SHORT,12,8,4,82 +4841146,30,SHORT,13,6,2,45 +4841148,30,SHORT,14,9,-10,205 +4841150,30,SHORT,15,-1,2,8 +4841152,30,SHORT,16,5,8,94 +4841154,30,SHORT,17,-15,0,230 +4841156,30,SHORT,18,-3,2,17 +4841158,30,SHORT,19,6,2,47 +4841160,30,SHORT,20,10,-2,123 +4841162,30,SHORT,21,-6,0,39 +4841164,30,SHORT,22,-3,-7,71 +4841166,30,SHORT,23,8,0,75 +4841168,30,SHORT,24,1,9,92 +4841170,30,SHORT,25,2,4,26 +4841172,30,SHORT,26,0,-5,26 +4841174,30,SHORT,27,-4,-1,24 +4841176,30,SHORT,28,9,0,96 +4841178,30,SHORT,29,1,-4,24 +4841180,30,SHORT,30,3,0,14 +4841182,30,SHORT,31,-4,-13,202 +4841184,30,SHORT,32,-8,5,97 +4841186,30,SHORT,33,9,6,125 +4841188,30,SHORT,34,-4,0,20 +4841190,30,SHORT,35,-13,6,235 +4841192,30,SHORT,36,11,-11,252 +4841194,30,SHORT,37,-5,3,39 +4841196,30,SHORT,38,2,9,90 +4841198,30,SHORT,39,-5,-1,27 +4841200,30,SHORT,40,5,-7,96 +4841202,30,SHORT,41,-9,-9,185 +4841204,30,SHORT,42,-5,2,32 +4841206,30,SHORT,43,-9,9,179 +4841208,30,SHORT,44,4,-7,77 +4841210,30,SHORT,45,7,-1,65 +4841212,30,SHORT,46,11,-4,155 +4841214,30,SHORT,47,-9,-1,100 +4841216,30,SHORT,48,8,1,72 +4841218,30,SHORT,49,9,13,272 +4841220,30,SHORT,50,0,10,110 +4841222,30,SHORT,51,-2,-7,67 +4841224,30,SHORT,52,3,-3,22 +4841226,30,SHORT,53,12,-4,188 +4841228,30,SHORT,54,-2,-8,84 +4841230,30,SHORT,55,0,-8,77 +4841232,30,SHORT,56,-4,-2,24 +4841234,30,SHORT,57,3,-1,16 +4841236,30,SHORT,58,-4,2,29 +4841238,30,SHORT,59,-3,5,41 +4841240,30,SHORT,60,3,0,15 +4841242,30,SHORT,61,0,0,0 +4841244,30,SHORT,62,0,-3,10 +4841246,30,SHORT,63,-2,-2,16 +4841248,30,SHORT,64,3,12,160 +4841250,30,SHORT,65,-10,5,136 +4841252,30,SHORT,66,4,5,49 +4841254,30,SHORT,67,2,-1,9 +4841256,30,SHORT,68,27,54,3735 +4841258,30,SHORT,69,0,55,3050 +4841260,30,SHORT,70,-7,63,4071 +4841262,30,SHORT,71,-12,53,2993 +4841264,30,SHORT,72,-32,43,2952 +4841266,30,SHORT,73,-34,44,3145 +4841268,30,SHORT,74,-39,32,2595 +4841270,30,SHORT,75,-44,25,2635 +4841272,30,SHORT,76,-58,6,3505 +4841274,30,SHORT,77,-56,0,3226 +4841276,30,SHORT,78,-55,-14,3329 +4841278,30,SHORT,79,-46,-20,2565 +4841280,30,SHORT,80,-35,-32,2360 +4841282,30,SHORT,81,-41,-35,2991 +4841284,30,SHORT,82,-34,-54,4193 +4841286,30,SHORT,83,-2,8,83 +4841288,30,SHORT,84,-2,0,6 +4841290,30,SHORT,85,2,-6,43 +4841292,30,SHORT,86,0,-3,12 +4841294,30,SHORT,87,-4,-3,31 +4841296,30,SHORT,88,0,6,42 +4841298,30,SHORT,89,0,0,0 +4841300,30,SHORT,90,-9,4,102 +4841302,30,SHORT,91,4,3,32 +4841304,30,SHORT,92,5,3,47 +4841306,30,SHORT,93,-1,-8,72 +4841308,30,SHORT,94,-1,9,92 +4841310,30,SHORT,95,10,-1,106 +4841312,30,SHORT,96,1,13,172 +4841314,30,SHORT,97,7,2,55 +4841316,30,SHORT,98,-6,2,47 +4841318,30,SHORT,99,2,3,18 +4841320,30,SHORT,100,4,0,17 +4841322,30,SHORT,101,-3,2,20 +4841324,30,SHORT,102,-4,8,92 +4841326,30,SHORT,103,-1,-2,7 +4841328,30,SHORT,104,2,-2,10 +4841330,30,SHORT,105,-5,-2,40 +4841332,30,SHORT,106,10,-1,112 +4841334,30,SHORT,107,-7,1,60 +4841336,30,SHORT,108,3,2,22 +4841338,30,SHORT,109,-5,-1,33 +4841340,30,SHORT,110,-4,2,23 +4841342,30,SHORT,111,-1,0,3 +4841344,30,SHORT,112,7,1,56 +4841346,30,SHORT,113,0,-4,22 +4841348,30,SHORT,114,4,2,25 +4841350,30,SHORT,115,0,6,46 +4841352,30,SHORT,116,7,-2,60 +4841354,30,SHORT,117,-1,2,8 +4841356,30,SHORT,118,-23,21,1035 +4841358,30,SHORT,119,-21,13,647 +4841360,30,SHORT,120,-35,3,1294 +4841362,30,SHORT,121,-32,4,1081 +4841364,30,SHORT,122,-25,-8,718 +4841366,30,SHORT,123,-35,-7,1354 +4841368,30,SHORT,124,-19,-13,572 +4841370,30,SHORT,125,-23,-18,906 +4841372,30,SHORT,126,-21,-24,1066 +4841374,30,SHORT,127,-5,-24,635 +4841376,30,SHORT,128,-12,-23,716 +4841378,30,SHORT,129,-3,-25,678 +4841380,30,SHORT,130,0,-29,848 +4841382,30,SHORT,131,10,-25,749 +4841384,30,SHORT,132,23,-26,1231 +4841386,30,SHORT,133,-1,-1,4 +4841388,30,SHORT,134,-1,-7,54 +4841390,30,SHORT,135,-2,-2,14 +4841392,30,SHORT,136,3,-1,15 +4841394,30,SHORT,137,2,-2,13 +4841396,30,SHORT,138,3,9,95 +4841398,30,SHORT,139,12,5,194 +4841400,30,SHORT,140,0,1,1 +4841402,30,SHORT,141,-2,-1,8 +4841404,30,SHORT,142,-4,-5,46 +4841406,30,SHORT,143,-7,-1,63 +4841408,30,SHORT,144,-3,2,18 +4841410,30,SHORT,145,1,1,4 +4841412,30,SHORT,146,7,-5,84 +4841414,30,SHORT,147,-7,-1,58 +4841416,30,SHORT,148,-2,0,4 +4841418,30,SHORT,149,0,-3,10 +4841420,30,SHORT,150,-5,6,79 +4841422,30,SHORT,151,2,5,34 +4841424,30,SHORT,152,1,1,4 +4841426,30,SHORT,153,-4,7,78 +4841428,30,SHORT,154,-4,-5,54 +4841430,30,SHORT,155,-9,9,187 +4841432,30,SHORT,156,1,-2,7 +4841434,30,SHORT,157,1,10,104 +4841436,30,SHORT,158,0,-1,4 +4841438,30,SHORT,159,4,-9,101 +4841440,30,SHORT,160,8,3,83 +4841442,30,SHORT,161,5,-6,68 +4841444,30,SHORT,162,6,-3,60 +4841446,30,SHORT,163,-1,1,3 +4841448,30,SHORT,164,1,5,37 +4841450,30,SHORT,165,1,0,2 +4841452,30,SHORT,166,-1,-7,61 +4841454,30,SHORT,167,0,-3,12 +4841456,30,SHORT,168,-3,-7,68 +4841458,30,SHORT,169,-2,8,76 +4841460,30,SHORT,170,-6,0,43 +4841462,30,SHORT,171,-2,0,6 +4841464,30,SHORT,172,-1,-2,7 +4841466,30,SHORT,173,-3,-1,12 +4841468,30,SHORT,174,1,0,2 +4841470,30,SHORT,175,0,-4,17 +4841472,30,SHORT,176,-5,-3,44 +4841474,30,SHORT,177,0,-2,7 +4841476,30,SHORT,178,0,-4,25 +4841478,30,SHORT,179,4,-1,24 +4841480,30,SHORT,180,0,1,3 +4841482,30,SHORT,181,1,1,5 +4841484,30,SHORT,182,2,-3,19 +4841486,30,SHORT,183,0,-3,15 +4841488,30,SHORT,184,0,1,3 +4841490,30,SHORT,185,8,-6,115 +4841492,30,SHORT,186,-7,3,76 +4841494,30,SHORT,187,-10,-4,137 +4841496,30,SHORT,188,8,1,71 +4841498,30,SHORT,189,0,-1,2 +4841500,30,SHORT,190,-1,0,2 +4841502,30,SHORT,191,0,-5,26 +4841504,30,SHORT,192,-4,-5,48 +4841506,30,SHORT,193,-13,-9,262 +4841508,30,SHORT,194,-10,-10,227 +4841510,30,SHORT,195,-3,-10,127 +4841512,30,SHORT,196,-6,-18,373 +4841514,30,SHORT,197,8,-9,154 +4841516,30,SHORT,198,-2,-1,9 +4841518,30,SHORT,199,6,-7,100 +4841520,30,SHORT,200,0,-18,336 +4841522,30,SHORT,201,11,-8,209 +4841524,30,SHORT,202,28,-8,885 +4841526,30,SHORT,203,15,-2,249 +4841528,30,SHORT,204,18,3,368 +4841530,30,SHORT,205,13,13,370 +4841532,30,SHORT,206,13,-2,195 +4841534,30,SHORT,207,9,11,215 +4841536,30,SHORT,208,-9,-1,89 +4841538,30,SHORT,209,-3,-1,15 +4841540,30,SHORT,210,-3,6,53 +4841542,30,SHORT,211,12,-1,166 +4841544,30,SHORT,212,3,-7,62 +4841546,30,SHORT,213,3,-10,121 +4841548,30,SHORT,214,0,-4,25 +4841550,30,SHORT,215,-1,0,3 +4841552,30,SHORT,216,1,-5,31 +4841554,30,SHORT,217,-6,2,47 +4841556,30,SHORT,218,6,1,37 +4841558,30,SHORT,219,-3,-4,32 +4841560,30,SHORT,220,4,-1,19 +4841562,30,SHORT,221,0,0,0 +4841564,30,SHORT,222,-2,0,4 +4841566,30,SHORT,223,-8,5,97 +4841568,30,SHORT,224,-4,-4,41 +4841570,30,SHORT,225,-4,-1,21 +4841572,30,SHORT,226,1,-3,12 +4841574,30,SHORT,227,1,-3,14 +4841576,30,SHORT,228,9,7,151 +4841578,30,SHORT,229,12,4,168 +4841580,30,SHORT,230,4,-1,19 +4841582,30,SHORT,231,-2,-2,13 +4841584,30,SHORT,232,-7,-2,62 +4841586,30,SHORT,233,-4,-6,64 +4841588,30,SHORT,234,10,2,114 +4841590,30,SHORT,235,7,2,60 +4841592,30,SHORT,236,-4,-2,31 +4841594,30,SHORT,237,-5,-2,36 +4841596,30,SHORT,238,2,10,118 +4841598,30,SHORT,239,0,-1,2 +4841600,30,SHORT,240,6,4,62 +4841602,30,SHORT,241,4,-2,30 +4841604,30,SHORT,242,0,0,0 +4841606,30,SHORT,243,0,6,45 +4841608,30,SHORT,244,-8,-9,166 +4841610,30,SHORT,245,-1,-6,46 +4841612,30,SHORT,246,0,-3,16 +4841614,30,SHORT,247,4,0,21 +4841616,30,SHORT,248,3,3,30 +4841618,30,SHORT,249,10,3,116 +4841620,30,SHORT,250,-4,-3,34 +4841622,30,SHORT,251,7,1,54 +4841624,30,SHORT,252,-2,9,96 +4841626,30,SHORT,253,-6,5,67 +4841628,30,SHORT,254,5,5,53 +4841630,30,SHORT,255,-2,-3,19 +4841632,30,SHORT,256,-4,3,34 +4841634,30,SHORT,257,14,2,229 +4841636,30,SHORT,258,0,11,142 +4841638,30,SHORT,259,0,0,0 +4841640,30,SHORT,260,11,-5,158 +4841642,30,SHORT,261,-5,0,34 +4841644,30,SHORT,262,-5,12,202 +4841646,30,SHORT,263,-1,0,3 +4841648,30,SHORT,264,4,-12,184 +4841650,30,SHORT,265,-1,-1,6 +4841652,30,SHORT,266,-1,3,14 +4841654,30,SHORT,267,3,0,10 +4841656,30,SHORT,268,2,-5,37 +4841658,30,SHORT,269,-4,-1,20 +4841660,30,SHORT,270,4,0,17 +4841662,30,SHORT,271,2,-7,69 +4841664,30,SHORT,272,2,-4,22 +4841666,30,SHORT,273,-1,3,15 +4841668,30,SHORT,274,0,1,4 +4841670,30,SHORT,275,0,2,4 +4841672,30,SHORT,276,0,0,0 +4841674,30,SHORT,277,-3,3,28 +4841676,30,SHORT,278,1,2,12 +4841678,30,SHORT,279,0,-1,1 +4841680,30,SHORT,280,-2,-3,22 +4841682,30,SHORT,281,-2,4,24 +4841684,30,SHORT,282,0,-1,2 +4841686,30,SHORT,283,9,-3,104 +4841688,30,SHORT,284,2,-9,105 +4841690,30,SHORT,285,2,0,4 +4841692,30,SHORT,286,3,-5,35 +4841694,30,SHORT,287,-2,1,10 +4841696,30,SHORT,288,-4,-10,133 +4841698,30,SHORT,289,0,2,6 +4841700,30,SHORT,290,1,4,23 +4841702,30,SHORT,291,-7,0,63 +4841704,30,SHORT,292,2,-2,12 +4841706,30,SHORT,293,2,-5,39 +4841708,30,SHORT,294,15,-8,301 +4841710,30,SHORT,295,6,-7,106 +4841712,30,SHORT,296,13,-9,270 +4841714,30,SHORT,297,7,0,57 +4841716,30,SHORT,298,8,-2,86 +4841718,30,SHORT,299,11,7,175 +4841720,30,SHORT,300,8,2,69 +4841722,30,SHORT,301,5,4,48 +4841724,30,SHORT,302,5,6,73 +4841726,30,SHORT,303,2,10,109 +4841728,30,SHORT,304,1,8,77 +4841730,30,SHORT,305,0,4,25 +4841732,30,SHORT,306,-6,11,179 +4841734,30,SHORT,307,-1,7,53 +4841736,30,SHORT,308,8,1,68 +4841738,30,SHORT,309,-9,-2,89 +4841740,30,SHORT,310,6,3,62 +4841742,30,SHORT,311,12,2,157 +4841744,30,SHORT,312,1,2,10 +4841746,30,SHORT,313,-6,-2,44 +4841748,30,SHORT,314,-6,-9,126 +4841750,30,SHORT,315,3,0,9 +4841752,30,SHORT,316,-2,2,16 +4841754,30,SHORT,317,-9,0,87 +4841756,30,SHORT,318,0,0,0 +4841758,30,SHORT,319,-6,-4,63 +4841760,30,SHORT,320,3,-1,16 +4841762,30,SHORT,321,-1,-5,33 +4841764,30,SHORT,322,-3,5,37 +4841766,30,SHORT,323,-6,-6,84 +4841768,30,SHORT,324,9,-6,129 +4841770,30,SHORT,325,5,-7,93 +4841772,30,SHORT,326,-11,-8,207 +4841774,30,SHORT,327,-2,0,8 +4841776,30,SHORT,328,-2,0,7 +4841778,30,SHORT,329,-2,-5,37 +4841780,30,SHORT,330,0,-8,73 +4841782,30,SHORT,331,-4,-3,31 +4841784,30,SHORT,332,1,-1,3 +4841786,30,SHORT,333,0,2,7 +4841788,30,SHORT,334,-9,11,204 +4841790,30,SHORT,335,0,2,6 +4841792,30,SHORT,336,8,0,74 +4841794,30,SHORT,337,-1,6,46 +4841796,30,SHORT,338,2,4,26 +4841798,30,SHORT,339,-1,1,5 +4841800,30,SHORT,340,0,0,0 +4841802,30,SHORT,341,-8,-2,80 +4841804,30,SHORT,342,1,1,2 +4841806,30,SHORT,343,7,-8,134 +4841808,30,SHORT,344,0,6,40 +4841810,30,SHORT,345,0,2,8 +4841812,30,SHORT,346,-2,1,9 +4841814,30,SHORT,347,3,0,9 +4841816,30,SHORT,348,3,2,18 +4841818,30,SHORT,349,0,2,4 +4841820,30,SHORT,350,6,0,38 +4841822,30,SHORT,351,4,6,60 +4841824,30,SHORT,352,0,7,63 +4841826,30,SHORT,353,0,-4,21 +4841828,30,SHORT,354,-3,3,24 +4841830,30,SHORT,355,0,3,10 +4841832,30,SHORT,356,0,0,0 +4841834,30,SHORT,357,-6,-5,66 +4841836,30,SHORT,358,5,0,32 +4841838,30,SHORT,359,2,-8,75 +4841840,30,SHORT,360,-8,-4,94 +4841842,30,SHORT,361,-15,3,241 +4841844,30,SHORT,362,-1,3,12 +4841846,30,SHORT,363,-1,-4,26 +4841848,30,SHORT,364,3,2,15 +4841850,30,SHORT,365,3,-3,26 +4841852,30,SHORT,366,-7,1,58 +4841854,30,SHORT,367,0,-5,32 +4841856,30,SHORT,368,-4,3,28 +4841858,30,SHORT,369,1,-3,16 +4841860,30,SHORT,370,4,6,66 +4841862,30,SHORT,371,0,-6,44 +4841864,30,SHORT,372,0,0,1 +4841866,30,SHORT,373,-1,1,3 +4841868,30,SHORT,374,-8,-2,88 +4841870,30,SHORT,375,-5,10,132 +4841872,30,SHORT,376,3,0,10 +4841874,30,SHORT,377,-2,1,10 +4841876,30,SHORT,378,4,8,100 +4841878,30,SHORT,379,5,1,28 +4841880,30,SHORT,380,-5,0,25 +4841882,30,SHORT,381,1,-7,58 +4841884,30,SHORT,382,-7,-7,119 +4841886,30,SHORT,383,-8,-4,92 +4841888,30,SHORT,384,0,-8,71 +4841890,30,SHORT,385,0,4,17 +4841892,30,SHORT,386,2,0,6 +4841894,30,SHORT,387,-5,-2,32 +4841896,30,SHORT,388,7,1,56 +4841898,30,SHORT,389,-3,-6,60 +4841900,30,SHORT,390,7,0,60 +4841902,30,SHORT,391,-1,-7,55 +4841904,30,SHORT,392,4,-9,104 +4841906,30,SHORT,393,0,11,122 +4841908,30,SHORT,394,-1,1,3 +4841910,30,SHORT,395,-5,-9,108 +4841912,30,SHORT,396,-4,0,23 +4841914,30,SHORT,397,2,-1,10 +4841916,30,SHORT,398,0,-3,11 +4841918,30,SHORT,399,-3,6,51 +4841920,30,SHORT,400,2,1,9 +4841922,30,SHORT,401,6,0,42 +4841924,30,SHORT,402,0,8,75 +4841926,30,SHORT,403,-1,2,11 +4841928,30,SHORT,404,-2,3,17 +4841930,30,SHORT,405,0,1,2 +4841932,30,SHORT,406,2,-4,26 +4841934,30,SHORT,407,4,0,18 +4841936,30,SHORT,408,4,0,17 +4841938,30,SHORT,409,-6,7,98 +4841940,30,SHORT,410,-5,-2,39 +4841942,30,SHORT,411,-1,-10,111 +4841944,30,SHORT,412,-3,-7,67 +4841946,30,SHORT,413,-3,4,32 +4841948,30,SHORT,414,-5,-4,50 +4841950,30,SHORT,415,-7,0,52 +4841952,30,SHORT,416,0,5,31 +4841954,30,SHORT,417,1,-4,25 +4841956,30,SHORT,418,6,-1,45 +4841958,30,SHORT,419,6,1,40 +4841960,30,SHORT,420,-4,0,21 +4841962,30,SHORT,421,5,4,52 +4841964,30,SHORT,422,8,8,137 +4841966,30,SHORT,423,8,0,66 +4841968,30,SHORT,424,-4,5,48 +4841970,30,SHORT,425,9,6,137 +4841972,30,SHORT,426,0,-6,38 +4841974,30,SHORT,427,5,2,40 +4841976,30,SHORT,428,2,3,18 +4841978,30,SHORT,429,1,-2,9 +4841980,30,SHORT,430,-5,-1,36 +4841982,30,SHORT,431,7,-1,52 +4841984,30,SHORT,432,-7,-9,144 +4841986,30,SHORT,433,-4,-2,30 +4841988,30,SHORT,434,-1,3,16 +4841990,30,SHORT,435,-4,0,20 +4841992,30,SHORT,436,1,0,2 +4841994,30,SHORT,437,0,-4,23 +4841996,30,SHORT,438,0,5,30 +4841998,30,SHORT,439,-6,-6,92 +4842000,30,SHORT,440,1,10,107 +4842002,30,SHORT,441,3,-2,23 +4842004,30,SHORT,442,-2,-2,13 +4842006,30,SHORT,443,0,-4,19 +4842008,30,SHORT,444,-6,4,61 +4842010,30,SHORT,445,-2,1,8 +4842012,30,SHORT,446,5,4,43 +4842014,30,SHORT,447,-9,4,106 +4842016,30,SHORT,448,1,1,6 +4842018,30,SHORT,449,5,-2,43 +4842020,30,SHORT,450,-3,5,41 +4842022,30,SHORT,451,7,-1,54 +4842024,30,SHORT,452,-1,5,35 +4842026,30,SHORT,453,3,0,13 +4842028,30,SHORT,454,-3,1,10 +4842030,30,SHORT,455,-3,-6,52 +4842032,30,SHORT,456,0,6,36 +4842034,30,SHORT,457,5,-10,136 +4842036,30,SHORT,458,0,-11,143 +4842038,30,SHORT,459,3,8,87 +4842040,30,SHORT,460,-3,6,49 +4842042,30,SHORT,461,0,-5,33 +4842044,30,SHORT,462,6,1,45 +4842046,30,SHORT,463,-4,-1,25 +4842048,30,SHORT,464,-1,1,3 +4842050,30,SHORT,465,0,0,0 +4842052,30,SHORT,466,6,-8,118 +4842054,30,SHORT,467,12,-4,174 +4842056,30,SHORT,468,-2,-1,6 +4842058,30,SHORT,469,1,0,1 +4842060,30,SHORT,470,10,1,103 +4842062,30,SHORT,471,-4,0,21 +4842064,30,SHORT,472,3,-1,12 +4842066,30,SHORT,473,6,1,40 +4842068,30,SHORT,474,11,0,131 +4842070,30,SHORT,475,-2,0,7 +4842072,30,SHORT,476,-1,7,53 +4842074,30,SHORT,477,2,5,35 +4842076,30,SHORT,478,8,-2,75 +4842078,30,SHORT,479,0,-3,16 +4842080,30,SHORT,480,5,1,39 +4842082,30,SHORT,481,7,-1,57 +4842084,30,SHORT,482,-3,-3,22 +4842086,30,SHORT,483,-1,-10,103 +4842088,30,SHORT,484,-6,-7,105 +4842090,30,SHORT,485,0,-1,1 +4842092,30,SHORT,486,1,-1,4 +4842094,30,SHORT,487,-6,5,63 +4842096,30,SHORT,488,-7,-10,153 +4842098,30,SHORT,489,4,-3,27 +4842100,30,SHORT,490,-5,-2,38 +4842102,30,SHORT,491,3,-5,46 +4842104,30,SHORT,492,0,4,17 +4842106,30,SHORT,493,-3,-3,24 +4842108,30,SHORT,494,3,-5,48 +4842110,30,SHORT,495,6,-5,75 +4842112,30,SHORT,496,0,-2,7 +4842114,30,SHORT,497,-7,9,137 +4842116,30,SHORT,498,1,2,8 +4842118,30,SHORT,499,3,3,23 +4842120,30,SHORT,500,-1,2,6 +4842122,30,SHORT,501,0,-4,18 +4842124,30,SHORT,502,6,10,148 +4842126,30,SHORT,503,-7,-9,147 +4842128,30,SHORT,504,0,0,0 +4842130,30,SHORT,505,6,10,146 +4842132,30,SHORT,506,-1,1,6 +4842134,30,SHORT,507,2,1,6 +4842136,30,SHORT,508,1,-7,53 +4842138,30,SHORT,509,-4,-2,24 +4842140,30,SHORT,510,-2,7,53 +4842142,30,SHORT,511,0,2,7 +5016644,31,SHORT,0,18,-7,419 +5016646,31,SHORT,1,9,1,83 +5016648,31,SHORT,2,-5,-9,115 +5016650,31,SHORT,3,-1,-8,68 +5016652,31,SHORT,4,-1,-2,9 +5016654,31,SHORT,5,5,9,113 +5016656,31,SHORT,6,-3,8,81 +5016658,31,SHORT,7,-1,2,5 +5016660,31,SHORT,8,-5,1,39 +5016662,31,SHORT,9,10,-5,131 +5016664,31,SHORT,10,0,-9,98 +5016666,31,SHORT,11,4,-1,26 +5016668,31,SHORT,12,5,4,47 +5016670,31,SHORT,13,-6,3,52 +5016672,31,SHORT,14,0,-10,104 +5016674,31,SHORT,15,0,2,5 +5016676,31,SHORT,16,-8,-12,230 +5016678,31,SHORT,17,-2,-5,39 +5016680,31,SHORT,18,-12,-12,321 +5016682,31,SHORT,19,11,9,206 +5016684,31,SHORT,20,-5,18,382 +5016686,31,SHORT,21,6,-3,49 +5016688,31,SHORT,22,-6,0,38 +5016690,31,SHORT,23,-2,-11,133 +5016692,31,SHORT,24,0,6,47 +5016694,31,SHORT,25,-15,14,444 +5016696,31,SHORT,26,1,8,78 +5016698,31,SHORT,27,3,-5,46 +5016700,31,SHORT,28,7,7,112 +5016702,31,SHORT,29,-3,3,27 +5016704,31,SHORT,30,1,-1,3 +5016706,31,SHORT,31,1,-9,91 +5016708,31,SHORT,32,4,-2,26 +5016710,31,SHORT,33,-1,9,98 +5016712,31,SHORT,34,-3,14,232 +5016714,31,SHORT,35,7,-7,112 +5016716,31,SHORT,36,-3,-1,14 +5016718,31,SHORT,37,-9,-3,110 +5016720,31,SHORT,38,16,9,357 +5016722,31,SHORT,39,2,-15,247 +5016724,31,SHORT,40,-2,-5,39 +5016726,31,SHORT,41,-7,-1,51 +5016728,31,SHORT,42,-14,-10,327 +5016730,31,SHORT,43,1,2,11 +5016732,31,SHORT,44,-3,-4,29 +5016734,31,SHORT,45,0,1,3 +5016736,31,SHORT,46,4,8,104 +5016738,31,SHORT,47,0,7,55 +5016740,31,SHORT,48,-5,7,80 +5016742,31,SHORT,49,4,-15,279 +5016744,31,SHORT,50,-7,5,90 +5016746,31,SHORT,51,8,1,80 +5016748,31,SHORT,52,-2,7,70 +5016750,31,SHORT,53,-4,-1,19 +5016752,31,SHORT,54,-12,-1,164 +5016754,31,SHORT,55,-5,-2,33 +5016756,31,SHORT,56,2,6,44 +5016758,31,SHORT,57,-2,-2,15 +5016760,31,SHORT,58,10,-4,133 +5016762,31,SHORT,59,0,-5,26 +5016764,31,SHORT,60,0,0,0 +5016766,31,SHORT,61,0,1,3 +5016768,31,SHORT,62,-1,5,38 +5016770,31,SHORT,63,0,-7,51 +5016772,31,SHORT,64,-3,7,63 +5016774,31,SHORT,65,6,10,143 +5016776,31,SHORT,66,5,-4,48 +5016778,31,SHORT,67,0,1,1 +5016780,31,SHORT,68,-52,4,2751 +5016782,31,SHORT,69,-50,-16,2791 +5016784,31,SHORT,70,-52,-34,3974 +5016786,31,SHORT,71,-53,-37,4288 +5016788,31,SHORT,72,-28,-49,3258 +5016790,31,SHORT,73,-22,-55,3565 +5016792,31,SHORT,74,-9,-41,1837 +5016794,31,SHORT,75,0,-59,3599 +5016796,31,SHORT,76,14,-55,3268 +5016798,31,SHORT,77,23,-50,3126 +5016800,31,SHORT,78,37,-45,3476 +5016802,31,SHORT,79,36,-30,2318 +5016804,31,SHORT,80,49,-26,3177 +5016806,31,SHORT,81,55,-18,3390 +5016808,31,SHORT,82,48,-8,2383 +5016810,31,SHORT,83,1,-4,26 +5016812,31,SHORT,84,7,0,51 +5016814,31,SHORT,85,3,0,11 +5016816,31,SHORT,86,0,-4,16 +5016818,31,SHORT,87,-2,-9,91 +5016820,31,SHORT,88,-1,-4,20 +5016822,31,SHORT,89,6,-5,66 +5016824,31,SHORT,90,0,-5,32 +5016826,31,SHORT,91,-1,4,26 +5016828,31,SHORT,92,-3,3,26 +5016830,31,SHORT,93,10,-3,124 +5016832,31,SHORT,94,-7,-2,66 +5016834,31,SHORT,95,0,-6,42 +5016836,31,SHORT,96,-1,2,10 +5016838,31,SHORT,97,0,-1,1 +5016840,31,SHORT,98,-5,-6,79 +5016842,31,SHORT,99,7,1,62 +5016844,31,SHORT,100,0,0,1 +5016846,31,SHORT,101,1,0,2 +5016848,31,SHORT,102,-1,-2,9 +5016850,31,SHORT,103,4,-4,34 +5016852,31,SHORT,104,1,0,3 +5016854,31,SHORT,105,0,-3,9 +5016856,31,SHORT,106,-4,-4,44 +5016858,31,SHORT,107,-2,0,4 +5016860,31,SHORT,108,0,-4,21 +5016862,31,SHORT,109,2,-7,67 +5016864,31,SHORT,110,-2,-5,36 +5016866,31,SHORT,111,1,-2,7 +5016868,31,SHORT,112,-5,3,37 +5016870,31,SHORT,113,-1,2,7 +5016872,31,SHORT,114,-3,3,26 +5016874,31,SHORT,115,3,-3,24 +5016876,31,SHORT,116,1,-3,17 +5016878,31,SHORT,117,-2,0,6 +5016880,31,SHORT,118,11,32,1165 +5016882,31,SHORT,119,5,26,724 +5016884,31,SHORT,120,5,29,921 +5016886,31,SHORT,121,-1,31,1017 +5016888,31,SHORT,122,-10,23,646 +5016890,31,SHORT,123,-19,26,1082 +5016892,31,SHORT,124,-17,28,1145 +5016894,31,SHORT,125,-27,18,1078 +5016896,31,SHORT,126,-25,5,666 +5016898,31,SHORT,127,-18,-8,416 +5016900,31,SHORT,128,-35,-7,1282 +5016902,31,SHORT,129,-39,-11,1669 +5016904,31,SHORT,130,-27,-14,948 +5016906,31,SHORT,131,-24,-11,729 +5016908,31,SHORT,132,-11,-22,619 +5016910,31,SHORT,133,-5,-2,38 +5016912,31,SHORT,134,5,6,72 +5016914,31,SHORT,135,2,-1,9 +5016916,31,SHORT,136,-6,-12,208 +5016918,31,SHORT,137,-4,12,178 +5016920,31,SHORT,138,-3,-8,79 +5016922,31,SHORT,139,10,4,131 +5016924,31,SHORT,140,-2,-1,6 +5016926,31,SHORT,141,0,0,1 +5016928,31,SHORT,142,3,6,49 +5016930,31,SHORT,143,0,0,0 +5016932,31,SHORT,144,-2,-5,35 +5016934,31,SHORT,145,4,-3,27 +5016936,31,SHORT,146,5,-4,46 +5016938,31,SHORT,147,0,6,36 +5016940,31,SHORT,148,2,0,4 +5016942,31,SHORT,149,-5,9,115 +5016944,31,SHORT,150,2,5,33 +5016946,31,SHORT,151,0,-5,30 +5016948,31,SHORT,152,-2,-3,20 +5016950,31,SHORT,153,0,4,25 +5016952,31,SHORT,154,0,-4,19 +5016954,31,SHORT,155,6,-4,58 +5016956,31,SHORT,156,3,-8,84 +5016958,31,SHORT,157,1,-1,4 +5016960,31,SHORT,158,0,9,82 +5016962,31,SHORT,159,-5,-3,44 +5016964,31,SHORT,160,-2,3,22 +5016966,31,SHORT,161,-7,-1,62 +5016968,31,SHORT,162,2,3,19 +5016970,31,SHORT,163,3,2,17 +5016972,31,SHORT,164,2,4,25 +5016974,31,SHORT,165,-6,-8,111 +5016976,31,SHORT,166,-7,1,54 +5016978,31,SHORT,167,-1,1,4 +5016980,31,SHORT,168,6,-2,41 +5016982,31,SHORT,169,-1,0,3 +5016984,31,SHORT,170,0,-1,3 +5016986,31,SHORT,171,3,-4,27 +5016988,31,SHORT,172,6,9,134 +5016990,31,SHORT,173,1,-2,9 +5016992,31,SHORT,174,9,8,157 +5016994,31,SHORT,175,-11,0,136 +5016996,31,SHORT,176,2,-1,5 +5016998,31,SHORT,177,3,-2,16 +5017000,31,SHORT,178,2,0,7 +5017002,31,SHORT,179,-8,0,65 +5017004,31,SHORT,180,4,3,35 +5017006,31,SHORT,181,-2,-4,21 +5017008,31,SHORT,182,2,7,68 +5017010,31,SHORT,183,1,-1,4 +5017012,31,SHORT,184,6,-1,44 +5017014,31,SHORT,185,0,-2,4 +5017016,31,SHORT,186,5,0,27 +5017018,31,SHORT,187,1,2,10 +5017020,31,SHORT,188,2,1,7 +5017022,31,SHORT,189,-2,5,33 +5017024,31,SHORT,190,5,-1,30 +5017026,31,SHORT,191,0,-2,8 +5017028,31,SHORT,192,-4,4,41 +5017030,31,SHORT,193,-3,-13,182 +5017032,31,SHORT,194,-2,-11,149 +5017034,31,SHORT,195,-2,-14,215 +5017036,31,SHORT,196,0,-7,49 +5017038,31,SHORT,197,12,-5,191 +5017040,31,SHORT,198,7,-8,137 +5017042,31,SHORT,199,7,-6,103 +5017044,31,SHORT,200,18,-7,378 +5017046,31,SHORT,201,16,0,267 +5017048,31,SHORT,202,15,0,239 +5017050,31,SHORT,203,17,0,295 +5017052,31,SHORT,204,14,4,224 +5017054,31,SHORT,205,9,8,173 +5017056,31,SHORT,206,9,8,162 +5017058,31,SHORT,207,9,6,127 +5017060,31,SHORT,208,0,-2,8 +5017062,31,SHORT,209,2,-1,6 +5017064,31,SHORT,210,-4,-7,78 +5017066,31,SHORT,211,2,0,9 +5017068,31,SHORT,212,-8,-4,93 +5017070,31,SHORT,213,1,5,35 +5017072,31,SHORT,214,0,-6,38 +5017074,31,SHORT,215,-4,0,19 +5017076,31,SHORT,216,-2,4,29 +5017078,31,SHORT,217,-2,-6,53 +5017080,31,SHORT,218,-2,0,5 +5017082,31,SHORT,219,0,-9,92 +5017084,31,SHORT,220,0,-3,15 +5017086,31,SHORT,221,1,-3,12 +5017088,31,SHORT,222,-7,2,60 +5017090,31,SHORT,223,5,2,32 +5017092,31,SHORT,224,-1,-2,7 +5017094,31,SHORT,225,5,-3,45 +5017096,31,SHORT,226,-7,-5,87 +5017098,31,SHORT,227,-2,5,42 +5017100,31,SHORT,228,1,8,71 +5017102,31,SHORT,229,2,-6,47 +5017104,31,SHORT,230,3,6,54 +5017106,31,SHORT,231,0,-2,6 +5017108,31,SHORT,232,-2,3,21 +5017110,31,SHORT,233,-7,-4,79 +5017112,31,SHORT,234,1,2,6 +5017114,31,SHORT,235,7,5,91 +5017116,31,SHORT,236,4,-4,39 +5017118,31,SHORT,237,3,-1,14 +5017120,31,SHORT,238,6,8,113 +5017122,31,SHORT,239,-2,-11,143 +5017124,31,SHORT,240,3,2,15 +5017126,31,SHORT,241,8,1,75 +5017128,31,SHORT,242,-1,0,4 +5017130,31,SHORT,243,-5,2,34 +5017132,31,SHORT,244,-6,1,41 +5017134,31,SHORT,245,-4,2,25 +5017136,31,SHORT,246,2,-8,74 +5017138,31,SHORT,247,2,0,6 +5017140,31,SHORT,248,-3,-7,65 +5017142,31,SHORT,249,2,-1,10 +5017144,31,SHORT,250,0,0,0 +5017146,31,SHORT,251,8,-3,93 +5017148,31,SHORT,252,0,-2,6 +5017150,31,SHORT,253,6,8,111 +5017152,31,SHORT,254,6,-3,52 +5017154,31,SHORT,255,1,-3,12 +5017156,31,SHORT,256,0,6,38 +5017158,31,SHORT,257,6,-4,58 +5017160,31,SHORT,258,4,0,18 +5017162,31,SHORT,259,-14,1,211 +5017164,31,SHORT,260,-2,0,6 +5017166,31,SHORT,261,-2,1,9 +5017168,31,SHORT,262,-3,-1,13 +5017170,31,SHORT,263,2,-8,79 +5017172,31,SHORT,264,0,-9,85 +5017174,31,SHORT,265,-3,0,16 +5017176,31,SHORT,266,1,5,29 +5017178,31,SHORT,267,1,6,42 +5017180,31,SHORT,268,-3,3,21 +5017182,31,SHORT,269,0,3,14 +5017184,31,SHORT,270,5,5,66 +5017186,31,SHORT,271,3,2,18 +5017188,31,SHORT,272,1,-9,94 +5017190,31,SHORT,273,4,7,82 +5017192,31,SHORT,274,6,5,79 +5017194,31,SHORT,275,9,2,92 +5017196,31,SHORT,276,7,-2,64 +5017198,31,SHORT,277,7,1,66 +5017200,31,SHORT,278,4,-5,50 +5017202,31,SHORT,279,0,2,5 +5017204,31,SHORT,280,4,2,25 +5017206,31,SHORT,281,6,1,48 +5017208,31,SHORT,282,-8,-1,83 +5017210,31,SHORT,283,3,-8,77 +5017212,31,SHORT,284,5,-3,40 +5017214,31,SHORT,285,3,-1,12 +5017216,31,SHORT,286,7,-2,56 +5017218,31,SHORT,287,4,-4,41 +5017220,31,SHORT,288,2,0,6 +5017222,31,SHORT,289,8,-9,159 +5017224,31,SHORT,290,0,3,14 +5017226,31,SHORT,291,1,6,40 +5017228,31,SHORT,292,2,5,36 +5017230,31,SHORT,293,7,-11,186 +5017232,31,SHORT,294,6,-13,235 +5017234,31,SHORT,295,11,-11,263 +5017236,31,SHORT,296,8,-5,108 +5017238,31,SHORT,297,7,-7,109 +5017240,31,SHORT,298,8,-1,75 +5017242,31,SHORT,299,10,0,114 +5017244,31,SHORT,300,14,5,234 +5017246,31,SHORT,301,9,0,88 +5017248,31,SHORT,302,6,6,87 +5017250,31,SHORT,303,2,3,19 +5017252,31,SHORT,304,3,10,125 +5017254,31,SHORT,305,-1,12,154 +5017256,31,SHORT,306,6,10,144 +5017258,31,SHORT,307,8,3,88 +5017260,31,SHORT,308,7,-1,61 +5017262,31,SHORT,309,2,2,13 +5017264,31,SHORT,310,-4,8,97 +5017266,31,SHORT,311,-1,-1,4 +5017268,31,SHORT,312,-5,2,40 +5017270,31,SHORT,313,6,1,40 +5017272,31,SHORT,314,0,-2,6 +5017274,31,SHORT,315,3,2,20 +5017276,31,SHORT,316,-8,10,182 +5017278,31,SHORT,317,3,-2,19 +5017280,31,SHORT,318,-2,3,17 +5017282,31,SHORT,319,0,0,1 +5017284,31,SHORT,320,0,-2,6 +5017286,31,SHORT,321,2,-2,9 +5017288,31,SHORT,322,-7,3,67 +5017290,31,SHORT,323,-2,-2,9 +5017292,31,SHORT,324,-2,0,6 +5017294,31,SHORT,325,0,-7,50 +5017296,31,SHORT,326,-1,0,1 +5017298,31,SHORT,327,0,-1,2 +5017300,31,SHORT,328,-1,0,1 +5017302,31,SHORT,329,2,9,94 +5017304,31,SHORT,330,0,2,5 +5017306,31,SHORT,331,-1,-3,17 +5017308,31,SHORT,332,-3,6,51 +5017310,31,SHORT,333,2,7,72 +5017312,31,SHORT,334,3,4,36 +5017314,31,SHORT,335,4,-1,22 +5017316,31,SHORT,336,1,2,10 +5017318,31,SHORT,337,2,-9,100 +5017320,31,SHORT,338,1,6,45 +5017322,31,SHORT,339,0,3,11 +5017324,31,SHORT,340,5,-2,37 +5017326,31,SHORT,341,0,-6,37 +5017328,31,SHORT,342,0,-1,1 +5017330,31,SHORT,343,-12,2,171 +5017332,31,SHORT,344,-1,3,18 +5017334,31,SHORT,345,6,-1,51 +5017336,31,SHORT,346,-4,-8,87 +5017338,31,SHORT,347,7,4,79 +5017340,31,SHORT,348,4,-1,26 +5017342,31,SHORT,349,1,11,143 +5017344,31,SHORT,350,2,-1,8 +5017346,31,SHORT,351,3,0,9 +5017348,31,SHORT,352,-3,4,35 +5017350,31,SHORT,353,0,0,0 +5017352,31,SHORT,354,-4,-4,43 +5017354,31,SHORT,355,-2,-3,21 +5017356,31,SHORT,356,0,10,101 +5017358,31,SHORT,357,8,-4,92 +5017360,31,SHORT,358,13,6,228 +5017362,31,SHORT,359,-9,4,105 +5017364,31,SHORT,360,0,1,3 +5017366,31,SHORT,361,1,-3,14 +5017368,31,SHORT,362,0,5,27 +5017370,31,SHORT,363,6,9,134 +5017372,31,SHORT,364,3,4,29 +5017374,31,SHORT,365,8,-6,104 +5017376,31,SHORT,366,0,-6,49 +5017378,31,SHORT,367,-1,6,39 +5017380,31,SHORT,368,-5,0,30 +5017382,31,SHORT,369,-4,3,32 +5017384,31,SHORT,370,-3,0,10 +5017386,31,SHORT,371,0,2,6 +5017388,31,SHORT,372,-5,-4,50 +5017390,31,SHORT,373,3,-10,121 +5017392,31,SHORT,374,-5,1,31 +5017394,31,SHORT,375,-3,-10,116 +5017396,31,SHORT,376,4,-5,50 +5017398,31,SHORT,377,1,7,65 +5017400,31,SHORT,378,1,-4,20 +5017402,31,SHORT,379,-5,0,30 +5017404,31,SHORT,380,6,-5,73 +5017406,31,SHORT,381,-2,-5,40 +5017408,31,SHORT,382,5,-2,34 +5017410,31,SHORT,383,-4,-8,96 +5017412,31,SHORT,384,-3,-1,13 +5017414,31,SHORT,385,-2,6,54 +5017416,31,SHORT,386,2,-3,17 +5017418,31,SHORT,387,5,7,87 +5017420,31,SHORT,388,8,-4,97 +5017422,31,SHORT,389,-2,-5,37 +5017424,31,SHORT,390,0,-2,8 +5017426,31,SHORT,391,3,1,17 +5017428,31,SHORT,392,5,0,31 +5017430,31,SHORT,393,1,5,32 +5017432,31,SHORT,394,10,-7,158 +5017434,31,SHORT,395,-4,0,19 +5017436,31,SHORT,396,2,0,8 +5017438,31,SHORT,397,9,3,97 +5017440,31,SHORT,398,-3,1,10 +5017442,31,SHORT,399,0,0,0 +5017444,31,SHORT,400,-2,4,20 +5017446,31,SHORT,401,8,-2,85 +5017448,31,SHORT,402,-2,-4,28 +5017450,31,SHORT,403,6,-7,97 +5017452,31,SHORT,404,5,0,26 +5017454,31,SHORT,405,-2,0,7 +5017456,31,SHORT,406,12,0,168 +5017458,31,SHORT,407,-1,8,75 +5017460,31,SHORT,408,-1,9,92 +5017462,31,SHORT,409,0,3,15 +5017464,31,SHORT,410,3,-11,135 +5017466,31,SHORT,411,-2,13,175 +5017468,31,SHORT,412,1,7,61 +5017470,31,SHORT,413,-4,-10,129 +5017472,31,SHORT,414,-5,-6,66 +5017474,31,SHORT,415,3,-5,39 +5017476,31,SHORT,416,-2,8,84 +5017478,31,SHORT,417,0,5,26 +5017480,31,SHORT,418,-2,-4,25 +5017482,31,SHORT,419,5,-9,124 +5017484,31,SHORT,420,4,1,23 +5017486,31,SHORT,421,-9,4,110 +5017488,31,SHORT,422,0,-6,40 +5017490,31,SHORT,423,4,-4,40 +5017492,31,SHORT,424,0,0,0 +5017494,31,SHORT,425,0,1,2 +5017496,31,SHORT,426,5,0,27 +5017498,31,SHORT,427,4,0,19 +5017500,31,SHORT,428,0,-10,112 +5017502,31,SHORT,429,0,2,4 +5017504,31,SHORT,430,0,-4,24 +5017506,31,SHORT,431,-3,7,63 +5017508,31,SHORT,432,6,6,77 +5017510,31,SHORT,433,1,5,32 +5017512,31,SHORT,434,9,4,120 +5017514,31,SHORT,435,-2,-1,10 +5017516,31,SHORT,436,4,-3,32 +5017518,31,SHORT,437,1,-7,54 +5017520,31,SHORT,438,-4,3,35 +5017522,31,SHORT,439,-2,-1,7 +5017524,31,SHORT,440,1,-5,29 +5017526,31,SHORT,441,10,1,103 +5017528,31,SHORT,442,8,0,65 +5017530,31,SHORT,443,-3,3,19 +5017532,31,SHORT,444,5,-4,47 +5017534,31,SHORT,445,3,-4,30 +5017536,31,SHORT,446,-4,-11,142 +5017538,31,SHORT,447,2,-12,166 +5017540,31,SHORT,448,2,0,7 +5017542,31,SHORT,449,-9,-7,140 +5017544,31,SHORT,450,-1,-6,50 +5017546,31,SHORT,451,3,0,11 +5017548,31,SHORT,452,0,-6,47 +5017550,31,SHORT,453,0,7,51 +5017552,31,SHORT,454,-9,-7,140 +5017554,31,SHORT,455,-3,-6,50 +5017556,31,SHORT,456,5,0,34 +5017558,31,SHORT,457,-5,0,34 +5017560,31,SHORT,458,4,3,40 +5017562,31,SHORT,459,0,-8,79 +5017564,31,SHORT,460,-8,-4,96 +5017566,31,SHORT,461,2,1,6 +5017568,31,SHORT,462,-8,-5,100 +5017570,31,SHORT,463,0,-3,11 +5017572,31,SHORT,464,3,1,18 +5017574,31,SHORT,465,-6,-7,94 +5017576,31,SHORT,466,7,-8,117 +5017578,31,SHORT,467,-7,-10,169 +5017580,31,SHORT,468,-3,1,16 +5017582,31,SHORT,469,5,3,38 +5017584,31,SHORT,470,5,1,33 +5017586,31,SHORT,471,-2,-9,92 +5017588,31,SHORT,472,-10,-1,103 +5017590,31,SHORT,473,0,1,2 +5017592,31,SHORT,474,5,1,31 +5017594,31,SHORT,475,-3,6,52 +5017596,31,SHORT,476,1,1,4 +5017598,31,SHORT,477,-2,-3,17 +5017600,31,SHORT,478,-7,9,154 +5017602,31,SHORT,479,-5,-5,55 +5017604,31,SHORT,480,0,7,61 +5017606,31,SHORT,481,0,1,1 +5017608,31,SHORT,482,9,3,93 +5017610,31,SHORT,483,-7,-3,67 +5017612,31,SHORT,484,2,11,138 +5017614,31,SHORT,485,-1,3,13 +5017616,31,SHORT,486,-3,5,37 +5017618,31,SHORT,487,6,-2,47 +5017620,31,SHORT,488,-3,-3,23 +5017622,31,SHORT,489,11,2,132 +5017624,31,SHORT,490,3,3,23 +5017626,31,SHORT,491,-4,0,17 +5017628,31,SHORT,492,-2,-2,11 +5017630,31,SHORT,493,-1,1,5 +5017632,31,SHORT,494,0,-5,27 +5017634,31,SHORT,495,0,4,17 +5017636,31,SHORT,496,-3,-2,21 +5017638,31,SHORT,497,-3,2,18 +5017640,31,SHORT,498,-6,-7,92 +5017642,31,SHORT,499,-5,-4,45 +5017644,31,SHORT,500,-1,-5,38 +5017646,31,SHORT,501,6,3,46 +5017648,31,SHORT,502,-4,-4,37 +5017650,31,SHORT,503,3,-5,39 +5017652,31,SHORT,504,3,0,16 +5017654,31,SHORT,505,2,4,24 +5017656,31,SHORT,506,0,1,1 +5017658,31,SHORT,507,2,-2,14 +5017660,31,SHORT,508,0,-2,7 +5017662,31,SHORT,509,0,-10,120 +5017664,31,SHORT,510,-1,-5,33 +5017666,31,SHORT,511,2,-2,11