diff --git a/projects/base_system/block_design.tcl b/projects/base_system/block_design.tcl new file mode 100644 index 0000000000000000000000000000000000000000..80ab85eaa9c8662cb1c21208b16e9936985567f9 --- /dev/null +++ b/projects/base_system/block_design.tcl @@ -0,0 +1,30 @@ +# Create clk_wiz +cell xilinx.com:ip:clk_wiz pll_0 { + PRIMITIVE PLL + PRIM_IN_FREQ.VALUE_SRC USER + PRIM_IN_FREQ 125.0 + PRIM_SOURCE Differential_clock_capable_pin + CLKOUT1_USED true + CLKOUT1_REQUESTED_OUT_FREQ 125.0 + USE_RESET false +} { + clk_in1_p adc_clk_p_i + clk_in1_n adc_clk_n_i +} + +# Create processing_system7 +cell xilinx.com:ip:processing_system7 ps_0 { + PCW_IMPORT_BOARD_PRESET cfg/red_pitaya.xml + PCW_USE_S_AXI_ACP 1 + PCW_USE_DEFAULT_ACP_USER_VAL 1 +} { + M_AXI_GP0_ACLK pll_0/clk_out1 + S_AXI_ACP_ACLK pll_0/clk_out1 +} + +# Create all required interconnections +apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config { + make_external {FIXED_IO, DDR} + Master Disable + Slave Disable +} [get_bd_cells ps_0] diff --git a/projects/cfg_test/block_design.tcl b/projects/cfg_test/block_design.tcl new file mode 100644 index 0000000000000000000000000000000000000000..51fa542cdcd254c4f1437d40cdaa8b958eb54506 --- /dev/null +++ b/projects/cfg_test/block_design.tcl @@ -0,0 +1,48 @@ +source projects/base_system/block_design.tcl + +# Create xlconstant +cell xilinx.com:ip:xlconstant const_0 + +# Create proc_sys_reset +cell xilinx.com:ip:proc_sys_reset rst_0 {} { + ext_reset_in const_0/dout +} + +# Create c_counter_binary +cell xilinx.com:ip:c_counter_binary cntr_0 { + Output_Width 32 +} { + CLK pll_0/clk_out1 +} + +# Create port_slicer +cell labdpr:user:port_slicer slice_0 { + DIN_FROM 26 DIN_TO 26 +} { + din cntr_0/Q +} + +# Create axi_cfg_register +cell labdpr:user:axi_cfg_register cfg_0 { + CFG_DATA_WIDTH 1024 + AXI_ADDR_WIDTH 7 + AXI_DATA_WIDTH 32 +} + +addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0 + +# Create port_slicer +cell labdpr:user:port_slicer slice_1 { + DIN_WIDTH 1024 DIN_FROM 134 DIN_TO 128 +} { + din cfg_0/cfg_data +} + +# Create xlconcat +cell xilinx.com:ip:xlconcat concat_0 { + IN1_WIDTH 7 +} { + In0 slice_0/dout + In1 slice_1/dout + dout led_o +} diff --git a/projects/gpio_led_test/block_design.tcl b/projects/gpio_led_test/block_design.tcl new file mode 100644 index 0000000000000000000000000000000000000000..06376a358f82839f9418f04521637ea84eced20c --- /dev/null +++ b/projects/gpio_led_test/block_design.tcl @@ -0,0 +1,56 @@ +source projects/base_system/block_design.tcl + +#Enable interrupts +set_property -dict [list CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_IRQ_F2P_INTR {1}] [get_bd_cells ps_0] + +# Create xlconstant +cell xilinx.com:ip:xlconstant const_0 + +# Create proc_sys_reset +cell xilinx.com:ip:proc_sys_reset rst_0 {} { + ext_reset_in const_0/dout +} + +# Create axis_rp_adc +cell labdpr:user:axis_rp_adc adc_0 { + ADC_DATA_WIDTH 14 +} { + aclk pll_0/clk_out1 + adc_dat_a adc_dat_a_i + adc_dat_b adc_dat_b_i + adc_csn adc_csn_o +} + +# Create c_counter_binary +cell xilinx.com:ip:c_counter_binary cntr_0 { + Output_Width 32 +} { + CLK pll_0/clk_out1 +} + +# Create xlslice +cell xilinx.com:ip:xlslice slice_0 { + DIN_WIDTH 32 DIN_FROM 26 DIN_TO 26 DOUT_WIDTH 1 +} { + Din cntr_0/Q +} + +# Create GPIO core +cell xilinx.com:ip:axi_gpio axi_gpio_0 { + C_GPIO_WIDTH 8 + C_GPIO2_WIDTH 1 + C_ALL_OUTPUTS 1 + C_IS_DUAL 1 + C_ALL_INPUTS 0 + C_ALL_INPUTS_2 1 + C_INTERRUPT_PRESENT 1 + C_ALL_OUTPUTS 1 +} { + s_axi_aclk pll_0/clk_out1 + s_axi_aresetn rst_0/peripheral_aresetn + ip2intc_irpt ps_0/IRQ_F2P + gpio_io_o led_o + gpio2_io_i slice_0/Dout +} + +addr 0x40000000 4K axi_gpio_0/S_AXI /ps_0/M_AXI_GP0 diff --git a/projects/gpio_led_test/gpio_led_test.c b/projects/gpio_led_test/gpio_led_test.c new file mode 100644 index 0000000000000000000000000000000000000000..bd79c4a74b5a5fe7c0bf50834880205f6d4419c3 --- /dev/null +++ b/projects/gpio_led_test/gpio_led_test.c @@ -0,0 +1,575 @@ +/* basic_design_zynq_hw_exerciser.c + * + * This program demonstrates the basic capabilities of a Zynq platform + * communicating with two axi_gpio peripherals (from the IP catalog) that + * are implemented as hardware in the PL. + * + * NOTE: THE GPIO THAT IS CONTAINED IN THE PS IS NOT BEING USED + * + * One of the GPIO's is configured as an 8 bit output driving 8 LED's. + * The other GPIO is configured as a three input device being driven + * from push buttons. + * + * The program functions in a forever loop, monitoring the input push + * buttons. The three buttons are UP, DOWN, and STOP that directly + * control the a binary counting pattern on the LED's. + * + * This application is written to either, use the Standalone library + * or be compiled as a Linux application. Either flow is supported in + * the SDK programming development. The default compilation is using + * the Standalone library. To compile this application as a Linux + * application, add to the properties of the associated application + * project, a #define of a symbol named "LINUX_APP". Select properties and + * C/C++ Build => Settings => ARM Linux gcc compiler => Symbols, + * adding a -D LINUX_APP to the gcc compiler tool command line. + * + * The hardware (axi_gpio) physical device pinout in the PL may vary + * with the target evaluation board being used. This variation is + * typically manifested in the constraints file which determines + * device pin locations for the actual pin numbers used for the LED's + * and pushbuttons. Other variations in the hardware may be needed to + * accommodate the fact that varying numbers of pushbutton inputs or + * LED output actually exist. + * + * The goal is that this application can be targeted to multiple + * hardware Zynq platforms (or configurations) either as a Standalone + * or Linux application. + * + * THE FOLLOWING HARDWARE PLATFORMS ARE DEFINED + * ZC702 BOARD + * LED's - Eight LED's, DS15-DS22, located towards the center of the + * board from the SD card slot + * Push Buttons - Only two buttons are use, located adjacent to the LED's + * UP - SW7 + * DOWN - SW5 + * STOP - Pressing both, SW5 and SW7, at the same time provides a STOP + * (Due to a lack of pushbuttons accessible by PL pins, hardware + * in the PL was added to emulate a third button) + * + * ZC702 BOARD WITH CE (Customer Education) FMC CARD IN FMC1 SLOT + * LED's - Eight LED's, LD0-LD7, located between slide switches and LCD display + * Push Buttons - Rosetta buttons located on CE FMC card, + * UP - BTN3 - West + * DOWN - BTN0 - Center + * STOP - BTN1 - East + * + * ****************************************************************************************************************** + * + * + * basic_design_exerciser + * Ver.: 1.0 6/1/2012 WK/LR + * + * This code generates an LED pattern for the 8 bit LED array present on the ZC702 board. It must have + * one of several symbols defined: + * hardware_test - infinite loop, long delays for LEDs so user can visually recognize what is happening, uses standalone drivers + * profiler_test - finite loop for gprof, short delays so profiler doesn't report all the activity being in the wait_loop function, uses standalone drivers + * CSP_test - infinite loop, short delays so multiple datum can be captured with the Analyzer, uses standalone drivers + * LINUX_APP - infinite loop, long delays for LEDs so user can visually recogize what is happening, uses Linux drivers + * + * ****************************************************************************************************************** + */ + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <unistd.h> + +// Stuff needed for Linux DEVMEM access +#define MAP_SIZE 4096UL +#define MAP_MASK (MAP_SIZE - 1) +#define TRUE 1 +#define FALSE 1 +typedef int u32; // add this compatibility for int's between Linux and Standalone + +// Linux pointers to GPIO's in PL hardware +void *mapped_led_dev_base; // Address of LED GPIO +void *mapped_button_dev_base; // Address of Push Button GPIO +void *mapped_base; // Address of device memory window, it is global for visibility in main to unmount device memory +int memfd; // device memory handle for Linux device to memory mapping, it is global for visibility in main to unmount device memory + +// Linux application needs gpio base address and register offsets, Standalone application gets it from xparameters.h +#define GPIO_BUTTON_BASE_ADDRESS 0x41240000 +#define GPIO_LED_BASE_ADDRESS 0x40000000 +#define GPIO_DATA_OFFSET 0x0000 +#define GPIO_DIRECTION_OFFSET 0x0004 + +// access the serial output +#define print printf + +// constants +#define LED_DELAY_NORMAL 5000000 +#define LED_DELAY_PROFILE 2 +#define BUTTON_CHANNEL 1 +#define LED_CHANNEL 1 +#define ALL_OUTPUTS 0 +#define ALL_INPUTS 0xffffffff + + +// function prototypes (functions defined in this file after the main) +void *Linux_GPIO_initialize(int gpio_base_address, int direction, int first_call); + +// for the hardware exerciser... +void hardware_exerciser(); // name of routine follows common 'C' language convention +#define PI (double)3.141592653 // approximation of PI +void do_sine_sample(int sample); // takes sample and calls other routines to get results to LEDs, serial port +void doBarGraph(int value, int style); // name of routine follows common Java language convention (legal for C) +void driveBarGraph(int value); // actually selects which LEDs are active and makes peripheral call +#define CYLON 1 +#define BAR 2 +#define BINARY 3 +double sine(double angle_in_radians); +double factorial(int final_term); +char *itoa(int value, char *string, int radix); +char *strcat (char *destination, const char *source); +void delay_loop(long int delay_count); +int buttons_get_state(void); +void LEDs_driver(int pattern); + +int LED_delay_max; // maximum value to delay to for the LED wait loop + +/* + * *********************************************************** + */ +int main() { + + // local variable + int mode = 0; // used to check that one of the environment variables used + + // let the user know that we're starting + print("---basic_design_zynq Exerciser---\n\r"); + + //***** initialize the GPIOs ***** + // For Linux access memory mapped GPIO without kernel driver and initialize. + // The function returns a pointer address to the associated GPIO and sets the GPIO direction + mapped_led_dev_base = Linux_GPIO_initialize(GPIO_LED_BASE_ADDRESS, ALL_OUTPUTS, TRUE); + mapped_button_dev_base = Linux_GPIO_initialize(GPIO_BUTTON_BASE_ADDRESS, ALL_INPUTS, FALSE); + + + // determine the use of this software - are we exercising the hardware or doing the profiling exercise? +#ifdef hardware_test + LED_delay_max = LED_DELAY_NORMAL; + print("running the hardware test...\n\r"); + mode = 1; +#endif + +#ifdef profiler_test + LED_delay_max = LED_DELAY_PROFILE; + print("running the profiler code...\n\r"); + mode = 2; +#endif + +#ifdef CSP_test + LED_delay_max = LED_DELAY_PROFILE; + print("running the CSP analyzer code...\n\r"); + mode = 3; +#endif + + LED_delay_max = LED_DELAY_NORMAL; + print("running the Linux app...\n\r"); + mode = 4; + + // check to see that one or the other mode was selected, otherwise warn the user and abort + if (mode != 0) { + hardware_exerciser(); // read switches, detect changes, increment/decrement counter, display count on LEDs... + } else { + print("you must set the symbol \"hardware_test\", \"profiler_test\", \"CSP_test\", or \"LINUX_APP\" in the compiler settings!\n\r"); + } + + print("---Exiting main---\n\r"); // never reached... + + // unmap the memory used for the GPIO device before exiting + // Linux only, but will never be reached + // It is a good programming practice to always release the memory space the device was accessing + // Since the Standalone drivers can always access memory, this sort of functionality is not needed + if (munmap(mapped_base, MAP_SIZE) == -1) { + printf("Can't unmap memory from user space.\n"); + exit(0); + } + printf("Memory Unmapped\n"); + close(memfd); + + return 0; +} + + + +/* + * ************** Hardware Exerciser Code ************************* + */ +#define UP 0 +#define LEFT 0 +#define DOWN 1 +#define RIGHT 1 +#define STOP 2 + +#define ONE_PERIOD 128 +#define AMPLITUDE 256 +#define ABS(a) (((a) < 0) ? -(a) : (a)) + +/* + * **************************************************************************************************** + * HARDWARE EXERCISER CODE + * **************************************************************************************************** + */ + +void hardware_exerciser() { + // local variables + u32 last_button_state = 0; + u32 current_button_state = 0; + u32 button_difference = 0; + int count_direction = UP; + int sample = 0; + int keep_running = 1; + int profile_iteration_count = 500000; // used only in profile mode + + // deliberate infinite loop + while (keep_running) { + // read current switch configuration + current_button_state = buttons_get_state(); + button_difference = (current_button_state ^ last_button_state) & current_button_state; // detect a change and that it has been pushed (not released) + if (button_difference != 0) { + + // has anything changed based on the buttons? + if (button_difference & 0x04) { print("Stop counting..."); count_direction = STOP; } + else if (button_difference & 0x02) { print("Counting down..."); count_direction = DOWN; } + else if (button_difference & 0x01) { print("Counting up..."); count_direction = UP; } + } + last_button_state = current_button_state; // update the button status to prevent runaway button action + + // compute the next sample number (period of 256) + if (count_direction = UP) { sample++; sample %= ONE_PERIOD; } + else if (count_direction = DOWN) { sample--; if (sample < -1) sample = ONE_PERIOD-1; } + else { /* no change */} + + // do the math and drive the LEDs + do_sine_sample(sample); + + // wait loop - caution - delay loops like this are removed when optimization is turned on! + delay_loop(LED_delay_max); // delay for a slower display + + // if this is the profiler mode, we need to quit after a while +#ifdef profiler_test + keep_running = profile_iteration_count--; +#endif + + } +} + + +// compute sine, drive LEDs and serial port +// 0 < sample < ONE_PERIOD +void do_sine_sample(int location_in_period) { + // local variables + double radian_equivalent; + int sine_value; + char buf[32],*message, *strValue; // used in hardware_test mode only + + // do the computation of this point for sine + radian_equivalent = (double)(location_in_period)/(double)(ONE_PERIOD) * 3.1415927f * 2.0; // one full circle + sine_value = (int)((double)(AMPLITUDE) * sine(radian_equivalent) / 2); // this is +/- (i.e. range -1:1 converted to 0:1), so... + sine_value += AMPLITUDE/2; // bias this up so that 0 is in the middle + + // drive the bar graph display + driveBarGraph(sine_value); + +#ifdef hardware_test + // display the value on the serial port and wait a bit for the LEDs/user to catch up - but only in hardware test mode + // no output will be present in the profiler_test + strValue = itoa(sine_value,buf,10); + message = strcat(strValue,"..."); + xil_printf(message); +#endif +} + +/* + * sine(angle in radians) + * + * where: 0 <= angle in radians <= 2 PI + * + * does Taylor series expansion (4 terms) to compute sine + * taylor series good only for small angles - use reflection technique to determine value outside of Q1 + * Q2 = PI - x + * Q3 = - (x - PI) + * Q4 = - (2PI - x) + * + * Note: this algorithm deliberately uses a slow, iterative way to compute factorials. The faster way: + * int factorial[] = { 1, 1, 2, 6, 24, 120, 720, 5040 }; // the "fast" way to do it - precompute for the # of terms you need, then it's just a memory lookup + * result = angle_in_radians - X3/factorial[3] + X5/factorial[5] - X7/factorial[7]; + * + */ +double sine(double angle_in_radians) { + double X2; + double X3; + double X5; + double X7; + double result; + int quadrant = 1; // begin by assuming Q1 + + // determine quadrant and reflect horizontally (if necessary) + if (angle_in_radians > 3*PI/2) { // in Q4? + quadrant = 4; // remember for later + angle_in_radians = 2 * PI - angle_in_radians; // do horizontal (x) reflection, y reflection done later + } else if (angle_in_radians > PI) { // in Q3? + quadrant = 3; // remember for later + angle_in_radians = angle_in_radians - PI; // no x reflection, y reflection done later + } else if (angle_in_radians > PI/2) { // in Q2? + quadrant = 2; // remember for later + angle_in_radians = PI - angle_in_radians; // do horizontal (x) reflection + } + + // compute powers of angle_in_radians + X2 = angle_in_radians * angle_in_radians; + X3 = X2 * angle_in_radians; + X5 = X3 * X2; + X7 = X5 * X2; + + // compute the sine approximation to 4 places for Q1 + result = angle_in_radians - X3/factorial(3) + X5/factorial(5) - X7/factorial(7); + + // do vertical reflection for Q3 and Q4 + if (quadrant > 2) { + result *= -1; // flip the Q1/Q2 result + } + + return result; +} + +double factorial(int final_term) { + double result = 1.0; + int term; + + for (term=2; term<=final_term; term++) { + result *= term; + } + + return result; +} + + +/****************************************************************************************************** + * LINUX GPIO INITIALIZATION + * This function performs two operations: + * 1) Opens a device to memory window in Linux so a GPIO that exists at a physical address is mapped + * to a fixed logical address. This logical address is returned by the function. + * 2) Initialize the GPIO for either input or output mode. + * + * INPUT PARAMETERS: + * gpio_base_address - physical hardware base address of GPIO, you have to get this from XML file + * direction - 32 bits indicating direction for each bit; 0 - output; 1 - input + * first_call - boolean indicating that this is first call to function. The first time and only the first + * time should the Linux device memory mapping service be mounted. Call for subsequent + * gpio mapping this should be set to FALSE (0). + * + * RETURNS: + * mapped_dev_base - memory pointer to the GPIO that was specified by the gpio_base_address + *******************************************************************************************************/ +void *Linux_GPIO_initialize(int gpio_base_address, int direction, int first_call) +{ + void *mapped_dev_base; + off_t dev_base = gpio_base_address; + + // Linux service to directly access PL hardware as memory without using a device driver + // The memory mapping to device service should only be called once + if (first_call) { + memfd = open("/dev/mem", O_RDWR | O_SYNC); + if (memfd == -1) { + printf("Can't open /dev/mem.\n"); + exit(0); + } + printf("/dev/mem opened.\n"); + } + + // Map one page of memory into user space such that the device is in that page, but it may not + // be at the start of the page. + mapped_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, dev_base & ~MAP_MASK); + if (mapped_base == (void *) -1) { + printf("Can't map the memory to user space for LED GPIO.\n"); + exit(0); + } + printf("LED GPIO memory mapped at address %p.\n", mapped_base); + + // Get the address of the device in user space which will be an offset from the base + // that was mapped as memory is mapped at the start of a page + mapped_dev_base = mapped_base + (dev_base & MAP_MASK); + + // Slight delay for Linux memory access problem + usleep(50); + // write to the direction GPIO direction register to set as all inputs or outputs + *((volatile unsigned long *) (mapped_dev_base + GPIO_DIRECTION_OFFSET)) = direction; + return mapped_dev_base; +} + +/* + * driveBarGraph(12 bit value) + * + * calls doBarGraph. this routine determines which of the 8 possible bins/bars should be illuminated + * + */ +#define NUMBER_OF_LEDS 8 +void driveBarGraph(int value) { + char buf[32]; // used in hardware test mode + double bin_range = (AMPLITUDE) / (NUMBER_OF_LEDS); // how large is each bin? + int nBars = (int)((double)value / bin_range); // how many bars should be lit? + +#ifdef hardware_test + // only print the diagnostic text in hardware_test mode + xil_printf(itoa(nBars,buf,10)); print("\n\r"); +#endif + + // turn on the proper LEDs based on the # of bars and the style + doBarGraph(nBars,CYLON); // +} + + +/* + * doBarGraph(device, value to display, style in which to display + * + * + * example value = 5, style shown below: LED 7 6 5 4 3 2 1 0 + * Style: BAR - solid up to value - - * * * * * * * = on, - = off + * CYLON - single bar at value - - * - - - - - + * BINARY- binary representation of value - - - - - * - * + * other - displays error pattern - * - * - * - * + * + */ +void doBarGraph(int value, int style) { + + if (style == BAR) { + switch (value) { + case 0: LEDs_driver(0x00); break; + case 1: LEDs_driver(0x01); break; + case 2: LEDs_driver(0x03); break; + case 3: LEDs_driver(0x07); break; + case 4: LEDs_driver(0x0f); break; + case 5: LEDs_driver(0x1f); break; + case 6: LEDs_driver(0x3f); break; + case 7: LEDs_driver(0x7f); break; + case 8: LEDs_driver(0xff); break; + default: LEDs_driver(0x55); // non-contiguous pattern indicates error + } + } else if (style == CYLON) { + switch (value) { + case 0: LEDs_driver(0x01); break; + case 1: LEDs_driver(0x02); break; + case 2: LEDs_driver(0x04); break; + case 3: LEDs_driver(0x08); break; + case 4: LEDs_driver(0x10); break; + case 5: LEDs_driver(0x20); break; + case 6: LEDs_driver(0x40); break; + case 7: LEDs_driver(0x80); break; + default: LEDs_driver(0x55); // non-contiguous pattern indicates error + } + } else if (style == BINARY) { + LEDs_driver(value); // simple binary value to display + } else { + LEDs_driver(0x69); // different error pattern + } + +} + + +/* + * *** buttons_get_state() + * + * returns an integer representing the value of the buttons + * 0 - no buttons pressed + * 1 - left/down button pressed + * 2 - right/up button pressed + * 3 - both buttons pressed + * + * this function is coded this way so that it is clear what the Linux vs. Standalone/bare-metal are. + */ +int buttons_get_state() +{ + // local variables + int current_button_state = 0; + // Linux read of gpio, notice that it accesses the data register of the GPIO as a memory location, no device driver needed! + current_button_state = *((volatile unsigned long *) (mapped_button_dev_base + GPIO_DATA_OFFSET)); +} + + +/* + * *** LEDs_driver(led image (int)) + * + * sets the LED channel 1 device to the passed value + * + * this function is coded this way so that it is clear what the Linux vs. Standalone/bare-metal are. + */ +void LEDs_driver(int led_image) +{ + // Linux write to gpio, by writing to a memory address of the gpio data register, no device driver needed! + *((volatile unsigned long *) (mapped_led_dev_base + GPIO_DATA_OFFSET)) = led_image; +} + + +/* + * *** delay_loop(int delay_count) + * + * finite loop which causes a simple delay + * could have been also performed, more accurately, using the usleep() function + * + */ +void delay_loop(long int count) +{ + int i; + for (i=0; i<count; i++); +} + + +/* + * *** itoa + * + * converts an integer into a string - also found in the C library + * + */ +char *itoa(int value, char *string, int radix) +{ + char tmp[33]; + char *tp = tmp; + int i; + unsigned v; + int sign; + char *sp; + + if (radix > 36 || radix <= 1) { string = "radix out of range 1..36"; return 0; } + + sign = (radix == 10 && value < 0); + if (sign) { v = -value; } + else { v = (unsigned)value; } + while (v || tp == tmp) { + i = v % radix; + v = v / radix; + if (i < 10) { *tp++ = i+'0'; } + else { *tp++ = i + 'a' - 10; } + } + + if (string == 0) { + string = (char *)malloc((tp-tmp)+sign+1); + // xil_printf("call to malloc() made\n\r"); + } + sp = string; + + if (sign) { *sp++ = '-'; } + while (tp > tmp) { *sp++ = *--tp; } + *sp = 0; + return string; +} + +/* + * *** strcat + * + * returns the concatonation of two strings + * + * may also be found in string.h + * + */ +char * strcat ( char * destination, const char * source ){ + char *d = destination; + while (*d) ++d; + while ((*d++ = *source++) != '\0') ; + return (destination); +} + + + diff --git a/projects/lago_v1_3/adc.tcl b/projects/lago_v1_3/adc.tcl new file mode 100644 index 0000000000000000000000000000000000000000..ac08dc20c95038028b5f67d9c9627ec14fb304ea --- /dev/null +++ b/projects/lago_v1_3/adc.tcl @@ -0,0 +1,79 @@ + +# Create xlconstant +cell xilinx.com:ip:xlconstant const_2 { + CONST_WIDTH 16 + CONST_VAL 1 +} + +# Create dc removal circuit +cell labdpr:user:axis_dc_removal dc_removal_0 {} { + aclk /pll_0/clk_out1 + aresetn /reset_0/Dout + S_AXIS /adc_0/M_AXIS + k1_i const_2/dout + k2_i const_2/dout +} + +# Create pps generator +cell labdpr:user:pps_gen pps_0 {} { + aclk /pll_0/clk_out1 + aresetn /reset_0/Dout +} + +# Create lago trigger +cell labdpr:user:axis_lago_trigger trigger_0 { + DATA_ARRAY_LENGTH 32 +} { + S_AXIS dc_removal_0/M_AXIS + aclk /pll_0/clk_out1 + aresetn /reset_0/Dout + trig_lvl_a_i /trig_lvl_a/dout + trig_lvl_b_i /trig_lvl_b/dout + subtrig_lvl_a_i /subtrig_lvl_a/dout + subtrig_lvl_b_i /subtrig_lvl_b/dout + pps_i pps_0/pps_o + clk_cnt_pps_i pps_0/clk_cnt_pps_o + temp_i /reg_temp/dout + pressure_i /reg_pressure/dout + time_i /reg_time/dout + date_i /reg_date/dout + latitude_i /reg_latitude/dout + longitude_i /reg_longitude/dout + altitude_i /reg_altitude/dout + satellites_i /reg_satellite/dout + scaler_a_i /reg_trig_scaler_a/dout + scaler_b_i /reg_trig_scaler_b/dout +} + +# Create the tlast generator +cell labdpr:user:axis_tlast_gen tlast_gen_0 { + AXIS_TDATA_WIDTH 32 + PKT_CNTR_BITS 32 +} { + S_AXIS trigger_0/M_AXIS + aclk /pll_0/clk_out1 + aresetn /reset_1/Dout +} + +# Create axis_dwidth_converter +cell xilinx.com:ip:axis_dwidth_converter conv_0 { + S_TDATA_NUM_BYTES.VALUE_SRC USER + S_TDATA_NUM_BYTES 4 + M_TDATA_NUM_BYTES 8 +} { + S_AXIS tlast_gen_0/M_AXIS + aclk /pll_0/clk_out1 + aresetn /reset_2/Dout +} + +# Create axis_ram_writer +cell labdpr:user:axis_ram_writer writer_0 { + ADDR_WIDTH 20 + AXI_ID_WIDTH 3 +} { + aclk /pll_0/clk_out1 + aresetn /reset_2/Dout + S_AXIS conv_0/M_AXIS + M_AXI /ps_0/S_AXI_ACP +} + diff --git a/projects/lago_v1_3/block_design.tcl b/projects/lago_v1_3/block_design.tcl new file mode 100644 index 0000000000000000000000000000000000000000..c8dea1e5ce783c1e02b923c46a15bb8b0d07ae4e --- /dev/null +++ b/projects/lago_v1_3/block_design.tcl @@ -0,0 +1,336 @@ +source projects/base_system/block_design.tcl + + +# Create xlconstant +cell xilinx.com:ip:xlconstant const_0 + +# Create proc_sys_reset +cell xilinx.com:ip:proc_sys_reset rst_0 {} { + ext_reset_in const_0/dout +} + +#Enable interrupts +set_property -dict [list CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_IRQ_F2P_INTR {1}] [get_bd_cells ps_0] + +# Delete input/output port +delete_bd_objs [get_bd_ports exp_p_tri_io] +delete_bd_objs [get_bd_ports exp_n_tri_io] + +# Create input port +create_bd_port -dir I -from 7 -to 7 exp_n_tri_io +create_bd_port -dir O -from 7 -to 7 exp_p_tri_io +create_bd_port -dir I -from 0 -to 0 ext_resetn + +# Create axis_rp_adc +cell labdpr:user:axis_rp_adc adc_0 { + ADC_DATA_WIDTH 14 +} { + aclk pll_0/clk_out1 + adc_dat_a adc_dat_a_i + adc_dat_b adc_dat_b_i + adc_csn adc_csn_o +} + +# Create axi_cfg_register +cell labdpr:user:axi_cfg_register cfg_0 { + CFG_DATA_WIDTH 1024 + AXI_ADDR_WIDTH 32 + AXI_DATA_WIDTH 32 +} + +#Create concatenator +cell xilinx.com:ip:xlconcat concat_0 { + NUM_PORTS 6 +} { + dout led_o +} + +#Create concatenator +cell xilinx.com:ip:xlconcat concat_1 { + NUM_PORTS 4 +} { + dout dac_pwm_o +} + +# Create axi_intc +cell xilinx.com:ip:axi_intc axi_intc_0 { + C_IRQ_CONNECTION 1 + C_S_AXI_ACLK_FREQ_MHZ 125.0 + C_PROCESSOR_CLK_FREQ_MHZ 125.0 +} { + irq ps_0/IRQ_F2P +} + +# Create axi_sts_register +cell labdpr:user:axi_sts_register sts_0 { + STS_DATA_WIDTH 32 + AXI_ADDR_WIDTH 32 + AXI_DATA_WIDTH 32 +} { } + +# Create xlslice for reset fifo, pps_gen and trigger modules. off=0 +cell labdpr:user:port_slicer reset_0 { + DIN_WIDTH 1024 DIN_FROM 0 DIN_TO 0 +} { + din cfg_0/cfg_data +} + +# Create xlslice for reset tlast_gen. off=0 +cell labdpr:user:port_slicer reset_1 { + DIN_WIDTH 1024 DIN_FROM 1 DIN_TO 1 +} { + din cfg_0/cfg_data +} + +# Create xlslice for reset conv_0 and writer_0. off=0 +cell labdpr:user:port_slicer reset_2 { + DIN_WIDTH 1024 DIN_FROM 2 DIN_TO 2 +} { + din cfg_0/cfg_data +} + +# Create xlslice for set the # of samples to get. off=1 +cell labdpr:user:port_slicer nsamples { + DIN_WIDTH 1024 DIN_FROM 63 DIN_TO 32 +} { + din cfg_0/cfg_data +} + +# Create xlslice for set the trigger_lvl_a. off=2 +cell labdpr:user:port_slicer trig_lvl_a { + DIN_WIDTH 1024 DIN_FROM 95 DIN_TO 64 +} { + din cfg_0/cfg_data +} + +# Create xlslice for set the trigger_lvl_b. off=3 +cell labdpr:user:port_slicer trig_lvl_b { + DIN_WIDTH 1024 DIN_FROM 127 DIN_TO 96 +} { + din cfg_0/cfg_data +} + +# Create xlslice for set the subtrigger_lvl_a. off=4 +cell labdpr:user:port_slicer subtrig_lvl_a { + DIN_WIDTH 1024 DIN_FROM 159 DIN_TO 128 +} { + din cfg_0/cfg_data +} + +# Create xlslice for set the subtrigger_lvl_b. off=5 +cell labdpr:user:port_slicer subtrig_lvl_b { + DIN_WIDTH 1024 DIN_FROM 191 DIN_TO 160 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the temperature data. off=6 +cell labdpr:user:port_slicer reg_temp { + DIN_WIDTH 1024 DIN_FROM 223 DIN_TO 192 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the pressure data. off=7 +cell labdpr:user:port_slicer reg_pressure { + DIN_WIDTH 1024 DIN_FROM 255 DIN_TO 224 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the time data. off=8 +cell labdpr:user:port_slicer reg_time { + DIN_WIDTH 1024 DIN_FROM 287 DIN_TO 256 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the date data. off=9 +cell labdpr:user:port_slicer reg_date { + DIN_WIDTH 1024 DIN_FROM 319 DIN_TO 288 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the latitude data. off=10 +cell labdpr:user:port_slicer reg_latitude { + DIN_WIDTH 1024 DIN_FROM 351 DIN_TO 320 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the longitude data. off=11 +cell labdpr:user:port_slicer reg_longitude { + DIN_WIDTH 1024 DIN_FROM 383 DIN_TO 352 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the altitude data. off=12 +cell labdpr:user:port_slicer reg_altitude { + DIN_WIDTH 1024 DIN_FROM 415 DIN_TO 384 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the satellite data. off=13 +cell labdpr:user:port_slicer reg_satellite { + DIN_WIDTH 1024 DIN_FROM 447 DIN_TO 416 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the trigger scaler a. off=14 +cell labdpr:user:port_slicer reg_trig_scaler_a { + DIN_WIDTH 1024 DIN_FROM 479 DIN_TO 448 +} { + din cfg_0/cfg_data +} + +# Create xlslice for the trigger scaler b. off=15 +cell labdpr:user:port_slicer reg_trig_scaler_b { + DIN_WIDTH 1024 DIN_FROM 511 DIN_TO 480 +} { + din cfg_0/cfg_data +} + +# Create port_slicer for cfg RAM writer. off=22 +cell labdpr:user:port_slicer cfg_ram_wr { + DIN_WIDTH 1024 DIN_FROM 735 DIN_TO 704 +} { + din cfg_0/cfg_data +} + +# Create xlslice for set the gpsen_i input +cell labdpr:user:port_slicer gpsen { + DIN_WIDTH 1024 DIN_FROM 4 DIN_TO 4 +} { + din cfg_0/cfg_data +} + +# Create proc_sys_reset +cell xilinx.com:ip:proc_sys_reset rst_1 {} { + slowest_sync_clk pll_0/clk_out1 + dcm_locked pll_0/locked + ext_reset_in ext_resetn +} + +module fadc_0 { + source projects/lago_v1_3/adc.tcl +} { + writer_0/sts_data sts_0/sts_data + pps_0/resetn_i rst_1/peripheral_aresetn + pps_0/int_o axi_intc_0/intr + writer_0/cfg_data cfg_ram_wr/dout + writer_0/M_AXI ps_0/S_AXI_ACP + tlast_gen_0/pkt_length nsamples/dout + pps_0/gpsen_i gpsen/dout + pps_0/pps_i exp_n_tri_io + pps_0/pps_sig_o exp_p_tri_io + pps_0/pps_gps_led_o concat_0/In0 + pps_0/false_pps_led_o concat_0/In1 +} + +#Now all related to the DAC PWM +# Create xlslice. off=0 +cell labdpr:user:port_slicer reset_3 { + DIN_WIDTH 1024 DIN_FROM 3 DIN_TO 3 +} { + din cfg_0/cfg_data +} + +# Create xlslice. off=16 +cell labdpr:user:port_slicer cfg_dac_pwm_0 { + DIN_WIDTH 1024 DIN_FROM 543 DIN_TO 512 +} { + din cfg_0/cfg_data +} + +# Create xlslice.. off=17 +cell labdpr:user:port_slicer cfg_dac_pwm_1 { + DIN_WIDTH 1024 DIN_FROM 575 DIN_TO 544 +} { + din cfg_0/cfg_data +} + +# Create xlslice.. off=18 +cell labdpr:user:port_slicer cfg_dac_pwm_2 { + DIN_WIDTH 1024 DIN_FROM 607 DIN_TO 576 +} { + din cfg_0/cfg_data +} + +# Create xlslice.. off=19 +cell labdpr:user:port_slicer cfg_dac_pwm_3 { + DIN_WIDTH 1024 DIN_FROM 639 DIN_TO 608 +} { + din cfg_0/cfg_data +} + +module slow_dac_0 { + source projects/lago_v1_3/slow_dac.tcl +} { + gen_0/pwm_o concat_1/In0 + gen_0/led_o concat_0/In2 + gen_0/data_i cfg_dac_pwm_0/Dout + gen_1/pwm_o concat_1/In1 + gen_1/led_o concat_0/In3 + gen_1/data_i cfg_dac_pwm_1/Dout + gen_2/pwm_o concat_1/In2 + gen_2/led_o concat_0/In4 + gen_2/data_i cfg_dac_pwm_2/Dout + gen_3/pwm_o concat_1/In3 + gen_3/led_o concat_0/In5 + gen_3/data_i cfg_dac_pwm_3/Dout +} + +#XADC related +# Create xadc +cell xilinx.com:ip:xadc_wiz xadc_wiz_0 { + DCLK_FREQUENCY 125 + ADC_CONVERSION_RATE 500 + XADC_STARUP_SELECTION channel_sequencer + CHANNEL_AVERAGING 64 + OT_ALARM false + USER_TEMP_ALARM false + VCCINT_ALARM false + VCCAUX_ALARM false + ENABLE_VCCPINT_ALARM false + ENABLE_VCCPAUX_ALARM false + ENABLE_VCCDDRO_ALARM false + CHANNEL_ENABLE_CALIBRATION true + CHANNEL_ENABLE_TEMPERATURE true + CHANNEL_ENABLE_VCCINT true + CHANNEL_ENABLE_VP_VN true + CHANNEL_ENABLE_VAUXP0_VAUXN0 true + CHANNEL_ENABLE_VAUXP1_VAUXN1 true + CHANNEL_ENABLE_VAUXP8_VAUXN8 true + CHANNEL_ENABLE_VAUXP9_VAUXN9 true + AVERAGE_ENABLE_VP_VN true + AVERAGE_ENABLE_VAUXP0_VAUXN0 true + AVERAGE_ENABLE_VAUXP1_VAUXN1 true + AVERAGE_ENABLE_VAUXP8_VAUXN8 true + AVERAGE_ENABLE_VAUXP9_VAUXN9 true + AVERAGE_ENABLE_TEMPERATURE true + AVERAGE_ENABLE_VCCINT true + EXTERNAL_MUX_CHANNEL VP_VN + SINGLE_CHANNEL_SELECTION TEMPERATURE +} {} + +connect_bd_intf_net [get_bd_intf_ports Vp_Vn] [get_bd_intf_pins xadc_wiz_0/Vp_Vn] +connect_bd_intf_net [get_bd_intf_ports Vaux0] [get_bd_intf_pins xadc_wiz_0/Vaux0] +connect_bd_intf_net [get_bd_intf_ports Vaux1] [get_bd_intf_pins xadc_wiz_0/Vaux1] +connect_bd_intf_net [get_bd_intf_ports Vaux8] [get_bd_intf_pins xadc_wiz_0/Vaux8] +connect_bd_intf_net [get_bd_intf_ports Vaux9] [get_bd_intf_pins xadc_wiz_0/Vaux9] + +addr 0x40000000 4K axi_intc_0/S_AXI /ps_0/M_AXI_GP0 + +addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0 + +addr 0x40002000 4K sts_0/S_AXI /ps_0/M_AXI_GP0 + +addr 0x40003000 4K xadc_wiz_0/s_axi_lite /ps_0/M_AXI_GP0 + + +group_bd_cells PS7 [get_bd_cells rst_0] [get_bd_cells rst_1] [get_bd_cells pll_0] [get_bd_cells const_0] [get_bd_cells ps_0] [get_bd_cells ps_0_axi_periph] + diff --git a/projects/lago_v1_3/ports.xdc b/projects/lago_v1_3/ports.xdc new file mode 100644 index 0000000000000000000000000000000000000000..ff256d11c022b18c3865e2caec0b33af40abd6f5 --- /dev/null +++ b/projects/lago_v1_3/ports.xdc @@ -0,0 +1,7 @@ +set_property IOSTANDARD LVCMOS33 [get_ports {ext_resetn}] +set_property SLEW FAST [get_ports {ext_resetn}] +set_property DRIVE 8 [get_ports {ext_resetn}] +set_property PULLTYPE PULLUP [get_ports {ext_resetn}] + +set_property PACKAGE_PIN J16 [get_ports {ext_resetn}] + diff --git a/projects/lago_v1_3/slow_dac.tcl b/projects/lago_v1_3/slow_dac.tcl new file mode 100644 index 0000000000000000000000000000000000000000..03ac194549e07eac3671f99b10e12af12460f9a6 --- /dev/null +++ b/projects/lago_v1_3/slow_dac.tcl @@ -0,0 +1,40 @@ +#Create PWM generator +cell labdpr:user:ramp_gen:1.0 gen_0 { + COUNT_NBITS 20 + COUNT_MOD 5000 + DATA_BITS 16 +} { + aclk /pll_0/clk_out1 + aresetn /reset_3/Dout +} + +#Create PWM generator +cell labdpr:user:ramp_gen:1.0 gen_1 { + COUNT_NBITS 20 + COUNT_MOD 5000 + DATA_BITS 16 +} { + aclk /pll_0/clk_out1 + aresetn /reset_3/Dout +} + +#Create PWM generator +cell labdpr:user:ramp_gen:1.0 gen_2 { + COUNT_NBITS 20 + COUNT_MOD 5000 + DATA_BITS 16 +} { + aclk /pll_0/clk_out1 + aresetn /reset_3/Dout +} + +#Create PWM generator +cell labdpr:user:ramp_gen:1.0 gen_3 { + COUNT_NBITS 20 + COUNT_MOD 5000 + DATA_BITS 16 +} { + aclk /pll_0/clk_out1 + aresetn /reset_3/Dout +} + diff --git a/projects/lago_v1_3/src/Makefile b/projects/lago_v1_3/src/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d9b4e5552811e84ccd2b0acc75a8fa438eed4161 --- /dev/null +++ b/projects/lago_v1_3/src/Makefile @@ -0,0 +1,16 @@ +CC=gcc +FLAGS=-Wall -O3 -li2c +ARCH=arm +CROSS_COMPILE=arm-xilinx-linux-gnueabi- + +#### +PROG=lago +EXTRA=uart_rp.c nmea_rp.c gps_rp.c zynq_io.c bmp180.c + +all: $(PROG) + +$(PROG): $(PROG).c $(EXTRA) + $(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm -lpthread + +clean: + rm -f $(PROG) diff --git a/projects/lago_v1_3/src/bmp180.c b/projects/lago_v1_3/src/bmp180.c new file mode 100644 index 0000000000000000000000000000000000000000..99f3323e9d5df8a586793ad052bd81755b181b42 --- /dev/null +++ b/projects/lago_v1_3/src/bmp180.c @@ -0,0 +1,366 @@ +#include "bmp180.h" + +/* Lookup table for BMP180 register addresses */ +int32_t bmp180_register_table[11][2] = +{ + {BMP180_REG_AC1_H, 1}, + {BMP180_REG_AC2_H, 1}, + {BMP180_REG_AC3_H, 1}, + {BMP180_REG_AC4_H, 0}, + {BMP180_REG_AC5_H, 0}, + {BMP180_REG_AC6_H, 0}, + {BMP180_REG_B1_H, 1}, + {BMP180_REG_B2_H, 1}, + {BMP180_REG_MB_H, 1}, + {BMP180_REG_MC_H, 1}, + {BMP180_REG_MD_H, 1} +}; + +/* + * Returns the raw measured temperature value of this BMP180 sensor. + * + * @param bmp180 sensor + */ +static int32_t bmp180_read_raw_temperature(void *_bmp) +{ + bmp180_t* bmp = TO_BMP(_bmp); + i2c_smbus_write_byte_data(bmp->file, BMP180_CTRL, BMP180_TMP_READ_CMD); + + usleep(BMP180_TMP_READ_WAIT_US); + int32_t data = i2c_smbus_read_word_data(bmp->file, BMP180_REG_TMP) & 0xFFFF; + + data = ((data << 8) & 0xFF00) + (data >> 8); + + return data; +} + +/* + * Returns the raw measured pressure value of this BMP180 sensor. + * + * @param bmp180 sensor + */ +static int32_t bmp180_read_raw_pressure(void *_bmp, uint8_t oss) +{ + bmp180_t* bmp = TO_BMP(_bmp); + uint16_t wait; + uint8_t cmd; + + switch(oss) { + case BMP180_PRE_OSS1: + wait = BMP180_PRE_OSS1_WAIT_US; cmd = BMP180_PRE_OSS1_CMD; + break; + + case BMP180_PRE_OSS2: + wait = BMP180_PRE_OSS2_WAIT_US; cmd = BMP180_PRE_OSS2_CMD; + break; + + case BMP180_PRE_OSS3: + wait = BMP180_PRE_OSS3_WAIT_US; cmd = BMP180_PRE_OSS3_CMD; + break; + + case BMP180_PRE_OSS0: + default: + wait = BMP180_PRE_OSS0_WAIT_US; cmd = BMP180_PRE_OSS0_CMD; + break; + } + + i2c_smbus_write_byte_data(bmp->file, BMP180_CTRL, cmd); + + usleep(wait); + + int32_t msb, lsb, xlsb, data; + msb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE) & 0xFF; + lsb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE+1) & 0xFF; + xlsb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE+2) & 0xFF; + + data = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - bmp->oss); + + return data; +} + +/** + * Returns the measured pressure in pascal. + * + * @param bmp180 sensor + * @return pressure + */ +float bmp180_pressure(void *_bmp) +{ + bmp180_t* bmp = TO_BMP(_bmp); + long UT, UP, B6, B5, X1, X2, X3, B3, p; + unsigned long B4, B7; + + UT = bmp180_read_raw_temperature(_bmp); + UP = bmp180_read_raw_pressure(_bmp, bmp->oss); + + X1 = ((UT - bmp->ac6) * bmp->ac5) >> 15; + X2 = (bmp->mc << 11) / (X1 + bmp->md); + + B5 = X1 + X2; + + B6 = B5 - 4000; + + X1 = (bmp->b2 * (B6 * B6) >> 12) >> 11; + X2 = (bmp->ac2 * B6) >> 11; + X3 = X1 + X2; + + B3 = ((((bmp->ac1 * 4) + X3) << bmp->oss) + 2) / 4; + X1 = (bmp->ac3 * B6) >> 13; + X2 = (bmp->b1 * ((B6 * B6) >> 12)) >> 16; + X3 = ((X1 + X2) + 2) >> 2; + + + B4 = bmp->ac4 * (unsigned long)(X3 + 32768) >> 15; + B7 = ((unsigned long) UP - B3) * (50000 >> bmp->oss); + + if(B7 < 0x80000000) { + p = (B7 * 2) / B4; + } else { + p = (B7 / B4) * 2; + } + + X1 = (p >> 8) * (p >> 8); + X1 = (X1 * 3038) >> 16; + X2 = (-7357 * p) >> 16; + p = p + ((X1 + X2 + 3791) >> 4); + + return p; +} + +/* + * Sets the address for the i2c device file. + * + * @param bmp180 sensor + */ +static int bmp180_set_addr(void *_bmp) +{ + bmp180_t* bmp = TO_BMP(_bmp); + int error; + + if((error = ioctl(bmp->file, I2C_SLAVE, bmp->address)) < 0) { + DEBUG("error: ioctl() failed\n"); + } + + return error; +} + +/* + * Frees allocated memory in the init function. + * + * @param bmp180 sensor + */ +static void bmp180_init_error_cleanup(void *_bmp) +{ + bmp180_t* bmp = TO_BMP(_bmp); + + if(bmp->i2c_device != NULL) { + free(bmp->i2c_device); + bmp->i2c_device = NULL; + } + + free(bmp); + bmp = NULL; +} + +/* + * Reads a single calibration coefficient from the BMP180 eprom. + * + * @param bmp180 sensor + */ +static void bmp180_read_eprom_reg(void *_bmp, int32_t *_store, uint8_t reg, int32_t sign) +{ + bmp180_t *bmp = TO_BMP(_bmp); + int32_t data = i2c_smbus_read_word_data(bmp->file, reg) & 0xFFFF; + + // i2c_smbus_read_word_data assumes little endian + // but ARM uses big endian. Thus the ordering of the bytes is reversed. + // data = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 bit position + // | lsb | msb | + + // msb + lsb + *_store = ((data << 8) & 0xFF00) + (data >> 8); + + if(sign && (*_store > 32767)) { + *_store -= 65536; + } +} + +/* + * Reads the eprom of this BMP180 sensor. + * + * @param bmp180 sensor + */ +void bmp180_read_eprom(void *_bmp) +{ + bmp180_t *bmp = TO_BMP(_bmp); + + int32_t *bmp180_register_addr[11] = { + &bmp->ac1, &bmp->ac2, &bmp->ac3, &bmp->ac4, &bmp->ac5, &bmp->ac6, + &bmp->b1, &bmp->b2, &bmp->mb, &bmp->mc, &bmp->md + }; + + uint8_t sign, reg; + int32_t *data; + int i; + for(i = 0; i < 11; i++) { + reg = (uint8_t) bmp180_register_table[i][0]; + sign = (uint8_t) bmp180_register_table[i][1]; + data = bmp180_register_addr[i]; + bmp180_read_eprom_reg(_bmp, data, reg, sign); + } +} + +/** + * Dumps the eprom values of this BMP180 sensor. + * + * @param bmp180 sensor + * @param bmp180 eprom struct + */ +void bmp180_dump_eprom(void *_bmp, bmp180_eprom_t *eprom) +{ + bmp180_t *bmp = TO_BMP(_bmp); + eprom->ac1 = bmp->ac1; + eprom->ac2 = bmp->ac2; + eprom->ac3 = bmp->ac3; + eprom->ac4 = bmp->ac4; + eprom->ac5 = bmp->ac5; + eprom->ac6 = bmp->ac6; + eprom->b1 = bmp->b1; + eprom->b2 = bmp->b2; + eprom->mb = bmp->mb; + eprom->mc = bmp->mc; + eprom->md = bmp->md; +} + +/** + * Creates a BMP180 sensor object. + * + * @param i2c device address + * @param i2c device file path + * @return bmp180 sensor + */ +void *bmp180_init(int address, const char* i2c_device_filepath) +{ + DEBUG("device: init using address %#x and i2cbus %s\n", address, i2c_device_filepath); + + // setup BMP180 + void *_bmp = malloc(sizeof(bmp180_t)); + if(_bmp == NULL) { + DEBUG("error: malloc returns NULL pointer\n"); + return NULL; + } + + bmp180_t *bmp = TO_BMP(_bmp); + bmp->address = address; + + // setup i2c device path + bmp->i2c_device = (char*) malloc(strlen(i2c_device_filepath) * sizeof(char)); + if(bmp->i2c_device == NULL) { + DEBUG("error: malloc returns NULL pointer!\n"); + bmp180_init_error_cleanup(bmp); + return NULL; + } + + // copy string + strcpy(bmp->i2c_device, i2c_device_filepath); + + // open i2c device + int file; + if((file = open(bmp->i2c_device, O_RDWR)) < 0) { + DEBUG("error: %s open() failed\n", bmp->i2c_device); + bmp180_init_error_cleanup(bmp); + return NULL; + } + bmp->file = file; + + // set i2c device address + if(bmp180_set_addr(_bmp) < 0) { + bmp180_init_error_cleanup(bmp); + return NULL; + } + + // setup i2c device + bmp180_read_eprom(_bmp); + bmp->oss = 0; + + DEBUG("device: open ok\n"); + + return _bmp; +} + +/** + * Closes a BMP180 object. + * + * @param bmp180 sensor + */ +void bmp180_close(void *_bmp) +{ + if(_bmp == NULL) { + return; + } + + DEBUG("close bmp180 device\n"); + bmp180_t *bmp = TO_BMP(_bmp); + + if(close(bmp->file) < 0) { + DEBUG("error: %s close() failed\n", bmp->i2c_device); + } + + free(bmp->i2c_device); // free string + bmp->i2c_device = NULL; + free(bmp); // free bmp structure + _bmp = NULL; +} + +/** + * Returns the measured temperature in celsius. + * + * @param bmp180 sensor + * @return temperature + */ +float bmp180_temperature(void *_bmp) +{ + bmp180_t* bmp = TO_BMP(_bmp); + long UT, X1, X2, B5; + float T; + + UT = bmp180_read_raw_temperature(_bmp); + + DEBUG("UT=%lu\n",UT); + + X1 = ((UT - bmp->ac6) * bmp->ac5) >> 15; + X2 = (bmp->mc << 11) / (X1 + bmp->md); + B5 = X1 + X2; + T = ((B5 + 8) >> 4) / 10.0; + + return T; +} + +/** + * Returns altitude in meters based on the measured pressure + * and temperature of this sensor. + * + * @param bmp180 sensor + * @return altitude + */ +float bmp180_altitude(void *_bmp) +{ + float p, alt; + p = bmp180_pressure(_bmp); + alt = 44330 * (1 - pow(( (p/100) / BMP180_SEA_LEVEL),1/5.255)); + + return alt; +} + +/** + * Sets the oversampling setting for this sensor. + * + * @param bmp180 sensor + * @param oversampling mode + */ +void bmp180_set_oss(void *_bmp, int oss) +{ + bmp180_t* bmp = TO_BMP(_bmp); + bmp->oss = oss; +} + diff --git a/projects/lago_v1_3/src/bmp180.h b/projects/lago_v1_3/src/bmp180.h new file mode 100644 index 0000000000000000000000000000000000000000..ecaaab8dfbd37825238eb31c05e57073fff3d1c4 --- /dev/null +++ b/projects/lago_v1_3/src/bmp180.h @@ -0,0 +1,142 @@ +#ifndef __BMP180__ +#define __BMP180__ + +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <i2c/smbus.h> +#include <linux/i2c-dev.h> +#include <math.h> +#include<unistd.h> +#include<inttypes.h> + +#define BMP180_PRE_OSS0 0 // ultra low power +#define BMP180_PRE_OSS1 1 // standard +#define BMP180_PRE_OSS2 2 // high resolution +#define BMP180_PRE_OSS3 3 // ultra high resoultion + +/* AC register */ +#define BMP180_REG_AC1_H 0xAA +#define BMP180_REG_AC2_H 0xAC +#define BMP180_REG_AC3_H 0xAE +#define BMP180_REG_AC4_H 0xB0 +#define BMP180_REG_AC5_H 0xB2 +#define BMP180_REG_AC6_H 0xB4 + +/* B1 register */ +#define BMP180_REG_B1_H 0xB6 + +/* B2 register */ +#define BMP180_REG_B2_H 0xB8 + +/* MB register */ +#define BMP180_REG_MB_H 0xBA + +/* MC register */ +#define BMP180_REG_MC_H 0xBC + +/* MD register */ +#define BMP180_REG_MD_H 0xBE + +/* AC register */ +#define BMP180_CTRL 0xF4 + +/* Temperature register */ +#define BMP180_REG_TMP 0xF6 + +/* Pressure register */ +#define BMP180_REG_PRE 0xF6 + +/* Temperature read command */ +#define BMP180_TMP_READ_CMD 0x2E + +/* Waiting time in us for reading temperature values */ +#define BMP180_TMP_READ_WAIT_US 5000 + +/* Pressure oversampling modes */ +#define BMP180_PRE_OSS0 0 // ultra low power +#define BMP180_PRE_OSS1 1 // standard +#define BMP180_PRE_OSS2 2 // high resolution +#define BMP180_PRE_OSS3 3 // ultra high resoultion + +/* Pressure read commands */ +#define BMP180_PRE_OSS0_CMD 0x34 +#define BMP180_PRE_OSS1_CMD 0x74 +#define BMP180_PRE_OSS2_CMD 0xB4 +#define BMP180_PRE_OSS3_CMD 0xF4 + +/* Waiting times in us for reading pressure values */ +#define BMP180_PRE_OSS0_WAIT_US 5000 +#define BMP180_PRE_OSS1_WAIT_US 8000 +#define BMP180_PRE_OSS2_WAIT_US 14000 +#define BMP180_PRE_OSS3_WAIT_US 26000 + +/* Average sea-level pressure in hPa */ +#define BMP180_SEA_LEVEL 1013.25 + +/* Define debug function. */ +//#define __BMP180_DEBUG__ +#ifdef __BMP180_DEBUG__ +#define DEBUG(...) printf(__VA_ARGS__) +#else +#define DEBUG(...) +#endif + +/* Shortcut to cast void pointer to a bmp180_t pointer */ +#define TO_BMP(x) (bmp180_t*) x + +/* Basic structure for the bmp180 sensor */ +typedef struct { + /* file descriptor */ + int file; + /* i2c device address */ + int address; + /* BMP180 oversampling mode */ + int oss; + /* i2c device file path */ + char *i2c_device; + /* Eprom values */ + int32_t ac1; + int32_t ac2; + int32_t ac3; + int32_t ac4; + int32_t ac5; + int32_t ac6; + int32_t b1; + int32_t b2; + int32_t mb; + int32_t mc; + int32_t md; +} bmp180_t; + + +/* Lookup table for BMP180 register addresses */ +extern int32_t bmp180_register_table[11][2]; + +typedef struct { + /* Eprom values */ + int ac1; + int ac2; + int ac3; + int ac4; + int ac5; + int ac6; + int b1; + int b2; + int mb; + int mc; + int md; +} bmp180_eprom_t; + +/* Prototypes for helper functions */ +void bmp180_read_eprom(void *_bmp); +void *bmp180_init(int address, const char* i2c_device_filepath); +void bmp180_close(void *_bmp); +void bmp180_set_oss(void *_bmp, int oss); +float bmp180_pressure(void *_bmp); +float bmp180_temperature(void *_bmp); +float bmp180_altitude(void *_bmp); +void bmp180_dump_eprom(void *_bmp, bmp180_eprom_t *eprom); + +#endif diff --git a/projects/lago_v1_3/src/defs.h b/projects/lago_v1_3/src/defs.h new file mode 100644 index 0000000000000000000000000000000000000000..104ff7078f07d06663424fda158256f8b6c4d444 --- /dev/null +++ b/projects/lago_v1_3/src/defs.h @@ -0,0 +1,136 @@ +#define _CRT_SECURE_NO_WARNINGS + +#define _FILE_OFFSET_BITS 64 + +#ifndef EXP +#define EXP "LAGO" +#endif + +/* Output format version */ +#define DATAVERSION 5 +#define VERSION 2 +#define REVISION 1 + +#define MAXCHRLEN 1024 +#define BLOCKSIZE 16384 +#define MAXFILENAMELEN 255 +#define MAXPRESS 1100 //1100Hpa +#define PRESSUREBLOCKSIZE 22 +#define GPSBLOCKSIZE 64 + +#define XIL_AXI_INTC_BASEADDR 0x40000000 +#define XIL_AXI_INTC_HIGHADDR 0x40000FFF + +#define XIL_AXI_INTC_ISR_OFFSET 0x0 +#define XIL_AXI_INTC_IPR_OFFSET 0x4 +#define XIL_AXI_INTC_IER_OFFSET 0x8 +#define XIL_AXI_INTC_IAR_OFFSET 0xC +#define XIL_AXI_INTC_SIE_OFFSET 0x10 +#define XIL_AXI_INTC_CIE_OFFSET 0x14 +#define XIL_AXI_INTC_IVR_OFFSET 0x18 +#define XIL_AXI_INTC_MER_OFFSET 0x1C +#define XIL_AXI_INTC_IMR_OFFSET 0x20 +#define XIL_AXI_INTC_ILR_OFFSET 0x24 +#define XIL_AXI_INTC_IVAR_OFFSET 0x100 + +#define XIL_AXI_INTC_MER_ME_MASK 0x00000001 +#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002 + +//CFG +#define CFG_RESET_GRAL_OFFSET 0x0 +#define CFG_NSAMPLES_OFFSET 0x4 +#define CFG_TRLVL_1_OFFSET 0x8 +#define CFG_TRLVL_2_OFFSET 0xC +#define CFG_STRLVL_1_OFFSET 0x10 +#define CFG_STRLVL_2_OFFSET 0x14 +#define CFG_TEMPERATURE_OFFSET 0x18 +#define CFG_PRESSURE_OFFSET 0x1C +#define CFG_TIME_OFFSET 0x20 +#define CFG_LATITUDE_OFFSET 0x24 +#define CFG_LONGITUDE_OFFSET 0x28 +#define CFG_ALTITUDE_OFFSET 0x2C +#define CFG_SATELLITE_OFFSET 0x30 +#define CFG_HV1_OFFSET 0x40 +#define CFG_HV2_OFFSET 0x44 + +//CFG Slow DAC +#define CFG_DAC_PWM0_OFFSET 0x40 +#define CFG_DAC_PWM1_OFFSET 0x44 +#define CFG_DAC_PWM2_OFFSET 0x48 +#define CFG_DAC_PWM3_OFFSET 0x4C + +#define ENBL_ALL_MASK 0xFFFFFFFF +#define RST_ALL_MASK 0x00000000 +#define RST_PPS_TRG_FIFO_MASK 0x00000001 +#define RST_TLAST_GEN_MASK 0x00000002 +#define RST_WRITER_MASK 0x00000004 +#define RST_AO_MASK 0x00000008 +#define FGPS_EN_MASK 0x00000010 + +//STS +#define STS_STATUS_OFFSET 0x0 + +//XADC +#define XADC_SRR_OFFSET 0x0 +#define XADC_SR_OFFSET 0x4 +#define XADC_AOSR_OFFSET 0x8 +#define XADC_CONVSTR_OFFSET 0xC +#define XADC_SYSMONRR_OFFSET 0x10 +#define XADC_GIER_OFFSET 0x5C +#define XADC_IPISR_OFFSET 0x60 +#define XADC_IPIER_OFFSET 0x68 +#define XADC_TEMPERATURE_OFFSET 0x200 +#define XADC_VCCINT_OFFSET 0x204 +#define XADC_VCCAUX_OFFSET 0x208 +#define XADC_VPVN_OFFSET 0x20C +#define XADC_VREFP_OFFSET 0x210 +#define XADC_VREFN_OFFSET 0x214 +#define XADC_VBRAM_OFFSET 0x218 +#define XADC_UNDEF_OFFSET 0x21C +#define XADC_SPLYOFF_OFFSET 0x220 +#define XADC_ADCOFF_OFFSET 0x224 +#define XADC_GAIN_ERR_OFFSET 0x228 +#define XADC_ZDC_SPLY_OFFSET 0x234 +#define XADC_ZDC_AUX_SPLY_OFFSET 0x238 +#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C +#define XADC_VAUX_PN_0_OFFSET 0x240 +#define XADC_VAUX_PN_1_OFFSET 0x244 +#define XADC_VAUX_PN_2_OFFSET 0x248 +#define XADC_VAUX_PN_3_OFFSET 0x24C +#define XADC_VAUX_PN_4_OFFSET 0x250 +#define XADC_VAUX_PN_5_OFFSET 0x254 +#define XADC_VAUX_PN_6_OFFSET 0x258 +#define XADC_VAUX_PN_7_OFFSET 0x25C +#define XADC_VAUX_PN_8_OFFSET 0x260 +#define XADC_VAUX_PN_9_OFFSET 0x264 +#define XADC_VAUX_PN_10_OFFSET 0x268 +#define XADC_VAUX_PN_11_OFFSET 0x26C +#define XADC_VAUX_PN_12_OFFSET 0x270 +#define XADC_VAUX_PN_13_OFFSET 0x274 +#define XADC_VAUX_PN_14_OFFSET 0x278 +#define XADC_VAUX_PN_15_OFFSET 0x27C + +#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET +#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET +#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET +#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET + +#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99) + + +//#define XIL_AXI_INTC_IPISR_INT_OCCURED_MASK 0x00000001 +//#define XIL_AXI_INTC2_IPISR_INT_OCCURED_MASK 0x00000002 +//#define XIL_AXI_INTC_GIER_ENABLE_INT_MASK 0x80000000 +// +//#define XIL_AXI_INTC_CSR_CASC_MASK 0x00000800 +//#define XIL_AXI_INTC_CSR_ENABLE_ALL_MASK 0x00000400 +//#define XIL_AXI_INTC_CSR_ENABLE_PWM_MASK 0x00000200 +//#define XIL_AXI_INTC_CSR_ENABLE_TMR_MASK 0x00000080 +//#define XIL_AXI_INTC_CSR_ENABLE_INT_MASK 0x00000040 +//#define XIL_AXI_INTC_CSR_LOAD_MASK 0x00000020 +//#define XIL_AXI_INTC_CSR_AUTO_RELOAD_MASK 0x00000010 +//#define XIL_AXI_INTC_CSR_EXT_CAPTURE_MASK 0x00000008 +//#define XIL_AXI_INTC_CSR_EXT_GENERATE_MASK 0x00000004 +//#define XIL_AXI_INTC_CSR_DOWN_COUNT_MASK 0x00000002 +//#define XIL_AXI_INTC_CSR_CAPTURE_MODE_MASK 0x00000001 + diff --git a/projects/lago_v1_3/src/globaldefs.h b/projects/lago_v1_3/src/globaldefs.h new file mode 100644 index 0000000000000000000000000000000000000000..33b3ac5ac8dcfd53ba594b6df1168f2f7480845d --- /dev/null +++ b/projects/lago_v1_3/src/globaldefs.h @@ -0,0 +1,20 @@ +#define _CRT_SECURE_NO_WARNINGS + +#define _FILE_OFFSET_BITS 64 + +#ifndef EXP +#define EXP "LAGO" +#endif + +/* Output format version */ +#define DATAVERSION 5 +#define VERSION 2 +#define REVISION 0 + +#define MAXCHRLEN 1024 +#define BLOCKSIZE 16384 +#define MAXFILENAMELEN 255 +#define MAXPRESS 1100 //1100Hpa +#define PRESSUREBLOCKSIZE 22 +#define GPSBLOCKSIZE 64 + diff --git a/projects/lago_v1_3/src/gps_rp.c b/projects/lago_v1_3/src/gps_rp.c new file mode 100644 index 0000000000000000000000000000000000000000..708a69158fc59d6ab23c3f0ccd1d747aae8534e9 --- /dev/null +++ b/projects/lago_v1_3/src/gps_rp.c @@ -0,0 +1,96 @@ +#include "gps_rp.h" + +static double gps_deg_dec(double deg_point) +{ + double ddeg; + double sec = modf(deg_point, &ddeg)*60; + int deg = (int)(ddeg/100); + int min = (int)(deg_point-(deg*100)); + + double absdlat = round(deg * 1000000.); + double absmlat = round(min * 1000000.); + double absslat = round(sec * 1000000.); + + return round(absdlat + (absmlat/60) + (absslat/3600)) /1000000; +} + +// Convert lat and lon to decimals (from deg) +static void gps_convert_deg_to_dec(double *latitude, char ns, double *longitude, char we) +{ + double lat = (ns == 'N') ? *latitude : -1 * (*latitude); + double lon = (we == 'E') ? *longitude : -1 * (*longitude); + + *latitude = gps_deg_dec(lat); + *longitude = gps_deg_dec(lon); +} + +void gps_init(void) +{ + rp_UartInit(); + rp_UartConfig(); +} + +void gps_on(void) +{ +} + +// Compute the GPS location using decimal scale +void gps_location(loc_t *coord) +{ + uint8_t status = _EMPTY; + while(status != _COMPLETED) { + gpgga_t gpgga; + gprmc_t gprmc; + char buffer[256]; + + rp_UartReadln(buffer, 256); + switch (rp_NmeaGetMessageType(buffer)) { + case NMEA_GPGGA: + rp_NmeaParseGpgga(buffer, &gpgga); + + gps_convert_deg_to_dec(&(gpgga.latitude), gpgga.lat, &(gpgga.longitude), gpgga.lon); + + coord->times = gpgga.times; + coord->latitude = gpgga.latitude; + coord->longitude = gpgga.longitude; + coord->altitude = gpgga.altitude; + coord->satellites = gpgga.satellites; + + status |= NMEA_GPGGA; + break; + case NMEA_GPRMC: + rp_NmeaParseGprmc(buffer, &gprmc); + + coord->speed = gprmc.speed; + coord->course = gprmc.course; + coord->date = gprmc.date; + + status |= NMEA_GPRMC; + break; + } + } +} + +void gps_off(void) +{ + //Write off + rp_UartClose(); +} + +int gps_print_data() +{ + gps_init(); + + loc_t data; + + gps_location(&data); + + printf("Time : %06d\n",(uint32_t)data.times); + printf("Date : %06d\n",(uint32_t)data.date); + printf("Latitude : %lf\n", data.latitude); + printf("Longitude : %lf\n", data.longitude); + printf("Altitude : %.1lf\n", data.altitude); + printf("Satellites: %d\n", (uint32_t)data.satellites); + + return 0; +} diff --git a/projects/lago_v1_3/src/gps_rp.h b/projects/lago_v1_3/src/gps_rp.h new file mode 100644 index 0000000000000000000000000000000000000000..046a852a76dce31a715548532618217f124fed0d --- /dev/null +++ b/projects/lago_v1_3/src/gps_rp.h @@ -0,0 +1,28 @@ +#ifndef _GPS_RP_H_ +#define _GPS_RP_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +#include "nmea_rp.h" +#include "uart_rp.h" + +typedef struct location { + double times; + double date; + double latitude; + double longitude; + double speed; + double altitude; + double course; + double satellites; +} loc_t; + +void gps_init(void); +void gps_on(void); +void gps_location(loc_t *); +void gps_off(void); +int gps_print_data(void); + +#endif diff --git a/projects/lago_v1_3/src/lago.c b/projects/lago_v1_3/src/lago.c new file mode 100644 index 0000000000000000000000000000000000000000..bb1bf3c8ee1cbacc245c00abad92c58345a48a7e --- /dev/null +++ b/projects/lago_v1_3/src/lago.c @@ -0,0 +1,1000 @@ +#include "lago.h" + +//***************************************************** +// Pressure, temperature and other constants +//**************************************************** +double gps_lat,gps_lon,gps_alt; + +//Globals +int interrupted = 0; +int n_dev; +uint32_t reg_off; +int32_t reg_val; +//double r_val; +int limit; +int current; +loc_t g_data; +// detector rates +int r1,r2; +// timing horrible hack +int hack=0; + +int fReadReg, fGetCfgStatus, fGetPT, fGetGPS, fGetXADC, fInitSystem, fWriteReg, + fSetCfgReg, fToFile, fToStdout, fFile, fCount, fByte, fRegValue, fData, + fFirstTime=1, fshowversion; + +char charAction[MAXCHRLEN], scRegister[MAXCHRLEN], charReg[MAXCHRLEN], + charFile[MAXCHRLEN], charCurrentFile[MAXCHRLEN], charCount[MAXCHRLEN], + scByte[MAXCHRLEN], charRegValue[MAXCHRLEN], charCurrentMetaData[MAXCHRLEN]; + +//FILE *fhin = NULL; +FILE *fhout = NULL; +FILE *fhmtd = NULL; +struct FLContext *handle = NULL; + +#ifdef FUTURE +unordered_map<string, string> hConfigs; +#endif + +//**************************************************** +// Time globals for filenames +//**************************************************** +time_t fileTime; +struct tm *fileDate; +int falseGPS=0; + +//**************************************************** +// Metadata +//**************************************************** +// Metadata calculations, dataversion v5 need them +// average rates and deviation per trigger condition +// average baseline and deviation per channel +// using long int as max_rate ~ 50 kHz * 3600 s = 1.8x10^7 ~ 2^(20.5) +// and is even worst for baseline +#define MTD_TRG 8 +#define MTD_BL 3 +#define MTD_BLBIN 1 +//daq time +int mtd_seconds=0; +// trigger rates +long int mtd_rates[MTD_TRG], mtd_rates2[MTD_TRG]; +//base lines +long int mtd_bl[MTD_BL], mtd_bl2[MTD_BL]; +int mtd_iBin=0; +long int mtd_cbl=0; +// deat time defined as the number of missing pulses over the total number +// of triggers. We can determine missing pulses as the sum of the differences +// between consecutive pulses +long int mtd_dp = 0, mtd_cdp = 0, mtd_pulse_cnt = 0, mtd_pulse_pnt = 0; +// and finally, a vector of strings to handle configs file. I'm also including a +// hash table +// for future implementations. For now, we just dump the lago-configs file +//vector <string> configs_lines; +int position; +int main(int argc, char *argv[]) +{ + int rc; + //PT device + float t, p, alt, volt; + char *i2c_device = "/dev/i2c-0"; + int address = 0x77; + + void *bmp = bmp180_init(address, i2c_device); + + bmp180_eprom_t eprom; + bmp180_dump_eprom(bmp, &eprom); + + + bmp180_set_oss(bmp, 1); + //end PT device + + pthread_t not_gps; + //pthread_t actual_gps; + + //Check the arguments + if (!parse_param(argc, argv)) { + show_usage(argv[0]); + return 1; + } + + //initialize devices. TODO: add error checking + intc_init(); + cfg_init(); + sts_init(); + xadc_init(); + cma_init(); + //printf("dev_size es: %d ...\n",dev_size); + //printf("Set writer address...\n"); + rd_reg_value(1, CFG_WR_ADDR_OFFSET,0); + //printf("dev_size es: %d ...\n",dev_size); + wr_reg_value(1, CFG_WR_ADDR_OFFSET, dev_size,0); + + //Check if it is the first time we access the PL + //This is for initial configuration + //default is MASTER mode, using false PPS + if (dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET) == 0) //first time access + { + printf("Initializing registers...\n"); + init_system(); + //FIXME: here i should initialise my thread for working with false PPS + rc = pthread_create(¬_gps,NULL,thread_isr_not_gps,NULL); + if (rc != EXIT_SUCCESS) { + perror("pthread_create :: error \n"); + exit(EXIT_FAILURE); + } + + enable_interrupt(); + } + + //Ckeck if we should use GPS data or PC data + /* if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 0) //ok, we should use GPS data + { + rc = pthread_create(&actual_gps,NULL,thread_isr,NULL); + if (rc != EXIT_SUCCESS) { + perror("pthread_create :: error \n"); + exit(EXIT_FAILURE); + } + + enable_interrupt(); + }*/ + + signal(SIGINT, signal_handler); + + if(fReadReg) { + rd_reg_value(n_dev, reg_off,1); // Read single register + } + else if (fWriteReg) { + wr_reg_value(n_dev, reg_off, reg_val, 1); // Write single register + } + else if (fSetCfgReg) { + if (fRegValue) set_voltage(reg_off, atoi(charRegValue)); // For HV, OV + else wr_reg_value(1,reg_off, atoi(charRegValue), 1); // For t1, t2, st1, st2 + } + else if (fGetCfgStatus) { + rd_cfg_status(); // Get registers status + } + else if (fGetPT) { + if(bmp != NULL){ + //int i; + //for(i = 0; i < 10; i++) { + t = bmp180_temperature(bmp); + p = bmp180_pressure(bmp); + alt = bmp180_altitude(bmp); + // Temperature in Celsius, Presure in HectoPascal and Altitude in meters + printf("Temperature = %.1f, Pressure = %.2f, Altitude= %.1f\n", t, p/100., alt); + //usleep(2 * 1000 * 1000); + //} + + bmp180_close(bmp); + }else{ + printf("Error! NO BMP device is present!\n"); + } + } + else if (fGetGPS) { + if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present + printf("No GPS device is present or enabled!!!\n"); + } + else{ + gps_print_data(); // Print GPS data to stdout + } + } + else if (fInitSystem) { + printf("Initializing registers...\n"); + init_system(); + } + else if (fGetXADC) { + printf("Reading XADC channels...\n"); + printf("Voltage CH1: %.3f\n",get_voltage(XADC_AI0_OFFSET)); + printf("Voltage CH2: %.3f\n",get_voltage(XADC_AI1_OFFSET)); + volt = get_voltage(XADC_AI2_OFFSET); + printf("Voltage CH3: %.3f V (%.1f V)\n",volt, (volt/0.0031949)); + volt = get_voltage(XADC_AI3_OFFSET); + printf("Voltage CH4: %.3f V (%.1f V)\n",volt, (volt/0.0031949)); + printf("Base temperature CH1: %.1f ºC\n",get_temp_AD592(XADC_AI0_OFFSET)); + printf("Base temperature CH2: %.1f ºC\n",get_temp_AD592(XADC_AI1_OFFSET)); + + } + else if (fToFile || fToStdout) { + + limit = 1024*1024; // whole memory + current = -2; // new readout system, hack due to using +4 for readout + // enter normal mode for tlast_gen + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2); + // enter normal mode for pps_gen, fifo and trigger modules + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1); + // enter normal mode for data converter and writer + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4); + + //FIXME: here we should enable interrupts + while(!interrupted){ + // alarm(2); // setting 1 sec timeout + // read writer position + //position = dev_read(sts_ptr, STS_STATUS_OFFSET); + wait_for_interrupt(intc_fd, intc_ptr); + read_buffer(position, bmp); + // alarm(0); // cancelling 1 sec timeout + } + // reset pps_gen, fifo and trigger modules + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1); + /* reset data converter and writer */ + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4); + // enter reset mode for tlast_gen + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2); + + } + + // unmap and close the devices + munmap(intc_ptr, sysconf(_SC_PAGESIZE)); + munmap(cfg_ptr, sysconf(_SC_PAGESIZE)); + munmap(sts_ptr, sysconf(_SC_PAGESIZE)); + munmap(xadc_ptr, sysconf(_SC_PAGESIZE)); + //munmap(mem_ptr, sysconf(_SC_PAGESIZE)); + + close(intc_fd); + close(cfg_fd); + close(sts_fd); + close(xadc_fd); + + return 0; + +} + +void signal_handler(int sig) +{ + interrupted = 1; +} + +int wait_for_interrupt(int fd_int, void *dev_ptr) +{ + uint32_t value; + uint32_t info = 1; /* unmask */ + + ssize_t nb = write(fd_int, &info, sizeof(info)); + if (nb != (ssize_t)sizeof(info)) { + perror("write"); + close(fd_int); + exit(EXIT_FAILURE); + } + + // block (timeout for poll) on the file waiting for an interrupt + struct pollfd fds = + { + .fd = fd_int, + .events = POLLIN, + }; + + int ret = poll(&fds, 1, 1000); + //printf("ret is : %d\n", ret); + if (ret >= 1) { + nb = read(fd_int, &info, sizeof(info)); + if (nb == (ssize_t)sizeof(info)) { + /* Do something in response to the interrupt. */ + value = dev_read(dev_ptr, XIL_AXI_INTC_IPR_OFFSET); + if ((value & 0x00000001) != 0) { + dev_write(dev_ptr, XIL_AXI_INTC_IAR_OFFSET, 1); + // read writer position + position = dev_read(sts_ptr, STS_STATUS_OFFSET); + + } + } else { + perror("poll()"); + close(fd_int); + exit(EXIT_FAILURE); + } + } + return ret; +} + +void *thread_isr(void *p) +{ + int32_t g_tim, g_dat, g_lat, g_lon, g_alt, g_sat; + //initialize GPS connection + gps_init(); + while(1) + if (wait_for_interrupt(intc_fd, intc_ptr)){ + //get GPS data + gps_location(&g_data); + //write GPS data into registers + //FIXME: see how and where to write pressure and temperature data + // convert float to int32_t to write to FPGA + g_tim = (int32_t)(g_data.times); + g_dat = (int32_t)(g_data.date); + g_lat = (int32_t)(g_data.latitude * 65536); + g_lon = (int32_t)(g_data.longitude * 65536); + g_alt = (int32_t)(g_data.altitude * 65536); + g_sat = (int32_t)(g_data.satellites); + + dev_write(cfg_ptr,CFG_TIME_OFFSET, g_tim); + dev_write(cfg_ptr,CFG_DATE_OFFSET, g_dat); + dev_write(cfg_ptr,CFG_LATITUDE_OFFSET, g_lat); + dev_write(cfg_ptr,CFG_LONGITUDE_OFFSET, g_lon); + dev_write(cfg_ptr,CFG_ALTITUDE_OFFSET, g_alt); + dev_write(cfg_ptr,CFG_SATELLITE_OFFSET, g_sat); + //printf("%lf %lf\n", gps_data.latitude, gps_data.longitude); + } +} + +void *thread_isr_not_gps(void *p) +{ + //int32_t g_tim, g_dat, g_lat, g_lon, g_alt, g_sat; + while(1) + if (wait_for_interrupt(intc_fd, intc_ptr)){ + //write GPS data into registers + //FIXME: see how and where to write pressure and temperature data + // convert float to int32_t to write to FPGA + /*g_tim = (int32_t)(g_data.times); + g_dat = (int32_t)(g_data.date); + g_lat = (int32_t)(g_data.latitude * 65536); + g_lon = (int32_t)(g_data.longitude * 65536); + g_alt = (int32_t)(g_data.altitude * 65536); + g_sat = (int32_t)(g_data.satellites); + + dev_write(cfg_ptr,CFG_TIME_OFFSET, g_tim); + dev_write(cfg_ptr,CFG_DATE_OFFSET, g_dat); + dev_write(cfg_ptr,CFG_LATITUDE_OFFSET, g_lat); + dev_write(cfg_ptr,CFG_LONGITUDE_OFFSET, g_lon); + dev_write(cfg_ptr,CFG_ALTITUDE_OFFSET, g_alt); + dev_write(cfg_ptr,CFG_SATELLITE_OFFSET, g_sat); + */ + //printf("%lf %lf\n", gps_data.latitude, gps_data.longitude); + } +} + +void show_usage(char *progname) +{ + if (fshowversion) { + printf("LAGO ACQUA BRC v%dr%d data v%d\n",VERSION,REVISION,DATAVERSION); + } else { + printf("\n\tThe LAGO ACQUA suite\n"); + printf("\tData acquisition system for the LAGO BRC electronic\n"); + printf("\t(c) 2012-Today, The LAGO Project, http://lagoproject.net\n"); + printf("\t(c) 2012, LabDPR, http://labdpr.cab.cnea.gov.ar\n"); + printf("\n\tThe LAGO Project, lago@lagoproject.org\n"); + printf("\n\tDPR Lab. 2021\n"); + printf("\tH. Arnaldi, lharnaldi@gmail.com\n"); + printf("\tX. Bertou, bertou@gmail.com\n"); + printf("\t%s v%dr%d comms soft\n\n",EXP,VERSION,REVISION); + printf("Usage: %s <action> <register> <value> [options]\n", progname); + + printf("\n\tActions:\n"); + // printf("\t-r\t\t\t\tGet a single register value\n"); + // printf("\t-p\t\t\t\tSet a value into a single register\n"); + printf("\t-a\t\t\t\tGet all registers status\n"); + printf("\t-s\t\t\t\tSet registers\n"); + printf("\t-f\t\t\t\tStart DAQ and save data to file\n"); + printf("\t-o\t\t\t\tStart DAQ and send data to stdout\n"); + printf("\t-g\t\t\t\tGet GPS data\n"); + printf("\t-t\t\t\t\tGet Pressure and Temperature data\n"); + printf("\t-i\t\t\t\tInitialise registers to default values\n"); + printf("\t-x\t\t\t\tRead the voltage in the XADC channels\n"); + printf("\t-v\t\t\t\tShow DAQ version\n"); + + printf("\n\tRegisters:\n"); + printf("\tt1, t2\t\t\t\tSpecify triggers 1 and 2\n"); + printf("\tsc1, sc2\t\t\tSpecify scaling factor 1 and 2\n"); + //printf("\tst1, st2, st3\t\t\tSpecify subtriggers 1, 2 and + //3\n"); + printf("\thv1, hv2\t\t\tSpecify high voltages\n"); + printf("\tov1, ov2, ov3, ov4\t\tSpecify output voltages\n"); + //printf("\tiv1, iv2, iv3, iv4\t\t\tRead input voltages\n"); + + printf("\n\tOptions:\n"); + printf("\t-f <filename>\t\t\tSpecify file name\n"); + //printf("\t-c <# bytes>\t\t\tNumber of bytes to read/write\n"); + //printf("\t-b <byte>\t\t\tValue to load into register\n"); + + printf("\n\n"); + } +} + +//TODO: change this function to just strncpy +void StrcpyS(char *szDst, size_t cchDst, const char *szSrc) +{ + +#if defined (WIN32) + + strcpy_s(szDst, cchDst, szSrc); + +#else + + if ( 0 < cchDst ) { + + strncpy(szDst, szSrc, cchDst - 1); + szDst[cchDst - 1] = '\0'; + } + +#endif +} + +int parse_param(int argc, char *argv[]) +{ + + int arg; + + // Initialize default flag values + fReadReg = 0; + fWriteReg = 0; + fGetCfgStatus = 0; + fSetCfgReg = 0; + fToFile = 0; + fToStdout = 0; + fGetPT = 0; + fGetGPS = 0; + fFile = 0; + fCount = 0; + fByte = 0; + fData = 0; + fRegValue = 0; + fGetXADC = 0; + + // Ensure sufficient paramaters. Need at least program name and action + // flag + if (argc < 2) + { + return 0; + } + + // The first parameter is the action to perform. Copy the first + // parameter into the action string. + StrcpyS(charAction, MAXCHRLEN, argv[1]); + if(strcmp(charAction, "-r") == 0) { + fReadReg = 1; + } + else if( strcmp(charAction, "-w") == 0) { + fWriteReg = 1; + } + else if( strcmp(charAction, "-a") == 0) { + fGetCfgStatus = 1; + return 1; + } + else if( strcmp(charAction, "-v") == 0) { + fshowversion = 1; + return 0; + } + else if( strcmp(charAction, "-s") == 0) { + fSetCfgReg = 1; + } + else if( strcmp(charAction, "-f") == 0) { + fToFile = 1; + } + else if( strcmp(charAction, "-o") == 0) { + fToStdout = 1; + return 1; + } + else if( strcmp(charAction, "-t") == 0) { + fGetPT = 1; + return 1; + } + else if( strcmp(charAction, "-g") == 0) { + fGetGPS = 1; + return 1; + } + else if( strcmp(charAction, "-i") == 0) { + fInitSystem = 1; + return 1; + } + else if( strcmp(charAction, "-x") == 0) { + fGetXADC = 1; + return 1; + } + else { // unrecognized action + return 0; + } + + // Second paramater is target register on device. Copy second paramater + // to the register string + if((fReadReg == 1) || (fWriteReg == 1)) { + StrcpyS(charReg, MAXCHRLEN, argv[2]); + if(strcmp(charReg, "intc") == 0) { + n_dev = 0; + } + else if(strcmp(charReg, "cfg") == 0) { + n_dev = 1; + } + else if(strcmp(charReg, "sts") == 0) { + n_dev = 2; + } + else if(strcmp(charReg, "xadc") == 0) { + n_dev = 3; + } + else { // unrecognized device to set + return 0; + } + reg_off = strtoul(argv[3],NULL, 16); + //FIXME: see if this can be done better + if (fWriteReg) reg_val = strtoul(argv[4],NULL,16); + return 1; + } + + else if(fSetCfgReg) { + StrcpyS(charReg, MAXCHRLEN, argv[2]); + // Registers for Triggers + if(strcmp(charReg, "t1") == 0) { + reg_off = CFG_TRLVL_1_OFFSET; + } + else if(strcmp(charReg, "t2") == 0) { + reg_off = CFG_TRLVL_2_OFFSET; + } + // Registers for Subtriggers + else if(strcmp(charReg, "st1") == 0) { + reg_off = CFG_STRLVL_1_OFFSET; + } + else if(strcmp(charReg, "st2") == 0) { + reg_off = CFG_STRLVL_2_OFFSET; + } + // Registers for High Voltage + else if(strcmp(charReg, "hv1") == 0) { + reg_off = CFG_HV1_OFFSET; + } + else if(strcmp(charReg, "hv2") == 0) { + reg_off = CFG_HV2_OFFSET; + } + // Registers for output voltages + else if(strcmp(charReg, "ov1") == 0) { + reg_off = CFG_HV1_OFFSET; + } + else if(strcmp(charReg, "ov2") == 0) { + reg_off = CFG_HV2_OFFSET; + } + else if(strcmp(charReg, "ov3") == 0) { + reg_off = CFG_HV3_OFFSET; + } + else if(strcmp(charReg, "ov4") == 0) { + reg_off = CFG_HV4_OFFSET; + } + // Registers for scalers + else if(strcmp(charReg, "sc1") == 0) { + reg_off = CFG_TR_SCAL_A_OFFSET; + } + else if(strcmp(charReg, "sc2") == 0) { + reg_off = CFG_TR_SCAL_B_OFFSET; + } + // Unrecognized + else { // unrecognized register to set + return 0; + } + //charCount[0] = '4'; + //fCount = 1; + StrcpyS(charRegValue, 16, argv[3]); + if((strncmp(charReg, "hv", 2) == 0) || (strncmp(charReg, "ov", 2) == 0)) { + if (atoi(charRegValue)>2500) { + printf ("Error: maximum voltage is 2500 mV\n"); + exit(1); + } + fRegValue = 1; + } + //fData = 1; FIXME: not used apparently + } + else if(fToFile) { + if(argv[2] != NULL) { + StrcpyS(charFile, MAXFILENAMELEN, argv[2]); + fFile = 1; + } + else { + return 0; + } + } + else { + StrcpyS(scRegister, MAXCHRLEN, argv[2]); + + // Parse the command line parameters. + arg = 3; + while(arg < argc) { + + // Check for the -f parameter used to specify the + // input/output file name. + if (strcmp(argv[arg], "-f") == 0) { + arg += 1; + if (arg >= argc) { + return 0; + } + StrcpyS(charFile, 16, argv[arg++]); + fFile = 1; + } + + // Check for the -c parameter used to specify the number + // of bytes to read/write from file. + else if (strcmp(argv[arg], "-c") == 0) { + arg += 1; + if (arg >= argc) { + return 0; + } + StrcpyS(charCount, 16, argv[arg++]); + fCount = 1; + } + + // Check for the -b paramater used to specify the value + // of a single data byte to be written to the register + else if (strcmp(argv[arg], "-b") == 0) { + arg += 1; + if (arg >= argc) { + return 0; + } + StrcpyS(scByte, 16, argv[arg++]); + fByte = 1; + } + + // Not a recognized parameter + else { + return 0; + } + } // End while + + // Input combination validity checks + if( fWriteReg && !fByte ) { + printf("Error: No byte value provided\n"); + return 0; + } + if( (fToFile ) && !fFile ) { + printf("Error: No filename provided\n"); + return 0; + } + + return 1; + } + return 1; +} + +int new_file() +{ + char buf[256]; + time_t currt=time(NULL); + //uint32_t i; + + if (!fToStdout) { + if (fhout) { + fclose(fhout); + } + /*if (fhmtd) { + //before to close the file we have to fill DAQ status metadata + // Average and deviation trigger rates + double mtd_avg[MTD_TRG], mtd_dev[MTD_TRG]; + if (!mtd_seconds) { + for (int i=0; i<MTD_TRG; i++) + mtd_avg[i] = mtd_dev[i] = -1.; + } + else { + for (int i=0; i<MTD_TRG; i++) { + mtd_avg[i] = 1. * mtd_rates[i] / mtd_seconds; + mtd_dev[i] = sqrt(1. * mtd_rates2[i] / mtd_seconds - mtd_avg[i] * mtd_avg[i]); + } + } + for (int i=1; i<MTD_TRG; i++) + fprintf(fhmtd, "triggerRateAvg%02d=%lf\n", i, mtd_avg[i]); + for (int i=1; i<MTD_TRG; i++) + fprintf(fhmtd, "trigggerRateDev%02d=%lf\n", i, mtd_dev[i]); + for (int i=0; i<MTD_TRG; i++) + mtd_rates[i] = mtd_rates2[i] = 0; + //baselines + double mtd_bl_avg[MTD_BL], mtd_bl_dev[MTD_BL]; + double mtd_cdpf; + if (!mtd_cbl) { + for (int i=0; i<MTD_BL; i++) + mtd_bl_avg[i] = mtd_bl_dev[i] = -1.; + mtd_cdpf = -1; + } + else { + for (int i=0; i<MTD_BL; i++) { + mtd_bl_avg[i] = 1. * mtd_bl[i] / mtd_cbl; + mtd_bl_dev[i] = sqrt(1. * mtd_bl2[i] / mtd_cbl - mtd_bl_avg[i] * mtd_bl_avg[i]); + } + mtd_cdpf = 1. * mtd_cdp / mtd_cbl; + } + for (int i=1; i<MTD_BL; i++) + fprintf(fhmtd, "baselineAvg%02d=%lf\n", i+1, mtd_bl_avg[i]); + for (int i=1; i<MTD_BL; i++) + fprintf(fhmtd, "baselineDev%02d=%lf\n", i+1, mtd_bl_dev[i]); + for (int i=0; i<MTD_BL; i++) + mtd_bl[i] = mtd_bl2[i] = 0; + // daq time, pulses and dead time + fprintf(fhmtd, "daqTime=%d\n", mtd_seconds); + fprintf(fhmtd, "totalPulses=%ld\n", mtd_cbl); + fprintf(fhmtd, "totalPulsesLost=%ld\n", mtd_cdp); + fprintf(fhmtd, "fractionPulsesLost=%le\n", mtd_cdpf); + //and now, let's close the file + mtd_seconds = 0; + mtd_cbl = mtd_cdp = 0; + fclose(fhmtd); + }*/ + fileTime=timegm(fileDate); + fileDate=gmtime(&fileTime); // filling all fields with properly computed values (for new month/year) + if (falseGPS) { + snprintf(charCurrentFile,MAXCHRLEN,"%s_nogps_%04d_%02d_%02d_%02dh00.dat",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour); + snprintf(charCurrentMetaData,MAXCHRLEN,"%s_nogps_%04d_%02d_%02d_%02dh00.mtd",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour); + } + else { + snprintf(charCurrentFile,MAXCHRLEN,"%s_%04d_%02d_%02d_%02dh00.dat",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour); + snprintf(charCurrentMetaData,MAXCHRLEN,"%s_%04d_%02d_%02d_%02dh00.mtd",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour); + } + fhout = fopen(charCurrentFile, "ab"); + //fhmtd = fopen(charCurrentMetaData, "w"); + //fprintf(stderr,"Opening files %s and %s for data taking\n",charCurrentFile, charCurrentMetaData); + fprintf(stderr,"Opening file %s at %02dh%02d for data taking\n",charCurrentFile,fileDate->tm_hour,fileDate->tm_min); + } + fprintf(fhout,"# v %d\n", DATAVERSION); + fprintf(fhout,"# #\n"); + fprintf(fhout,"# # This is a %s raw data file, version %d\n",EXP,DATAVERSION); + fprintf(fhout,"# # It contains the following data:\n"); + fprintf(fhout,"# # <N1> <N2> : line with values of the 2 ADC for a triggered pulse\n"); + //fprintf(fhout,"# # it is a subtrigger with the pulse maximum bin if only one such line is found\n"); + //fprintf(fhout,"# # it is a trigger with the full pulse if 16 lines are found\n"); + fprintf(fhout,"# # # t <C> <V> : end of a trigger\n"); + fprintf(fhout,"# # gives the channel trigger (<C>: 3 bit mask) and 125 MHz clock count (<V>) of the trigger time\n"); + fprintf(fhout,"# # # c <C> : internal trigger counter\n"); + fprintf(fhout,"# # # x f <V> : 125 MHz frequency\n"); + fprintf(fhout,"# # # x t <V> : temperature value\n"); + fprintf(fhout,"# # # x p <V> : pressure value\n"); + fprintf(fhout,"# # # x r1 <V> : pulse rate at channel 1\n"); + fprintf(fhout,"# # # x r2 <V> : pulse rate at channel 2\n"); + fprintf(fhout,"# # # x h <HH:MM:SS> <DD/MM/YYYY> <S> : GPS time (every new second, last number is seconds since EPOCH)\n"); + fprintf(fhout,"# # # x s <T> C <P> hPa <A> m : temperature <T>, pressure <P> and altitude (from pressure) <A>\n"); + fprintf(fhout,"# # # x g <LAT> <LON> <ALT> : GPS data - latitude, longitude, altitude\n"); + fprintf(fhout,"# # # x v <HV1> <HV2> : HV voltages for channels 1 and 2\n"); + fprintf(fhout,"# # # x b <B1> <B2> <B3> : baselines (NOT IMPLEMENTED IN LAGO)\n"); + fprintf(fhout,"# # In case of error, an unfinished line will be finished by # E @@@\n"); + fprintf(fhout,"# # Followed by a line with # E <N> and the error message in human readable format, where <N> is the error code:\n"); + fprintf(fhout,"# # # E 1 : read timeout of 2 seconds\n"); + fprintf(fhout,"# # # E 2 : too many buffer reading tries\n"); + fprintf(fhout,"# # # E 3 : unknown word from FPGA\n"); + fprintf(fhout,"# #\n"); + fprintf(fhout,"# # Current registers setting\n"); + fprintf(fhout,"# #\n"); + // Save settings into file + fprintf(fhout,"# x c T1 %d\n",dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET)); + fprintf(fhout,"# x c T2 %d\n",dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET)); + { + //float a = 0.0382061, b = 4.11435; // For gain = 1.45 + float a = 0.0882006, b = 7.73516; // For gain = 3.2 + fprintf(fhout,"# x c HV1 %.1f mV\n",a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b); + fprintf(fhout,"# x c HV2 %.1f mV\n",a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b); + } + fprintf(fhout,"# x c SC1 %d\n",dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET)); + fprintf(fhout,"# x c SC2 %d\n",dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET)); + gethostname(buf, 256); + fprintf(fhout,"# # This file was started on %s\n",buf); + // fprintf(fhmtd, "daqHost=\"%s\"\n",buf); + ctime_r(&currt,buf); + fprintf(fhout,"# # Machine local time was %s",buf); + strtok(buf, "\n"); + // fprintf(fhmtd, "machineTime=\"%s\"\n",buf); + if (falseGPS) fprintf(fhout,"# # WARNING, there is no GPS, using PC time\n"); + fprintf(fhout,"# #\n"); + // fprintf(fhmtd, "dataFile=\"%s\"\n",charCurrentFile); + // fprintf(fhmtd, "metadataFile=\"%s\"\n",charCurrentMetaData); + // fprintf(fhmtd, "daqVersion=%d\n",VERSION); + // fprintf(fhmtd, "daqUseGPS=%s", (!falseGPS)?"true":"false"); + // fprintf(fhmtd, "dataVersion=%d\n",DATAVERSION); + // for (i=0; i<configs_lines.size(); i++) + // fprintf(fhmtd, "%s\n", configs_lines[i].c_str()); + // fprintf(fhmtd, "version=\"LAGO ACQUA BRC v%dr%d data v%d\"\n",VERSION,REVISION,DATAVERSION); + fflush(fhout); + // fflush(fhmtd); + return 0; +} + +int r[MTD_TRG]; + +int read_buffer(int pos, void *bmp) +{ + uint32_t wo; + int16_t ch[2]; + //uint32_t i, j; + uint32_t i; + //int offset; + int trig; + //int32_t v_temp; + int readinit=0; + int readend=limit; + + if (fToStdout) + fhout=stdout; + if (fFirstTime) { + // if no GPS + if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // get time form PC + fileTime=time(NULL); + fileDate=gmtime(&fileTime); // filling all fields + falseGPS=1; + } + else { + fileTime=time(NULL); + fileDate=gmtime(&fileTime); + //FIXME: fill with actual data + fileDate->tm_sec=55; + fileDate->tm_min=55; + fileDate->tm_hour=10; + fileDate->tm_mday=29; + fileDate->tm_mon=8; + fileDate->tm_year=2018; + + fileTime=timegm(fileDate); + fileDate=gmtime(&fileTime); // filling all fields + } + if (fhout != stdout) { + //FIXME: here read PyT data + + } + new_file(); + fFirstTime=0; + } + + // pos is the number of 8 bytes word written. I need the memory + // location... Therefore, pos=pos*8 + //pos=pos*4; + + //printf("%d %d %d\n",current,pos,limit); + //fprintf(fhout,"# XB %d %d %d\n", current,pos,limit); + // print 512 IN1 and IN2 samples if ready, otherwise sleep 1 ms + // compare current writing location (pos) with previous (limit) + // if current<pos, then read from current to pos and adjust current + // if current>pos, then read from current to end of buffer and set current to 0 at the end + if (current==limit-2) current=-2; // hack, because I do +4 next to read from next position + if (current<pos+2) { + readinit=current+2; + readend=pos; + } else if (current>pos) { + readinit=current+2; + readend=limit; // note: don't read after limit + } + if(current!=pos) { + + //printf("# # # # NEW BUFFER %d %d %d %d %d \n", readinit, readend, current, pos, limit); + //offset = limit > 0 ? 0 : 4096*1024; + //limit = limit > 0 ? 0 : 512*1024; + + //for(i = readinit; i < readend; i+=4) { + for(i = readinit; i < readend; i++) { + ch[0] = *((cma_ptr + 2*i + 0)); + ch[1] = *((cma_ptr + 2*i + 1)); + //printf("%5d %5d\n", ch[0], ch[1]); + wo = *((uint32_t *)(cma_ptr + 2*i)); + if (wo>>30==0) { + fprintf(fhout,"%5hd %5hd\n", (((ch[0]>>13)<<14) + ((ch[0]>>13)<<15) + ch[0]),(((ch[1]>>13)<<14) + ((ch[1]>>13)<<15) + ch[1])); + mtd_iBin++; + if (mtd_iBin == MTD_BLBIN) { + mtd_bl[0] += ch[0]; + mtd_bl2[0] += ch[0] * ch[0]; + mtd_bl[1] += ch[1]; + mtd_bl2[1] += ch[1] * ch[1]; + mtd_cbl++; + } + } + else { + if (wo>>30==1) { //get trigger status and counter between PPS + fprintf(fhout,"# t %d %d\n", (wo>>27)&0x7, wo&0x7FFFFFF); + trig=(wo>>27)&0x7; + r[trig]++; + mtd_iBin=0; + } + else { + if (wo>>30==2) {//get counter status + mtd_pulse_pnt = mtd_pulse_cnt; + mtd_pulse_cnt = (wo&0x3FFFFFFF); + mtd_dp = (mtd_pulse_cnt - mtd_pulse_pnt - 1); + if (mtd_dp > 0 && mtd_pulse_pnt) + mtd_cdp += mtd_dp; + fprintf(fhout,"# c %ld\n", mtd_pulse_cnt); + } + else { + switch(wo>>27) { + case 0x18: + fprintf(fhout,"# x f %d \n", wo&0x07FFFFFF);//PPS counter + break; + case 0x19: + fprintf(fhout,"# x t %.1f \n", bmp180_temperature(bmp)); + break; + case 0x1A: + fprintf(fhout,"# x p %.2f \n", (bmp180_pressure(bmp)/100.)); + break; + case 0x1B: + if(falseGPS) { + fileDate->tm_sec++; + if (fileDate->tm_sec==60 && fileDate->tm_min==59) { // new hour + if (!fToStdout) + new_file(); + } + else { + fileTime=timegm(fileDate); + fileDate=gmtime(&fileTime); // filling all fields with properly comupted values (for new month/year) + } + } + else { + if ((uint32_t)fileDate->tm_hour!=((wo>>16)&0x000000FF)) { + // new hour of data + if ((uint32_t)fileDate->tm_hour>((wo>>16)&0x000000FF)) { // new day + fileDate->tm_mday++; + } + fileDate->tm_hour=(wo>>16)&0x000000FF; + if (!fToStdout) + new_file(); + } + fileDate->tm_hour=(wo>>16)&0x000000FF; + fileDate->tm_min=(wo>>8)&0x000000FF; + fileDate->tm_sec=wo&0x000000FF; + } + mtd_seconds++; + fileTime=timegm(fileDate); + fileDate=gmtime(&fileTime); // filling all fields with properly computed values (for new month/year) + fprintf(fhout,"# x h %02d:%02d:%02d %02d/%02d/%04d %d %d\n", + fileDate->tm_hour, fileDate->tm_min, fileDate->tm_sec, + fileDate->tm_mday, fileDate->tm_mon+1,fileDate->tm_year+1900, + (int)fileTime,wo&0x03FFFFFF + ); + fprintf(fhout,"# x v %.1f %.1f\n",(get_voltage(XADC_AI2_OFFSET)/0.0031949),(get_voltage(XADC_AI3_OFFSET)/0.0031949)); + fprintf(fhout,"# p %u %.1f %.1f\n",hack++,get_temp_AD592(XADC_AI0_OFFSET),get_temp_AD592(XADC_AI1_OFFSET)); + if (hack%60==0) printf("\n"); + printf("rates %5d %5d, PPS %u \r",r1,r2,hack); + fflush(stdout); + /*fprintf(stderr,"# %02d:%02d:%02d %02d/%02d/%04d %d - second %d - rates: %d %d %d (%d - %d - %d) [%d]\r", + fileDate->tm_hour, fileDate->tm_min, fileDate->tm_sec, + fileDate->tm_mday, fileDate->tm_mon+1, fileDate->tm_year+1900, + (int)fileTime, + mtd_seconds, + r[1], r[2], r[4], r[3], r[5], r[6], r[7] + );*/ + //for (j=0; j<MTD_TRG; j++) { + // mtd_rates[i] += r[i]; + // mtd_rates2[i] += r[i] * r[i]; + // r[i] = 0; + //} + break; + //FIXME: see if can add the FPGA interface in this stage + case 0x1C: // Longitude, latitude, defined by other bits + switch(((wo)>>24) & 0x7) { + case 0: + gps_lat=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0; + //gps_lat=v_temp/65536.0; + break; + case 1: + gps_lon=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0; + //gps_lat=v_temp/65536.0; + break; + case 2: + gps_alt=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0; + //gps_lat=v_temp/65536.0; + //fprintf(fhout,"# x g %.6f %.6f %.2f\n",gps_lat,gps_lon,gps_alt); + fprintf(fhout,"# x g %.6f %.6f %.2f\n",g_data.latitude,g_data.longitude,g_data.altitude); + //tmp_gps_lon=((wo & 0xFFFFFF)<<8); + break; + /*case 3: FIXME: here is the date data + // Not used here + //gps_lon=((int)(tmp_gps_lon+(wo & 0xFF)))/3600000.; + break; + case 4: + //tmp_gps_elips=((wo & 0xFFFFFF)<<8); + break; + case 5: + //gps_elips=((int)(tmp_gps_elips+(wo & 0xFF)))/100.; + //fprintf(fhout,"# x g %.6f %.6f %.2f\n",gps_lat,gps_lon,gps_elips); + break;*/ + default: + break; + } + break; + case 0x1D: //rate ch1 counter + fprintf(fhout,"# r1 %d \n", (int32_t)wo&0x00FFFFFF); + r1= (int32_t)wo&0x00FFFFFF; + break; + case 0x1E: //rate ch2 counter + fprintf(fhout,"# r2 %d \n", (int32_t)wo&0x00FFFFFF); + r2= (int32_t)wo&0x00FFFFFF; + break; + default: + fprintf(fhout,"# E @@@\n"); + fprintf(fhout,"# E 3 - unknown word from FPGA: %d %x\n",wo>>27,wo>>27); + break; + } + } + } + } + current=i; + } + } + return 1; +} + diff --git a/projects/lago_v1_3/src/lago.h b/projects/lago_v1_3/src/lago.h new file mode 100644 index 0000000000000000000000000000000000000000..2c07e341a8e60088498349072e92979314dd759d --- /dev/null +++ b/projects/lago_v1_3/src/lago.h @@ -0,0 +1,48 @@ +#ifndef _MAIN_H_ +#define _MAIN_H_ + +#include <poll.h> +#include <signal.h> +#include <string.h> +#include <time.h> +//#include <fstream> +//#include <iostream> +//#include <vector> + +#define _GNU_SOURCE +#include <pthread.h> + +#include "zynq_io.h" +#include "gps_rp.h" +#include "bmp180.h" +#include "globaldefs.h" + +typedef struct ldata +{ + int trigg_1; // trigger level ch1 + int trigg_2; // trigger level ch2 + int strigg_1; // sub-trigger level ch1 + int strigg_2; // sub-trigger level ch2 + int nsamples; // N of samples + int time; + double latitude; + char lat; + double longitude; + char lon; + uint8_t quality; + uint8_t satellites; + double altitude; +} ldata_t; + +int main(int argc, char *argv[]); +void signal_handler(int sig); +int wait_for_interrupt(int fd_int, void *dev_ptr); +void *thread_isr_not_gps(void *p); +void *thread_isr(void *p); +void show_usage(char *progname); +void StrcpyS(char *szDst, size_t cchDst, const char *szSrc); +int parse_param(int argc, char *argv[]); +int new_file(void); +int read_buffer(int position, void *bmp); + +#endif diff --git a/projects/lago_v1_3/src/nmea_rp.c b/projects/lago_v1_3/src/nmea_rp.c new file mode 100644 index 0000000000000000000000000000000000000000..d8c5446bf9e17c46295dd96ffd0696733b218e23 --- /dev/null +++ b/projects/lago_v1_3/src/nmea_rp.c @@ -0,0 +1,148 @@ +#include "nmea_rp.h" + +static uint8_t rp_NmeaValidChecksum(const char *message) +{ + uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16); + + char p; + uint8_t sum = 0; + ++message; + while ((p = *message++) != '*') { + sum ^= p; + } + + if (sum != checksum) { + return NMEA_CHECKSUM_ERR; + } + + return _EMPTY; +} + +void rp_NmeaParseGpgga(char *nmea, gpgga_t *loc) +{ + char *ptr = nmea; + + ptr = strchr(ptr, ',')+1; //skip time + loc->times = atof(ptr); + + ptr = strchr(ptr, ',')+1; + loc->latitude = atof(ptr); + + ptr = strchr(ptr, ',')+1; + switch (ptr[0]) { + case 'N': + loc->lat = 'N'; + break; + case 'S': + loc->lat = 'S'; + break; + case ',': + loc->lat = '\0'; + break; + } + + ptr = strchr(ptr, ',')+1; + loc->longitude = atof(ptr); + + ptr = strchr(ptr, ',')+1; + switch (ptr[0]) { + case 'W': + loc->lon = 'W'; + break; + case 'E': + loc->lon = 'E'; + break; + case ',': + loc->lon = '\0'; + break; + } + + ptr = strchr(ptr, ',')+1; + loc->quality = (uint8_t)atoi(ptr); + + ptr = strchr(ptr, ',')+1; + loc->satellites = (uint8_t)atoi(ptr); + + ptr = strchr(ptr, ',')+1; + + ptr = strchr(ptr, ',')+1; + loc->altitude = atof(ptr); +} + +void rp_NmeaParseGprmc(char *nmea, gprmc_t *loc) +{ + char *ptr = nmea; + + ptr = strchr(ptr, ',')+1; //skip time + loc->times = atof(ptr); + + ptr = strchr(ptr, ',')+1; //skip status + + ptr = strchr(ptr, ',')+1; + loc->latitude = atof(ptr); + + ptr = strchr(ptr, ',')+1; + switch (ptr[0]) { + case 'N': + loc->lat = 'N'; + break; + case 'S': + loc->lat = 'S'; + break; + case ',': + loc->lat = '\0'; + break; + } + + ptr = strchr(ptr, ',')+1; + loc->longitude = atof(ptr); + + ptr = strchr(ptr, ',')+1; + switch (ptr[0]) { + case 'W': + loc->lon = 'W'; + break; + case 'E': + loc->lon = 'E'; + break; + case ',': + loc->lon = '\0'; + break; + } + + ptr = strchr(ptr, ',')+1; + loc->speed = atof(ptr); + + ptr = strchr(ptr, ',')+1; + loc->course = atof(ptr); + + ptr = strchr(ptr, ',')+1; + loc->date = atof(ptr); +} + +/** + * Get the message type (GPGGA, GPRMC, etc..) + * + * This function filters out also wrong packages (invalid checksum) + * + * @param message The NMEA message + * @return The type of message if it is valid + */ +uint8_t rp_NmeaGetMessageType(const char *message) +{ + uint8_t checksum = 0; + if ((checksum = rp_NmeaValidChecksum(message)) != _EMPTY) { + return checksum; + } + + if (strstr(message, NMEA_GPGGA_STR) != NULL) { + return NMEA_GPGGA; + } + + if (strstr(message, NMEA_GPRMC_STR) != NULL) { + return NMEA_GPRMC; + } + + return NMEA_UNKNOWN; +} + diff --git a/projects/lago_v1_3/src/nmea_rp.h b/projects/lago_v1_3/src/nmea_rp.h new file mode 100644 index 0000000000000000000000000000000000000000..819c5e132f3d0502a3a048d199979a380f71542d --- /dev/null +++ b/projects/lago_v1_3/src/nmea_rp.h @@ -0,0 +1,48 @@ +#ifndef _NMEA_RP_H_ +#define _NMEA_RP_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include <string.h> +#include <math.h> + +#define _EMPTY 0x00 +#define NMEA_GPRMC 0x01 +#define NMEA_GPRMC_STR "$GPRMC" +#define NMEA_GPGGA 0x02 +#define NMEA_GPGGA_STR "$GPGGA" +#define NMEA_UNKNOWN 0x00 +#define _COMPLETED 0x03 + +#define NMEA_CHECKSUM_ERR 0x80 +#define NMEA_MESSAGE_ERR 0xC0 + +typedef struct gpgga { + double times; + double latitude; + char lat; + double longitude; + char lon; + uint8_t quality; + uint8_t satellites; + double altitude; +} gpgga_t; + +typedef struct gprmc { + double times; + double latitude; + char lat; + double longitude; + char lon; + double speed; + double course; + double date; +} gprmc_t; + +uint8_t rp_NmeaGetMessageType(const char *); +void rp_NmeaParseGpgga(char *, gpgga_t *); +void rp_NmeaParseGprmc(char *, gprmc_t *); + +#endif + diff --git a/projects/lago_v1_3/src/uart_rp.c b/projects/lago_v1_3/src/uart_rp.c new file mode 100644 index 0000000000000000000000000000000000000000..8c8391c588c174fca38c5a81f6af27617c8b6c50 --- /dev/null +++ b/projects/lago_v1_3/src/uart_rp.c @@ -0,0 +1,79 @@ +#include "uart_rp.h" + +/* File descriptor definition */ +int uart_fd = -1; + +int rp_UartInit(void) +{ + uart_fd = open(PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY); + + if(uart_fd == -1){ + fprintf(stderr, "Failed to open uart.\n"); + return -1; + } + return 0; +} + +void rp_UartConfig(void) +{ + struct termios options; + tcgetattr(uart_fd, &options); + /*Configure the UART + see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html */ + options.c_cflag = B9600 | CS8 | CLOCAL | CREAD; + options.c_iflag = IGNPAR; + options.c_oflag = 0; + options.c_lflag = 0; + /* Setting attributes */ + tcflush(uart_fd, TCIFLUSH); + tcsetattr(uart_fd, TCSANOW, &options); +} + +int rp_UartPrintln(const char *line, int len) +{ + if (uart_fd != -1) { + char *cpstr = (char *)malloc((len+1) * sizeof(char)); + strcpy(cpstr, line); + cpstr[len-1] = '\r'; + cpstr[len] = '\n'; + + int count = write(uart_fd, cpstr, len+1); + if (count < 0) { + fprintf(stderr, "UART TX error.\n"); + return -1; + } + free(cpstr); + } + return 0; +} + +/* Read a line from UART */ +int rp_UartReadln(char *buffer, int len) +{ + char c; + char *b = buffer; + int rx_length = -1; + + while(1) { + rx_length = read(uart_fd, (void*)(&c), 1); + + if (rx_length <= 0) { + //wait for messages + sleep(1); + } else { + if (c == '\n') { + *b++ = '\0'; + break; + } + *b++ = c; + } + } + return 0; +} + +void rp_UartClose(void) +{ + tcflush(uart_fd, TCIFLUSH); + close(uart_fd); +} + diff --git a/projects/lago_v1_3/src/uart_rp.h b/projects/lago_v1_3/src/uart_rp.h new file mode 100644 index 0000000000000000000000000000000000000000..72e0fbcfe7a4f2c3d4fbdf02c0b8fce8e9d270da --- /dev/null +++ b/projects/lago_v1_3/src/uart_rp.h @@ -0,0 +1,23 @@ +#ifndef _UART_RP_H_ +#define _UART_RP_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <termios.h> +#include <inttypes.h> +#include <string.h> + +//Default name for UART port in E2 expansion conector +#ifndef PORTNAME +#define PORTNAME "/dev/ttyPS1" +#endif + +int rp_UartInit(void); +void rp_UartConfig(void); +int rp_UartPrintln(const char *, int); +int rp_UartReadln(char *, int); +void rp_UartClose(void); + +#endif diff --git a/projects/lago_v1_3/src/zynq_io.c b/projects/lago_v1_3/src/zynq_io.c new file mode 100644 index 0000000000000000000000000000000000000000..772c6b431af5c19059e8543d872724795d007448 --- /dev/null +++ b/projects/lago_v1_3/src/zynq_io.c @@ -0,0 +1,519 @@ +#include "zynq_io.h" + +int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd; +void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr; +volatile int16_t *cma_ptr; +uint32_t dev_size; + +void dev_write(void *dev_base, uint32_t offset, int32_t value) +{ + *((volatile unsigned *)(dev_base + offset)) = value; +} + +uint32_t dev_read(void *dev_base, uint32_t offset) +{ + return *((volatile unsigned *)(dev_base + offset)); +} + +/*int dev_init(int n_dev) + { + char *uiod; = "/dev/uio1"; + + printf("Initializing device...\n"); + +// open the UIO device file to allow access to the device in user space +cfg_fd = open(uiod, O_RDWR); +if (cfg_fd < 1) { +printf("cfg_init: Invalid UIO device file:%s.\n", uiod); +return -1; +} + +dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size"); + +// mmap the cfgC device into user space +cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0); +if (cfg_ptr == MAP_FAILED) { +printf("cfg_init: mmap call failure.\n"); +return -1; +} + +return 0; +}*/ + +int32_t rd_reg_value(int n_dev, uint32_t reg_off, uint8_t debug) +{ + int32_t reg_val; + switch(n_dev) + { + case 0: + reg_val = dev_read(intc_ptr, reg_off); + break; + case 1: + reg_val = dev_read(cfg_ptr, reg_off); + break; + case 2: + reg_val = dev_read(sts_ptr, reg_off); + break; + case 3: + reg_val = dev_read(xadc_ptr, reg_off); + break; + default: + printf("Invalid option: %d\n", n_dev); + return -1; + } + if(debug) + printf("Complete. Received data 0x%08x\n", reg_val); + //printf("Complete. Received data %d\n", reg_val); + + return reg_val; +} + +int32_t wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug) +{ + switch(n_dev) + { + case 0: + dev_write(intc_ptr, reg_off, reg_val); + break; + case 1: + dev_write(cfg_ptr, reg_off, reg_val); + break; + case 2: + dev_write(sts_ptr, reg_off, reg_val); + break; + case 3: + dev_write(xadc_ptr, reg_off, reg_val); + break; + default: + printf("Invalid option: %d\n", n_dev); + return -1; + } + if(debug) + printf("Complete. Data written: 0x%08x\n", reg_val); + //printf("Complete. Data written: %d\n", reg_val); + + return 0; +} + +int32_t rd_cfg_status(void) +{ + //float a = 0.0382061, b = 4.11435; // For gain = 1.45 + float a = 0.0882006, b = 7.73516; // For gain = 3.2 + + printf("#Trigger Level Ch1 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET)); + printf("#Trigger Level Ch2 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET)); + //printf("#Subtrigger Ch1 = %d\n", dev_read(cfg_ptr, CFG_STRLVL_1_OFFSET)); + //printf("#Subtrigger Ch2 = %d\n", dev_read(cfg_ptr, CFG_STRLVL_2_OFFSET)); + printf("#High Voltage 1 = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b); + printf("#High Voltage 2 = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b); + printf("#Trigger Scaler 1 = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET)); + printf("#Trigger Scaler 2 = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET)); + if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present + printf("#No GPS device is present or enabled\n"); + }else{ + printf("#Using GPS data\n"); + } + if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>5) & 0x1) == 0) //Slave + { + printf("#Working mode is SLAVE\n"); + }else{ + printf("#Working mode is MASTER\n"); + } + printf("\n"); + printf("Status from registers complete!\n"); + return 0; +} + +static uint32_t get_memory_size(char *sysfs_path_file) +{ + FILE *size_fp; + uint32_t size; + + // open the file that describes the memory range size that is based on + // the reg property of the node in the device tree + size_fp = fopen(sysfs_path_file, "r"); + + if (!size_fp) { + printf("unable to open the uio size file\n"); + exit(-1); + } + + // get the size which is an ASCII string such as 0xXXXXXXXX and then be + // stop using the file + if(fscanf(size_fp, "0x%08X", &size) == EOF){ + printf("unable to get the size of the uio size file\n"); + exit(-1); + } + fclose(size_fp); + + return size; +} + +int intc_init(void) +{ + char *uiod = "/dev/uio0"; + + //printf("Initializing INTC device...\n"); + + // open the UIO device file to allow access to the device in user space + intc_fd = open(uiod, O_RDWR); + if (intc_fd < 1) { + printf("intc_init: Invalid UIO device file:%s.\n", uiod); + return -1; + } + + dev_size = get_memory_size("/sys/class/uio/uio0/maps/map0/size"); + + // mmap the INTC device into user space + intc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, intc_fd, 0); + if (intc_ptr == MAP_FAILED) { + printf("intc_init: mmap call failure.\n"); + return -1; + } + + return 0; +} + +int cfg_init(void) +{ + char *uiod = "/dev/uio1"; + + //printf("Initializing CFG device...\n"); + + // open the UIO device file to allow access to the device in user space + cfg_fd = open(uiod, O_RDWR); + if (cfg_fd < 1) { + printf("cfg_init: Invalid UIO device file:%s.\n", uiod); + return -1; + } + + dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size"); + + // mmap the cfgC device into user space + cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0); + if (cfg_ptr == MAP_FAILED) { + printf("cfg_init: mmap call failure.\n"); + return -1; + } + + return 0; +} + +int sts_init(void) +{ + char *uiod = "/dev/uio4"; + + //printf("Initializing STS device...\n"); + + // open the UIO device file to allow access to the device in user space + sts_fd = open(uiod, O_RDWR); + if (sts_fd < 1) { + printf("sts_init: Invalid UIO device file:%s.\n", uiod); + return -1; + } + + dev_size = get_memory_size("/sys/class/uio/uio4/maps/map0/size"); + + // mmap the STS device into user space + sts_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, sts_fd, 0); + if (sts_ptr == MAP_FAILED) { + printf("sts_init: mmap call failure.\n"); + return -1; + } + + return 0; +} + +int xadc_init(void) +{ + char *uiod = "/dev/uio5"; + + //printf("Initializing XADC device...\n"); + + // open the UIO device file to allow access to the device in user space + xadc_fd = open(uiod, O_RDWR); + if (xadc_fd < 1) { + printf("xadc_init: Invalid UIO device file:%s.\n", uiod); + return -1; + } + + dev_size = get_memory_size("/sys/class/uio/uio5/maps/map0/size"); + + // mmap the XADC device into user space + xadc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, xadc_fd, 0); + if (xadc_ptr == MAP_FAILED) { + printf("xadc_init: mmap call failure.\n"); + return -1; + } + + return 0; +} + +int mem_init(void) +{ + char *mem_name = "/dev/mem"; + + //printf("Initializing mem device...\n"); + + // open the UIO device file to allow access to the device in user space + mem_fd = open(mem_name, O_RDWR); + if (mem_fd < 1) { + printf("mem_init: Invalid device file:%s.\n", mem_name); + return -1; + } + + dev_size = 2048*sysconf(_SC_PAGESIZE); + + // mmap the mem device into user space + mem_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0x1E000000); + if (mem_ptr == MAP_FAILED) { + printf("mem_init: mmap call failure.\n"); + return -1; + } + + return 0; +} + +int hst0_init(void) +{ + char *mem_name = "/dev/mem"; + + //printf("Initializing mem device...\n"); + + // open the UIO device file to allow access to the device in user space + hst0_fd = open(mem_name, O_RDWR); + if (hst0_fd < 1) { + printf("hst0_init: Invalid device file:%s.\n", mem_name); + return -1; + } + + // mmap the mem device into user space + hst0_ptr = mmap(NULL, 16*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, hst0_fd, HST0_BASEADDR); + if (hst0_ptr == MAP_FAILED) { + printf("mem_init: mmap call failure.\n"); + return -1; + } + + return 0; +} + +int hst1_init(void) +{ + char *mem_name = "/dev/mem"; + + //printf("Initializing mem device...\n"); + + // open the UIO device file to allow access to the device in user space + hst1_fd = open(mem_name, O_RDWR); + if (hst1_fd < 1) { + printf("hst1_init: Invalid device file:%s.\n", mem_name); + return -1; + } + + // mmap the mem device into user space + hst1_ptr = mmap(NULL, 16*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, hst1_fd, HST1_BASEADDR); + if (hst1_ptr == MAP_FAILED) { + printf("mem_init: mmap call failure.\n"); + return -1; + } + + return 0; +} + +int cma_init(void) +{ + char *cma_name = "/dev/cma"; + + //printf("Initializing mem device...\n"); + + // open the UIO device file to allow access to the device in user space + cma_fd = open(cma_name, O_RDWR); + if (cma_fd < 1) { + printf("cma_init: Invalid device file:%s.\n", cma_name); + return -1; + } + + dev_size = 1024*sysconf(_SC_PAGESIZE); + + if(ioctl(cma_fd, CMA_ALLOC, &dev_size) < 0) { + perror("ioctl"); + return EXIT_FAILURE; + } + // mmap the mem device into user space + cma_ptr = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, cma_fd, 0); + if (cma_ptr == MAP_FAILED) { + printf("cma_init: mmap call failure.\n"); + return -1; + } + + return 0; +} + +float get_voltage(uint32_t offset) +{ + int16_t value; + value = (int16_t) dev_read(xadc_ptr, offset); + // printf("The Voltage is: %lf V\n", (value>>4)*XADC_CONV_VAL); + return ((value>>4)*XADC_CONV_VAL); +} + +/*void set_voltage(uint32_t offset, int32_t value) + { +//fit after calibration. See file data_calib.txt in /ramp_test directory +// y = a*x + b +//a = 0.0382061 +//b = 4.11435 +uint32_t dac_val; +float a = 0.0382061, b = 4.11435; + +dac_val = (uint32_t)(value - b)/a; + +dev_write(cfg_ptr, offset, dac_val); +printf("The Voltage is: %d mV\n", value); +printf("The DAC value is: %d DACs\n", dac_val); +} +*/ + +void set_voltage(uint32_t offset, int32_t value) +{ + //fit after calibration. See file data_calib2.txt in /ramp_test directory + // y = a*x + b + //a = 0.0882006 + //b = 7.73516 + uint32_t dac_val; + float a = 0.0882006, b = 7.73516; + + dac_val = (uint32_t)(value - b)/a; + + dev_write(cfg_ptr, offset, dac_val); + printf("The Voltage is: %d mV\n", value); + printf("The DAC value is: %d DACs\n", dac_val); +} + +float get_temp_AD592(uint32_t offset) +{ + float value; + value = get_voltage(offset); + return ((value*1000)-273.15); +} + +//System initialization +int init_system(void) +{ + uint32_t reg_val; + + //FIXME: replace hardcoded values for defines + // set trigger_lvl_1 + dev_write(cfg_ptr,CFG_TRLVL_1_OFFSET,8190); + + // set trigger_lvl_2 + dev_write(cfg_ptr,CFG_TRLVL_2_OFFSET,8190); + + // set subtrigger_lvl_1 + dev_write(cfg_ptr,CFG_STRLVL_1_OFFSET,8190); + + // set subtrigger_lvl_2 + dev_write(cfg_ptr,CFG_STRLVL_2_OFFSET,8190); + + // set hv1 and hv2 to zero + dev_write(cfg_ptr,CFG_HV1_OFFSET,0); + dev_write(cfg_ptr,CFG_HV2_OFFSET,0); + + // reset ramp generators + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~8); + + // reset pps_gen, fifo and trigger modules + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1); + + /* reset data converter and writer */ + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4); + + // enter reset mode for tlast_gen + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2); + + // set number of samples + dev_write(cfg_ptr,CFG_NSAMPLES_OFFSET, 1024 * 1024); + + // set default value for trigger scalers a and b + dev_write(cfg_ptr,CFG_TR_SCAL_A_OFFSET, 1); + dev_write(cfg_ptr,CFG_TR_SCAL_B_OFFSET, 1); + + // enter normal mode for tlast_gen + /* reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + //printf("reg_val : 0x%08x\n",reg_val); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2); + //printf("written reg_val tlast : 0x%08x\n",reg_val | 2); + // enter normal mode for pps_gen, fifo and trigger modules + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + //printf("reg_val : 0x%08x\n",reg_val); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1); + //printf("written reg_val pps_gen, fifo : 0x%08x\n",reg_val | 1); + */ + // enable false GPS + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + //printf("reg_val : 0x%08x\n",reg_val); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | FGPS_EN_MASK); + //printf("written reg_val : 0x%08x\n",reg_val | 16); + // disable + //dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~16); + //dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~FGPS_EN_MASK); + //printf("written reg_val : 0x%08x\n",reg_val & ~16); + + /* // enter normal mode for data converter and writer + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4); + //printf("written reg_val : 0x%08hx\n",reg_val | 4); + */ + // enter normal mode for ramp generators + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 8); + // enter in MASTER mode (default) + reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET); + dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 0x20); + + return 0; +} + +int enable_interrupt(void) +{ + // steps to accept interrupts -> as pg. 26 of pg099-axi-intc.pdf + //1) Each bit in the IER corresponding to an interrupt must be set to 1. + dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 1); + //2) There are two bits in the MER. The ME bit must be set to enable the + //interrupt request outputs. + dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK | XIL_AXI_INTC_MER_HIE_MASK); + //dev_write(dev_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK); + + //The next block of code is to test interrupts by software + //3) Software testing can now proceed by writing a 1 to any bit position + //in the ISR that corresponds to an existing interrupt input. + /* dev_write(intc_ptr,XIL_AXI_INTC_IPR_OFFSET, 1); + + for(a=0; a<10; a++) + { + wait_for_interrupt(fd, dev_ptr); + dev_write(dev_ptr,XIL_AXI_INTC_ISR_OFFSET, 1); //regenerate interrupt + } + */ + return 0; + +} + +int disable_interrupt(void) +{ + uint32_t value; + //Disable interrupt INTC0 + dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 0); + //disable IRQ + value = dev_read(intc_ptr, XIL_AXI_INTC_MER_OFFSET); + dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, value | ~1); + //Acknowledge any previous interrupt + dev_write(intc_ptr, XIL_AXI_INTC_IAR_OFFSET, 1); + + return 0; +} + diff --git a/projects/lago_v1_3/src/zynq_io.h b/projects/lago_v1_3/src/zynq_io.h new file mode 100644 index 0000000000000000000000000000000000000000..ba466da87eadb67d983e57d2e42340f23a0eb3dd --- /dev/null +++ b/projects/lago_v1_3/src/zynq_io.h @@ -0,0 +1,163 @@ +#ifndef _ZYNQ_IO_H_ +#define _ZYNQ_IO_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <unistd.h> +#include <sys/ioctl.h> + +#define CMA_ALLOC _IOWR('Z', 0, uint32_t) +#define INTC_BASEADDR 0x40000000 +#define INTC_HIGHADDR 0x40000FFF + +#define CFG_BASEADDR 0x40001000 +#define CFG_HIGHADDR 0x40001FFF + +#define STS_BASEADDR 0x40002000 +#define STS_HIGHADDR 0x40002FFF + +#define XADC_BASEADDR 0x40003000 +#define XADC_HIGHADDR 0x40003FFF + +#define HST0_BASEADDR 0x40010000 +#define HST0_HIGHADDR 0x4001FFFF + +#define HST1_BASEADDR 0x40020000 +#define HST1_HIGHADDR 0x4002FFFF + +#define XIL_AXI_INTC_ISR_OFFSET 0x0 +#define XIL_AXI_INTC_IPR_OFFSET 0x4 +#define XIL_AXI_INTC_IER_OFFSET 0x8 +#define XIL_AXI_INTC_IAR_OFFSET 0xC +#define XIL_AXI_INTC_SIE_OFFSET 0x10 +#define XIL_AXI_INTC_CIE_OFFSET 0x14 +#define XIL_AXI_INTC_IVR_OFFSET 0x18 +#define XIL_AXI_INTC_MER_OFFSET 0x1C +#define XIL_AXI_INTC_IMR_OFFSET 0x20 +#define XIL_AXI_INTC_ILR_OFFSET 0x24 +#define XIL_AXI_INTC_IVAR_OFFSET 0x100 + +#define XIL_AXI_INTC_MER_ME_MASK 0x00000001 +#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002 + +//CFG +#define CFG_RESET_GRAL_OFFSET 0x0 +#define CFG_NSAMPLES_OFFSET 0x4 +#define CFG_TRLVL_1_OFFSET 0x8 +#define CFG_TRLVL_2_OFFSET 0xC +#define CFG_STRLVL_1_OFFSET 0x10 +#define CFG_STRLVL_2_OFFSET 0x14 +#define CFG_TEMPERATURE_OFFSET 0x18 +#define CFG_PRESSURE_OFFSET 0x1C +#define CFG_TIME_OFFSET 0x20 +#define CFG_DATE_OFFSET 0x24 +#define CFG_LATITUDE_OFFSET 0x28 +#define CFG_LONGITUDE_OFFSET 0x2C +#define CFG_ALTITUDE_OFFSET 0x30 +#define CFG_SATELLITE_OFFSET 0x34 +#define CFG_TR_SCAL_A_OFFSET 0x38 +#define CFG_TR_SCAL_B_OFFSET 0x3C +#define CFG_HV1_OFFSET 0x4C //DAC_PWM3 +#define CFG_HV2_OFFSET 0x48 //DAC_PWM2 +#define CFG_HV3_OFFSET 0x40 //DAC_PWM0 +#define CFG_HV4_OFFSET 0x44 //DAC_PWM1 +#define CFG_HST0_OFFSET 0x50 +#define CFG_HST1_OFFSET 0x54 +#define CFG_WR_ADDR_OFFSET 0x58 //writer address + +//CFG Slow DAC +#define CFG_DAC_PWM0_OFFSET 0x40 +#define CFG_DAC_PWM1_OFFSET 0x44 +#define CFG_DAC_PWM2_OFFSET 0x48 +#define CFG_DAC_PWM3_OFFSET 0x4C + +#define ENBL_ALL_MASK 0xFFFFFFFF +#define RST_ALL_MASK 0x00000000 +#define RST_PPS_TRG_FIFO_MASK 0x00000001 +#define RST_TLAST_GEN_MASK 0x00000002 +#define RST_WRITER_MASK 0x00000004 +#define RST_AO_MASK 0x00000008 +#define FGPS_EN_MASK 0x00000010 + +//STS +#define STS_STATUS_OFFSET 0x0 + +//XADC +//See page 17 of PG091 +#define XADC_SRR_OFFSET 0x00 //Software reset register +#define XADC_SR_OFFSET 0x04 //Status Register +#define XADC_AOSR_OFFSET 0x08 //Alarm Out Status Register +#define XADC_CONVSTR_OFFSET 0x0C //CONVST Register +#define XADC_SYSMONRR_OFFSET 0x10 //XADC Reset Register +#define XADC_GIER_OFFSET 0x5C //Global Interrupt Enable Register +#define XADC_IPISR_OFFSET 0x60 //IP Interrupt Status Register +#define XADC_IPIER_OFFSET 0x68 //IP Interrupt Enable Register +#define XADC_TEMPERATURE_OFFSET 0x200 //Temperature +#define XADC_VCCINT_OFFSET 0x204 //VCCINT +#define XADC_VCCAUX_OFFSET 0x208 //VCCAUX +#define XADC_VPVN_OFFSET 0x20C //VP/VN +#define XADC_VREFP_OFFSET 0x210 //VREFP +#define XADC_VREFN_OFFSET 0x214 //VREFN +#define XADC_VBRAM_OFFSET 0x218 //VBRAM +#define XADC_UNDEF_OFFSET 0x21C //Undefined +#define XADC_SPLYOFF_OFFSET 0x220 //Supply Offset +#define XADC_ADCOFF_OFFSET 0x224 //ADC Offset +#define XADC_GAIN_ERR_OFFSET 0x228 //Gain Error +#define XADC_ZDC_SPLY_OFFSET 0x234 //Zynq-7000 Device Core Supply +#define XADC_ZDC_AUX_SPLY_OFFSET 0x238 //Zynq-7000 Device Core Aux Supply +#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C //Zynq-7000 Device Core Memory Supply +#define XADC_VAUX_PN_0_OFFSET 0x240 //VAUXP[0]/VAUXN[0] +#define XADC_VAUX_PN_1_OFFSET 0x244 //VAUXP[1]/VAUXN[1] +#define XADC_VAUX_PN_2_OFFSET 0x248 //VAUXP[2]/VAUXN[2] +#define XADC_VAUX_PN_3_OFFSET 0x24C //VAUXP[3]/VAUXN[3] +#define XADC_VAUX_PN_4_OFFSET 0x250 //VAUXP[4]/VAUXN[4] +#define XADC_VAUX_PN_5_OFFSET 0x254 //VAUXP[5]/VAUXN[5] +#define XADC_VAUX_PN_6_OFFSET 0x258 //VAUXP[6]/VAUXN[6] +#define XADC_VAUX_PN_7_OFFSET 0x25C //VAUXP[7]/VAUXN[7] +#define XADC_VAUX_PN_8_OFFSET 0x260 //VAUXP[8]/VAUXN[8] +#define XADC_VAUX_PN_9_OFFSET 0x264 //VAUXP[9]/VAUXN[9] +#define XADC_VAUX_PN_10_OFFSET 0x268 //VAUXP[10]/VAUXN[10] +#define XADC_VAUX_PN_11_OFFSET 0x26C //VAUXP[11]/VAUXN[11] +#define XADC_VAUX_PN_12_OFFSET 0x270 //VAUXP[12]/VAUXN[12] +#define XADC_VAUX_PN_13_OFFSET 0x274 //VAUXP[13]/VAUXN[13] +#define XADC_VAUX_PN_14_OFFSET 0x278 //VAUXP[14]/VAUXN[14] +#define XADC_VAUX_PN_15_OFFSET 0x27C //VAUXP[15]/VAUXN[15] + +#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET +#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET +#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET +#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET + +#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99) +#define XADC_RDIV_VAL 1.883236177 //voltage divisor in board (15k+16.983k)/16.983k = 1.88 +#define XADC_BASE_HVDIV 0.00294088 //voltage divisor in HV base board (100k/31.3Meg) = 3.194888179. The value I put here is the measured one. + +extern int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd; +extern void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr; +extern volatile int16_t *cma_ptr; +extern uint32_t dev_size; + +void dev_write(void *dev_base, uint32_t offset, int32_t value); +uint32_t dev_read(void *dev_base, uint32_t offset); +//int dev_init(int n_dev); +int32_t rd_reg_value(int n_dev, uint32_t reg_off, uint8_t degug); +int32_t wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug); +int32_t rd_cfg_status(void); +int intc_init(void); +int cfg_init(void); +int sts_init(void); +int xadc_init(void); +int mem_init(void); +int cma_init(void); +float get_voltage(uint32_t offset); +void set_voltage(uint32_t offset, int32_t value); +float get_temp_AD592(uint32_t offset); +int init_system(void); +int enable_interrupt(void); +int disable_interrupt(void); + +#endif + diff --git a/projects/led_blinker/app/index.html b/projects/led_blinker/app/index.html deleted file mode 100644 index 11f7dfe5413654d2d0510fad5afa1ea8374eff22..0000000000000000000000000000000000000000 --- a/projects/led_blinker/app/index.html +++ /dev/null @@ -1,24 +0,0 @@ -<!doctype html> -<html> -<head> -<meta charset="utf-8"> -<title>LED blinker</title> -<link rel="stylesheet" href="/css/main.css"> -<link rel="stylesheet" href="/css/pygments.css"> -</head> -<body> -<div id="header"> -<div id="logo"> -<a href="/">Back to all apps</a> -</div> -<div id="menu"> -<a href="https://github.com/pavel-demin/red-pitaya-notes" target="_blank">Source</a> -<a href="https://github.com/pavel-demin/red-pitaya-notes/issues" target="_blank">Issues</a> -</div> -</div> -<div id="content"> -<h1>LED blinker</h1> -<p>The LED blinker application is ready.</p> -</div> -</body> -</html> diff --git a/projects/led_blinker/app/start.sh b/projects/led_blinker/app/start.sh deleted file mode 100755 index c2cb31d1eefd065502e603fdbe0b6b3e6c4f59c1..0000000000000000000000000000000000000000 --- a/projects/led_blinker/app/start.sh +++ /dev/null @@ -1,7 +0,0 @@ -#! /bin/sh - -apps_dir=/media/mmcblk0p1/apps - -source $apps_dir/stop.sh - -cat $apps_dir/led_blinker/led_blinker.bit > /dev/xdevcfg