├── illuminate ├── src │ ├── ledarrays_custom │ │ └── .put_custom_led_array_cpp_files_here │ ├── .DS_Store │ └── ledarrays │ │ ├── sci.asym.r0.cpp │ │ ├── sci.iris.cpp │ │ └── sci.round.r1.cpp ├── .DS_Store ├── .vscode │ ├── arduino.json │ └── c_cpp_properties.json ├── illuminate.h ├── commandrouting.h ├── constants.h ├── ledsequence.h ├── ledarrayinterface.h ├── commandrouting.cpp ├── ledarray.h ├── illuminate.ino └── commandconstants.h ├── doc └── logo.png ├── .gitmodules ├── .gitignore ├── LICENSE └── README.md /illuminate/src/ledarrays_custom/.put_custom_led_array_cpp_files_here: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sci-microscopy/illuminate/HEAD/doc/logo.png -------------------------------------------------------------------------------- /illuminate/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sci-microscopy/illuminate/HEAD/illuminate/.DS_Store -------------------------------------------------------------------------------- /illuminate/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sci-microscopy/illuminate/HEAD/illuminate/src/.DS_Store -------------------------------------------------------------------------------- /illuminate/.vscode/arduino.json: -------------------------------------------------------------------------------- 1 | { 2 | "configuration": "usb=serial,speed=600,opt=o2std,keys=en-us", 3 | "board": "teensy:avr:teensy40", 4 | "port": "COM40", 5 | "sketch": "illuminate.ino" 6 | } -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "illuminate/src/TLC5955"] 2 | path = illuminate/src/TLC5955 3 | url = https://github.com/zfphil/TLC5955.git 4 | [submodule "illuminate/src/analogComp"] 5 | path = illuminate/src/analogComp 6 | url = https://github.com/orangkucing/analogComp.git 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Custom led array folder 35 | illuminate/src/ledarrays_custom/* 36 | !illuminate/src/ledarrays_custom/.put_custom_led_array_cpp_files_here 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Zack Phillips, Regents of the University of California 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /illuminate/illuminate.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORTff 27 | 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #ifndef ILLUMINATE_H 33 | #define ILLUMINATE_H 34 | 35 | #define VERSION 2.33 36 | 37 | // This file allows the user to define which LED array interface is used. This should be set before compilation. 38 | // The value these are set to does not matter - only that they are defined. 39 | //#define USE_QUADRANT_ARRAY // currently broken; cannot test 40 | //#define USE_QUASI_DOME_ARRAY // currently broken; cannot test 41 | //#define USE_SCI_ROUND_ARRAY 42 | //#define USE_SCI_ROUND_ARRAY_R1 43 | //#define USE_SCI_IRIS 44 | //#define USE_SCI_DOME_R1 45 | //#define USE_SCI_DOME_R2 46 | #define USE_SCI_DOME_R3 47 | //#define USE_QUAD_LULED_ARRAY 48 | //#define USE_LUMINI_RING 49 | //#define USE_SCI_ASYM_ARRAY 50 | //#define USE_SCI_EPI_ARRAY 51 | //#define USE_SCI_BIG_WING_ARRAY 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /illuminate/commandrouting.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef ROUTING_H 32 | #define ROUTING_H 33 | 34 | #include "illuminate.h" 35 | #include 36 | #include 37 | 38 | #define DELIMITER '.' 39 | 40 | // Need to declare command router since it is used by the command_item struct; 41 | class CommandRouter; 42 | 43 | typedef struct command_item { 44 | const char *name; 45 | const char *description; 46 | const char *syntax; 47 | int (*func)(CommandRouter *cmd, int argc, const char **argv); 48 | } command_item_t; 49 | 50 | class CommandRouter { 51 | public: 52 | int init(command_item_t *commands, int buffer_size, 53 | char *serial_buffer, int argv_max, 54 | const char **argv_buffer); 55 | int help(int argc, char **argv); 56 | int process_serial_stream(); 57 | 58 | char *buffer = nullptr; // Allow for terminating null byte 59 | int buffer_size = 0; 60 | 61 | private: 62 | int route(int argc, const char **argv); 63 | 64 | const char **argv; 65 | int argv_max = 0; 66 | 67 | int incoming; 68 | 69 | bool malloc_used = false; 70 | command_item_t *command_list; 71 | }; 72 | 73 | extern CommandRouter cmd; 74 | #endif 75 | -------------------------------------------------------------------------------- /illuminate/constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "illuminate.h" 32 | 33 | #ifndef CONSTANTS_H 34 | #define CONSTANTS_H 35 | 36 | // Serial line ending 37 | static const char SERIAL_LINE_ENDING[] = "\n"; 38 | 39 | // Serial command termiator 40 | static const char SERIAL_COMMAND_TERMINATOR[] = "-==-"; 41 | 42 | // Serial delimeter 43 | static const char SERIAL_DELIMITER[] = "."; 44 | 45 | // PSU Sensing constants 46 | #define PSU_SENSING_AND_MONITORING 2 47 | #define PSU_SENSING_ONLY 1 48 | #define NO_PSU_SENSING 0 49 | 50 | // Trigger mode constants 51 | #define TRIG_MODE_NONE 0 52 | #define TRIG_MODE_ITERATION -1 // trigger at the start of each iteration (when the user 53 | #define TRIG_MODE_START -2 // Triggering at the start of each acquisition 54 | 55 | // Trigger timing constants 56 | #define TRIGGER_OUTPUT_PULSE_WIDTH_DEFAULT 500 57 | #define TRIGGER_OUTPUT_DELAY_DEFAULT 0 58 | #define TRIGGER_TIMEOUT_DEFAULT 3600.0 59 | #define TRIGGER_INPUT_POLARITY_DEFAULT 1 60 | #define TRIGGER_OUTPUT_POLARITY_DEFAULT 1 61 | 62 | // Misc constants 63 | #define MIN_SEQUENCE_DELAY 5 // Min deblur pattern delay in ms (set by hardware) 64 | #define MIN_SEQUENCE_DELAY_FAST 2 // Min deblur pattern delay for fast sequence in us (set by hardware) 65 | #define MAX_SEQUENCE_DELAY 2000 // Global maximum amount to wait inside a sequence loop 66 | #define INVALID_NA -2000.0 // Rep```resents an invalid NA 67 | 68 | // Command mode constants 69 | #define COMMAND_MODE_LONG 1 70 | #define COMMAND_MODE_SHORT 0 71 | 72 | // Response Lengths 73 | #define MAX_RESPONSE_LENGTH_SHORT 100 74 | #define MAX_RESPONSE_LENGTH_LONG 100 75 | 76 | // EEPROM Addresses 77 | #define DEMO_MODE_ADDRESS 50 78 | #define PN_ADDRESS 100 79 | #define SN_ADDRESS 200 80 | #define STORED_NA_ADDRESS 301 81 | #define STORED_DISTANCE_ADDRESS 302 82 | #define STORED_COLOR_R_ADDRESS 303 83 | #define STORED_COLOR_G_ADDRESS 304 84 | #define STORED_COLOR_B_ADDRESS 305 85 | #define STORED_GSCLK_ADDRESS 306 86 | #define STORED_SCLK_ADDRESS 307 87 | #define STORED_BRIGHTNESS_ADDRESS 308 88 | #define STORED_COMMAND_MODE_ADDRESS 309 89 | #define STORED_AUTOLOAD_LAST_STATE 310 90 | 91 | // Serial characters 92 | #define COMMAND_END "-==-" 93 | 94 | // Error Codes 95 | #define ERROR_CODE_COUNT 20 96 | 97 | #define NO_ERROR 0 98 | #define ERROR_NOT_IMPLEMENTED 1 99 | #define ERROR_ARGUMENT_COUNT 2 100 | #define ERROR_SOURCE_DISCONNECTED 3 101 | #define ERROR_ARGS_SET_TRIGGER_TIMEOUT 4 102 | #define ERROR_COSINE_FACTOR 5 103 | #define ERROR_MAC_ADDRESS 6 104 | #define ERROR_POWER_SENSING_NOT_SUPPORTED 7 105 | #define ERROR_INVALID_ARGUMENT 8 106 | #define ERROR_NOT_SUPPORTED_BY_DEVICE 9 107 | #define ERROR_ARGUMENT_RANGE 10 108 | #define ERROR_TRIGGER_CONFIG 11 109 | #define ERROR_END_OF_SEQUENCE 12 110 | #define ERROR_SEQUENCE_DELAY 13 111 | #define ERROR_TRIGGER_TIMEOUT 14 112 | #define ERROR_COMMAND_INTERRUPTED 15 113 | #define ERROR_INVALID_COMMAND 16 114 | #define ERROR_MEMORY_ALLOC 17 115 | #define ERROR_COMMAND_TOO_LONG 18 116 | #define ERROR_SEQUENCE_FULL 19 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /illuminate/ledsequence.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef LEDSEQUENCE_H 32 | #define LEDSEQUENCE_H 33 | 34 | #include "Arduino.h" 35 | #include "illuminate.h" 36 | #include "ledarrayinterface.h" 37 | #include "constants.h" 38 | 39 | // Define LED Sequence Object 40 | struct LedSequence 41 | { 42 | uint16_t length = 0; // Length of values 43 | volatile uint16_t * led_counts; // Number of LEDs in each values 44 | volatile uint16_t * * led_list; // LED numbers used in each entry 45 | volatile uint16_t number_of_patterns_assigned = 0; // Number of patterns which have been assigned 46 | volatile uint16_t current_pattern_led_index = 0; // Current led index within current pattern 47 | uint8_t color_channel_count = 1; 48 | uint8_t bit_depth = 8; 49 | int debug = 1; 50 | 51 | void reset() 52 | { 53 | deallocate(); 54 | } 55 | 56 | void allocate(uint16_t values_length) 57 | { 58 | led_list = new volatile uint16_t * [values_length]; 59 | led_counts = new volatile uint16_t [values_length]; 60 | 61 | // Assign new vector length 62 | length = values_length; 63 | } 64 | 65 | void append(uint16_t led_number) 66 | { 67 | // Assign led number 68 | led_list[number_of_patterns_assigned - 1][current_pattern_led_index] = led_number; 69 | 70 | // Increment number of LEDs stored in this pattern 71 | current_pattern_led_index++; 72 | } 73 | 74 | bool increment(uint16_t led_count) 75 | { 76 | if (number_of_patterns_assigned < length) 77 | { 78 | // increment number of patterns assigned 79 | number_of_patterns_assigned++; 80 | 81 | // store the number of leds in this pattern 82 | led_counts[number_of_patterns_assigned - 1] = led_count; 83 | 84 | if (led_count > 0) 85 | led_list[number_of_patterns_assigned - 1] = new uint16_t[led_count]; 86 | 87 | // Reset the pattern led index 88 | current_pattern_led_index = 0; 89 | 90 | // Let user know we haven't reached capacity 91 | return true; 92 | } 93 | else 94 | { 95 | Serial.print(F("Sequence length (")); Serial.print(length); Serial.printf(F(") reached. %s"), SERIAL_LINE_ENDING); 96 | return false; 97 | } 98 | } 99 | 100 | void deallocate() 101 | { 102 | for (uint16_t values_index = 0; values_index < number_of_patterns_assigned; values_index++) 103 | if (led_counts[values_index] > 0) 104 | delete[] led_list[values_index]; 105 | 106 | if (number_of_patterns_assigned > 0) 107 | { 108 | delete[] led_list; 109 | delete[] led_counts; 110 | } 111 | 112 | number_of_patterns_assigned = 0; 113 | current_pattern_led_index = 0; 114 | } 115 | 116 | void print(int command_mode) 117 | { 118 | // Print header 119 | if (command_mode == COMMAND_MODE_LONG) 120 | Serial.printf(F("Sequence has %d patterns:%s"), length, SERIAL_LINE_ENDING); 121 | else 122 | Serial.printf(F("{\n \"sequence\": [%s"), SERIAL_LINE_ENDING); 123 | 124 | // Print values 125 | for (uint16_t pattern_index = 0; pattern_index < number_of_patterns_assigned; pattern_index++) 126 | print(pattern_index, command_mode); 127 | 128 | // Print footer 129 | if (command_mode == COMMAND_MODE_SHORT) 130 | Serial.printf(F(" ]%s}%s"), SERIAL_LINE_ENDING, SERIAL_LINE_ENDING); 131 | } 132 | 133 | void print(uint16_t pattern_index, int command_mode) 134 | { 135 | if (command_mode == COMMAND_MODE_LONG) 136 | { 137 | Serial.print("Pattern "); 138 | Serial.print(pattern_index); 139 | Serial.print(" ("); 140 | Serial.print(led_counts[pattern_index]); 141 | Serial.printf(" leds):"); 142 | for (uint16_t led_index = 0; led_index < led_counts[pattern_index]; led_index++) 143 | { 144 | Serial.print(F(" ")); 145 | Serial.print(led_list[pattern_index][led_index]); 146 | if (led_index < led_counts[pattern_index] - 1) 147 | Serial.printf(F(",")); 148 | } 149 | Serial.print(SERIAL_LINE_ENDING); 150 | } 151 | else 152 | { 153 | Serial.print("["); 154 | for (uint16_t led_index = 0; led_index < led_counts[pattern_index]; led_index++) 155 | { 156 | Serial.print(led_list[pattern_index][led_index]); 157 | if (led_index < led_counts[pattern_index] - 1) 158 | Serial.printf(F(","), SERIAL_LINE_ENDING); 159 | } 160 | if (pattern_index < number_of_patterns_assigned - 1) 161 | Serial.printf(F("],%s"), SERIAL_LINE_ENDING); 162 | else 163 | Serial.printf(F("]%s"), SERIAL_LINE_ENDING); 164 | } 165 | } 166 | }; 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /illuminate/ledarrayinterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef LEDARRAYINTERFACE_H 32 | #define LEDARRAYINTERFACE_H 33 | 34 | #include "illuminate.h" 35 | #include 36 | #include 37 | #include "constants.h" 38 | 39 | 40 | class LedArrayInterface { 41 | public: 42 | static int8_t device_setup(); 43 | int8_t device_reset(); 44 | 45 | // Note that passing a -1 for led_number or color_channel_index sets all LEDs or all color channels respectively 46 | void set_led(int16_t led_number, int16_t color_channel_index, uint16_t value); // LED brightness (16-bit) 47 | void set_led(int16_t led_number, int16_t color_channel_index, uint8_t value); // LED brightness (8-bit) 48 | void set_led(int16_t led_number, int16_t color_channel_index, bool value); // LED brightness (boolean) 49 | 50 | // Get LED Value 51 | uint16_t get_led_value(uint16_t led_number, int color_channel_index); 52 | 53 | // Clear array 54 | static void clear(); 55 | 56 | // Get and set trigger state 57 | int send_trigger_pulse(int trigger_index, uint16_t delay_us, bool inverse_polarity); 58 | static void trigger_pin_interrupt_0(); 59 | static void trigger_pin_interrupt_1(); 60 | 61 | // Update array 62 | static void update(); 63 | 64 | // Debug 65 | bool get_debug(); 66 | void set_debug(int state); 67 | 68 | // Set channel 69 | void set_channel(int16_t channel_number, int16_t color_channel_number, uint16_t value); 70 | void set_channel(int16_t channel_number, int16_t color_channel_number, uint8_t value); 71 | void set_channel(int16_t channel_number, int16_t color_channel_number, bool value); 72 | 73 | // Set pin order 74 | void set_pin_order(int16_t led_number, int16_t color_channel_index, uint8_t position); 75 | 76 | // Maximum current limits 77 | void set_max_current_enforcement(bool enforce); 78 | bool get_max_current_enforcement(); 79 | void set_max_current_limit(float limit); 80 | float get_max_current_limit(); 81 | 82 | // Not implemented function 83 | void not_implemented(const char * command_name); 84 | 85 | // Device and Software Descriptors 86 | static const char * device_name; 87 | static const char * device_hardware_revision; 88 | static const int16_t led_count; 89 | static const uint16_t center_led; 90 | static const int trigger_output_count; 91 | static const int trigger_input_count; 92 | static const int color_channel_count; 93 | static const char color_channel_names[]; 94 | static const float color_channel_center_wavelengths_nm[]; 95 | static const float color_channel_fwhm_wavelengths_nm[]; 96 | static const int bit_depth; 97 | static const int16_t tlc_chip_count; 98 | static const bool supports_fast_sequence; 99 | static const float led_array_distance_z_default; 100 | static const char * device_commandNamesShort[]; 101 | static const char * device_commandNamesLong[]; 102 | static const uint8_t device_command_count; 103 | static const uint16_t device_command_pattern_dimensions[][2]; 104 | static const uint16_t *device_command_pattern_list[]; 105 | static const int power_sense_pin; 106 | static const float min_source_voltage; 107 | 108 | // Debug flag 109 | static int debug; 110 | 111 | // Triggering Variables 112 | static const int trigger_output_pin_list[]; 113 | static const int trigger_input_pin_list[]; 114 | static bool trigger_input_state[]; 115 | 116 | // LED positionsde 117 | static const int16_t PROGMEM led_positions[][5]; 118 | static const int16_t PROGMEM arbitrary_led_list[][1]; 119 | static float led_position_list_na[][2]; 120 | 121 | // Device-specific commands 122 | uint8_t get_device_command_count(); 123 | const char * get_device_command_name_short(int device_command_index); 124 | const char * get_device_command_name_long(int device_command_index); 125 | uint32_t get_device_command_led_list_size(int device_command_index); 126 | uint16_t get_device_command_led_list_element(int device_command_index, uint16_t pattern_index, uint16_t led_index); 127 | 128 | // Serial and part numbers 129 | uint16_t get_serial_number(); 130 | 131 | uint16_t get_part_number(); 132 | void set_part_number(uint16_t part_number); 133 | void set_serial_number(uint16_t serial_number); 134 | 135 | // Hardware-related functions 136 | void set_sclk_baud_rate(uint32_t new_baud_rate); 137 | uint32_t get_sclk_baud_rate(); 138 | void set_gsclk_frequency(uint32_t new_gsclk_freq); 139 | uint32_t get_gsclk_frequency(); 140 | void set_global_shutter_state(bool state); 141 | bool get_global_shutter_state(); 142 | 143 | // Source voltage checking 144 | int16_t source_sense_pin = -1; 145 | int16_t source_reference_value = -1; 146 | float get_power_source_voltage(); 147 | bool is_power_source_plugged_in(); 148 | int16_t get_device_power_sensing_capability(); 149 | bool get_power_source_monitoring_state(); 150 | void set_power_source_monitoring_state(int state); 151 | void source_change_interrupt(); 152 | 153 | int8_t set_register(uint32_t register_, int8_t value); 154 | int8_t get_register(uint32_t register_); 155 | }; 156 | 157 | #endif 158 | -------------------------------------------------------------------------------- /illuminate/commandrouting.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #include "commandrouting.h" 32 | #include 33 | #include 34 | #include "constants.h" 35 | 36 | // Syntax is: {short code, long error description} 37 | const char* error_code_list[ERROR_CODE_COUNT][2] = { 38 | 39 | // No Error 40 | {"0", "No Error"}, 41 | 42 | // High-level Errors 43 | {"NI", "Command not implemented."}, 44 | 45 | // Sequence 46 | {"ARGS", "Wrong number of arguments."}, 47 | 48 | // Power source disconnected 49 | {"PSRC", "(LedArray::sourceConnected): Source Disconnected"}, 50 | 51 | // Trigger Settings 52 | {"TRIGT", "Trigger Timeout."}, 53 | 54 | // Cosine Factor 55 | {"COS", "Invalid cosine factor."}, 56 | 57 | // MAC address generation 58 | {"MAC", "Mac address generation failed."}, 59 | 60 | // PSU Sensing 61 | {"PSUSENS", "PSU sensing not supported on this device."}, 62 | 63 | // Invalid Argument 64 | {"BADARG", "Invalid argument."}, 65 | 66 | // Invalid Argument 67 | {"NOT_SUPPORTED_BY_DEVICE", "Device does not support this feature."}, 68 | 69 | // Invalid Argument 70 | {"ARG_RANGE", "Invalid argument range."}, 71 | 72 | // Invalid Argument 73 | {"TRIG_CONFIG", "Triggering not configured."}, 74 | 75 | // Sequence zeros too long 76 | {"END_OF_SEQ", "Reached end of sequence."}, 77 | 78 | // Sequence zeros too long 79 | {"SEQ_DELAY", "Sequence period was shorter than LED update rate."}, 80 | 81 | // Sequence zeros too long 82 | {"TRIG_TIMEOUT", "Trigger timeout."}, 83 | 84 | // Sequence zeros too long 85 | {"INTERRUPTED", "Command interrupted."}, 86 | 87 | // Invalid command 88 | {"INVALID_COMMAND", "Invalid command."}, 89 | 90 | // Not enough memory for operation 91 | {"MEMORY", "Not enough memory for operation."}, 92 | 93 | // Invalid command 94 | {"COMMAND_LENGTH", "Command too long."}, 95 | 96 | // Sequence full 97 | {"SEQUENCE_FULL", "Sequence is full."} 98 | 99 | }; 100 | 101 | int CommandRouter::init(command_item_t *commands, int buffer_size, 102 | char *serial_buffer, int argv_max, 103 | const char **argv_buffer) 104 | { 105 | this->buffer = serial_buffer; 106 | this->argv = argv_buffer; 107 | this->buffer_size = buffer_size; 108 | this->argv_max = argv_max; 109 | this->command_list = commands; 110 | this->malloc_used = false; 111 | return NO_ERROR; 112 | } 113 | 114 | int CommandRouter::route(int argc, const char **argv) { 115 | 116 | if (argc == 0) 117 | return NO_ERROR; 118 | 119 | for (int i = 0; command_list[i].name != nullptr; i++) 120 | if (strcmp(argv[0], command_list[i].name) == 0) 121 | return command_list[i].func(this, argc, argv); 122 | 123 | return ERROR_INVALID_COMMAND; 124 | } 125 | 126 | int CommandRouter::help(int argc, char **argv) { 127 | 128 | if (argc == 1) 129 | { 130 | Serial.print(F("-----------------------------------\n")); 131 | Serial.print(F("Command List:\n")); 132 | Serial.print(F("-----------------------------------\n")); 133 | for (int i = 0; command_list[i].name != nullptr; i++) 134 | { 135 | Serial.print(F("COMMAND: \n ")); 136 | Serial.print(command_list[i].name); 137 | Serial.print("\n"); 138 | Serial.print(F("SYNTAX:\n ")); 139 | Serial.print(command_list[i].syntax); 140 | Serial.print("\n"); 141 | Serial.print(F("DESCRIPTION:\n ")); 142 | Serial.print(command_list[i].description); 143 | Serial.print("\n"); 144 | Serial.print(F("-----------------------------------\n")); 145 | } 146 | return NO_ERROR; 147 | } 148 | else if (argc == 2) 149 | { 150 | for (int i = 0; command_list[i].name != nullptr; i++) 151 | { 152 | if (strcmp(argv[1], command_list[i].name) == 0) 153 | { 154 | Serial.print(F("COMMAND: \n ")); 155 | Serial.print(command_list[i].name); 156 | Serial.print("\n"); 157 | Serial.print(F("SYNTAX:\n ")); 158 | Serial.print(command_list[i].syntax); 159 | Serial.print("\n"); 160 | Serial.print(F("DESCRIPTION:\n ")); 161 | Serial.print(command_list[i].description); 162 | Serial.print("\n"); 163 | Serial.print(F("-----------------------------------\n")); 164 | } 165 | } 166 | return NO_ERROR; 167 | } 168 | 169 | return ERROR_INVALID_ARGUMENT; 170 | } 171 | 172 | 173 | int CommandRouter::process_serial_stream() { 174 | int argc; 175 | int bytes_read = 0; 176 | int bytes_read_max = buffer_size - 1 - 1; 177 | int result; 178 | 179 | // Set input buffer to second character in input buffer 180 | char *input_buffer = &this->buffer[1]; 181 | this->buffer[0] = '\0'; // Null terminate the return string 182 | 183 | // TODO: is this limit correct? 184 | while (bytes_read < bytes_read_max) 185 | { 186 | incoming = Serial.read(); 187 | 188 | // Newline 189 | if (incoming == '\n' || incoming == '\r') 190 | break; 191 | 192 | input_buffer[bytes_read] = (char)incoming; 193 | bytes_read++; 194 | } 195 | 196 | // Flush remaining parts of serial buffer 197 | if (bytes_read == bytes_read_max) 198 | { 199 | while (true) 200 | { 201 | incoming = Serial.read(); 202 | if (incoming == '\n' || incoming == '\r') 203 | break; 204 | } 205 | return ERROR_COMMAND_TOO_LONG; 206 | } 207 | 208 | if (bytes_read == 0) 209 | return NO_ERROR; 210 | 211 | // Set null terminating character 212 | input_buffer[bytes_read] = '\0'; 213 | 214 | // Tokenize strings 215 | argc = 0; 216 | argv[argc] = strtok(input_buffer, "."); 217 | while (argv[argc] != NULL) 218 | { 219 | delayMicroseconds(1); // For teensy 4.0 220 | argv[++argc] = strtok(NULL, "."); 221 | } 222 | 223 | // Call route command 224 | result = route(argc, argv); 225 | 226 | // Print the error message, if any 227 | if (result > 0) 228 | { 229 | if (result < ERROR_CODE_COUNT) 230 | Serial.printf("ERROR[%d]: %s\n", result, error_code_list[result][1]); 231 | else 232 | Serial.printf("ERROR[%d]: INVALID ERROR CODE %s", result, '\n'); 233 | } 234 | else 235 | Serial.printf("%s%s", COMMAND_END, SERIAL_LINE_ENDING); 236 | 237 | return result; 238 | } 239 | -------------------------------------------------------------------------------- /illuminate/ledarray.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef LEDARRAY_H 32 | #define LEDARRAY_H 33 | 34 | #include "illuminate.h" 35 | #include "ledarrayinterface.h" 36 | #include "ledsequence.h" 37 | #include "constants.h" 38 | #include 39 | 40 | class LedArray { 41 | public: 42 | 43 | // LED array control object 44 | LedArrayInterface * led_array_interface; 45 | 46 | // Device setup and demo 47 | int reset(uint16_t argc, char ** argv); // Reset the Array 48 | int run_demo(); // Run a demo which tests the functions below 49 | 50 | // Pattern commands 51 | int draw_led_list(uint16_t argc, char ** argv); 52 | int draw_dpc(uint16_t argc, char ** argv); 53 | int draw_brightfield(uint16_t argc, char ** argv);; 54 | int draw_half_annulus(uint16_t argc, char * *argv); 55 | int draw_color_darkfield(uint16_t argc, char * * argv); 56 | int draw_annulus(uint16_t argc, char * * argv); 57 | int draw_quadrant(uint16_t argc, char * *argv); 58 | int draw_darkfield(uint16_t argc, char * *argv); 59 | int draw_cdpc(uint16_t argc, char * *argv); 60 | int fill_array(); 61 | int clear(); 62 | int disco(); 63 | int water_drop(); 64 | int set_global_shutter_state(uint16_t argc, char ** argv); 65 | 66 | // Drawing primatives 67 | void draw_primative_quadrant(int quadrant_number, float start_na, float end_na, bool include_center); 68 | void draw_primative_circle(float start_na, float end_na); 69 | void draw_primative_half_circle(float angle_deg, float start_na, float end_na); 70 | void draw_primative_led_scan(uint16_t delay_ms, float start_na, float end_na, bool print_indicies); 71 | 72 | // Triggering 73 | int trigger_input_test(uint16_t channel); 74 | int trigger_setup(uint16_t argc, char ** argv); 75 | int send_trigger_pulse(int trigger_index, bool show_output); 76 | bool wait_for_trigger_state(int trigger_index, bool state); 77 | 78 | // Setting system parameters 79 | int set_na(uint16_t argc, char ** argv); 80 | int set_inner_na(uint16_t argc, char ** argv); 81 | int set_array_distance(uint16_t argc, char ** argv); 82 | int set_color(int16_t argc, char ** argv); 83 | int set_brightness(int16_t argc, char ** argv); 84 | int set_single_color(int16_t argc, char ** argv); 85 | void build_na_list(float boardDistance); 86 | int set_auto_clear(uint16_t argc, char ** argv); 87 | int set_max_current_enforcement(uint16_t argc, char ** argv); 88 | int set_max_current_limit(uint16_t argc, char ** argv); 89 | 90 | // Custom sequences 91 | int run_custom_sequence(uint16_t argc, char ** argv); 92 | int step_custom_sequence(uint16_t argc, char ** argv); 93 | int set_custom_sequence_value(uint16_t argc, char ** argv); 94 | int print_custom_sequence(uint16_t argc, char ** argv); 95 | int restart_custom_sequence(uint16_t argc, char ** argv); 96 | int set_custom_sequence_length(uint16_t argc, char ** argv); 97 | 98 | // Pre-defined sequences 99 | int run_sequence_dpc(uint16_t argc, char ** argv); 100 | int run_sequence_individual_leds(uint16_t argc, char ** argv); 101 | int run_sequence_individual_brightfield_leds(uint16_t argc, char ** argv); 102 | int run_sequence_individual_darkfield_leds(uint16_t argc, char ** argv); 103 | 104 | int print_part_number(uint16_t argc, char ** argv); 105 | int print_serial_number(uint16_t argc, char ** argv); 106 | 107 | int set_debug(uint16_t argc, char ** argv); 108 | 109 | // Printing system state and information 110 | int print_led_positions(uint16_t argc, char * *argv, bool print_na); 111 | int print_led_values(uint16_t argc, char * *argv); 112 | int print_about(uint16_t argc, char * *argv); 113 | int print_system_parameters(uint16_t argc, char * *argv); 114 | int print_version(uint16_t argc, char * *argv); 115 | 116 | // Internal functions 117 | void setup(); // Setup command 118 | void set_interface(LedArrayInterface * interface); 119 | void not_implemented(const char * command_name); 120 | int draw_channel(uint16_t argc, char * *argv); 121 | int set_pin_order(uint16_t argc, char * *argv); 122 | int scan_led_range(uint16_t delay_ms, float start_na, float end_na, bool print_indicies, uint16_t sequence_run_count); 123 | 124 | int print_mac_address(); 125 | int set_sclk_baud_rate(uint16_t argc, char ** argv); 126 | int set_gsclk_frequency(uint16_t argc, char ** argv); 127 | int set_command_mode(const char * mode); 128 | 129 | // Note that passing a -1 for led_number or color_channel_index sets all LEDs or all color channels respectively 130 | int set_led(int16_t led_number, int16_t color_channel_index, uint16_t value); // LED brightness (16-bit) 131 | int set_led(int16_t led_number, int16_t color_channel_index, uint8_t value); // LED brightness (8-bit) 132 | int set_led(int16_t led_number, int16_t color_channel_index, bool value); // LED brightness (boolean) 133 | 134 | // Device-specific commands 135 | uint8_t get_device_command_count(); 136 | const char * get_device_command_name_short(int device_command_index); 137 | const char * get_device_command_name_long(int device_command_index); 138 | int device_command(int device_command_index, uint16_t argc, char * *argv); 139 | 140 | // Demo mode 141 | int set_demo_mode(uint16_t argc, char ** argv); 142 | 143 | // Printing 144 | void print(const char * short_command, const char * long_command); 145 | void clear_output_buffers(); 146 | 147 | // Short and long responses 148 | char output_buffer_short[MAX_RESPONSE_LENGTH_SHORT]; 149 | char output_buffer_long[MAX_RESPONSE_LENGTH_LONG]; 150 | 151 | // Source voltage sensing 152 | int print_power_supply_plugged(uint16_t argc, char ** argv); 153 | int set_power_supply_sensing(uint16_t argc, char ** argv); 154 | int print_power_supply_voltage(uint16_t argc, char ** argv); 155 | 156 | // Trigger Configuration 157 | int set_trigger_input_mode(uint16_t argc, char ** argv); 158 | int set_trigger_output_mode(uint16_t argc, char ** argv); 159 | int set_trigger_input_timeout(uint16_t argc, char ** argv); 160 | int set_trigger_output_pulse_width(uint16_t argc, char ** argv); 161 | int set_trigger_output_delay(uint16_t argc, char ** argv); 162 | int set_trigger_input_polarity(uint16_t argc, char ** argv); 163 | int set_trigger_output_polarity(uint16_t argc, char ** argv); 164 | int get_trigger_input_pins(uint16_t argc, char ** argv); 165 | int get_trigger_output_pins(uint16_t argc, char ** argv); 166 | 167 | int set_cosine_factor(uint16_t argc, char ** argv); 168 | void calculate_max_na(); 169 | 170 | int8_t store_parameters(); 171 | int8_t recall_parameters(bool quiet); 172 | 173 | // Demo Mode 174 | int8_t set_demo_mode(int8_t mode); 175 | int8_t get_demo_mode(); 176 | 177 | int8_t set_autoload_on_reboot(uint16_t argc, char ** argv); 178 | 179 | uint16_t get_serial_number(); 180 | void set_serial_number(uint16_t serial_number); 181 | uint16_t get_part_number(); 182 | void set_part_number(uint16_t part_number); 183 | 184 | int8_t initialize_hardware(uint16_t argc, char ** argv); 185 | 186 | private: 187 | 188 | // DPC angles 189 | float dpc_pattern_angles[4] = {0.0, 180.0, 270.0, 90.0}; 190 | 191 | /* DPC Commands */ 192 | const char * DPC_RIGHT1 = "r"; 193 | const char * DPC_RIGHT2 = "right"; 194 | 195 | const char * DPC_LEFT1 = "l"; 196 | const char * DPC_LEFT2 = "left"; 197 | 198 | const char * DPC_TOP1 = "t"; 199 | const char * DPC_TOP2 = "top"; 200 | 201 | const char * DPC_BOTTOM1 = "b"; 202 | const char * DPC_BOTTOM2 = "bottom"; 203 | 204 | // Defualt brightness 205 | const uint8_t LED_VALUE_DEFAULT = 10; 206 | 207 | // LED sequence object for storage and retreival 208 | static LedSequence led_sequence; 209 | 210 | // LED Controller Parameters 211 | boolean auto_clear_flag = true; 212 | boolean initial_setup = true; 213 | int debug_level = 0; 214 | float objective_na = 0.25; 215 | float inner_na = 0.0; 216 | float led_array_distance_z = 60.0; 217 | int color_channel_count = 3; 218 | char * device_name; 219 | int8_t default_brightness = 63; 220 | uint8_t cosine_factor; 221 | bool normalize_color = true; 222 | bool global_shutter_state = true; 223 | uint32_t gsclk_frequency = 2000000; 224 | 225 | // Trigger Input (feedback) Settings 226 | static volatile float trigger_feedback_timeout_ms; 227 | static volatile uint32_t * trigger_output_pulse_width_list_us; 228 | static volatile uint32_t * trigger_output_start_delay_list_us; 229 | static volatile int * trigger_input_mode_list; 230 | static volatile int * trigger_output_mode_list; 231 | static volatile bool * trigger_input_polarity_list; 232 | static volatile bool * trigger_output_polarity_list; 233 | static volatile int trigger_input_count; 234 | static volatile int trigger_output_count; 235 | static volatile float trigger_input_timeout; 236 | static const int * trigger_output_pin_list; 237 | static const int * trigger_input_pin_list; 238 | const float INPUT_TRIGGER_WAIT_PERIOD_US = 1; 239 | 240 | // Default illumination 241 | uint8_t * led_value; // Current led values for each channel 242 | uint8_t * led_color; // 8-bit color balance 243 | uint8_t led_brightness; // 8-bit brightness 244 | 245 | // Sequence stepping index 246 | uint16_t sequence_number_displayed = 0; 247 | 248 | // timer variable 249 | static volatile uint16_t pattern_index; 250 | 251 | // Command mode 252 | bool command_mode = COMMAND_MODE_LONG; 253 | 254 | // These should be made persistant 255 | const float led_array_distance_z_default = 50.0; 256 | const float na_default = 0.25; 257 | const uint8_t led_brightness_default = 255; 258 | const float inner_na_default = 0.0; 259 | const uint8_t cosine_factor_default = 0.0; 260 | 261 | // Internal variable for maximum na of this array, at this geometry. 262 | float max_na; 263 | 264 | // Constants for clock frequencies 265 | const uint32_t SCLK_BAUD_RATE = 7000000; 266 | const uint32_t GSCLK_FREQUENCY = 6000000; 267 | 268 | 269 | }; 270 | 271 | #endif 272 | -------------------------------------------------------------------------------- /illuminate/illuminate.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #define LICENSE_TEXT \ 32 | "Copyright (c) 2024, Zachary Phillips\n" \ 33 | "Copyright (c) 2018, Zachary Phillips (UC Berkeley)\n" \ 34 | "All rights reserved.\n" \ 35 | "\n"\ 36 | "BSD 3-Clause License\n"\ 37 | "\n"\ 38 | "Redistribution and use in source and binary forms, with or without\n" \ 39 | "modification, are permitted provided that the following conditions are met:\n" \ 40 | " Redistributions of source code must retain the above copyright\n" \ 41 | " notice, this list of conditions and the following disclaimer.\n" \ 42 | " Redistributions in binary form must reproduce the above copyright\n" \ 43 | " notice, this list of conditions and the following disclaimer in the\n" \ 44 | " documentation and/or other materials provided with the distribution.\n" \ 45 | " Neither the name of the UC Berkeley nor the\n" \ 46 | " names of its contributors may be used to endorse or promote products\n" \ 47 | " derived from this software without specific prior written permission.\n" \ 48 | "\n"\ 49 | "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND\n" \ 50 | "ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n" \ 51 | "WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n" \ 52 | "DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY\n" \ 53 | "DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n" \ 54 | "(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n" \ 55 | "LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n" \ 56 | "ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" \ 57 | "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n" \ 58 | " SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" 59 | #define SERIAL_BAUD_RATE 115200 60 | 61 | // Include various files depending on which LED array is used 62 | #include "illuminate.h" 63 | #include "commandrouting.h" 64 | #include "commandconstants.h" 65 | #include "ledarray.h" 66 | #include "ledarrayinterface.h" 67 | 68 | // Command Router inputs 69 | #define BUFFER_SIZE 1024 * 16 70 | #define ARGV_MAX 300 71 | char serial_buffer[BUFFER_SIZE]; 72 | const char *argv_buffer[ARGV_MAX]; 73 | 74 | // Initialize objects 75 | LedArrayInterface led_array_interface; 76 | LedArray led_array; 77 | CommandRouter cmd; 78 | 79 | // This command runs once at power-on 80 | void setup() 81 | { 82 | // Initialize serial interface 83 | Serial.begin(SERIAL_BAUD_RATE); 84 | 85 | cmd.init(command_list, BUFFER_SIZE, serial_buffer, ARGV_MAX, 86 | argv_buffer); 87 | 88 | // Initialize LED Array 89 | led_array.set_interface(&led_array_interface); 90 | led_array.setup(); 91 | 92 | // Print the about screen when connected 93 | led_array.print_about(0, (char **) NULL); 94 | 95 | } 96 | 97 | // This command runs continuously after setup() runs once 98 | void loop() 99 | { 100 | // Loop until we recieve a command, then parse it. 101 | if (Serial.available()) 102 | cmd.process_serial_stream(); 103 | } 104 | 105 | int info_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_about(argc, (char * *) argv);} 106 | int reset_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.reset(argc, (char * *) argv);} 107 | int version_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_version(argc, (char * *) argv);} 108 | int license_func(CommandRouter *cmd, int argc, const char **argv) { Serial.print(LICENSE_TEXT); return NO_ERROR; } 109 | int demo_func(CommandRouter *cmd, int argc, const char **argv) { return led_array.set_demo_mode(argc, (char * *) argv); } 110 | int help_func(CommandRouter *cmd, int argc, const char **argv) { return cmd->help(argc, (char * *) argv);} 111 | int store_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.store_parameters();} 112 | int recall_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.recall_parameters(false);} 113 | int autoload_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_autoload_on_reboot(argc, (char * *) argv);} 114 | 115 | int autoclear_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_auto_clear(argc, (char * *) argv); } 116 | int na_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_na(argc, (char * *) argv); } 117 | int na_inner_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_inner_na(argc, (char * *) argv); } 118 | int color_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_color(argc, (char * *) argv); } 119 | int set_single_color_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_single_color(argc, (char * *) argv);}; 120 | int brightness_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_brightness(argc, (char * *) argv); } 121 | int array_distance_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_array_distance(argc, (char * *) argv); } 122 | int cosine_func(CommandRouter *cmd, int argc, const char **argv) { return led_array.set_cosine_factor(argc, (char * *) argv); } 123 | 124 | int set_led_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_led_list(argc, (char * *)argv); } 125 | 126 | int clear_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.clear(); } 127 | int fill_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.fill_array(); } 128 | int brightfield_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_brightfield(argc, (char * *) argv); } 129 | int darkfield_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_darkfield(argc, (char * *) argv); } 130 | int dpc_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_dpc(argc, (char * *) argv); } 131 | int cdpc_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_cdpc(argc, (char * *)argv); } 132 | int annulus_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_annulus(argc, (char * *)argv); } 133 | int half_annulus_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_half_annulus(argc, (char * *)argv); } 134 | int quadrant_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_quadrant(argc, (char * *) argv); } 135 | int color_darkfield_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_color_darkfield(argc, (char * *) argv); } 136 | 137 | int scan_full_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.run_sequence_individual_leds(argc, (char * *) argv); } 138 | int scan_brightfield_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.run_sequence_individual_brightfield_leds(argc, (char * *) argv); } 139 | int scan_darkfield_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.run_sequence_individual_darkfield_leds(argc, (char * *) argv); } 140 | 141 | int set_custom_sequence_length_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_custom_sequence_length(argc, (char * *) argv); } 142 | int set_custom_sequence_value_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_custom_sequence_value(argc, (char * *) argv); } 143 | int run_sequence_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.run_custom_sequence(argc, (char * *) argv); } 144 | int print_custom_sequence_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_custom_sequence(argc, (char * *) argv); } 145 | int step_sequence_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.step_custom_sequence(argc, (char * *) argv); } 146 | int restart_sequence_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.restart_custom_sequence(argc, (char * *) argv); } 147 | 148 | int trigger_func(CommandRouter *cmd, int argc, const char **argv) { if (argc == 1) return led_array.send_trigger_pulse(0, true); else if (argc == 2) return led_array.send_trigger_pulse(atoi(argv[1]), true); else return ERROR_ARGUMENT_COUNT;} 149 | int trigger_setup_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.trigger_setup(argc, (char * *) argv); } 150 | int trigger_test_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.trigger_input_test(strtoul((char *) argv[0], NULL, 0)); } 151 | int draw_channel_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.draw_channel(argc, (char * *) argv); } 152 | int debug_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_debug(argc, (char * *) argv); } 153 | int set_pin_order_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_pin_order(argc, (char * *) argv); } 154 | int wait_func(CommandRouter *cmd, int argc, const char **argv){ if (argc == 0) delay(1000); else delay(strtoul(argv[1], NULL, 0)); return NO_ERROR; } 155 | int set_max_current_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_max_current_limit(argc, (char * *) argv); } 156 | int set_max_current_enforcement_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_max_current_enforcement(argc, (char * *) argv); } 157 | 158 | int print_led_values_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_led_values(argc, (char * *) argv); } 159 | int print_led_positions_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_led_positions(argc, (char * *) argv, false); } 160 | int print_parameters_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_system_parameters(argc, (char * *) argv); } 161 | int print_led_positions_na(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_led_positions(argc, (char * *) argv, true); } 162 | 163 | int disco_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.disco(); } 164 | int water_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.water_drop(); } 165 | 166 | int get_pn_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_part_number(argc, (char * *) argv); } 167 | int get_sn_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_serial_number(argc, (char * *) argv); } 168 | 169 | int run_dpc_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.run_sequence_dpc(argc, (char * *) argv); } 170 | 171 | int set_baud_rate_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_sclk_baud_rate(argc, (char * *) argv); } 172 | int set_gsclk_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_gsclk_frequency(argc, (char * *) argv); } 173 | 174 | int set_human_mode_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_command_mode("human"); } 175 | int set_machine_mode_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_command_mode("machine"); } 176 | 177 | int power_sensing_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_power_supply_sensing(argc, (char * *) argv); } 178 | int power_source_voltage_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.print_power_supply_voltage(argc, (char * *) argv); } 179 | 180 | int trigger_input_mode_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_trigger_input_mode(argc, (char * *) argv); } 181 | int trigger_output_mode_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_trigger_output_mode(argc, (char * *) argv); } 182 | int trigger_input_timeout_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_trigger_input_timeout(argc, (char * *) argv); } 183 | int trigger_output_pulse_width_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_trigger_output_pulse_width(argc, (char * *) argv); } 184 | int trigger_input_polarity_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_trigger_input_polarity(argc, (char * *) argv); } 185 | int trigger_output_polarity_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_trigger_output_polarity(argc, (char * *) argv); } 186 | int trigger_output_delay_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_trigger_output_delay(argc, (char * *) argv); } 187 | int trigger_input_pin_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.get_trigger_input_pins(argc, (char * *) argv); } 188 | int trigger_output_pin_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.get_trigger_output_pins(argc, (char * *) argv); } 189 | int global_shutter_func(CommandRouter *cmd, int argc, const char **argv){ return led_array.set_global_shutter_state(argc, (char * *) argv); } 190 | 191 | int hw_initialize_function(CommandRouter *cmd, int argc, const char **argv){ return led_array.initialize_hardware(argc, (char * *) argv); } 192 | -------------------------------------------------------------------------------- /illuminate/commandconstants.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef COMMANDCONSTANTS_H 32 | #define COMMANDCONSTANTS_H 33 | 34 | #include "illuminate.h" 35 | 36 | int info_func(CommandRouter *cmd, int argc, const char **argv); 37 | int reset_func(CommandRouter *cmd, int argc, const char **argv); 38 | int version_func(CommandRouter *cmd, int argc, const char **argv); 39 | int license_func(CommandRouter *cmd, int argc, const char **argv); 40 | int demo_func(CommandRouter *cmd, int argc, const char **argv); 41 | int help_func(CommandRouter *cmd, int argc, const char **argv); 42 | int store_func(CommandRouter *cmd, int argc, const char **argv); 43 | int recall_func(CommandRouter *cmd, int argc, const char **argv); 44 | int autoload_func(CommandRouter *cmd, int argc, const char **argv); 45 | 46 | int autoclear_func(CommandRouter *cmd, int argc, const char **argv); 47 | int na_func(CommandRouter *cmd, int argc, const char **argv); 48 | int na_inner_func(CommandRouter *cmd, int argc, const char **argv); 49 | int color_func(CommandRouter *cmd, int argc, const char **argv); 50 | int brightness_func(CommandRouter *cmd, int argc, const char **argv); 51 | int array_distance_func(CommandRouter *cmd, int argc, const char **argv); 52 | 53 | int set_led_func(CommandRouter *cmd, int argc, const char **argv); 54 | 55 | int clear_func(CommandRouter *cmd, int argc, const char **argv); 56 | int fill_func(CommandRouter *cmd, int argc, const char **argv); 57 | int brightfield_func(CommandRouter *cmd, int argc, const char **argv); 58 | int darkfield_func(CommandRouter *cmd, int argc, const char **argv); 59 | int dpc_func(CommandRouter *cmd, int argc, const char **argv); 60 | int cdpc_func(CommandRouter *cmd, int argc, const char **argv); 61 | int annulus_func(CommandRouter *cmd, int argc, const char **argv); 62 | int half_annulus_func(CommandRouter *cmd, int argc, const char **argv); 63 | int quadrant_func(CommandRouter *cmd, int argc, const char **argv); 64 | int color_darkfield_func(CommandRouter *cmd, int argc, const char **argv); 65 | 66 | int scan_full_func(CommandRouter *cmd, int argc, const char **argv); 67 | int scan_brightfield_func(CommandRouter *cmd, int argc, const char **argv); 68 | int scan_darkfield_func(CommandRouter *cmd, int argc, const char **argv); 69 | 70 | int set_custom_sequence_length_func(CommandRouter *cmd, int argc, const char **argv); 71 | int set_custom_sequence_value_func(CommandRouter *cmd, int argc, const char **argv); 72 | int run_sequence_func(CommandRouter *cmd, int argc, const char **argv); 73 | int print_custom_sequence_func(CommandRouter *cmd, int argc, const char **argv); 74 | int step_sequence_func(CommandRouter *cmd, int argc, const char **argv); 75 | int restart_sequence_func(CommandRouter *cmd, int argc, const char **argv); 76 | 77 | int trigger_func(CommandRouter *cmd, int argc, const char **argv); 78 | int trigger_setup_func(CommandRouter *cmd, int argc, const char **argv); 79 | int trigger_test_func(CommandRouter *cmd, int argc, const char **argv); 80 | int draw_channel_func(CommandRouter *cmd, int argc, const char **argv); 81 | int debug_func(CommandRouter *cmd, int argc, const char **argv); 82 | int set_pin_order_func(CommandRouter *cmd, int argc, const char **argv); 83 | int wait_func(CommandRouter *cmd, int argc, const char **argv); 84 | int set_max_current_func(CommandRouter *cmd, int argc, const char **argv); 85 | int set_max_current_enforcement_func(CommandRouter *cmd, int argc, const char **argv); 86 | 87 | int print_led_values_func(CommandRouter *cmd, int argc, const char **argv); 88 | int print_led_positions_func(CommandRouter *cmd, int argc, const char **argv); 89 | int print_parameters_func(CommandRouter *cmd, int argc, const char **argv); 90 | int print_led_positions_na(CommandRouter *cmd, int argc, const char **argv); 91 | 92 | int disco_func(CommandRouter *cmd, int argc, const char **argv); 93 | int demo_func(CommandRouter *cmd, int argc, const char **argv); 94 | int water_func(CommandRouter *cmd, int argc, const char **argv); 95 | 96 | int get_sn_func(CommandRouter *cmd, int argc, const char **argv); 97 | int get_pn_func(CommandRouter *cmd, int argc, const char **argv); 98 | 99 | int run_dpc_func(CommandRouter *cmd, int argc, const char **argv); 100 | 101 | int set_baud_rate_func(CommandRouter *cmd, int argc, const char **argv); 102 | int set_gsclk_func(CommandRouter *cmd, int argc, const char **argv); 103 | 104 | int set_human_mode_func(CommandRouter *cmd, int argc, const char **argv); 105 | int set_machine_mode_func(CommandRouter *cmd, int argc, const char **argv); 106 | 107 | int power_sensing_func(CommandRouter *cmd, int argc, const char **argv); 108 | int power_source_voltage_func(CommandRouter *cmd, int argc, const char **argv); 109 | 110 | int trigger_input_mode_func(CommandRouter *cmd, int argc, const char **argv); 111 | int trigger_output_mode_func(CommandRouter *cmd, int argc, const char **argv); 112 | int trigger_input_timeout_func(CommandRouter *cmd, int argc, const char **argv); 113 | int trigger_output_pulse_width_func(CommandRouter *cmd, int argc, const char **argv); 114 | int trigger_input_polarity_func(CommandRouter *cmd, int argc, const char **argv); 115 | int trigger_output_polarity_func(CommandRouter *cmd, int argc, const char **argv); 116 | int trigger_output_delay_func(CommandRouter *cmd, int argc, const char **argv); 117 | int trigger_input_pin_func(CommandRouter *cmd, int argc, const char **argv); 118 | int trigger_output_pin_func(CommandRouter *cmd, int argc, const char **argv); 119 | 120 | int cosine_func(CommandRouter *cmd, int argc, const char **argv); 121 | int hw_initialize_function(CommandRouter *cmd, int argc, const char **argv); 122 | int set_single_color_func(CommandRouter *cmd, int argc, const char **argv); 123 | int global_shutter_func(CommandRouter *cmd, int argc, const char **argv); 124 | 125 | // Syntax is: {short command, long command, description, syntax} 126 | command_item_t command_list[] = { 127 | 128 | // High-level Commands 129 | {"about", "Displays information about this device", "about", info_func}, 130 | {"reset", "Runs setup routine again, for resetting LED array", "reboot", reset_func}, 131 | {"version", "Display controller version number", "version", version_func}, 132 | {"license", "Display software license for firmware residing on this teensy", "license", license_func}, 133 | {"?", "Display human-readable help information.", "license", help_func}, 134 | {"store", "Store device parameters", "store", store_func}, 135 | {"recall", "Recall stored device parameters", "recall", recall_func}, 136 | {"autoload", "Toggle/set whether previously stored settings are loaded on power-up. Value is persistant.", "autoload [or] autoload.1", autoload_func}, 137 | 138 | // System Parameters 139 | {"ac", "Toggle clearing of array between led updates. Calling without options toggles the state.", "ac --or-- ac.[0/1]", autoclear_func}, 140 | {"na", "Set na used for bf/df/dpc/cdpc patterns", "na.[na*100]", na_func}, 141 | {"nai", "Sets the inner NA. (nai.20 sets an inner NA of 0.20) Respected by bf, dpc, and rdpc commands. Default is 0", "nai.20", na_inner_func}, 142 | {"sc", "Set LED array color balance (RGB arrays only). Note values are normalized to current brightness (set by the `sb` command)", "sc.[`red` or `green` or `blue` or `white`] --or-- sc.[red_value].[green_value].[blue_value].", color_func}, 143 | {"ssc", "Set single color channel by index", "ssc.[channel index].[color]", set_single_color_func}, 144 | {"sb", "Set LED array brightness", "sb.[rgbVal] --or-- sb.[rVal].[gVal].[bVal]", brightness_func}, 145 | {"sad", "Set LED array distance", "sad.[dist (mm)]", array_distance_func}, 146 | 147 | // Single (or multiple) LED Display 148 | {"l", "Turn on a single LED (or multiple LEDs in a list)", "l.[led #].[led #], ...", set_led_func}, 149 | 150 | // General Display 151 | {"x", "Clear the LED array.", "x", clear_func}, 152 | {"gs", "Set the global shutter state to open (1) or closed (0), maintaining all other settings", "gs.0 --or-- gs.1", global_shutter_func}, 153 | {"ff", "Fill the LED array with default color.", "ff", fill_func}, 154 | {"bf", "Display brightfield pattern", "bf", brightfield_func}, 155 | {"df", "Display darkfield pattern", "df", darkfield_func}, 156 | {"dpc", "Illuminate half-circle (DPC) pattern", "dpc.[t/b/l/r] --or-- dpc.[top/bottom/left/right] --or-- dpc (will raw first pattern)", dpc_func}, 157 | {"cdpc", "Illuminate color DPC (cDPC) pattern", "cdpc.[rVal].[gVal].[bVal]) --or-- cdpc.[rgbVal]) --or-- cdpc", cdpc_func}, 158 | {"an", "Display annulus pattern set by min/max na", "an.[minNA*100].[maxNA*100]", annulus_func}, 159 | {"ha", "Illuminate half annulus", "ha.[type].[minNA*100].[maxNA*100]", half_annulus_func}, 160 | {"dq", "Draws single quadrant", "dq --or-- dq.[quadrant index]", quadrant_func}, 161 | {"cdf", "Draws color darkfield pattern", "cdf.[rVal].[gVal].[bVal]) --or-- cdf.[rgbVal]) --or-- cdf", color_darkfield_func}, 162 | 163 | // Single LED Scanning 164 | {"scf", "Scan all active LEDs. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print.", "scf.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence]", scan_full_func}, 165 | {"scb", "Scan all brightfield LEDs. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print.", "scb.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence]", scan_brightfield_func}, 166 | {"scd", "Scan all darkfield LEDs. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print.", "scd.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence]", scan_darkfield_func}, 167 | 168 | // Custom Sequence Scanning 169 | {"ssl", "Set sequence length, or the number of patterns to be cycles through (not the number of leds per pattern).", "ssl.[Sequence length]", set_custom_sequence_length_func}, 170 | {"ssv", "Set sequence value", "ssl.[# Number of LEDs], [LED number 0], [LED number 1]], [LED number 2], ...", set_custom_sequence_value_func}, 171 | {"rseq", "Runs sequence with specified delay between each update. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print.", "rseq.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence]", run_sequence_func}, 172 | {"pseq", "Prints sequence values to the terminal", "pseq", print_custom_sequence_func}, 173 | {"sseq", "Manually step through a sequence, incrementing the current index. May emit or wait for trigger signals depending on trigger settings.", "sseq", step_sequence_func}, 174 | {"xseq", "Resets sequence index to the first value, leaving the sequence unchanged.", "xseq", restart_sequence_func}, 175 | 176 | // Pre-defined sequences 177 | {"rdpc", "Runs a DPC sequence with specified delay between each update. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print.", "rdpc.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence]", run_dpc_func}, 178 | 179 | // Debugging, Low-level Access, etc. 180 | {"tr", "Output TTL trigger pulse to camera", "tr.[trigger index]", trigger_func}, 181 | {"trs", "Set up hardware (TTL) triggering for a single channel", "trs.[trigger index].[trigger input mode].[trigger output mode].[trigger pulse width, microseconds].['trigger delay between H and L pulses, microseconds]", trigger_setup_func}, 182 | {"trt", "Waits for trigger pulses on the defined channel", "trt.[trigger input index]", trigger_test_func}, 183 | {"ch", "Draw LED by hardware channel (use for debugging)", "dc.[led#]", draw_channel_func}, 184 | {"debug", "Toggle debug flag. Can call with or without options.", "dbg.[command router debug].[LED array (generic) debug].[LED interface debug] --or-- dbg (toggles all between level 1 or 0)", debug_func}, 185 | {"spo", "Sets pin order (R/G/B) for setup purposes. Also can flip individual leds by passing fourth argument.", "spo.[rChan].[gChan].[bChan] --or-- spo.[led#].[rChan].[gChan].[bChan]", set_pin_order_func}, 186 | {"delay", "Simply puts the device in a loop for the amount of time in ms", "delay.[length of time in ms]", wait_func}, 187 | {"mc", "Sets/Gets max current in amps", "mc.[current limit in amps]", set_max_current_func}, 188 | {"mce", "Sets/Gets whether or not max current limit is enforced (0 is no, all other values are yes)", "mce.[0, 1]", set_max_current_enforcement_func}, 189 | 190 | // Quering System State 191 | {"pvals", "Print led values for software interface", "pvals", print_led_values_func}, 192 | {"pledpos", "Prints the positions of each LED in cartesian coordinates.", "pledpos", print_led_positions_func}, 193 | {"pprops", "Prints system parameters such as NA, LED Array z-distance, etc. in the format of a json file", "pprops", print_parameters_func}, 194 | {"pledposna", "Prints the positions of each LED in NA coordinates (NA_x, NA_y, NA_distance", "pledposna", print_led_positions_na}, 195 | 196 | // Stored Patterns 197 | {"disco", "Illuminate a random color pattern of LEDs", "disco.[Number of LEDs in pattern]", disco_func}, 198 | {"demo", "Runs a demo routine to show what the array can do.", "demo", demo_func}, 199 | {"water", "Water drop demo", "water", water_func}, 200 | 201 | // Set part and serial number in EEPROM 202 | {"sn", "Gets device serial number", "sn", get_sn_func}, 203 | {"pn", "Gets device part number", "pn", get_pn_func}, 204 | 205 | // Functions to set baud rate and gsclk frequency (for TLC5955 based boards) 206 | {"sbr", "Sets SPI baud rate for TLC5955 Chips in Hz (baud)", "sbr.1000000", set_baud_rate_func}, 207 | {"sgs", "Sets GSCLK frequency in Hz", "sgs.1000000", set_gsclk_func}, 208 | 209 | {"human", "Sets command mode to human-readable", "human", set_human_mode_func}, 210 | {"machine", "Sets command mode to machine-readable", "machine", set_machine_mode_func}, 211 | 212 | {"pwrs", "Toggle power source sensing on or off.", "pwrs", power_sensing_func}, 213 | {"pwrv", "Print power source voltage.", "pwrv", power_source_voltage_func}, 214 | 215 | {"trinputmode", "Sets the trigger input mode for the given trigger index. This can be -2 for one trigger at the start of a sequence, -1 for one trigger at the start of each repeat in the sequence, 0 for off, or a positive integer N to emit every N patterns (e.g. 1 would emit every pattern). Default is 0.", "trinputmode.0.1", trigger_input_mode_func}, 216 | {"troutputmode", "Sets the trigger input mode for the given trigger index. This can be -2 for one trigger at the start of a sequence, -1 for one trigger at the start of each repeat in the sequence, 0 for off, or a positive integer N to emit every N patterns (e.g. 1 would emit every pattern). Default is 0.", "troutputmode.0.1", trigger_output_mode_func}, 217 | {"trinputtimeout", "Sets the trigger input timeout in seconds. Default is 60 (60s).", "trinputtimeout.10", trigger_input_timeout_func}, 218 | {"troutputpulsewidth", "Sets the trigger pulse width in microseconds, default is 1000.", "troutputpulsewidth.1000", trigger_output_pulse_width_func}, 219 | {"trinputpolarity", "Sets the trigger input polarity. 1=active high, 0=active low. Default is 1.", "trinputpolarity.1", trigger_input_polarity_func}, 220 | {"troutputpolarity", "Sets the trigger output polarity. 1=active high, 0=active low. Default is 1.", "troutputpolarity.1", trigger_output_polarity_func}, 221 | {"troutputdelay", "Sets the trigger delay in microseconds. Default is zero.", "troutputdelay.0", trigger_output_delay_func}, 222 | {"trinputpin", "Returns the Teensy pin of the trigger input signal. Used only for debugging.", "trinputpin", trigger_input_pin_func}, 223 | {"troutputpin", "Returns the Teensy pin of the trigger output signal. Used only for debugging.", "troutputpin", trigger_output_pin_func}, 224 | 225 | {"cos", "Returns or sets the cosine factor, used to scale LED intensity (so outer LEDs are brighter). Input is cos.[integer cosine factor]", "cos.2", cosine_func}, 226 | 227 | {"hwinit", "Manufacturer hardware initialization. Modifies persistant settings - do not use unless you know what you're doing.", "hwinit.[sn].[pn]", hw_initialize_function}, 228 | 229 | {nullptr, nullptr, nullptr, nullptr} 230 | }; 231 | 232 | #endif 233 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![logo](doc/logo.png) 2 | # Illuminate - Open-source LED array controller firmware 3 | Illuminate was designed to standardize the interface and functionality of LED array illuminators for optical microscopy. 4 | 5 | ## Install (Cross-platform) 6 | 1. Install [Arduino](https://www.arduino.cc/) software 7 | 2. Install [Teensyduino](https://www.pjrc.com/teensy/td_download.html) software (If using a teensy micro-controller) 8 | 3. If needed, install git. See [This Tutorial](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) 9 | 4. Check out the illuminate repostory: 10 | ```bash 11 | git clone https://github.com/zfphil/illuminate.git 12 | ``` 13 | 5. Check out the TLC5955 submodule (LED driver chips used for our devices) 14 | ```bash 15 | cd illuminate 16 | git submodule init 17 | git submodule update 18 | ``` 19 | 6. open illuminate.ino in Arduino software 20 | 7. Ensure correct device is selected in the `illuminate.h` file by uncommenting the appropriate `#define USE_*` line. Ensure only one of these lines is uncommented. 21 | 8. Select micro-controller from Tools -> Board, select port from Tools -> Port. If a port says "Teensy", this is usually the correct port to use. 22 | 9. Open Serial Monitor (Tools -> Serial Monitor), set line ending to Newline and baud rate to 115200 (default) 23 | 10. Press upload to load code onto Teensy. You may need to press the white button on the top of the micro-controller to trigger the upload. 24 | 11. Type command (ex: "bf") and press enter to send 25 | 26 | ## Interfaces 27 | All commands are sent over a serial (COM) port using a default baud rate of `115200`, and otherwise default settings. There are several ways to control these LED Arrays: 28 | - The Serial Monitor within the [Arduino IDE](https://www.arduino.cc/en/software) 29 | - The [Micro-Manager](https://micro-manager.org/Micro-Manager_Nightly_Builds) IlluminateLedArray Driver (nightly builds since 2019) 30 | - MATLAB and python via modules within the [The Illuminate Controller Repository](http://www.github.com/sci-microscopy/illuminate_controller) 31 | - Any standard serial library within other languages (C++, java, etc.) 32 | 33 | ## Commands 34 | Command help can be accessed by typing "?" into the Arduino terminal. These are also copied at the end of this file (see below) for convenience. 35 | Static patterns may be 36 | 37 | #### Triggering and Sequences 38 | While patterns may be executed statically using commands such as `bf` (brightfield), `df` (darkfield), or `dpc.t` (DPC Top), this firmware provides a sequencing interface which enables hardware-limited pattern updates as well as triggering support. 39 | Illuminate supports several pre-defined pattern sequences: 40 | - `scf`: Scan all LEDs, one at a time 41 | - `scb`: Scan all brightfield LEDs (within the na set by the `na` command) 42 | - `scd`: Scan all darkfield LEDs (within the na set by the `na` command) 43 | - `rdpc`: Scan four half-circle "DPC" patterns (within the na set by the `na` command) 44 | 45 | For all patterns, a delay betweenn pattern updates may be set using the first argument (e.g. `scf.500` will provide 500ms delay. Multiple pattern cycles may be kicked off using the second argument (e.g. `scf.0.2` will cycle through two patterns as fast as possible). 46 | Custom pattern sequences are also supported. See the `ssl`, `ssv`, `pseq`, and `rseq` commands below for more information. 47 | 48 | To enable triggering using SMA ports on the side of devices, The `tim` (trigger input mode) and `tom` (trigger output mode) commands can be used. 49 | The first argument is the trigger number (`0` or `1`), and the second argument is the mode: 50 | - `-2`: One pulse at the start of the first pattern cycle. Even if multiple pattern cycles are provided (second argument above), only one trigger pulse is sent. 51 | - `-1`: One pulxe at the start of each pattern sequence 52 | - `0`: This sequence will not wait for or emit any trigger signals 53 | - `1`: Emit or wait for one trigger pulse per pattern update. 54 | - `2`, `3`, `4`, ... `N`: Emit or wait for one trigger pulse per every `N` pattern updates. 55 | 56 | Trigger inputs and outputs use the same mode strings. Note that trigger inputs will wait up to the timeout set in `trinputtimeout` before erroring (30s is the default). 57 | Trigger polarity, pulse width, and short delays may be set via the api described below. 58 | 59 | Sending any serial command will halt a sequence (and discard that command, which will need to be re-sent to take effect). 60 | 61 | ## Devices 62 | This project is designed for led arrays which are controlled by a Teensy 3.2, Teensy 4.0, or Teensy 4.1 micro-controller. Additional micro-controllers should be easy to support if pins are configured correctly. 63 | 64 | #### Currently supported devices 65 | - Quasi-Dome Illuminator (Waller Lab, UC Berkeley) 66 | - Direct LED connection array (Waller Lab, UC Berkeley) 67 | - sci.round ([SCI Microscopy](https://sci-microscopy.com)) 68 | - sci.dome ([SCI Microscopy](https://sci-microscopy.com)) 69 | - Various custom devices by [SCI Microscopy](https://sci-microscopy.com) 70 | 71 | #### Adding New Devices 72 | New devices are created by adding a new .cpp file to the root directory of the project and providing functions for the LedArrayInterface class. Static variables within this class must also be defined in the cpp file (including LED positions, trigger ports, etc.). 73 | 74 | ## Contributions 75 | Pull requests will be reviewed as received, and are encouraged! 76 | 77 | ## API Reference 78 | ``` 79 | ----------------------------------- 80 | Command List: 81 | ----------------------------------- 82 | COMMAND: 83 | about 84 | SYNTAX: 85 | about 86 | DESCRIPTION: 87 | Displays information about this device 88 | ----------------------------------- 89 | COMMAND: 90 | reset 91 | SYNTAX: 92 | reboot 93 | DESCRIPTION: 94 | Runs setup routine again, for resetting LED array 95 | ----------------------------------- 96 | COMMAND: 97 | version 98 | SYNTAX: 99 | version 100 | DESCRIPTION: 101 | Display controller version number 102 | ----------------------------------- 103 | COMMAND: 104 | license 105 | SYNTAX: 106 | license 107 | DESCRIPTION: 108 | Display software license for firmware residing on this teensy 109 | ----------------------------------- 110 | COMMAND: 111 | ? 112 | SYNTAX: 113 | license 114 | DESCRIPTION: 115 | Display human-readable help information. 116 | ----------------------------------- 117 | COMMAND: 118 | store 119 | SYNTAX: 120 | store 121 | DESCRIPTION: 122 | Store device parameters 123 | ----------------------------------- 124 | COMMAND: 125 | recall 126 | SYNTAX: 127 | recall 128 | DESCRIPTION: 129 | Recall stored device parameters 130 | ----------------------------------- 131 | COMMAND: 132 | autoload 133 | SYNTAX: 134 | autoload [or] autoload.1 135 | DESCRIPTION: 136 | Toggle/set whether previously stored settings are loaded on power-up. Value is persistant. 137 | ----------------------------------- 138 | COMMAND: 139 | ac 140 | SYNTAX: 141 | ac --or-- ac.[0/1] 142 | DESCRIPTION: 143 | Toggle clearing of array between led updates. Calling without options toggles the state. 144 | ----------------------------------- 145 | COMMAND: 146 | na 147 | SYNTAX: 148 | na.[na*100] 149 | DESCRIPTION: 150 | Set na used for bf/df/dpc/cdpc patterns 151 | ----------------------------------- 152 | COMMAND: 153 | nai 154 | SYNTAX: 155 | nai.20 156 | DESCRIPTION: 157 | Sets the inner NA. (nai.20 sets an inner NA of 0.20) Respected by bf, dpc, and rdpc commands. Default is 0 158 | ----------------------------------- 159 | COMMAND: 160 | sc 161 | SYNTAX: 162 | sc.[`red` or `green` or `blue` or `white`] --or-- sc.[red_value].[green_value].[blue_value]. 163 | DESCRIPTION: 164 | Set LED array color balance (RGB arrays only). Note values are normalized to current brightness (set by the `sb` command) 165 | ----------------------------------- 166 | COMMAND: 167 | ssc 168 | SYNTAX: 169 | ssc.[channel index].[color] 170 | DESCRIPTION: 171 | Set single color channel by index 172 | ----------------------------------- 173 | COMMAND: 174 | sb 175 | SYNTAX: 176 | sb.[rgbVal] --or-- sb.[rVal].[gVal].[bVal] 177 | DESCRIPTION: 178 | Set LED array brightness 179 | ----------------------------------- 180 | COMMAND: 181 | sad 182 | SYNTAX: 183 | sad.[dist (mm)] 184 | DESCRIPTION: 185 | Set LED array distance 186 | ----------------------------------- 187 | COMMAND: 188 | l 189 | SYNTAX: 190 | l.[led #].[led #], ... 191 | DESCRIPTION: 192 | Turn on a single LED (or multiple LEDs in a list) 193 | ----------------------------------- 194 | COMMAND: 195 | x 196 | SYNTAX: 197 | x 198 | DESCRIPTION: 199 | Clear the LED array. 200 | ----------------------------------- 201 | COMMAND: 202 | gs 203 | SYNTAX: 204 | gs.0 --or-- gs.1 205 | DESCRIPTION: 206 | Set the global shutter state to open (1) or closed (0), maintaining all other settings 207 | ----------------------------------- 208 | COMMAND: 209 | ff 210 | SYNTAX: 211 | ff 212 | DESCRIPTION: 213 | Fill the LED array with default color. 214 | ----------------------------------- 215 | COMMAND: 216 | bf 217 | SYNTAX: 218 | bf 219 | DESCRIPTION: 220 | Display brightfield pattern 221 | ----------------------------------- 222 | COMMAND: 223 | df 224 | SYNTAX: 225 | df 226 | DESCRIPTION: 227 | Display darkfield pattern 228 | ----------------------------------- 229 | COMMAND: 230 | dpc 231 | SYNTAX: 232 | dpc.[t/b/l/r] --or-- dpc.[top/bottom/left/right] --or-- dpc (will raw first pattern) 233 | DESCRIPTION: 234 | Illuminate half-circle (DPC) pattern 235 | ----------------------------------- 236 | COMMAND: 237 | cdpc 238 | SYNTAX: 239 | cdpc.[rVal].[gVal].[bVal]) --or-- cdpc.[rgbVal]) --or-- cdpc 240 | DESCRIPTION: 241 | Illuminate color DPC (cDPC) pattern 242 | ----------------------------------- 243 | COMMAND: 244 | an 245 | SYNTAX: 246 | an.[minNA*100].[maxNA*100] 247 | DESCRIPTION: 248 | Display annulus pattern set by min/max na 249 | ----------------------------------- 250 | COMMAND: 251 | ha 252 | SYNTAX: 253 | ha.[type].[minNA*100].[maxNA*100] 254 | DESCRIPTION: 255 | Illuminate half annulus 256 | ----------------------------------- 257 | COMMAND: 258 | dq 259 | SYNTAX: 260 | dq --or-- dq.[quadrant index] 261 | DESCRIPTION: 262 | Draws single quadrant 263 | ----------------------------------- 264 | COMMAND: 265 | cdf 266 | SYNTAX: 267 | cdf.[rVal].[gVal].[bVal]) --or-- cdf.[rgbVal]) --or-- cdf 268 | DESCRIPTION: 269 | Draws color darkfield pattern 270 | ----------------------------------- 271 | COMMAND: 272 | scf 273 | SYNTAX: 274 | scf.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence] 275 | DESCRIPTION: 276 | Scan all active LEDs. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print. 277 | ----------------------------------- 278 | COMMAND: 279 | scb 280 | SYNTAX: 281 | scb.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence] 282 | DESCRIPTION: 283 | Scan all brightfield LEDs. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print. 284 | ----------------------------------- 285 | COMMAND: 286 | scd 287 | SYNTAX: 288 | scb.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence] 289 | DESCRIPTION: 290 | Scan all darkfield LEDs. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print. 291 | ----------------------------------- 292 | COMMAND: 293 | ssl 294 | SYNTAX: 295 | ssl.[Sequence length] 296 | DESCRIPTION: 297 | Set sequence length, or the number of patterns to be cycles through (not the number of leds per pattern). 298 | ----------------------------------- 299 | COMMAND: 300 | ssv 301 | SYNTAX: 302 | ssl.[# Number of LEDs], [LED number 0], [LED number 1]], [LED number 2], ... 303 | DESCRIPTION: 304 | Set sequence value 305 | ----------------------------------- 306 | COMMAND: 307 | rseq 308 | SYNTAX: 309 | rseq.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence] 310 | DESCRIPTION: 311 | Runs sequence with specified delay between each update. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print. 312 | ----------------------------------- 313 | COMMAND: 314 | pseq 315 | SYNTAX: 316 | pseq 317 | DESCRIPTION: 318 | Prints sequence values to the terminal 319 | ----------------------------------- 320 | COMMAND: 321 | sseq 322 | SYNTAX: 323 | sseq 324 | DESCRIPTION: 325 | Manually step through a sequence, incrementing the current index. May emit or wait for trigger signals depending on trigger settings. 326 | ----------------------------------- 327 | COMMAND: 328 | xseq 329 | SYNTAX: 330 | xseq 331 | DESCRIPTION: 332 | Resets sequence index to the first value, leaving the sequence unchanged. 333 | ----------------------------------- 334 | COMMAND: 335 | rdpc 336 | SYNTAX: 337 | rdpc.[(Optional - default=0) Delay between each pattern in ms].[(Optional - default=1) Number of times to execute sequence] 338 | DESCRIPTION: 339 | Runs a DPC sequence with specified delay between each update. May emit or wait for trigger signals depending on trigger settings. If update speed is too fast, a warning message will print. 340 | ----------------------------------- 341 | COMMAND: 342 | tr 343 | SYNTAX: 344 | tr.[trigger index] 345 | DESCRIPTION: 346 | Output TTL trigger pulse to camera 347 | ----------------------------------- 348 | COMMAND: 349 | trs 350 | SYNTAX: 351 | trs.[trigger index].[trigger input mode].[trigger output mode].[trigger pulse width].['trigger delay between H and L pulses] 352 | DESCRIPTION: 353 | Set up hardware (TTL) triggering for a single channel 354 | ----------------------------------- 355 | COMMAND: 356 | trt 357 | SYNTAX: 358 | trt.[trigger input index] 359 | DESCRIPTION: 360 | Waits for trigger pulses on the defined channel 361 | ----------------------------------- 362 | COMMAND: 363 | ch 364 | SYNTAX: 365 | dc.[led#] 366 | DESCRIPTION: 367 | Draw LED by hardware channel (use for debugging) 368 | ----------------------------------- 369 | COMMAND: 370 | debug 371 | SYNTAX: 372 | dbg.[command router debug].[LED array (generic) debug].[LED interface debug] --or-- dbg (toggles all between level 1 or 0) 373 | DESCRIPTION: 374 | Toggle debug flag. Can call with or without options. 375 | ----------------------------------- 376 | COMMAND: 377 | spo 378 | SYNTAX: 379 | spo.[rChan].[gChan].[bChan] --or-- spo.[led#].[rChan].[gChan].[bChan] 380 | DESCRIPTION: 381 | Sets pin order (R/G/B) for setup purposes. Also can flip individual leds by passing fourth argument. 382 | ----------------------------------- 383 | COMMAND: 384 | delay 385 | SYNTAX: 386 | delay.[length of time in ms] 387 | DESCRIPTION: 388 | Simply puts the device in a loop for the amount of time in ms 389 | ----------------------------------- 390 | COMMAND: 391 | mc 392 | SYNTAX: 393 | mc.[current limit in amps] 394 | DESCRIPTION: 395 | Sets/Gets max current in amps 396 | ----------------------------------- 397 | COMMAND: 398 | mce 399 | SYNTAX: 400 | mce.[0, 1] 401 | DESCRIPTION: 402 | Sets/Gets whether or not max current limit is enforced (0 is no, all other values are yes) 403 | ----------------------------------- 404 | COMMAND: 405 | pvals 406 | SYNTAX: 407 | pvals 408 | DESCRIPTION: 409 | Print led values for software interface 410 | ----------------------------------- 411 | COMMAND: 412 | pledpos 413 | SYNTAX: 414 | pledpos 415 | DESCRIPTION: 416 | Prints the positions of each LED in cartesian coordinates. 417 | ----------------------------------- 418 | COMMAND: 419 | pprops 420 | SYNTAX: 421 | pprops 422 | DESCRIPTION: 423 | Prints system parameters such as NA, LED Array z-distance, etc. in the format of a json file 424 | ----------------------------------- 425 | COMMAND: 426 | pledposna 427 | SYNTAX: 428 | pledposna 429 | DESCRIPTION: 430 | Prints the positions of each LED in NA coordinates (NA_x, NA_y, NA_distance 431 | ----------------------------------- 432 | COMMAND: 433 | disco 434 | SYNTAX: 435 | disco.[Number of LEDs in pattern] 436 | DESCRIPTION: 437 | Illuminate a random color pattern of LEDs 438 | ----------------------------------- 439 | COMMAND: 440 | demo 441 | SYNTAX: 442 | demo 443 | DESCRIPTION: 444 | Runs a demo routine to show what the array can do. 445 | ----------------------------------- 446 | COMMAND: 447 | water 448 | SYNTAX: 449 | water 450 | DESCRIPTION: 451 | Water drop demo 452 | ----------------------------------- 453 | COMMAND: 454 | sn 455 | SYNTAX: 456 | sn 457 | DESCRIPTION: 458 | Gets device serial number 459 | ----------------------------------- 460 | COMMAND: 461 | pn 462 | SYNTAX: 463 | pn 464 | DESCRIPTION: 465 | Gets device part number 466 | ----------------------------------- 467 | COMMAND: 468 | sbr 469 | SYNTAX: 470 | sbr.1000000 471 | DESCRIPTION: 472 | Sets SPI baud rate for TLC5955 Chips in Hz (baud) 473 | ----------------------------------- 474 | COMMAND: 475 | sgs 476 | SYNTAX: 477 | sgs.1000000 478 | DESCRIPTION: 479 | Sets GSCLK frequency in Hz 480 | ----------------------------------- 481 | COMMAND: 482 | human 483 | SYNTAX: 484 | human 485 | DESCRIPTION: 486 | Sets command mode to human-readable 487 | ----------------------------------- 488 | COMMAND: 489 | machine 490 | SYNTAX: 491 | machine 492 | DESCRIPTION: 493 | Sets command mode to machine-readable 494 | ----------------------------------- 495 | COMMAND: 496 | pwrs 497 | SYNTAX: 498 | pwrs 499 | DESCRIPTION: 500 | Toggle power source sensing on or off. 501 | ----------------------------------- 502 | COMMAND: 503 | pwrv 504 | SYNTAX: 505 | pwrv 506 | DESCRIPTION: 507 | Print power source voltage. 508 | ----------------------------------- 509 | COMMAND: 510 | trinputmode 511 | SYNTAX: 512 | trinputmode.0.1 513 | DESCRIPTION: 514 | Sets the trigger input mode for the given trigger index. This can be -2 for one trigger at the start of a sequence, -1 for one trigger at the start of each repeat in the sequence, 0 for off, or a positive integer N to emit every N patterns (e.g. 1 would emit every pattern). Default is 0. 515 | ----------------------------------- 516 | COMMAND: 517 | troutputmode 518 | SYNTAX: 519 | troutputmode.0.1 520 | DESCRIPTION: 521 | Sets the trigger input mode for the given trigger index. This can be -2 for one trigger at the start of a sequence, -1 for one trigger at the start of each repeat in the sequence, 0 for off, or a positive integer N to emit every N patterns (e.g. 1 would emit every pattern). Default is 0. 522 | ----------------------------------- 523 | COMMAND: 524 | trinputtimeout 525 | SYNTAX: 526 | trinputtimeout.10 527 | DESCRIPTION: 528 | Sets the trigger input timeout in seconds. Default is 60 (60s). 529 | ----------------------------------- 530 | COMMAND: 531 | trinputtimeout 532 | SYNTAX: 533 | trinputtimeout.10 534 | DESCRIPTION: 535 | Sets the trigger input timeout in seconds. Default is 60 (60s). 536 | ----------------------------------- 537 | COMMAND: 538 | troutputpulsewidth 539 | SYNTAX: 540 | troutputpulsewidth.1000 541 | DESCRIPTION: 542 | Sets the trigger pulse width in microseconds, default is 1000. 543 | ----------------------------------- 544 | COMMAND: 545 | trinputpolarity 546 | SYNTAX: 547 | trinputpolarity.1 548 | DESCRIPTION: 549 | Sets the trigger input polarity. 1=active high, 0=active low. Default is 1. 550 | ----------------------------------- 551 | COMMAND: 552 | troutputpolarity 553 | SYNTAX: 554 | troutputpolarity.1 555 | DESCRIPTION: 556 | Sets the trigger output polarity. 1=active high, 0=active low. Default is 1. 557 | ----------------------------------- 558 | COMMAND: 559 | troutputdelay 560 | SYNTAX: 561 | troutputdelay.0 562 | DESCRIPTION: 563 | Sets the trigger delay in microseconds. Default is zero. 564 | ----------------------------------- 565 | COMMAND: 566 | trinputpin 567 | SYNTAX: 568 | trinputpin 569 | DESCRIPTION: 570 | Returns the Teensy pin of the trigger input signal. Used only for debugging. 571 | ----------------------------------- 572 | COMMAND: 573 | troutputpin 574 | SYNTAX: 575 | troutputpin 576 | DESCRIPTION: 577 | Returns the Teensy pin of the trigger output signal. Used only for debugging. 578 | ----------------------------------- 579 | COMMAND: 580 | cos 581 | SYNTAX: 582 | cos.2 583 | DESCRIPTION: 584 | Returns or sets the cosine factor, used to scale LED intensity (so outer LEDs are brighter). Input is cos.[integer cosine factor] 585 | ----------------------------------- 586 | COMMAND: 587 | hwinit 588 | SYNTAX: 589 | hwinit.[sn].[pn] 590 | DESCRIPTION: 591 | Manufacturer hardware initialization. Modifies persistant settings - do not use unless you know what you're doing. 592 | ----------------------------------- 593 | ``` 594 | -------------------------------------------------------------------------------- /illuminate/src/ledarrays/sci.asym.r0.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | // Define which LED Array is used 32 | #include "../../illuminate.h" 33 | 34 | #ifdef USE_SCI_ASYM_ARRAY 35 | #include "../../ledarrayinterface.h" 36 | #include "../TLC5955/TLC5955.h" 37 | 38 | // Global shutter state 39 | bool global_shutter_state = true; 40 | 41 | // Pin definitions (used internally) 42 | const int GSCLK = 6; 43 | const int LAT = 3; 44 | const int SPI_MOSI = 11; 45 | const int SPI_CLK = 13; 46 | const int TRIGGER_OUTPUT_PIN_0 = 22; 47 | const int TRIGGER_INPUT_PIN_0 = 23; 48 | const int TRIGGER_OUTPUT_PIN_1 = 19; 49 | const int TRIGGER_INPUT_PIN_1 = 18; 50 | const int TRIGGER_OUTPUT_COUNT = 2; 51 | const int TRIGGER_INPUT_COUNT = 2; 52 | 53 | // EEPROM Addresses 54 | #define DEMO_MODE_ADDRESS 50 55 | #define PN_ADDRESS 100 56 | #define SN_ADDRESS 200 57 | 58 | // Device and Software Descriptors 59 | const char * LedArrayInterface::device_name = "sci.asym"; 60 | const char * LedArrayInterface::device_hardware_revision = "1.0"; 61 | const int16_t LedArrayInterface::led_count = 48; 62 | const uint16_t LedArrayInterface::center_led = 0; 63 | const int LedArrayInterface::trigger_output_count = 2; 64 | const int LedArrayInterface::trigger_input_count = 2; 65 | const int LedArrayInterface::color_channel_count = 3; 66 | const char LedArrayInterface::color_channel_names[] = {'r', 'g', 'b'}; 67 | const float LedArrayInterface::color_channel_center_wavelengths_nm[] = {480.0, 525.0, 625.0}; 68 | const float LedArrayInterface::color_channel_fwhm_wavelengths_nm[] = {20.0, 20.0, 20.0}; 69 | const int LedArrayInterface::bit_depth = 16; 70 | const bool LedArrayInterface::supports_fast_sequence = false; 71 | const float LedArrayInterface::led_array_distance_z_default = 50.0; 72 | int LedArrayInterface::debug = 0; 73 | const int LedArrayInterface::trigger_output_pin_list[] = {TRIGGER_OUTPUT_PIN_0, TRIGGER_OUTPUT_PIN_1}; 74 | const int LedArrayInterface::trigger_input_pin_list[] = {TRIGGER_INPUT_PIN_0, TRIGGER_INPUT_PIN_1}; 75 | bool LedArrayInterface::trigger_input_state[] = {false, false}; 76 | float LedArrayInterface::led_position_list_na[LedArrayInterface::led_count][2]; 77 | 78 | const uint8_t TLC5955::chip_count = 100; // Change to reflect number of TLC chips 79 | float TLC5955::max_current_amps = 10.0; // Maximum current output, amps 80 | bool TLC5955::enforce_max_current = true; // Whether to enforce max current limit 81 | 82 | // Define dot correction, pin rgb order, and grayscale data arrays in program memory 83 | uint8_t TLC5955::_dc_data[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 84 | uint8_t TLC5955::_rgb_order[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 85 | uint16_t TLC5955::_grayscale_data[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 86 | 87 | /**** Device-specific variables ****/ 88 | TLC5955 tlc; // TLC5955 object 89 | 90 | /**** Device-specific commands ****/ 91 | const uint8_t LedArrayInterface::device_command_count = 1; 92 | const char * LedArrayInterface::device_commandNamesShort[] = {"c"}; 93 | const char * LedArrayInterface::device_commandNamesLong[] = {"center"}; 94 | const uint16_t LedArrayInterface::device_command_pattern_dimensions[][2] = {{1,5}}; // Number of commands, number of LEDs in each command. 95 | 96 | PROGMEM const int16_t center_led_list[1][3] = { 97 | {0, 1, 2} 98 | }; 99 | 100 | // Define LED positions in cartesian coordinates (LED#, channel, x * 100mm, y * 100mm, z * 100mm) 101 | PROGMEM const int16_t LedArrayInterface::led_positions[48][5] = { 102 | {0, 7, -381, -225, 6000}, 103 | {1, 30, 381, -225, 6000}, 104 | {2, 37, 0, 450, 6000}, 105 | {3, 9, -573, -557, 6000}, 106 | {4, 8, -769, -217, 6000}, 107 | {5, 36, -196, 775, 6000}, 108 | {6, 38, 196, 775, 6000}, 109 | {7, 27, 769, -217, 6000}, 110 | {8, 17, 573, -557, 6000}, 111 | {9, 14, -775, -1043, 6000}, 112 | {10, 13, -1291, -150, 6000}, 113 | {11, 22, 1125, -650, 6000}, 114 | {12, 44, -515, 1193, 6000}, 115 | {13, 35, 0, 1300, 6000}, 116 | {14, 39, 515, 1193, 6000}, 117 | {15, 20, 1291, -150, 6000}, 118 | {16, 18, 775, -1043, 6000}, 119 | {17, 15, -1125, -650, 6000}, 120 | {18, 10, -1026, -1478, 6000}, 121 | {19, 3, -1410, -1118, 6000}, 122 | {20, 12, -1673, -662, 6000}, 123 | {21, 6, -1793, -150, 6000}, 124 | {22, 32, -766, 1628, 6000}, 125 | {23, 33, -263, 1780, 6000}, 126 | {24, 34, 263, 1780, 6000}, 127 | {25, 45, 766, 1628, 6000}, 128 | {26, 21, 1793, -150, 6000}, 129 | {27, 16, 1673, -662, 6000}, 130 | {28, 29, 1410, -1118, 6000}, 131 | {29, 19, 1026, -1478, 6000}, 132 | {30, 5, -1277, -1912, 6000}, 133 | {31, 11, -1604, -1647, 6000}, 134 | {32, 2, -1878, -1327, 6000}, 135 | {33, 4, -2088, -962, 6000}, 136 | {34, 1, -2229, -565, 6000}, 137 | {35, 0, -2295, -150, 6000}, 138 | {36, 46, -1017, 2062, 6000}, 139 | {37, 40, -624, 2213, 6000}, 140 | {38, 41, -210, 2290, 6000}, 141 | {39, 42, 210, 2290, 6000}, 142 | {40, 47, 624, 2213, 6000}, 143 | {41, 43, 1017, 2062, 6000}, 144 | {42, 28, 2295, -150, 6000}, 145 | {43, 31, 2229, -565, 6000}, 146 | {44, 25, 2088, -962, 6000}, 147 | {45, 24, 1878, -1327, 6000}, 148 | {46, 23, 1604, -1647, 6000}, 149 | {47, 26, 1277, -1912, 6000} 150 | }; 151 | bool LedArrayInterface::get_max_current_enforcement() 152 | { 153 | return TLC5955::enforce_max_current; 154 | } 155 | 156 | float LedArrayInterface::get_max_current_limit() 157 | { 158 | return TLC5955::max_current_amps; 159 | } 160 | 161 | void LedArrayInterface::set_max_current_enforcement(bool enforce) 162 | { 163 | TLC5955::enforce_max_current = enforce; 164 | } 165 | 166 | void LedArrayInterface::set_max_current_limit(float limit) 167 | { 168 | if (limit > 0) 169 | TLC5955::max_current_amps = limit; 170 | } 171 | 172 | void LedArrayInterface::set_pin_order(int16_t led_number, int16_t color_channel_index, uint8_t position) 173 | { 174 | tlc.set_pin_order_single(led_number, color_channel_index, position); 175 | } 176 | 177 | void LedArrayInterface::not_implemented(const char * command_name) 178 | { 179 | Serial.print(F("Command ")); 180 | Serial.print(command_name); 181 | Serial.printf(F(" is not implemented for this device.%s"), SERIAL_LINE_ENDING); 182 | } 183 | 184 | uint16_t LedArrayInterface::get_led_value(uint16_t led_number, int color_channel_index) 185 | { 186 | int16_t channel_number = (int16_t)pgm_read_word(&(led_positions[led_number][1])); 187 | if (channel_number >= 0) 188 | return tlc.get_single_channel(channel_number); 189 | else 190 | { 191 | Serial.print(F("ERROR (LedArrayInterface::get_led_value) - invalid LED number (")); 192 | Serial.print(led_number); 193 | Serial.printf(F(")%s"), SERIAL_LINE_ENDING); 194 | return 0; 195 | } 196 | } 197 | 198 | // Debug Variables 199 | bool LedArrayInterface::get_debug() 200 | { 201 | return (LedArrayInterface::debug); 202 | } 203 | 204 | void LedArrayInterface::set_debug(int state) 205 | { 206 | LedArrayInterface::debug = state; 207 | Serial.printf(F("(LedArrayInterface::set_debug): Set debug level to %d \n"), debug); 208 | } 209 | 210 | int LedArrayInterface::send_trigger_pulse(int trigger_index, uint16_t delay_us, bool inverse_polarity) 211 | { 212 | // Get trigger pin 213 | int trigger_pin = trigger_output_pin_list[trigger_index]; 214 | 215 | if (trigger_pin > 0) 216 | { 217 | // Write active state 218 | if (inverse_polarity) 219 | digitalWriteFast(trigger_pin, LOW); 220 | else 221 | digitalWriteFast(trigger_pin, HIGH); 222 | 223 | // Delay if desired 224 | if (delay_us > 0) 225 | delayMicroseconds(delay_us); 226 | 227 | // Write normal state 228 | if (inverse_polarity) 229 | digitalWriteFast(trigger_pin, HIGH); 230 | else 231 | digitalWriteFast(trigger_pin, LOW); 232 | return (1); 233 | } else { 234 | return (-1); 235 | } 236 | } 237 | 238 | void LedArrayInterface::set_global_shutter_state(bool state) 239 | { 240 | if (debug >= 1) 241 | { 242 | Serial.print("Setting Global Shutter state to "); 243 | Serial.print(state); 244 | Serial.print(SERIAL_LINE_ENDING); 245 | } 246 | 247 | // Store current state 248 | global_shutter_state = state; 249 | 250 | // Call the internal update method 251 | update(); 252 | } 253 | 254 | bool LedArrayInterface::get_global_shutter_state() 255 | { 256 | if (debug >= 1) 257 | { 258 | Serial.print("Getting Global Shutter state: "); 259 | Serial.print(global_shutter_state); 260 | Serial.print(SERIAL_LINE_ENDING); 261 | } 262 | 263 | return global_shutter_state; 264 | } 265 | 266 | 267 | void LedArrayInterface::update() 268 | { 269 | if (global_shutter_state) 270 | tlc.update(); 271 | else 272 | tlc.clear_without_modifying_pattern(); 273 | } 274 | 275 | void LedArrayInterface::clear() 276 | { 277 | tlc.set_all(0); 278 | update(); 279 | } 280 | 281 | 282 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, uint16_t value) 283 | { 284 | if (debug >= 2) 285 | { 286 | Serial.print(F("Drawing channel #")); 287 | Serial.print(channel_number); 288 | Serial.print(F(", color_channel #")); 289 | Serial.print(color_channel_number); 290 | Serial.print(F(" to value ")); 291 | Serial.print(value); 292 | Serial.print(SERIAL_LINE_ENDING); 293 | } 294 | 295 | if (channel_number >= 0) 296 | { 297 | if (color_channel_number < 0) 298 | tlc.set_single(channel_number, value); 299 | else 300 | tlc.set_single_rgb(channel_number, color_channel_number, value); 301 | } 302 | else 303 | { 304 | Serial.print(F("Error (LedArrayInterface::set_channel): Invalid channel (")); 305 | Serial.print(channel_number); 306 | Serial.printf(F(")%s"), SERIAL_LINE_ENDING); 307 | } 308 | } 309 | 310 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, uint8_t value) 311 | { 312 | set_channel(channel_number, color_channel_number, (uint16_t) (value * UINT16_MAX / UINT8_MAX)); 313 | } 314 | 315 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, bool value) 316 | { 317 | set_channel(channel_number, color_channel_number, (uint16_t) (value > 0 * UINT16_MAX)); 318 | } 319 | 320 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, uint16_t value) 321 | { 322 | if (debug >= 2) 323 | { 324 | Serial.print("U16 Setting led #"); 325 | Serial.print(led_number); 326 | Serial.print(", color channel #"); 327 | Serial.print(color_channel_number); 328 | Serial.print(" to value "); 329 | Serial.print(value); 330 | Serial.print(SERIAL_LINE_ENDING); 331 | } 332 | if (led_number < 0) 333 | { 334 | for (uint16_t led_index = 0; led_index < led_count; led_index++) 335 | { 336 | int16_t channel_number = (int16_t)pgm_read_word(&(led_positions[led_index][1])); 337 | set_channel(channel_number, color_channel_number, value); 338 | } 339 | } 340 | else 341 | { 342 | int16_t channel_number = (int16_t)pgm_read_word(&(led_positions[led_number][1])); 343 | set_channel(channel_number, color_channel_number, value); 344 | } 345 | } 346 | 347 | 348 | 349 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, uint8_t value) 350 | { 351 | if (debug >= 2) 352 | { 353 | Serial.print("U8 Setting led #"); 354 | Serial.print(led_number); 355 | Serial.print(", color channel #"); 356 | Serial.print(color_channel_number); 357 | Serial.print(SERIAL_LINE_ENDING); 358 | } 359 | set_led(led_number, color_channel_number, (uint16_t) (value * UINT16_MAX / UINT8_MAX)); 360 | } 361 | 362 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, bool value) 363 | { 364 | if (debug >= 2) 365 | { 366 | Serial.print("B Setting led #"); 367 | Serial.print(led_number); 368 | Serial.print(", color channel #"); 369 | Serial.print(color_channel_number); 370 | Serial.print(SERIAL_LINE_ENDING); 371 | } 372 | set_led(led_number, color_channel_number, (uint16_t) (value * UINT16_MAX)); 373 | } 374 | 375 | int8_t LedArrayInterface::device_reset() 376 | { 377 | return device_setup(); 378 | } 379 | 380 | int8_t LedArrayInterface::device_setup() 381 | { 382 | // Initialize TLC5955 383 | tlc.init(LAT, SPI_MOSI, SPI_CLK, GSCLK); 384 | 385 | // We must set dot correction values, so set them all to the brightest adjustment 386 | tlc.set_all_dc_data(127); 387 | 388 | // Set Max Current Values (see TLC5955 datasheet) 389 | tlc.set_max_current(3, 3, 3); // Go up to 7 390 | 391 | // Set Function Control Data Latch values. See the TLC5955 Datasheet for the purpose of this latch. 392 | // DSPRPT, TMGRST, RFRESH, ESPWM, LSDVLT 393 | tlc.set_function_data(true, true, true, true, true); 394 | 395 | // Set all LED current levels to max (127) 396 | int currentR = 127; 397 | int currentB = 127; 398 | int currentG = 127; 399 | tlc.set_brightness_current(currentR, currentB, currentG); 400 | 401 | // Update vontrol register 402 | tlc.update_control(); 403 | clear(); 404 | tlc.update_control(); 405 | 406 | // Set RGB pin order 407 | tlc.set_rgb_pin_order(0, 1, 2); 408 | 409 | // Update the GS register 410 | clear(); 411 | 412 | // Output trigger Pins 413 | for (int trigger_index = 0; trigger_index < trigger_output_count; trigger_index++) 414 | { 415 | pinMode(trigger_output_pin_list[trigger_index], OUTPUT); 416 | digitalWriteFast(trigger_output_pin_list[trigger_index], LOW); 417 | } 418 | 419 | // Input trigger pins 420 | attachInterrupt(digitalPinToInterrupt(trigger_input_pin_list[0]), trigger_pin_interrupt_0, CHANGE); 421 | attachInterrupt(digitalPinToInterrupt(trigger_input_pin_list[1]), trigger_pin_interrupt_1, CHANGE); 422 | 423 | return NO_ERROR; 424 | } 425 | 426 | void LedArrayInterface::trigger_pin_interrupt_0() 427 | { 428 | bool previous_state = trigger_input_state[0]; 429 | trigger_input_state[0] = digitalReadFast(trigger_input_pin_list[0]); 430 | bool new_state = trigger_input_state[0]; 431 | if (debug >= 2) 432 | Serial.printf("Recieved trigger pulse on pin 0. Previous state: %s New state: %s%s", previous_state ? "HIGH" : "LOW", new_state ? "HIGH" : "LOW", SERIAL_LINE_ENDING); 433 | } 434 | 435 | void LedArrayInterface::trigger_pin_interrupt_1() 436 | { 437 | bool previous_state = trigger_input_state[1]; 438 | trigger_input_state[1] = digitalReadFast(trigger_input_pin_list[1]); 439 | bool new_state = trigger_input_state[1]; 440 | if (debug >= 2) 441 | Serial.printf("Recieved trigger pulse on pin 1. Previous state: %s New state: %s%s", previous_state ? "HIGH" : "LOW", new_state ? "HIGH" : "LOW", SERIAL_LINE_ENDING); 442 | } 443 | 444 | void LedArrayInterface::source_change_interrupt() 445 | { 446 | Serial.printf(F("ERROR (LedArrayInterface::source_change_interrupt): PSU Monitoring not supported on this device."), SERIAL_LINE_ENDING); 447 | } 448 | 449 | float LedArrayInterface::get_power_source_voltage() 450 | { 451 | return -1.0; 452 | } 453 | 454 | bool LedArrayInterface::get_power_source_monitoring_state() 455 | { 456 | return false; 457 | } 458 | 459 | int16_t LedArrayInterface::get_device_power_sensing_capability() 460 | { 461 | return NO_PSU_SENSING; 462 | } 463 | 464 | void LedArrayInterface::set_power_source_monitoring_state(int new_state) 465 | { 466 | Serial.printf(F("ERROR (LedArrayInterface::set_power_source_monitoring_state): PSU Monitoring not supported on this device."), SERIAL_LINE_ENDING); 467 | } 468 | 469 | bool LedArrayInterface::is_power_source_plugged_in() 470 | { 471 | return true; 472 | } 473 | 474 | uint8_t LedArrayInterface::get_device_command_count() 475 | { 476 | return (LedArrayInterface::device_command_count); 477 | } 478 | 479 | const char * LedArrayInterface::get_device_command_name_short(int device_command_index) 480 | { 481 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 482 | return (LedArrayInterface::device_commandNamesShort[device_command_index]); 483 | else 484 | { 485 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 486 | return (""); 487 | } 488 | } 489 | 490 | const char * LedArrayInterface::get_device_command_name_long(int device_command_index) 491 | { 492 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 493 | return (LedArrayInterface::device_commandNamesLong[device_command_index]); 494 | else 495 | { 496 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 497 | return (""); 498 | } 499 | } 500 | 501 | uint32_t LedArrayInterface::get_device_command_led_list_size(int device_command_index) 502 | { 503 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 504 | { 505 | // Get stored pattern cound and led per pattern for this command 506 | uint16_t pattern_count = LedArrayInterface::device_command_pattern_dimensions[device_command_index][0]; 507 | uint16_t leds_per_pattern = LedArrayInterface::device_command_pattern_dimensions[device_command_index][1]; 508 | 509 | // Concatenate these two into 32-bit unsigned integer 510 | uint32_t concatenated = ((uint32_t)pattern_count) << 16 | leds_per_pattern; 511 | return (concatenated); 512 | } 513 | else 514 | { 515 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 516 | return (0); 517 | } 518 | } 519 | 520 | uint16_t LedArrayInterface::get_device_command_led_list_element(int device_command_index, uint16_t pattern_index, uint16_t led_index) 521 | { 522 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 523 | { 524 | uint32_t concatenated = get_device_command_led_list_size(device_command_index); 525 | uint16_t pattern_count = (uint16_t)(concatenated >> 16); 526 | uint16_t leds_per_pattern = (uint16_t)concatenated; 527 | 528 | if ((pattern_index < pattern_count) && (led_index < leds_per_pattern)) 529 | { 530 | if (device_command_index == 0) 531 | return (uint16_t)pgm_read_word(&(center_led_list[pattern_index][led_index])); 532 | else 533 | return 0; 534 | 535 | } 536 | else 537 | { 538 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid pattern index (%d) / led index (%d)"), pattern_index, led_index, SERIAL_LINE_ENDING); 539 | return (0); 540 | } 541 | } 542 | else 543 | { 544 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 545 | return (0); 546 | } 547 | } 548 | 549 | void LedArrayInterface::set_gsclk_frequency(uint32_t gsclk_frequency) 550 | { 551 | tlc.set_gsclk_frequency(gsclk_frequency); 552 | } 553 | 554 | uint32_t LedArrayInterface::get_gsclk_frequency() 555 | { 556 | return tlc.get_gsclk_frequency(); 557 | } 558 | 559 | void LedArrayInterface::set_sclk_baud_rate(uint32_t new_baud_rate) 560 | { 561 | tlc.set_sclk_frequency(new_baud_rate); 562 | } 563 | 564 | uint32_t LedArrayInterface::get_sclk_baud_rate() 565 | { 566 | return tlc.get_sclk_frequency(); 567 | } 568 | 569 | int8_t LedArrayInterface::set_register(uint32_t address, int8_t value) 570 | { 571 | EEPROM.write(address, value); 572 | return NO_ERROR; 573 | } 574 | 575 | int8_t LedArrayInterface::get_register(uint32_t address) 576 | { 577 | return EEPROM.read(address); 578 | } 579 | 580 | 581 | #endif 582 | -------------------------------------------------------------------------------- /illuminate/.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 4, 3 | "configurations": [ 4 | { 5 | "name": "Arduino", 6 | "compilerPath": "C:\\Users\\zackphillips\\AppData\\Local\\Arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1\\arm\\bin\\arm-none-eabi-g++", 7 | "compilerArgs": [ 8 | "-Wall", 9 | "-ffunction-sections", 10 | "-fdata-sections", 11 | "-nostdlib" 12 | ], 13 | "intelliSenseMode": "gcc-x64", 14 | "includePath": [ 15 | "C:\\Users\\zackphillips\\AppData\\Local\\Temp\\arduino\\sketches\\A21A2ABF02FCF657E9DC63408D971FB8\\pch", 16 | "C:\\Users\\zackphillips\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.59.0\\cores\\teensy4", 17 | "C:\\Users\\zackphillips\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.59.0\\libraries\\EEPROM", 18 | "C:\\Users\\zackphillips\\AppData\\Local\\Arduino15\\packages\\teensy\\hardware\\avr\\1.59.0\\libraries\\SPI", 19 | "c:\\users\\zackphillips\\appdata\\local\\arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1\\arm\\arm-none-eabi\\include\\c++\\11.3.1", 20 | "c:\\users\\zackphillips\\appdata\\local\\arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1\\arm\\arm-none-eabi\\include\\c++\\11.3.1\\arm-none-eabi", 21 | "c:\\users\\zackphillips\\appdata\\local\\arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1\\arm\\arm-none-eabi\\include\\c++\\11.3.1\\backward", 22 | "c:\\users\\zackphillips\\appdata\\local\\arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1\\arm\\lib\\gcc\\arm-none-eabi\\11.3.1\\include", 23 | "c:\\users\\zackphillips\\appdata\\local\\arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1\\arm\\lib\\gcc\\arm-none-eabi\\11.3.1\\include-fixed", 24 | "c:\\users\\zackphillips\\appdata\\local\\arduino15\\packages\\teensy\\tools\\teensy-compile\\11.3.1\\arm\\arm-none-eabi\\include" 25 | ], 26 | "forcedInclude": [ 27 | "C:\\Users\\zackphillips\\AppData\\Local\\Temp\\arduino\\sketches\\A21A2ABF02FCF657E9DC63408D971FB8\\pch\\Arduino.h" 28 | ], 29 | "cStandard": "c11", 30 | "cppStandard": "c++17", 31 | "defines": [ 32 | "__IMXRT1062__", 33 | "TEENSYDUINO=159", 34 | "ARDUINO=10607", 35 | "ARDUINO_TEENSY40", 36 | "F_CPU=600000000", 37 | "USB_SERIAL", 38 | "LAYOUT_US_ENGLISH", 39 | "__DBL_MIN_EXP__=(-1021)", 40 | "__HQ_FBIT__=15", 41 | "__cpp_attributes=200809L", 42 | "__cpp_nontype_template_parameter_auto=201606L", 43 | "__UINT_LEAST16_MAX__=0xffff", 44 | "__ARM_SIZEOF_WCHAR_T=4", 45 | "__ATOMIC_ACQUIRE=2", 46 | "__SFRACT_IBIT__=0", 47 | "__FLT_MIN__=1.1754943508222875e-38F", 48 | "__GCC_IEC_559_COMPLEX=0", 49 | "__cpp_aggregate_nsdmi=201304L", 50 | "__UFRACT_MAX__=0XFFFFP-16UR", 51 | "__UINT_LEAST8_TYPE__=unsigned char", 52 | "__DQ_FBIT__=63", 53 | "__INTMAX_C(c)=c ## LL", 54 | "__ULFRACT_FBIT__=32", 55 | "__CHAR_BIT__=8", 56 | "__USQ_IBIT__=0", 57 | "__UINT8_MAX__=0xff", 58 | "__ACCUM_FBIT__=15", 59 | "__WINT_MAX__=0xffffffffU", 60 | "__FLT32_MIN_EXP__=(-125)", 61 | "__cpp_static_assert=201411L", 62 | "__USFRACT_FBIT__=8", 63 | "__ORDER_LITTLE_ENDIAN__=1234", 64 | "__SIZE_MAX__=0xffffffffU", 65 | "__ARM_ARCH_ISA_ARM=1", 66 | "__WCHAR_MAX__=0xffffffffU", 67 | "__LACCUM_IBIT__=32", 68 | "__DBL_DENORM_MIN__=double(4.9406564584124654e-324L)", 69 | "__GCC_ATOMIC_CHAR_LOCK_FREE=1", 70 | "__GCC_IEC_559=0", 71 | "__FLT32X_DECIMAL_DIG__=17", 72 | "__FLT_EVAL_METHOD__=0", 73 | "__TQ_IBIT__=0", 74 | "__cpp_binary_literals=201304L", 75 | "__LLACCUM_MAX__=0X7FFFFFFFFFFFFFFFP-31LLK", 76 | "__FLT64_DECIMAL_DIG__=17", 77 | "__cpp_noexcept_function_type=201510L", 78 | "__GCC_ATOMIC_CHAR32_T_LOCK_FREE=1", 79 | "__cpp_variadic_templates=200704L", 80 | "__UINT_FAST64_MAX__=0xffffffffffffffffULL", 81 | "__SIG_ATOMIC_TYPE__=int", 82 | "__DBL_MIN_10_EXP__=(-307)", 83 | "__FINITE_MATH_ONLY__=0", 84 | "__ARMEL__=1", 85 | "__cpp_variable_templates=201304L", 86 | "__FLT32X_MAX_EXP__=1024", 87 | "__LFRACT_IBIT__=0", 88 | "__GNUC_PATCHLEVEL__=1", 89 | "__FLT32_HAS_DENORM__=1", 90 | "__LFRACT_MAX__=0X7FFFFFFFP-31LR", 91 | "__USA_FBIT__=16", 92 | "__UINT_FAST8_MAX__=0xffffffffU", 93 | "__cpp_rvalue_reference=200610L", 94 | "__cpp_nested_namespace_definitions=201411L", 95 | "__ARM_ARCH_4T__=1", 96 | "__INT8_C(c)=c", 97 | "__INT_LEAST8_WIDTH__=8", 98 | "__cpp_variadic_using=201611L", 99 | "__UINT_LEAST64_MAX__=0xffffffffffffffffULL", 100 | "__INT_LEAST8_MAX__=0x7f", 101 | "__SA_FBIT__=15", 102 | "__cpp_capture_star_this=201603L", 103 | "__SHRT_MAX__=0x7fff", 104 | "__LDBL_MAX__=1.7976931348623157e+308L", 105 | "__FRACT_MAX__=0X7FFFP-15R", 106 | "__cpp_if_constexpr=201606L", 107 | "__LDBL_IS_IEC_60559__=2", 108 | "__UFRACT_FBIT__=16", 109 | "__UFRACT_MIN__=0.0UR", 110 | "__UINT_LEAST8_MAX__=0xff", 111 | "__GCC_ATOMIC_BOOL_LOCK_FREE=1", 112 | "__UINTMAX_TYPE__=long long unsigned int", 113 | "__LLFRACT_EPSILON__=0x1P-63LLR", 114 | "__FLT_EVAL_METHOD_TS_18661_3__=0", 115 | "__CHAR_UNSIGNED__=1", 116 | "__UINT32_MAX__=0xffffffffUL", 117 | "__GXX_EXPERIMENTAL_CXX0X__=1", 118 | "__ULFRACT_MAX__=0XFFFFFFFFP-32ULR", 119 | "__TA_IBIT__=64", 120 | "__LDBL_MAX_EXP__=1024", 121 | "__WINT_MIN__=0U", 122 | "__FLT32X_IS_IEC_60559__=2", 123 | "__INT_LEAST16_WIDTH__=16", 124 | "__ULLFRACT_MIN__=0.0ULLR", 125 | "__SCHAR_MAX__=0x7f", 126 | "__WCHAR_MIN__=0U", 127 | "__INT64_C(c)=c ## LL", 128 | "__GCC_ATOMIC_POINTER_LOCK_FREE=1", 129 | "__LLACCUM_MIN__=(-0X1P31LLK-0X1P31LLK)", 130 | "__SIZEOF_INT__=4", 131 | "__FLT32X_MANT_DIG__=53", 132 | "__GCC_ATOMIC_CHAR16_T_LOCK_FREE=1", 133 | "__USACCUM_IBIT__=8", 134 | "__cpp_aligned_new=201606L", 135 | "__USER_LABEL_PREFIX__", 136 | "__FLT32_MAX_10_EXP__=38", 137 | "__STDC_HOSTED__=1", 138 | "__LFRACT_MIN__=(-0.5LR-0.5LR)", 139 | "__HA_IBIT__=8", 140 | "__cpp_decltype_auto=201304L", 141 | "__DBL_DIG__=15", 142 | "__FLT32_DIG__=6", 143 | "__FLT_EPSILON__=1.1920928955078125e-7F", 144 | "__APCS_32__=1", 145 | "__GXX_WEAK__=1", 146 | "__SHRT_WIDTH__=16", 147 | "__FLT32_IS_IEC_60559__=2", 148 | "__USFRACT_IBIT__=0", 149 | "__LDBL_MIN__=2.2250738585072014e-308L", 150 | "__DBL_IS_IEC_60559__=2", 151 | "__FRACT_MIN__=(-0.5R-0.5R)", 152 | "__cpp_threadsafe_static_init=200806L", 153 | "__DA_IBIT__=32", 154 | "__ARM_SIZEOF_MINIMAL_ENUM=1", 155 | "__FLT32X_HAS_INFINITY__=1", 156 | "__INT32_MAX__=0x7fffffffL", 157 | "__UQQ_FBIT__=8", 158 | "__INT_WIDTH__=32", 159 | "__SIZEOF_LONG__=4", 160 | "__UACCUM_MAX__=0XFFFFFFFFP-16UK", 161 | "__UINT16_C(c)=c", 162 | "__DECIMAL_DIG__=17", 163 | "__LFRACT_EPSILON__=0x1P-31LR", 164 | "__FLT64_EPSILON__=2.2204460492503131e-16F64", 165 | "__ULFRACT_MIN__=0.0ULR", 166 | "__INT16_MAX__=0x7fff", 167 | "__FLT64_MIN_EXP__=(-1021)", 168 | "__LDBL_HAS_QUIET_NAN__=1", 169 | "__ULACCUM_IBIT__=32", 170 | "__FLT64_MANT_DIG__=53", 171 | "__UACCUM_EPSILON__=0x1P-16UK", 172 | "__GNUC__=11", 173 | "__ULLACCUM_MAX__=0XFFFFFFFFFFFFFFFFP-32ULLK", 174 | "__GXX_RTTI=1", 175 | "__HQ_IBIT__=0", 176 | "__FLT_HAS_DENORM__=1", 177 | "__SIZEOF_LONG_DOUBLE__=8", 178 | "__SA_IBIT__=16", 179 | "__BIGGEST_ALIGNMENT__=8", 180 | "__STDC_UTF_16__=1", 181 | "__FLT64_MAX_10_EXP__=308", 182 | "__GNUC_STDC_INLINE__=1", 183 | "__DQ_IBIT__=0", 184 | "__cpp_delegating_constructors=200604L", 185 | "__FLT32_HAS_INFINITY__=1", 186 | "__DBL_MAX__=double(1.7976931348623157e+308L)", 187 | "__ULFRACT_IBIT__=0", 188 | "__cpp_raw_strings=200710L", 189 | "__INT_FAST32_MAX__=0x7fffffff", 190 | "__DBL_HAS_INFINITY__=1", 191 | "__cpp_deduction_guides=201703L", 192 | "__HAVE_SPECULATION_SAFE_VALUE=1", 193 | "__cpp_fold_expressions=201603L", 194 | "__ACCUM_IBIT__=16", 195 | "__THUMB_INTERWORK__=1", 196 | "__INTPTR_WIDTH__=32", 197 | "__UINT_LEAST32_MAX__=0xffffffffUL", 198 | "__ULLACCUM_IBIT__=32", 199 | "__LACCUM_MAX__=0X7FFFFFFFFFFFFFFFP-31LK", 200 | "__FLT32X_HAS_DENORM__=1", 201 | "__INT_FAST16_TYPE__=int", 202 | "__LDBL_HAS_DENORM__=1", 203 | "__cplusplus=201703L", 204 | "__cpp_ref_qualifiers=200710L", 205 | "__INT_LEAST32_MAX__=0x7fffffffL", 206 | "__ARM_PCS=1", 207 | "__ACCUM_MAX__=0X7FFFFFFFP-15K", 208 | "__DEPRECATED=1", 209 | "__cpp_rvalue_references=200610L", 210 | "__DBL_MAX_EXP__=1024", 211 | "__USACCUM_EPSILON__=0x1P-8UHK", 212 | "__WCHAR_WIDTH__=32", 213 | "__FLT32_MAX__=3.4028234663852886e+38F32", 214 | "__GCC_ATOMIC_LONG_LOCK_FREE=1", 215 | "__SFRACT_MAX__=0X7FP-7HR", 216 | "__FRACT_IBIT__=0", 217 | "__PTRDIFF_MAX__=0x7fffffff", 218 | "__UACCUM_MIN__=0.0UK", 219 | "__UACCUM_IBIT__=16", 220 | "__FLT32_HAS_QUIET_NAN__=1", 221 | "__GNUG__=11", 222 | "__LONG_LONG_MAX__=0x7fffffffffffffffLL", 223 | "__ULACCUM_MAX__=0XFFFFFFFFFFFFFFFFP-32ULK", 224 | "__cpp_nsdmi=200809L", 225 | "__SIZEOF_WINT_T__=4", 226 | "__LONG_LONG_WIDTH__=64", 227 | "__cpp_initializer_lists=200806L", 228 | "__FLT32_MAX_EXP__=128", 229 | "__ULLACCUM_MIN__=0.0ULLK", 230 | "__cpp_hex_float=201603L", 231 | "__GXX_ABI_VERSION=1016", 232 | "__UTA_FBIT__=64", 233 | "__FLT_MIN_EXP__=(-125)", 234 | "__UFRACT_IBIT__=0", 235 | "__cpp_enumerator_attributes=201411L", 236 | "__cpp_lambdas=200907L", 237 | "__INT_FAST64_TYPE__=long long int", 238 | "__FLT64_DENORM_MIN__=4.9406564584124654e-324F64", 239 | "__DBL_MIN__=double(2.2250738585072014e-308L)", 240 | "__SIZEOF_POINTER__=4", 241 | "__SIZE_TYPE__=unsigned int", 242 | "__DBL_HAS_QUIET_NAN__=1", 243 | "__FLT32X_EPSILON__=2.2204460492503131e-16F32x", 244 | "__LACCUM_MIN__=(-0X1P31LK-0X1P31LK)", 245 | "__FRACT_FBIT__=15", 246 | "__ULLACCUM_FBIT__=32", 247 | "__GXX_TYPEINFO_EQUALITY_INLINE=0", 248 | "__FLT64_MIN_10_EXP__=(-307)", 249 | "__ULLFRACT_EPSILON__=0x1P-64ULLR", 250 | "__USES_INITFINI__=1", 251 | "__REGISTER_PREFIX__", 252 | "__UINT16_MAX__=0xffff", 253 | "__ACCUM_MIN__=(-0X1P15K-0X1P15K)", 254 | "__SQ_IBIT__=0", 255 | "__FLT32_MIN__=1.1754943508222875e-38F32", 256 | "__UINT8_TYPE__=unsigned char", 257 | "__UHA_FBIT__=8", 258 | "__FLT_DIG__=6", 259 | "__NO_INLINE__=1", 260 | "__SFRACT_MIN__=(-0.5HR-0.5HR)", 261 | "__UTQ_FBIT__=128", 262 | "__DEC_EVAL_METHOD__=2", 263 | "__FLT_MANT_DIG__=24", 264 | "__LDBL_DECIMAL_DIG__=17", 265 | "__VERSION__=\"11.3.1 20220712\"", 266 | "__UINT64_C(c)=c ## ULL", 267 | "__ULLFRACT_FBIT__=64", 268 | "__cpp_unicode_characters=201411L", 269 | "__SOFTFP__=1", 270 | "__FRACT_EPSILON__=0x1P-15R", 271 | "__ULACCUM_MIN__=0.0ULK", 272 | "__UDA_FBIT__=32", 273 | "__LLACCUM_EPSILON__=0x1P-31LLK", 274 | "__GCC_ATOMIC_INT_LOCK_FREE=1", 275 | "__FLOAT_WORD_ORDER__=__ORDER_LITTLE_ENDIAN__", 276 | "__USFRACT_MIN__=0.0UHR", 277 | "__FLT32_MANT_DIG__=24", 278 | "__cpp_aggregate_bases=201603L", 279 | "__UQQ_IBIT__=0", 280 | "__USFRACT_MAX__=0XFFP-8UHR", 281 | "__SCHAR_WIDTH__=8", 282 | "__INT32_C(c)=c ## L", 283 | "__ORDER_PDP_ENDIAN__=3412", 284 | "__UHQ_FBIT__=16", 285 | "__LLACCUM_FBIT__=31", 286 | "__INT_FAST32_TYPE__=int", 287 | "__UINT_LEAST16_TYPE__=short unsigned int", 288 | "__DBL_HAS_DENORM__=1", 289 | "__cpp_rtti=199711L", 290 | "__UINT64_MAX__=0xffffffffffffffffULL", 291 | "__FLT_IS_IEC_60559__=2", 292 | "__UDQ_FBIT__=64", 293 | "__GNUC_WIDE_EXECUTION_CHARSET_NAME=\"UTF-32LE\"", 294 | "__INT8_TYPE__=signed char", 295 | "__cpp_digit_separators=201309L", 296 | "__ELF__=1", 297 | "__GCC_ASM_FLAG_OUTPUTS__=1", 298 | "__SACCUM_EPSILON__=0x1P-7HK", 299 | "__ULFRACT_EPSILON__=0x1P-32ULR", 300 | "__LLFRACT_FBIT__=63", 301 | "__FLT_RADIX__=2", 302 | "__INT_LEAST16_TYPE__=short int", 303 | "__LDBL_EPSILON__=2.2204460492503131e-16L", 304 | "__UINTMAX_C(c)=c ## ULL", 305 | "__SACCUM_MAX__=0X7FFFP-7HK", 306 | "__FLT32X_MIN__=2.2250738585072014e-308F32x", 307 | "__SIG_ATOMIC_MAX__=0x7fffffff", 308 | "__UACCUM_FBIT__=16", 309 | "__GCC_ATOMIC_WCHAR_T_LOCK_FREE=1", 310 | "__VFP_FP__=1", 311 | "__SIZEOF_PTRDIFF_T__=4", 312 | "__LACCUM_EPSILON__=0x1P-31LK", 313 | "__LDBL_DIG__=15", 314 | "__FLT64_IS_IEC_60559__=2", 315 | "__FLT32X_MIN_EXP__=(-1021)", 316 | "__INT_FAST16_MAX__=0x7fffffff", 317 | "__FLT64_DIG__=15", 318 | "__UINT_FAST32_MAX__=0xffffffffU", 319 | "__UINT_LEAST64_TYPE__=long long unsigned int", 320 | "__SFRACT_EPSILON__=0x1P-7HR", 321 | "__FLT_HAS_QUIET_NAN__=1", 322 | "__FLT_MAX_10_EXP__=38", 323 | "__LONG_MAX__=0x7fffffffL", 324 | "__SIZEOF_SIZE_T__=4", 325 | "__FLT_HAS_INFINITY__=1", 326 | "__GNUC_EXECUTION_CHARSET_NAME=\"UTF-8\"", 327 | "__cpp_unicode_literals=200710L", 328 | "__UINT_FAST16_TYPE__=unsigned int", 329 | "__ARM_32BIT_STATE=1", 330 | "__INT_FAST32_WIDTH__=32", 331 | "__CHAR16_TYPE__=short unsigned int", 332 | "__PRAGMA_REDEFINE_EXTNAME=1", 333 | "__SIZE_WIDTH__=32", 334 | "__INT_LEAST16_MAX__=0x7fff", 335 | "__INT64_MAX__=0x7fffffffffffffffLL", 336 | "__SACCUM_FBIT__=7", 337 | "__FLT32_DENORM_MIN__=1.4012984643248171e-45F32", 338 | "__SIG_ATOMIC_WIDTH__=32", 339 | "__INT_LEAST64_TYPE__=long long int", 340 | "__INT16_TYPE__=short int", 341 | "__INT_LEAST8_TYPE__=signed char", 342 | "__cpp_structured_bindings=201606L", 343 | "__SQ_FBIT__=31", 344 | "__ARM_ARCH_ISA_THUMB=1", 345 | "__INT_FAST8_MAX__=0x7fffffff", 346 | "__ARM_ARCH=4", 347 | "__INTPTR_MAX__=0x7fffffff", 348 | "__cpp_sized_deallocation=201309L", 349 | "__cpp_guaranteed_copy_elision=201606L", 350 | "__QQ_FBIT__=7", 351 | "__UTA_IBIT__=64", 352 | "__FLT64_HAS_QUIET_NAN__=1", 353 | "__FLT32_MIN_10_EXP__=(-37)", 354 | "__EXCEPTIONS=1", 355 | "__PTRDIFF_WIDTH__=32", 356 | "__LDBL_MANT_DIG__=53", 357 | "__SFRACT_FBIT__=7", 358 | "__cpp_range_based_for=201603L", 359 | "__SACCUM_MIN__=(-0X1P7HK-0X1P7HK)", 360 | "__FLT64_HAS_INFINITY__=1", 361 | "__STDCPP_DEFAULT_NEW_ALIGNMENT__=8", 362 | "__SIG_ATOMIC_MIN__=(-__SIG_ATOMIC_MAX__ - 1)", 363 | "__cpp_nontype_template_args=201411L", 364 | "__cpp_return_type_deduction=201304L", 365 | "__INTPTR_TYPE__=int", 366 | "__UINT16_TYPE__=short unsigned int", 367 | "__WCHAR_TYPE__=unsigned int", 368 | "__SIZEOF_FLOAT__=4", 369 | "__TQ_FBIT__=127", 370 | "__USQ_FBIT__=32", 371 | "__UINTPTR_MAX__=0xffffffffU", 372 | "__INT_FAST64_WIDTH__=64", 373 | "__cpp_decltype=200707L", 374 | "__FLT32_DECIMAL_DIG__=9", 375 | "__INT_FAST64_MAX__=0x7fffffffffffffffLL", 376 | "__GCC_ATOMIC_TEST_AND_SET_TRUEVAL=1", 377 | "__FLT_NORM_MAX__=3.4028234663852886e+38F", 378 | "__UINT_FAST64_TYPE__=long long unsigned int", 379 | "__cpp_inline_variables=201606L", 380 | "__INT_MAX__=0x7fffffff", 381 | "__LACCUM_FBIT__=31", 382 | "__USACCUM_MIN__=0.0UHK", 383 | "__UHA_IBIT__=8", 384 | "__INT64_TYPE__=long long int", 385 | "__FLT_MAX_EXP__=128", 386 | "__UTQ_IBIT__=0", 387 | "__DBL_MANT_DIG__=53", 388 | "__cpp_inheriting_constructors=201511L", 389 | "__INT_LEAST64_MAX__=0x7fffffffffffffffLL", 390 | "__WINT_TYPE__=unsigned int", 391 | "__UINT_LEAST32_TYPE__=long unsigned int", 392 | "__SIZEOF_SHORT__=2", 393 | "__ULLFRACT_IBIT__=0", 394 | "__FLT32_NORM_MAX__=3.4028234663852886e+38F32", 395 | "__LDBL_MIN_EXP__=(-1021)", 396 | "__arm__=1", 397 | "__FLT64_MAX__=1.7976931348623157e+308F64", 398 | "__UDA_IBIT__=32", 399 | "__WINT_WIDTH__=32", 400 | "__cpp_template_auto=201606L", 401 | "__INT_LEAST64_WIDTH__=64", 402 | "__FLT32X_MAX_10_EXP__=308", 403 | "__LFRACT_FBIT__=31", 404 | "__WCHAR_UNSIGNED__=1", 405 | "__LDBL_MAX_10_EXP__=308", 406 | "__ATOMIC_RELAXED=0", 407 | "__DBL_EPSILON__=double(2.2204460492503131e-16L)", 408 | "__UINT8_C(c)=c", 409 | "__FLT64_MAX_EXP__=1024", 410 | "__INT_LEAST32_TYPE__=long int", 411 | "__SIZEOF_WCHAR_T__=4", 412 | "__LLFRACT_MAX__=0X7FFFFFFFFFFFFFFFP-63LLR", 413 | "__FLT64_NORM_MAX__=1.7976931348623157e+308F64", 414 | "__INTMAX_MAX__=0x7fffffffffffffffLL", 415 | "__INT_FAST8_TYPE__=int", 416 | "__cpp_namespace_attributes=201411L", 417 | "__ULLACCUM_EPSILON__=0x1P-32ULLK", 418 | "__USACCUM_MAX__=0XFFFFP-8UHK", 419 | "__LDBL_HAS_INFINITY__=1", 420 | "__UHQ_IBIT__=0", 421 | "__ARM_FEATURE_COPROC=1", 422 | "__LLACCUM_IBIT__=32", 423 | "__FLT64_HAS_DENORM__=1", 424 | "__FLT32_EPSILON__=1.1920928955078125e-7F32", 425 | "__DBL_DECIMAL_DIG__=17", 426 | "__STDC_UTF_32__=1", 427 | "__INT_FAST8_WIDTH__=32", 428 | "__FLT32X_MAX__=1.7976931348623157e+308F32x", 429 | "__TA_FBIT__=63", 430 | "__DBL_NORM_MAX__=double(1.7976931348623157e+308L)", 431 | "__BYTE_ORDER__=__ORDER_LITTLE_ENDIAN__", 432 | "__UDQ_IBIT__=0", 433 | "__INTMAX_WIDTH__=64", 434 | "__ORDER_BIG_ENDIAN__=4321", 435 | "__cpp_runtime_arrays=198712L", 436 | "__UINT64_TYPE__=long long unsigned int", 437 | "__ACCUM_EPSILON__=0x1P-15K", 438 | "__UINT32_C(c)=c ## UL", 439 | "__cpp_alias_templates=200704L", 440 | "__FLT_DENORM_MIN__=1.4012984643248171e-45F", 441 | "__LLFRACT_IBIT__=0", 442 | "__INT8_MAX__=0x7f", 443 | "__LONG_WIDTH__=32", 444 | "__UINT_FAST32_TYPE__=unsigned int", 445 | "__FLT32X_NORM_MAX__=1.7976931348623157e+308F32x", 446 | "__CHAR32_TYPE__=long unsigned int", 447 | "__FLT_MAX__=3.4028234663852886e+38F", 448 | "__cpp_constexpr=201603L", 449 | "__USACCUM_FBIT__=8", 450 | "__INT32_TYPE__=long int", 451 | "__SIZEOF_DOUBLE__=8", 452 | "__cpp_exceptions=199711L", 453 | "__FLT_MIN_10_EXP__=(-37)", 454 | "__UFRACT_EPSILON__=0x1P-16UR", 455 | "__FLT64_MIN__=2.2250738585072014e-308F64", 456 | "__INT_LEAST32_WIDTH__=32", 457 | "__INTMAX_TYPE__=long long int", 458 | "__FLT32X_HAS_QUIET_NAN__=1", 459 | "__ATOMIC_CONSUME=1", 460 | "__GNUC_MINOR__=3", 461 | "__INT_FAST16_WIDTH__=32", 462 | "__UINTMAX_MAX__=0xffffffffffffffffULL", 463 | "__FLT32X_DENORM_MIN__=4.9406564584124654e-324F32x", 464 | "__HA_FBIT__=7", 465 | "__cpp_template_template_args=201611L", 466 | "__DBL_MAX_10_EXP__=308", 467 | "__LDBL_DENORM_MIN__=4.9406564584124654e-324L", 468 | "__INT16_C(c)=c", 469 | "__STDC__=1", 470 | "__FLT32X_DIG__=15", 471 | "__PTRDIFF_TYPE__=int", 472 | "__LLFRACT_MIN__=(-0.5LLR-0.5LLR)", 473 | "__ATOMIC_SEQ_CST=5", 474 | "__DA_FBIT__=31", 475 | "__UINT32_TYPE__=long unsigned int", 476 | "__FLT32X_MIN_10_EXP__=(-307)", 477 | "__UINTPTR_TYPE__=unsigned int", 478 | "__USA_IBIT__=16", 479 | "__ARM_EABI__=1", 480 | "__LDBL_MIN_10_EXP__=(-307)", 481 | "__cpp_generic_lambdas=201304L", 482 | "__SIZEOF_LONG_LONG__=8", 483 | "__ULACCUM_EPSILON__=0x1P-32ULK", 484 | "__cpp_user_defined_literals=200809L", 485 | "__SACCUM_IBIT__=8", 486 | "__GCC_ATOMIC_LLONG_LOCK_FREE=1", 487 | "__FLT_DECIMAL_DIG__=9", 488 | "__UINT_FAST16_MAX__=0xffffffffU", 489 | "__LDBL_NORM_MAX__=1.7976931348623157e+308L", 490 | "__GCC_ATOMIC_SHORT_LOCK_FREE=1", 491 | "__ULLFRACT_MAX__=0XFFFFFFFFFFFFFFFFP-64ULLR", 492 | "__UINT_FAST8_TYPE__=unsigned int", 493 | "__USFRACT_EPSILON__=0x1P-8UHR", 494 | "__ULACCUM_FBIT__=32", 495 | "__QQ_IBIT__=0", 496 | "__cpp_init_captures=201304L", 497 | "__ATOMIC_ACQ_REL=4", 498 | "__ATOMIC_RELEASE=3", 499 | "USBCON" 500 | ] 501 | } 502 | ] 503 | } -------------------------------------------------------------------------------- /illuminate/src/ledarrays/sci.iris.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | // Define which LED Array is used 32 | #include "../../illuminate.h" 33 | 34 | #ifdef USE_SCI_IRIS 35 | 36 | #include "../../ledarrayinterface.h" 37 | #include "../../constants.h" 38 | #include "../TLC5955/TLC5955.h" 39 | #include 40 | 41 | // Power monitoring commands 42 | #define DEVICE_SUPPORTS_POWER_SENSING 0 43 | #define DEVICE_SUPPORTS_ACTIVE_POWER_MONITORING 0 44 | #define PSU_ACTIVE_MONITORING_COMPARATOR_MODE 5 45 | 46 | #if DEVICE_SUPPORTS_ACTIVE_POWER_MONITORING 47 | #include "../TeensyComparator/TeensyComparator.h" 48 | #endif 49 | 50 | // Power sensing pin 51 | const int POWER_SENSE_PIN = 23; 52 | 53 | // Pin definitions (used internally) 54 | const int GSCLK = 6; 55 | const int LAT = 3; 56 | const int SPI_MOSI = 11; 57 | const int SPI_CLK = 13; 58 | const int TRIGGER_OUTPUT_PIN_0 = 22; 59 | const int TRIGGER_INPUT_PIN_0 = 21; 60 | const int TRIGGER_OUTPUT_COUNT = 1; 61 | const int TRIGGER_INPUT_COUNT = 1; 62 | const int COLOR_CHANNEL_COUNT = 1; 63 | const int LEDS_PER_CHIP = 48; 64 | 65 | // Power source sensing variables 66 | bool _psu_is_connected = true; 67 | bool _power_source_sensing_is_enabled = false; 68 | elapsedMillis _time_elapsed_debounce; 69 | uint32_t _warning_delay_ms = 10; 70 | bool global_shutter_state = true; 71 | 72 | // Device and Software Descriptors 73 | const char * LedArrayInterface::device_name = "sci.iris"; 74 | const char * LedArrayInterface::device_hardware_revision = "r0"; 75 | const int16_t LedArrayInterface::led_count = 256; 76 | const uint16_t LedArrayInterface::center_led = 0; 77 | const int LedArrayInterface::trigger_output_count = 1; 78 | const int LedArrayInterface::trigger_input_count = 1; 79 | const int LedArrayInterface::color_channel_count = 1; 80 | const char LedArrayInterface::color_channel_names[] = {'r'}; 81 | const float LedArrayInterface::color_channel_center_wavelengths_nm[] = {740.0}; 82 | const float LedArrayInterface::color_channel_fwhm_wavelengths_nm[] = {20.0}; 83 | const int LedArrayInterface::bit_depth = 8; 84 | const bool LedArrayInterface::supports_fast_sequence = false; 85 | float LedArrayInterface::led_position_list_na[LedArrayInterface::led_count][2]; 86 | 87 | const int LedArrayInterface::trigger_output_pin_list[] = {TRIGGER_OUTPUT_PIN_0}; 88 | const int LedArrayInterface::trigger_input_pin_list[] = {TRIGGER_INPUT_PIN_0}; 89 | bool LedArrayInterface::trigger_input_state[] = {false}; 90 | 91 | int LedArrayInterface::debug = 0; 92 | 93 | const uint8_t TLC5955::chip_count = 6; // Change to reflect number of TLC chips 94 | float TLC5955::max_current_amps = 8.0; // Maximum current output, amps 95 | bool TLC5955::enforce_max_current = true; // Whether to enforce max current limit 96 | 97 | // Define dot correction, pin rgb order, and grayscale data arrays in program memory 98 | uint8_t TLC5955::_dc_data[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 99 | uint8_t TLC5955::_rgb_order[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 100 | uint16_t TLC5955::_grayscale_data[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 101 | 102 | /**** Device-specific variables ****/ 103 | TLC5955 tlc; // TLC5955 object 104 | 105 | /**** Device-specific commands ****/ 106 | const uint8_t LedArrayInterface::device_command_count = 9; 107 | const char * LedArrayInterface::device_commandNamesShort[] = {}; 108 | const char * LedArrayInterface::device_commandNamesLong[] = {}; 109 | const uint16_t LedArrayInterface::device_command_pattern_dimensions[][2] = {{}}; // Number of commands, number of LEDs in each command. 110 | 111 | /**** Part number and Serial number addresses in EEPROM ****/ 112 | uint16_t pn_address = 100; 113 | uint16_t sn_address = 200; 114 | 115 | // Initialize LED positions 116 | const int16_t PROGMEM LedArrayInterface::led_positions[][5] = { 117 | {0, 96, 0, -800, 0}, 118 | {1, 113, -570, -570, 0}, 119 | {2, 48, -800, 0, 0}, 120 | {3, 65, -570, 570, 0}, 121 | {4, 0, 0, 800, 0}, 122 | {5, 17, 570, 570, 0}, 123 | {6, 144, 800, 0, 0}, 124 | {7, 161, 570, -570, 0}, 125 | {8, 109, 0, -1240, 0}, 126 | {9, 98, -475, -1146, 0}, 127 | {10, 111, -877, -877, 0}, 128 | {11, 101, -1146, -475, 0}, 129 | {12, 61, -1240, 0, 0}, 130 | {13, 50, -1146, 475, 0}, 131 | {14, 63, -877, 877, 0}, 132 | {15, 53, -475, 1146, 0}, 133 | {16, 13, 0, 1240, 0}, 134 | {17, 2, 475, 1146, 0}, 135 | {18, 15, 877, 877, 0}, 136 | {19, 5, 1146, 475, 0}, 137 | {20, 157, 1240, 0, 0}, 138 | {21, 146, 1146, -475, 0}, 139 | {22, 159, 877, -877, 0}, 140 | {23, 149, 475, -1146, 0}, 141 | {24, 122, 0, -1860, 0}, 142 | {25, 110, -481, -1797, 0}, 143 | {26, 108, -930, -1611, 0}, 144 | {27, 112, -1315, -1315, 0}, 145 | {28, 99, -1611, -930, 0}, 146 | {29, 100, -1797, -481, 0}, 147 | {30, 74, -1860, 0, 0}, 148 | {31, 62, -1797, 481, 0}, 149 | {32, 60, -1611, 930, 0}, 150 | {33, 64, -1315, 1315, 0}, 151 | {34, 51, -930, 1611, 0}, 152 | {35, 52, -481, 1797, 0}, 153 | {36, 26, 0, 1860, 0}, 154 | {37, 14, 481, 1797, 0}, 155 | {38, 12, 930, 1611, 0}, 156 | {39, 16, 1315, 1315, 0}, 157 | {40, 3, 1611, 930, 0}, 158 | {41, 4, 1797, 481, 0}, 159 | {42, 170, 1860, 0, 0}, 160 | {43, 158, 1797, -481, 0}, 161 | {44, 156, 1611, -930, 0}, 162 | {45, 160, 1315, -1315, 0}, 163 | {46, 147, 930, -1611, 0}, 164 | {47, 148, 481, -1797, 0}, 165 | {48, 121, 0, -2480, 0}, 166 | {49, 134, -431, -2442, 0}, 167 | {50, 133, -848, -2330, 0}, 168 | {51, 132, -1240, -2148, 0}, 169 | {52, 120, -1594, -1900, 0}, 170 | {53, 104, -1900, -1594, 0}, 171 | {54, 103, -2148, -1240, 0}, 172 | {55, 116, -2330, -848, 0}, 173 | {56, 102, -2442, -431, 0}, 174 | {57, 73, -2480, 0, 0}, 175 | {58, 86, -2442, 431, 0}, 176 | {59, 85, -2330, 848, 0}, 177 | {60, 84, -2148, 1240, 0}, 178 | {61, 72, -1900, 1594, 0}, 179 | {62, 56, -1594, 1900, 0}, 180 | {63, 55, -1240, 2148, 0}, 181 | {64, 68, -848, 2330, 0}, 182 | {65, 54, -431, 2442, 0}, 183 | {66, 25, 0, 2480, 0}, 184 | {67, 38, 431, 2442, 0}, 185 | {68, 37, 848, 2330, 0}, 186 | {69, 36, 1240, 2148, 0}, 187 | {70, 24, 1594, 1900, 0}, 188 | {71, 8, 1900, 1594, 0}, 189 | {72, 7, 2148, 1240, 0}, 190 | {73, 20, 2330, 848, 0}, 191 | {74, 6, 2442, 431, 0}, 192 | {75, 169, 2480, 0, 0}, 193 | {76, 182, 2442, -431, 0}, 194 | {77, 181, 2330, -848, 0}, 195 | {78, 180, 2148, -1240, 0}, 196 | {79, 168, 1900, -1594, 0}, 197 | {80, 152, 1594, -1900, 0}, 198 | {81, 151, 1240, -2148, 0}, 199 | {82, 164, 848, -2330, 0}, 200 | {83, 150, 431, -2442, 0}, 201 | {84, 125, 0, -3100, 0}, 202 | {85, 123, -405, -3073, 0}, 203 | {86, 137, -802, -2994, 0}, 204 | {87, 136, -1186, -2864, 0}, 205 | {88, 138, -1550, -2685, 0}, 206 | {89, 126, -1887, -2459, 0}, 207 | {90, 142, -2192, -2192, 0}, 208 | {91, 130, -2459, -1887, 0}, 209 | {92, 119, -2685, -1550, 0}, 210 | {93, 105, -2864, -1186, 0}, 211 | {94, 115, -2994, -802, 0}, 212 | {95, 114, -3073, -405, 0}, 213 | {96, 77, -3100, 0, 0}, 214 | {97, 75, -3073, 405, 0}, 215 | {98, 89, -2994, 802, 0}, 216 | {99, 88, -2864, 1186, 0}, 217 | {100, 90, -2685, 1550, 0}, 218 | {101, 78, -2459, 1887, 0}, 219 | {102, 94, -2192, 2192, 0}, 220 | {103, 82, -1887, 2459, 0}, 221 | {104, 71, -1550, 2685, 0}, 222 | {105, 57, -1186, 2864, 0}, 223 | {106, 67, -802, 2994, 0}, 224 | {107, 66, -405, 3073, 0}, 225 | {108, 29, 0, 3100, 0}, 226 | {109, 27, 405, 3073, 0}, 227 | {110, 41, 802, 2994, 0}, 228 | {111, 40, 1186, 2864, 0}, 229 | {112, 42, 1550, 2685, 0}, 230 | {113, 30, 1887, 2459, 0}, 231 | {114, 46, 2192, 2192, 0}, 232 | {115, 34, 2459, 1887, 0}, 233 | {116, 23, 2685, 1550, 0}, 234 | {117, 9, 2864, 1186, 0}, 235 | {118, 19, 2994, 802, 0}, 236 | {119, 18, 3073, 405, 0}, 237 | {120, 173, 3100, 0, 0}, 238 | {121, 171, 3073, -405, 0}, 239 | {122, 185, 2994, -802, 0}, 240 | {123, 184, 2864, -1186, 0}, 241 | {124, 186, 2685, -1550, 0}, 242 | {125, 174, 2459, -1887, 0}, 243 | {126, 190, 2192, -2192, 0}, 244 | {127, 178, 1887, -2459, 0}, 245 | {128, 167, 1550, -2685, 0}, 246 | {129, 153, 1186, -2864, 0}, 247 | {130, 163, 802, -2994, 0}, 248 | {131, 162, 405, -3073, 0}, 249 | {132, 124, 0, -3720, 0}, 250 | {133, 135, -417, -3697, 0}, 251 | {134, 140, -828, -3627, 0}, 252 | {135, 139, -1229, -3511, 0}, 253 | {136, 128, -1614, -3352, 0}, 254 | {137, 127, -1979, -3150, 0}, 255 | {138, 143, -2319, -2908, 0}, 256 | {139, 141, -2630, -2630, 0}, 257 | {140, 131, -2908, -2319, 0}, 258 | {141, 129, -3150, -1979, 0}, 259 | {142, 118, -3352, -1614, 0}, 260 | {143, 117, -3511, -1229, 0}, 261 | {144, 106, -3627, -828, 0}, 262 | {145, 107, -3697, -417, 0}, 263 | {146, 76, -3720, 0, 0}, 264 | {147, 87, -3697, 417, 0}, 265 | {148, 92, -3627, 828, 0}, 266 | {149, 91, -3511, 1229, 0}, 267 | {150, 80, -3352, 1614, 0}, 268 | {151, 79, -3150, 1979, 0}, 269 | {152, 95, -2908, 2319, 0}, 270 | {153, 93, -2630, 2630, 0}, 271 | {154, 83, -2319, 2908, 0}, 272 | {155, 81, -1979, 3150, 0}, 273 | {156, 70, -1614, 3352, 0}, 274 | {157, 69, -1229, 3511, 0}, 275 | {158, 58, -828, 3627, 0}, 276 | {159, 59, -417, 3697, 0}, 277 | {160, 28, 0, 3720, 0}, 278 | {161, 39, 417, 3697, 0}, 279 | {162, 44, 828, 3627, 0}, 280 | {163, 43, 1229, 3511, 0}, 281 | {164, 32, 1614, 3352, 0}, 282 | {165, 31, 1979, 3150, 0}, 283 | {166, 47, 2319, 2908, 0}, 284 | {167, 45, 2630, 2630, 0}, 285 | {168, 35, 2908, 2319, 0}, 286 | {169, 33, 3150, 1979, 0}, 287 | {170, 22, 3352, 1614, 0}, 288 | {171, 21, 3511, 1229, 0}, 289 | {172, 10, 3627, 828, 0}, 290 | {173, 11, 3697, 417, 0}, 291 | {174, 172, 3720, 0, 0}, 292 | {175, 183, 3697, -417, 0}, 293 | {176, 188, 3627, -828, 0}, 294 | {177, 187, 3511, -1229, 0}, 295 | {178, 176, 3352, -1614, 0}, 296 | {179, 175, 3150, -1979, 0}, 297 | {180, 191, 2908, -2319, 0}, 298 | {181, 189, 2630, -2630, 0}, 299 | {182, 179, 2319, -2908, 0}, 300 | {183, 177, 1979, -3150, 0}, 301 | {184, 166, 1614, -3352, 0}, 302 | {185, 165, 1229, -3511, 0}, 303 | {186, 154, 828, -3627, 0}, 304 | {187, 155, 417, -3697, 0}, 305 | {188, 97, 0, -4340, 0}, 306 | {189, 231, -400, -4321, 0}, 307 | {190, 232, -797, -4266, 0}, 308 | {191, 214, -1188, -4174, 0}, 309 | {192, 213, -1568, -4047, 0}, 310 | {193, 215, -1935, -3885, 0}, 311 | {194, 202, -2285, -3690, 0}, 312 | {195, 201, -2615, -3463, 0}, 313 | {196, 203, -2924, -3207, 0}, 314 | {197, 211, -3207, -2924, 0}, 315 | {198, 210, -3463, -2615, 0}, 316 | {199, 212, -3690, -2285, 0}, 317 | {200, 196, -3885, -1935, 0}, 318 | {201, 195, -4047, -1568, 0}, 319 | {202, 197, -4174, -1188, 0}, 320 | {203, 208, -4266, -797, 0}, 321 | {204, 207, -4321, -400, 0}, 322 | {205, 209, -4340, 0, 0}, 323 | {206, 193, -4321, 400, 0}, 324 | {207, 192, -4266, 797, 0}, 325 | {208, 194, -4174, 1188, 0}, 326 | {209, 205, -4047, 1568, 0}, 327 | {210, 204, -3885, 1935, 0}, 328 | {211, 206, -3690, 2285, 0}, 329 | {212, 218, -3463, 2615, 0}, 330 | {213, 216, -3207, 2924, 0}, 331 | {214, 217, -2924, 3207, 0}, 332 | {215, 230, -2615, 3463, 0}, 333 | {216, 228, -2285, 3690, 0}, 334 | {217, 229, -1935, 3885, 0}, 335 | {218, 221, -1568, 4047, 0}, 336 | {219, 219, -1188, 4174, 0}, 337 | {220, 220, -797, 4266, 0}, 338 | {221, 233, -400, 4321, 0}, 339 | {222, 49, 0, 4340, 0}, 340 | {223, 252, 400, 4321, 0}, 341 | {224, 254, 797, 4266, 0}, 342 | {225, 266, 1188, 4174, 0}, 343 | {226, 264, 1568, 4047, 0}, 344 | {227, 265, 1935, 3885, 0}, 345 | {228, 278, 2285, 3690, 0}, 346 | {229, 276, 2615, 3463, 0}, 347 | {230, 277, 2924, 3207, 0}, 348 | {231, 269, 3207, 2924, 0}, 349 | {232, 267, 3463, 2615, 0}, 350 | {233, 268, 3690, 2285, 0}, 351 | {234, 281, 3885, 1935, 0}, 352 | {235, 279, 4047, 1568, 0}, 353 | {236, 280, 4174, 1188, 0}, 354 | {237, 284, 4266, 797, 0}, 355 | {238, 282, 4321, 400, 0}, 356 | {239, 283, 4340, 0, 0}, 357 | {240, 272, 4321, -400, 0}, 358 | {241, 270, 4266, -797, 0}, 359 | {242, 271, 4174, -1188, 0}, 360 | {243, 287, 4047, -1568, 0}, 361 | {244, 285, 3885, -1935, 0}, 362 | {245, 244, 3690, -2285, 0}, 363 | {246, 243, 3463, -2615, 0}, 364 | {247, 245, 3207, -2924, 0}, 365 | {248, 256, 2924, -3207, 0}, 366 | {249, 255, 2615, -3463, 0}, 367 | {250, 257, 2285, -3690, 0}, 368 | {251, 241, 1935, -3885, 0}, 369 | {252, 240, 1568, -4047, 0}, 370 | {253, 242, 1188, -4174, 0}, 371 | {254, 253, 797, -4266, 0}, 372 | {255, 145, 400, -4321, 0}, 373 | }; 374 | 375 | void LedArrayInterface::set_max_current_enforcement(bool enforce) 376 | { 377 | TLC5955::enforce_max_current = enforce; 378 | } 379 | 380 | void LedArrayInterface::set_max_current_limit(float limit) 381 | { 382 | if (limit > 0) 383 | TLC5955::max_current_amps = limit; 384 | } 385 | 386 | void LedArrayInterface::not_implemented(const char * command_name) 387 | { 388 | Serial.print(F("Command ")); 389 | Serial.print(command_name); 390 | Serial.printf(F(" is not implemented for this device. %s"), SERIAL_LINE_ENDING); 391 | } 392 | 393 | uint16_t LedArrayInterface::get_led_value(uint16_t led_number, int color_channel_index) 394 | { 395 | int16_t channel_number = (int16_t)pgm_read_word(&(led_positions[led_number][1])); 396 | if (channel_number >= 0) 397 | return tlc.get_single_channel(channel_number); 398 | else 399 | { 400 | Serial.print(F("ERROR (LedArrayInterface::get_led_value) - invalid LED number (")); 401 | Serial.print(led_number); 402 | Serial.printf(F(")%s"), SERIAL_LINE_ENDING); 403 | return 0; 404 | } 405 | } 406 | 407 | void LedArrayInterface::set_pin_order(int16_t led_number, int16_t color_channel_index, uint8_t position) 408 | { 409 | not_implemented("set_pin_order"); 410 | } 411 | 412 | // Debug Variables 413 | bool LedArrayInterface::get_debug() 414 | { 415 | return (LedArrayInterface::debug); 416 | } 417 | 418 | void LedArrayInterface::set_debug(int state) 419 | { 420 | debug = state; 421 | Serial.printf(F("(LedArrayInterface::set_debug): Set debug level to %d \n"), debug); 422 | } 423 | 424 | int LedArrayInterface::send_trigger_pulse(int trigger_index, uint16_t delay_us, bool inverse_polarity) 425 | { 426 | // Get trigger pin 427 | int trigger_pin = trigger_output_pin_list[trigger_index]; 428 | 429 | if (trigger_pin > 0) 430 | { 431 | // Write active state 432 | if (inverse_polarity) 433 | digitalWriteFast(trigger_pin, LOW); 434 | else 435 | digitalWriteFast(trigger_pin, HIGH); 436 | 437 | // Delay if desired 438 | if (delay_us > 0) 439 | delayMicroseconds(delay_us); 440 | 441 | // Write normal state 442 | if (inverse_polarity) 443 | digitalWriteFast(trigger_pin, HIGH); 444 | else 445 | digitalWriteFast(trigger_pin, LOW); 446 | return 1; 447 | } 448 | else 449 | return -1; 450 | } 451 | 452 | void LedArrayInterface::update() 453 | { 454 | if (global_shutter_state) 455 | tlc.update(); 456 | else 457 | tlc.clear_without_modifying_pattern(); 458 | } 459 | 460 | void LedArrayInterface::clear() 461 | { 462 | tlc.set_all(0); 463 | update(); 464 | } 465 | 466 | bool LedArrayInterface::get_max_current_enforcement() 467 | { 468 | return TLC5955::enforce_max_current; 469 | } 470 | 471 | float LedArrayInterface::get_max_current_limit() 472 | { 473 | return TLC5955::max_current_amps; 474 | } 475 | 476 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, uint16_t value) 477 | { 478 | if (debug >= 2) 479 | { 480 | Serial.print(F("U16 Setting channel #")); 481 | Serial.print(channel_number); 482 | Serial.print(F(" to value ")); 483 | Serial.print(value); 484 | Serial.print(SERIAL_LINE_ENDING); 485 | } 486 | 487 | if (channel_number >= 0) 488 | tlc.set_single_channel(channel_number, value); 489 | else 490 | { 491 | Serial.print(F("Error (LedArrayInterface::set_channel): Invalid channel (")); 492 | Serial.print(channel_number); 493 | Serial.printf(F(")%s"), SERIAL_LINE_ENDING); 494 | } 495 | } 496 | 497 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, uint8_t value) 498 | { 499 | if (debug >= 2) 500 | { 501 | Serial.print("U8 Setting channel #"); 502 | Serial.print(channel_number); 503 | Serial.print(", color channel #"); 504 | Serial.print(color_channel_number); 505 | Serial.print(SERIAL_LINE_ENDING); 506 | } 507 | set_channel(channel_number, color_channel_number, (uint16_t)( value * UINT16_MAX / UINT8_MAX)); 508 | } 509 | 510 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, bool value) 511 | { 512 | if (debug >= 2) 513 | { 514 | Serial.print("U8 Setting channel #"); 515 | Serial.print(channel_number); 516 | Serial.print(", color channel #"); 517 | Serial.print(color_channel_number); 518 | Serial.print(SERIAL_LINE_ENDING); 519 | } 520 | set_channel(channel_number, color_channel_number, (uint16_t) (value * UINT16_MAX)); 521 | } 522 | 523 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, uint16_t value) 524 | { 525 | int16_t channel_number = -1; 526 | 527 | if (led_number < 0) 528 | { 529 | for (uint16_t led_index = 0; led_index < led_count; led_index++) 530 | { 531 | channel_number = (int16_t)pgm_read_word(&(led_positions[led_index][1])); 532 | set_channel(channel_number, color_channel_number, value); 533 | } 534 | } 535 | else 536 | { 537 | channel_number = (int16_t)pgm_read_word(&(led_positions[led_number][1])); 538 | set_channel(channel_number, color_channel_number, value); 539 | } 540 | 541 | if (debug >= 2) 542 | { 543 | Serial.print("U16 Set led #"); 544 | Serial.print(led_number); 545 | Serial.print(", channel #"); 546 | Serial.print(channel_number); 547 | Serial.print(", color channel #"); 548 | Serial.print(color_channel_number); 549 | Serial.print(" to value "); 550 | Serial.print(value); 551 | Serial.print(SERIAL_LINE_ENDING); 552 | } 553 | } 554 | 555 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, uint8_t value) 556 | { 557 | if (debug >= 2) 558 | { 559 | Serial.print("U8 Setting led #"); 560 | Serial.print(led_number); 561 | Serial.print(", color channel #"); 562 | Serial.print(color_channel_number); 563 | Serial.print(SERIAL_LINE_ENDING); 564 | } 565 | set_led(led_number, color_channel_number, (uint16_t) (value * UINT16_MAX / UINT8_MAX)); 566 | } 567 | 568 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, bool value) 569 | { 570 | if (debug >= 2) 571 | { 572 | Serial.print("B Setting led #"); 573 | Serial.print(led_number); 574 | Serial.print(", color channel #"); 575 | Serial.print(color_channel_number); 576 | Serial.print(SERIAL_LINE_ENDING); 577 | } 578 | set_led(led_number, color_channel_number, (uint16_t) (value * UINT16_MAX)); 579 | } 580 | 581 | void LedArrayInterface::set_global_shutter_state(bool state) 582 | { 583 | if (debug >= 1) 584 | { 585 | Serial.print("Setting Global Shutter state to "); 586 | Serial.print(state); 587 | Serial.print(SERIAL_LINE_ENDING); 588 | } 589 | 590 | // Store current state 591 | global_shutter_state = state; 592 | 593 | // Call the internal update method 594 | update(); 595 | } 596 | 597 | bool LedArrayInterface::get_global_shutter_state() 598 | { 599 | if (debug >= 1) 600 | { 601 | Serial.print("Getting Global Shutter state: "); 602 | Serial.print(global_shutter_state); 603 | Serial.print(SERIAL_LINE_ENDING); 604 | } 605 | 606 | return global_shutter_state; 607 | } 608 | 609 | 610 | int8_t LedArrayInterface::device_reset() 611 | { 612 | return device_setup(); 613 | } 614 | 615 | int8_t LedArrayInterface::device_setup() 616 | { 617 | pinMode(LAT, OUTPUT); 618 | // Initialize TLC5955 619 | tlc.init(LAT, SPI_MOSI, SPI_CLK, GSCLK); 620 | 621 | // We must set dot correction values, so set them all to the brightest adjustment 622 | tlc.set_all_dc_data(127); 623 | 624 | // Set Max Current Values (see TLC5955 datasheet) 625 | tlc.set_max_current(3, 3, 3); // Go up to 7 626 | 627 | // Set Function Control Data Latch values. See the TLC5955 Datasheet for the purpose of this latch. 628 | // DSPRPT, TMGRST, RFRESH, ESPWM, LSDVLT 629 | tlc.set_function_data(true, true, false, true, true); // WORKS with fast update 630 | 631 | // set all brightness levels to max (127) 632 | int currentR = 127; 633 | int currentB = 127; 634 | int currentG = 127; 635 | tlc.set_brightness_current(currentR, currentB, currentG); 636 | 637 | // Update Control Register 638 | tlc.update_control(); 639 | 640 | // Update the GS register (ideally LEDs should be dark up to here) 641 | tlc.set_all(0); 642 | tlc.update(); 643 | 644 | // Output trigger Pins 645 | for (int trigger_index = 0; trigger_index < trigger_output_count; trigger_index++) 646 | { 647 | pinMode(LedArrayInterface::trigger_output_pin_list[trigger_index], OUTPUT); 648 | digitalWriteFast(LedArrayInterface::trigger_output_pin_list[trigger_index], LOW); 649 | } 650 | 651 | 652 | // Output trigger pins 653 | for (int trigger_index = 0; trigger_index < trigger_output_count; trigger_index++) 654 | { 655 | pinMode(trigger_output_pin_list[trigger_index], OUTPUT); 656 | digitalWriteFast(trigger_output_pin_list[trigger_index], LOW); 657 | } 658 | 659 | // Input trigger pins 660 | attachInterrupt(digitalPinToInterrupt(trigger_input_pin_list[0]), trigger_pin_interrupt_0, CHANGE); 661 | attachInterrupt(digitalPinToInterrupt(trigger_input_pin_list[1]), trigger_pin_interrupt_1, CHANGE); 662 | 663 | return NO_ERROR; 664 | } 665 | 666 | void LedArrayInterface::trigger_pin_interrupt_0() 667 | { 668 | bool previous_state = trigger_input_state[0]; 669 | trigger_input_state[0] = digitalReadFast(trigger_input_pin_list[0]); 670 | bool new_state = trigger_input_state[0]; 671 | if (debug >= 2) 672 | Serial.printf("Recieved trigger pulse on pin 0. Previous state: %s New state: %s%s", previous_state ? "HIGH" : "LOW", new_state ? "HIGH" : "LOW", SERIAL_LINE_ENDING); 673 | } 674 | 675 | void LedArrayInterface::trigger_pin_interrupt_1() 676 | { 677 | Serial.printf(F("ERROR (LedArrayInterface::trigger_pin_interrupt_1): This board has only one trigger pin.%s"), SERIAL_LINE_ENDING); 678 | } 679 | 680 | void LedArrayInterface::source_change_interrupt() 681 | { 682 | Serial.printf(F("ERROR (LedArrayInterface::source_change_interrupt): PSU Monitoring not supported on this device.%s"), SERIAL_LINE_ENDING); 683 | } 684 | 685 | float LedArrayInterface::get_power_source_voltage() 686 | { 687 | return -1.0; 688 | } 689 | 690 | bool LedArrayInterface::get_power_source_monitoring_state() 691 | { 692 | return false; 693 | } 694 | 695 | int16_t LedArrayInterface::get_device_power_sensing_capability() 696 | { 697 | return NO_PSU_SENSING; 698 | } 699 | 700 | void LedArrayInterface::set_power_source_monitoring_state(int new_state) 701 | { 702 | Serial.printf(F("ERROR (LedArrayInterface::set_power_source_monitoring_state): PSU Monitoring not supported on this device."), SERIAL_LINE_ENDING); 703 | } 704 | 705 | bool LedArrayInterface::is_power_source_plugged_in() 706 | { 707 | return true; 708 | } 709 | 710 | uint8_t LedArrayInterface::get_device_command_count() 711 | { 712 | return (LedArrayInterface::device_command_count); 713 | } 714 | 715 | const char * LedArrayInterface::get_device_command_name_short(int device_command_index) 716 | { 717 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 718 | return (LedArrayInterface::device_commandNamesShort[device_command_index]); 719 | else 720 | { 721 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 722 | return (""); 723 | } 724 | } 725 | 726 | const char * LedArrayInterface::get_device_command_name_long(int device_command_index) 727 | { 728 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 729 | return (LedArrayInterface::device_commandNamesLong[device_command_index]); 730 | else 731 | { 732 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 733 | return (""); 734 | } 735 | } 736 | 737 | uint32_t LedArrayInterface::get_device_command_led_list_size(int device_command_index) 738 | { 739 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 740 | { 741 | // Get stored pattern cound and led per pattern for this command 742 | uint16_t pattern_count = LedArrayInterface::device_command_pattern_dimensions[device_command_index][0]; 743 | uint16_t leds_per_pattern = LedArrayInterface::device_command_pattern_dimensions[device_command_index][1]; 744 | 745 | // Concatenate these two into 32-bit unsigned integer 746 | uint32_t concatenated = ((uint32_t)pattern_count) << 16 | leds_per_pattern; 747 | return (concatenated); 748 | } 749 | else 750 | { 751 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 752 | return 0; 753 | } 754 | } 755 | 756 | uint16_t LedArrayInterface::get_device_command_led_list_element(int device_command_index, uint16_t pattern_index, uint16_t led_index) 757 | { 758 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 759 | { 760 | uint32_t concatenated = get_device_command_led_list_size(device_command_index); 761 | uint16_t pattern_count = (uint16_t)(concatenated >> 16); 762 | uint16_t leds_per_pattern = (uint16_t)concatenated; 763 | 764 | if ((pattern_index < pattern_count) && (led_index < leds_per_pattern)) 765 | { 766 | // if (device_command_index == 0) 767 | // return (uint16_t)pgm_read_word(&(hole_led_list[pattern_index][led_index])); 768 | // else if (device_command_index == 1) 769 | // return (uint16_t)pgm_read_word(&(uv_led_list[pattern_index][led_index])); 770 | // else 771 | return 0; 772 | 773 | } 774 | else 775 | { 776 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid pattern index (%d) / led index (%d)"), pattern_index, led_index, SERIAL_LINE_ENDING); 777 | return 0; 778 | } 779 | } 780 | else 781 | { 782 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 783 | return 0; 784 | } 785 | } 786 | 787 | void LedArrayInterface::set_gsclk_frequency(uint32_t gsclk_frequency) 788 | { 789 | tlc.set_gsclk_frequency(gsclk_frequency); 790 | } 791 | 792 | uint32_t LedArrayInterface::get_gsclk_frequency() 793 | { 794 | return tlc.get_gsclk_frequency(); 795 | } 796 | 797 | void LedArrayInterface::set_sclk_baud_rate(uint32_t new_baud_rate) 798 | { 799 | tlc.set_sclk_frequency(new_baud_rate); 800 | } 801 | 802 | uint32_t LedArrayInterface::get_sclk_baud_rate() 803 | { 804 | return tlc.get_sclk_frequency(); 805 | } 806 | 807 | int8_t LedArrayInterface::set_register(uint32_t address, int8_t value) 808 | { 809 | EEPROM.write(address, value); 810 | return NO_ERROR; 811 | } 812 | 813 | int8_t LedArrayInterface::get_register(uint32_t address) 814 | { 815 | return EEPROM.read(address); 816 | } 817 | 818 | 819 | #endif 820 | -------------------------------------------------------------------------------- /illuminate/src/ledarrays/sci.round.r1.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2021, Zack Phillips 3 | Copyright (c) 2018, Zachary Phillips (UC Berkeley) 4 | All rights reserved. 5 | 6 | BSD 3-Clause License 7 | 8 | Redistribution and use in source and binary forms, with or without 9 | modification, are permitted provided that the following conditions are met: 10 | Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | Neither the name of the UC Berkeley nor the 16 | names of its contributors may be used to endorse or promote products 17 | derived from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL ZACHARY PHILLIPS (UC BERKELEY) BE LIABLE FOR ANY 23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA , OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | // Define which LED Array is used 32 | #include "../../illuminate.h" 33 | 34 | #ifdef USE_SCI_ROUND_ARRAY_R1 35 | 36 | #include "../../ledarrayinterface.h" 37 | #include "../../constants.h" 38 | #include "../TLC5955/TLC5955.h" 39 | #include 40 | 41 | // Power monitoring commands 42 | #define DEVICE_SUPPORTS_POWER_SENSING 0 43 | #define DEVICE_SUPPORTS_ACTIVE_POWER_MONITORING 0 44 | #define PSU_ACTIVE_MONITORING_COMPARATOR_MODE 5 45 | 46 | #if DEVICE_SUPPORTS_ACTIVE_POWER_MONITORING 47 | #include "../TeensyComparator/TeensyComparator.h" 48 | #endif 49 | 50 | // Global shutter state 51 | bool global_shutter_state = true; 52 | 53 | // Power sensing pin 54 | const int POWER_SENSE_PIN = 23; 55 | 56 | // Pin definitions (used internally) 57 | const int GSCLK = 6; 58 | const int LAT = 3; 59 | const int SPI_MOSI = 11; 60 | const int SPI_CLK = 13; 61 | const int TRIGGER_OUTPUT_PIN_0 = 22; 62 | const int TRIGGER_INPUT_PIN_0 = 21; 63 | const int TRIGGER_OUTPUT_COUNT = 1; 64 | const int TRIGGER_INPUT_COUNT = 1; 65 | const int COLOR_CHANNEL_COUNT = 1; 66 | const int LEDS_PER_CHIP = 48; 67 | 68 | // Power source sensing variables 69 | bool _psu_is_connected = true; 70 | bool _power_source_sensing_is_enabled = false; 71 | elapsedMillis _time_elapsed_debounce; 72 | uint32_t _warning_delay_ms = 10; 73 | 74 | // Device and Software Descriptors 75 | const char * LedArrayInterface::device_name = "sci.round"; 76 | const char * LedArrayInterface::device_hardware_revision = "r1"; 77 | const int16_t LedArrayInterface::led_count = 257; 78 | const uint16_t LedArrayInterface::center_led = 0; 79 | const int LedArrayInterface::trigger_output_count = 1; 80 | const int LedArrayInterface::trigger_input_count = 1; 81 | const int LedArrayInterface::color_channel_count = 1; 82 | const char LedArrayInterface::color_channel_names[] = {'b'}; 83 | const float LedArrayInterface::color_channel_center_wavelengths_nm[] = {475.0}; 84 | const float LedArrayInterface::color_channel_fwhm_wavelengths_nm[] = {20.0}; 85 | const int LedArrayInterface::bit_depth = 16; 86 | const bool LedArrayInterface::supports_fast_sequence = false; 87 | float LedArrayInterface::led_position_list_na[LedArrayInterface::led_count][2]; 88 | 89 | const int LedArrayInterface::trigger_output_pin_list[] = {TRIGGER_OUTPUT_PIN_0}; 90 | const int LedArrayInterface::trigger_input_pin_list[] = {TRIGGER_INPUT_PIN_0}; 91 | bool LedArrayInterface::trigger_input_state[] = {false}; 92 | 93 | int LedArrayInterface::debug = 0; 94 | 95 | const uint8_t TLC5955::chip_count = 7; // Change to reflect number of TLC chips 96 | float TLC5955::max_current_amps = 8.0; // Maximum current output, amps 97 | bool TLC5955::enforce_max_current = true; // Whether to enforce max current limit 98 | 99 | // Define dot correction, pin rgb order, and grayscale data arrays in program memory 100 | uint8_t TLC5955::_dc_data[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 101 | uint8_t TLC5955::_rgb_order[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 102 | uint16_t TLC5955::_grayscale_data[TLC5955::chip_count][TLC5955::LEDS_PER_CHIP][TLC5955::COLOR_CHANNEL_COUNT]; 103 | 104 | /**** Device-specific variables ****/ 105 | TLC5955 tlc; // TLC5955 object 106 | 107 | /**** Device-specific commands ****/ 108 | const uint8_t LedArrayInterface::device_command_count = 1; 109 | const char * LedArrayInterface::device_commandNamesShort[] = {"c"}; 110 | const char * LedArrayInterface::device_commandNamesLong[] = {"center"}; 111 | const uint16_t LedArrayInterface::device_command_pattern_dimensions[][2] = {{1,5}}; // Number of commands, number of LEDs in each command. 112 | 113 | /**** Part number and Serial number addresses in EEPROM ****/ 114 | uint16_t pn_address = 100; 115 | uint16_t sn_address = 200; 116 | 117 | PROGMEM const int16_t center_led_list[1][5] = { 118 | {0, 1, 2, 3, 4} 119 | }; 120 | 121 | // Initialize LED positions 122 | const int16_t PROGMEM LedArrayInterface::led_positions[][5] = { 123 | {0, 1, 0, 0, 0}, 124 | {1, 96, 0, -620, 0}, 125 | {2, 113, -438, -438, 0}, 126 | {3, 48, -620, 0, 0}, 127 | {4, 65, -438, 438, 0}, 128 | {5, 0, 0, 620, 0}, 129 | {6, 17, 438, 438, 0}, 130 | {7, 144, 620, 0, 0}, 131 | {8, 161, 438, -438, 0}, 132 | {9, 109, 0, -1240, 0}, 133 | {10, 98, -475, -1146, 0}, 134 | {11, 111, -877, -877, 0}, 135 | {12, 101, -1146, -475, 0}, 136 | {13, 61, -1240, 0, 0}, 137 | {14, 50, -1146, 475, 0}, 138 | {15, 63, -877, 877, 0}, 139 | {16, 53, -475, 1146, 0}, 140 | {17, 13, 0, 1240, 0}, 141 | {18, 2, 475, 1146, 0}, 142 | {19, 15, 877, 877, 0}, 143 | {20, 5, 1146, 475, 0}, 144 | {21, 157, 1240, 0, 0}, 145 | {22, 146, 1146, -475, 0}, 146 | {23, 159, 877, -877, 0}, 147 | {24, 149, 475, -1146, 0}, 148 | {25, 122, 0, -1860, 0}, 149 | {26, 110, -481, -1797, 0}, 150 | {27, 108, -930, -1611, 0}, 151 | {28, 112, -1315, -1315, 0}, 152 | {29, 99, -1611, -930, 0}, 153 | {30, 100, -1797, -481, 0}, 154 | {31, 74, -1860, 0, 0}, 155 | {32, 62, -1797, 481, 0}, 156 | {33, 60, -1611, 930, 0}, 157 | {34, 64, -1315, 1315, 0}, 158 | {35, 51, -930, 1611, 0}, 159 | {36, 52, -481, 1797, 0}, 160 | {37, 26, 0, 1860, 0}, 161 | {38, 14, 481, 1797, 0}, 162 | {39, 12, 930, 1611, 0}, 163 | {40, 16, 1315, 1315, 0}, 164 | {41, 3, 1611, 930, 0}, 165 | {42, 4, 1797, 481, 0}, 166 | {43, 170, 1860, 0, 0}, 167 | {44, 158, 1797, -481, 0}, 168 | {45, 156, 1611, -930, 0}, 169 | {46, 160, 1315, -1315, 0}, 170 | {47, 147, 930, -1611, 0}, 171 | {48, 148, 481, -1797, 0}, 172 | {49, 121, 0, -2480, 0}, 173 | {50, 134, -431, -2442, 0}, 174 | {51, 133, -848, -2330, 0}, 175 | {52, 132, -1240, -2148, 0}, 176 | {53, 120, -1594, -1900, 0}, 177 | {54, 104, -1900, -1594, 0}, 178 | {55, 103, -2148, -1240, 0}, 179 | {56, 116, -2330, -848, 0}, 180 | {57, 102, -2442, -431, 0}, 181 | {58, 73, -2480, 0, 0}, 182 | {59, 86, -2442, 431, 0}, 183 | {60, 85, -2330, 848, 0}, 184 | {61, 84, -2148, 1240, 0}, 185 | {62, 72, -1900, 1594, 0}, 186 | {63, 56, -1594, 1900, 0}, 187 | {64, 55, -1240, 2148, 0}, 188 | {65, 68, -848, 2330, 0}, 189 | {66, 54, -431, 2442, 0}, 190 | {67, 25, 0, 2480, 0}, 191 | {68, 38, 431, 2442, 0}, 192 | {69, 37, 848, 2330, 0}, 193 | {70, 36, 1240, 2148, 0}, 194 | {71, 24, 1594, 1900, 0}, 195 | {72, 8, 1900, 1594, 0}, 196 | {73, 7, 2148, 1240, 0}, 197 | {74, 20, 2330, 848, 0}, 198 | {75, 6, 2442, 431, 0}, 199 | {76, 169, 2480, 0, 0}, 200 | {77, 182, 2442, -431, 0}, 201 | {78, 181, 2330, -848, 0}, 202 | {79, 180, 2148, -1240, 0}, 203 | {80, 168, 1900, -1594, 0}, 204 | {81, 152, 1594, -1900, 0}, 205 | {82, 151, 1240, -2148, 0}, 206 | {83, 164, 848, -2330, 0}, 207 | {84, 150, 431, -2442, 0}, 208 | {85, 125, 0, -3100, 0}, 209 | {86, 123, -405, -3073, 0}, 210 | {87, 137, -802, -2994, 0}, 211 | {88, 136, -1186, -2864, 0}, 212 | {89, 138, -1550, -2685, 0}, 213 | {90, 126, -1887, -2459, 0}, 214 | {91, 142, -2192, -2192, 0}, 215 | {92, 130, -2459, -1887, 0}, 216 | {93, 119, -2685, -1550, 0}, 217 | {94, 105, -2864, -1186, 0}, 218 | {95, 115, -2994, -802, 0}, 219 | {96, 114, -3073, -405, 0}, 220 | {97, 77, -3100, 0, 0}, 221 | {98, 75, -3073, 405, 0}, 222 | {99, 89, -2994, 802, 0}, 223 | {100, 88, -2864, 1186, 0}, 224 | {101, 90, -2685, 1550, 0}, 225 | {102, 78, -2459, 1887, 0}, 226 | {103, 94, -2192, 2192, 0}, 227 | {104, 82, -1887, 2459, 0}, 228 | {105, 71, -1550, 2685, 0}, 229 | {106, 57, -1186, 2864, 0}, 230 | {107, 67, -802, 2994, 0}, 231 | {108, 66, -405, 3073, 0}, 232 | {109, 29, 0, 3100, 0}, 233 | {110, 27, 405, 3073, 0}, 234 | {111, 41, 802, 2994, 0}, 235 | {112, 40, 1186, 2864, 0}, 236 | {113, 42, 1550, 2685, 0}, 237 | {114, 30, 1887, 2459, 0}, 238 | {115, 46, 2192, 2192, 0}, 239 | {116, 34, 2459, 1887, 0}, 240 | {117, 23, 2685, 1550, 0}, 241 | {118, 9, 2864, 1186, 0}, 242 | {119, 19, 2994, 802, 0}, 243 | {120, 18, 3073, 405, 0}, 244 | {121, 173, 3100, 0, 0}, 245 | {122, 171, 3073, -405, 0}, 246 | {123, 185, 2994, -802, 0}, 247 | {124, 184, 2864, -1186, 0}, 248 | {125, 186, 2685, -1550, 0}, 249 | {126, 174, 2459, -1887, 0}, 250 | {127, 190, 2192, -2192, 0}, 251 | {128, 178, 1887, -2459, 0}, 252 | {129, 167, 1550, -2685, 0}, 253 | {130, 153, 1186, -2864, 0}, 254 | {131, 163, 802, -2994, 0}, 255 | {132, 162, 405, -3073, 0}, 256 | {133, 124, 0, -3720, 0}, 257 | {134, 135, -417, -3697, 0}, 258 | {135, 140, -828, -3627, 0}, 259 | {136, 139, -1229, -3511, 0}, 260 | {137, 128, -1614, -3352, 0}, 261 | {138, 127, -1979, -3150, 0}, 262 | {139, 143, -2319, -2908, 0}, 263 | {140, 141, -2630, -2630, 0}, 264 | {141, 131, -2908, -2319, 0}, 265 | {142, 129, -3150, -1979, 0}, 266 | {143, 118, -3352, -1614, 0}, 267 | {144, 117, -3511, -1229, 0}, 268 | {145, 106, -3627, -828, 0}, 269 | {146, 107, -3697, -417, 0}, 270 | {147, 76, -3720, 0, 0}, 271 | {148, 87, -3697, 417, 0}, 272 | {149, 92, -3627, 828, 0}, 273 | {150, 91, -3511, 1229, 0}, 274 | {151, 80, -3352, 1614, 0}, 275 | {152, 79, -3150, 1979, 0}, 276 | {153, 95, -2908, 2319, 0}, 277 | {154, 93, -2630, 2630, 0}, 278 | {155, 83, -2319, 2908, 0}, 279 | {156, 81, -1979, 3150, 0}, 280 | {157, 70, -1614, 3352, 0}, 281 | {158, 69, -1229, 3511, 0}, 282 | {159, 58, -828, 3627, 0}, 283 | {160, 59, -417, 3697, 0}, 284 | {161, 28, 0, 3720, 0}, 285 | {162, 39, 417, 3697, 0}, 286 | {163, 44, 828, 3627, 0}, 287 | {164, 43, 1229, 3511, 0}, 288 | {165, 32, 1614, 3352, 0}, 289 | {166, 31, 1979, 3150, 0}, 290 | {167, 47, 2319, 2908, 0}, 291 | {168, 45, 2630, 2630, 0}, 292 | {169, 35, 2908, 2319, 0}, 293 | {170, 33, 3150, 1979, 0}, 294 | {171, 22, 3352, 1614, 0}, 295 | {172, 21, 3511, 1229, 0}, 296 | {173, 10, 3627, 828, 0}, 297 | {174, 11, 3697, 417, 0}, 298 | {175, 172, 3720, 0, 0}, 299 | {176, 183, 3697, -417, 0}, 300 | {177, 188, 3627, -828, 0}, 301 | {178, 187, 3511, -1229, 0}, 302 | {179, 176, 3352, -1614, 0}, 303 | {180, 175, 3150, -1979, 0}, 304 | {181, 191, 2908, -2319, 0}, 305 | {182, 189, 2630, -2630, 0}, 306 | {183, 179, 2319, -2908, 0}, 307 | {184, 177, 1979, -3150, 0}, 308 | {185, 166, 1614, -3352, 0}, 309 | {186, 165, 1229, -3511, 0}, 310 | {187, 154, 828, -3627, 0}, 311 | {188, 155, 417, -3697, 0}, 312 | {189, 97, 0, -4340, 0}, 313 | {190, 231, -400, -4321, 0}, 314 | {191, 232, -797, -4266, 0}, 315 | {192, 214, -1188, -4174, 0}, 316 | {193, 213, -1568, -4047, 0}, 317 | {194, 215, -1935, -3885, 0}, 318 | {195, 202, -2285, -3690, 0}, 319 | {196, 201, -2615, -3463, 0}, 320 | {197, 203, -2924, -3207, 0}, 321 | {198, 211, -3207, -2924, 0}, 322 | {199, 210, -3463, -2615, 0}, 323 | {200, 212, -3690, -2285, 0}, 324 | {201, 196, -3885, -1935, 0}, 325 | {202, 195, -4047, -1568, 0}, 326 | {203, 197, -4174, -1188, 0}, 327 | {204, 208, -4266, -797, 0}, 328 | {205, 207, -4321, -400, 0}, 329 | {206, 209, -4340, 0, 0}, 330 | {207, 193, -4321, 400, 0}, 331 | {208, 192, -4266, 797, 0}, 332 | {209, 194, -4174, 1188, 0}, 333 | {210, 205, -4047, 1568, 0}, 334 | {211, 204, -3885, 1935, 0}, 335 | {212, 206, -3690, 2285, 0}, 336 | {213, 218, -3463, 2615, 0}, 337 | {214, 216, -3207, 2924, 0}, 338 | {215, 217, -2924, 3207, 0}, 339 | {216, 230, -2615, 3463, 0}, 340 | {217, 228, -2285, 3690, 0}, 341 | {218, 229, -1935, 3885, 0}, 342 | {219, 221, -1568, 4047, 0}, 343 | {220, 219, -1188, 4174, 0}, 344 | {221, 220, -797, 4266, 0}, 345 | {222, 233, -400, 4321, 0}, 346 | {223, 49, 0, 4340, 0}, 347 | {224, 252, 400, 4321, 0}, 348 | {225, 254, 797, 4266, 0}, 349 | {226, 266, 1188, 4174, 0}, 350 | {227, 264, 1568, 4047, 0}, 351 | {228, 265, 1935, 3885, 0}, 352 | {229, 278, 2285, 3690, 0}, 353 | {230, 276, 2615, 3463, 0}, 354 | {231, 277, 2924, 3207, 0}, 355 | {232, 269, 3207, 2924, 0}, 356 | {233, 267, 3463, 2615, 0}, 357 | {234, 268, 3690, 2285, 0}, 358 | {235, 281, 3885, 1935, 0}, 359 | {236, 279, 4047, 1568, 0}, 360 | {237, 280, 4174, 1188, 0}, 361 | {238, 284, 4266, 797, 0}, 362 | {239, 282, 4321, 400, 0}, 363 | {240, 283, 4340, 0, 0}, 364 | {241, 272, 4321, -400, 0}, 365 | {242, 270, 4266, -797, 0}, 366 | {243, 271, 4174, -1188, 0}, 367 | {244, 287, 4047, -1568, 0}, 368 | {245, 285, 3885, -1935, 0}, 369 | {246, 244, 3690, -2285, 0}, 370 | {247, 243, 3463, -2615, 0}, 371 | {248, 245, 3207, -2924, 0}, 372 | {249, 256, 2924, -3207, 0}, 373 | {250, 255, 2615, -3463, 0}, 374 | {251, 257, 2285, -3690, 0}, 375 | {252, 241, 1935, -3885, 0}, 376 | {253, 240, 1568, -4047, 0}, 377 | {254, 242, 1188, -4174, 0}, 378 | {255, 253, 797, -4266, 0}, 379 | {256, 145, 400, -4321, 0} 380 | }; 381 | 382 | bool LedArrayInterface::get_max_current_enforcement() 383 | { 384 | return TLC5955::enforce_max_current; 385 | } 386 | 387 | float LedArrayInterface::get_max_current_limit() 388 | { 389 | return TLC5955::max_current_amps; 390 | } 391 | 392 | void LedArrayInterface::set_max_current_enforcement(bool enforce) 393 | { 394 | TLC5955::enforce_max_current = enforce; 395 | } 396 | 397 | void LedArrayInterface::set_max_current_limit(float limit) 398 | { 399 | if (limit > 0) 400 | TLC5955::max_current_amps = limit; 401 | } 402 | 403 | void LedArrayInterface::not_implemented(const char * command_name) 404 | { 405 | Serial.print(F("Command ")); 406 | Serial.print(command_name); 407 | Serial.printf(F(" is not implemented for this device. %s"), SERIAL_LINE_ENDING); 408 | } 409 | 410 | uint16_t LedArrayInterface::get_led_value(uint16_t led_number, int color_channel_index) 411 | { 412 | int16_t channel_number = (int16_t)pgm_read_word(&(led_positions[led_number][1])); 413 | if (channel_number >= 0) 414 | return tlc.get_single_channel(channel_number); 415 | else 416 | { 417 | Serial.print(F("ERROR (LedArrayInterface::get_led_value) - invalid LED number (")); 418 | Serial.print(led_number); 419 | Serial.printf(F(")%s"), SERIAL_LINE_ENDING); 420 | return 0; 421 | } 422 | } 423 | 424 | void LedArrayInterface::set_pin_order(int16_t led_number, int16_t color_channel_index, uint8_t position) 425 | { 426 | not_implemented("set_pin_order"); 427 | } 428 | 429 | // Debug Variables 430 | bool LedArrayInterface::get_debug() 431 | { 432 | return (LedArrayInterface::debug); 433 | } 434 | 435 | void LedArrayInterface::set_debug(int state) 436 | { 437 | debug = state; 438 | Serial.printf(F("(LedArrayInterface::set_debug): Set debug level to %d \n"), debug); 439 | } 440 | 441 | int LedArrayInterface::send_trigger_pulse(int trigger_index, uint16_t delay_us, bool inverse_polarity) 442 | { 443 | // Get trigger pin 444 | int trigger_pin = trigger_output_pin_list[trigger_index]; 445 | 446 | if (trigger_pin > 0) 447 | { 448 | // Write active state 449 | if (inverse_polarity) 450 | digitalWriteFast(trigger_pin, LOW); 451 | else 452 | digitalWriteFast(trigger_pin, HIGH); 453 | 454 | // Delay if desired 455 | if (delay_us > 0) 456 | delayMicroseconds(delay_us); 457 | 458 | // Write normal state 459 | if (inverse_polarity) 460 | digitalWriteFast(trigger_pin, HIGH); 461 | else 462 | digitalWriteFast(trigger_pin, LOW); 463 | return 1; 464 | } 465 | else 466 | return -1; 467 | } 468 | 469 | void LedArrayInterface::set_global_shutter_state(bool state) 470 | { 471 | if (debug >= 1) 472 | { 473 | Serial.print("Setting Global Shutter state to "); 474 | Serial.print(state); 475 | Serial.print(SERIAL_LINE_ENDING); 476 | } 477 | 478 | // Store current state 479 | global_shutter_state = state; 480 | 481 | // Call the internal update method 482 | update(); 483 | } 484 | 485 | bool LedArrayInterface::get_global_shutter_state() 486 | { 487 | if (debug >= 1) 488 | { 489 | Serial.print("Getting Global Shutter state: "); 490 | Serial.print(global_shutter_state); 491 | Serial.print(SERIAL_LINE_ENDING); 492 | } 493 | 494 | return global_shutter_state; 495 | } 496 | 497 | 498 | void LedArrayInterface::update() 499 | { 500 | if (global_shutter_state) 501 | tlc.update(); 502 | else 503 | tlc.clear_without_modifying_pattern(); 504 | } 505 | 506 | void LedArrayInterface::clear() 507 | { 508 | tlc.set_all(0); 509 | update(); 510 | } 511 | 512 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, uint16_t value) 513 | { 514 | if (debug >= 2) 515 | { 516 | Serial.print(F("U16 Setting channel #")); 517 | Serial.print(channel_number); 518 | Serial.print(F(" to value ")); 519 | Serial.print(value); 520 | Serial.print(SERIAL_LINE_ENDING); 521 | } 522 | 523 | if (channel_number >= 0) 524 | tlc.set_single_channel(channel_number, value); 525 | else 526 | { 527 | Serial.print(F("Error (LedArrayInterface::set_channel): Invalid channel (")); 528 | Serial.print(channel_number); 529 | Serial.printf(F(")%s"), SERIAL_LINE_ENDING); 530 | } 531 | } 532 | 533 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, uint8_t value) 534 | { 535 | if (debug >= 2) 536 | { 537 | Serial.print("U8 Setting channel #"); 538 | Serial.print(channel_number); 539 | Serial.print(", color channel #"); 540 | Serial.print(color_channel_number); 541 | Serial.print(SERIAL_LINE_ENDING); 542 | } 543 | set_channel(channel_number, color_channel_number, (uint16_t)( value * UINT16_MAX / UINT8_MAX)); 544 | } 545 | 546 | void LedArrayInterface::set_channel(int16_t channel_number, int16_t color_channel_number, bool value) 547 | { 548 | if (debug >= 2) 549 | { 550 | Serial.print("U8 Setting channel #"); 551 | Serial.print(channel_number); 552 | Serial.print(", color channel #"); 553 | Serial.print(color_channel_number); 554 | Serial.print(SERIAL_LINE_ENDING); 555 | } 556 | set_channel(channel_number, color_channel_number, (uint16_t) (value * UINT16_MAX)); 557 | } 558 | 559 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, uint16_t value) 560 | { 561 | int16_t channel_number = -1; 562 | 563 | if (led_number < 0) 564 | { 565 | for (uint16_t led_index = 0; led_index < led_count; led_index++) 566 | { 567 | channel_number = (int16_t)pgm_read_word(&(led_positions[led_index][1])); 568 | set_channel(channel_number, color_channel_number, value); 569 | } 570 | } 571 | else 572 | { 573 | channel_number = (int16_t)pgm_read_word(&(led_positions[led_number][1])); 574 | set_channel(channel_number, color_channel_number, value); 575 | } 576 | 577 | if (debug >= 2) 578 | { 579 | Serial.print("U16 Set led #"); 580 | Serial.print(led_number); 581 | Serial.print(", channel #"); 582 | Serial.print(channel_number); 583 | Serial.print(", color channel #"); 584 | Serial.print(color_channel_number); 585 | Serial.print(" to value "); 586 | Serial.print(value); 587 | Serial.print(SERIAL_LINE_ENDING); 588 | } 589 | } 590 | 591 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, uint8_t value) 592 | { 593 | if (debug >= 2) 594 | { 595 | Serial.print("U8 Setting led #"); 596 | Serial.print(led_number); 597 | Serial.print(", color channel #"); 598 | Serial.print(color_channel_number); 599 | Serial.print(SERIAL_LINE_ENDING); 600 | } 601 | set_led(led_number, color_channel_number, (uint16_t) (value * UINT16_MAX / UINT8_MAX)); 602 | } 603 | 604 | void LedArrayInterface::set_led(int16_t led_number, int16_t color_channel_number, bool value) 605 | { 606 | if (debug >= 2) 607 | { 608 | Serial.print("B Setting led #"); 609 | Serial.print(led_number); 610 | Serial.print(", color channel #"); 611 | Serial.print(color_channel_number); 612 | Serial.print(SERIAL_LINE_ENDING); 613 | } 614 | set_led(led_number, color_channel_number, (uint16_t) (value * UINT16_MAX)); 615 | } 616 | 617 | int8_t LedArrayInterface::device_reset() 618 | { 619 | return device_setup(); 620 | } 621 | 622 | int8_t LedArrayInterface::device_setup() 623 | { 624 | pinMode(LAT, OUTPUT); 625 | 626 | // Initialize TLC5955 627 | tlc.init(LAT, SPI_MOSI, SPI_CLK, GSCLK); 628 | 629 | // We must set dot correction values, so set them all to the brightest adjustment 630 | tlc.set_all_dc_data(127); 631 | 632 | // Set Max Current Values (see TLC5955 datasheet) 633 | tlc.set_max_current(3, 3, 3); // Go up to 7 634 | 635 | // Set Function Control Data Latch values. See the TLC5955 Datasheet for the purpose of this latch. 636 | // DSPRPT, TMGRST, RFRESH, ESPWM, LSDVLT 637 | tlc.set_function_data(true, true, false, true, true); // WORKS with fast update 638 | 639 | // set all brightness levels to max (127) 640 | int currentR = 127; 641 | 642 | int currentB = 127; 643 | int currentG = 127; 644 | tlc.set_brightness_current(currentR, currentB, currentG); 645 | 646 | // Update Control Register 647 | tlc.update_control(); 648 | clear(); 649 | tlc.update_control(); 650 | 651 | // Update the GS register (ideally LEDs should be dark up to here) 652 | clear(); 653 | 654 | // Output trigger pin 655 | pinMode(LedArrayInterface::trigger_output_pin_list[0], OUTPUT); 656 | digitalWriteFast(LedArrayInterface::trigger_output_pin_list[0], LOW); 657 | 658 | // Input trigger pin 659 | attachInterrupt(digitalPinToInterrupt(trigger_input_pin_list[0]), trigger_pin_interrupt_0, CHANGE); 660 | 661 | return NO_ERROR; 662 | } 663 | 664 | void LedArrayInterface::trigger_pin_interrupt_0() 665 | { 666 | bool previous_state = trigger_input_state[0]; 667 | trigger_input_state[0] = digitalReadFast(trigger_input_pin_list[0]); 668 | bool new_state = trigger_input_state[0]; 669 | if (debug >= 2) 670 | Serial.printf("Recieved trigger pulse on pin 0. Previous state: %s New state: %s%s", previous_state ? "HIGH" : "LOW", new_state ? "HIGH" : "LOW", SERIAL_LINE_ENDING); 671 | } 672 | 673 | 674 | void LedArrayInterface::source_change_interrupt() 675 | { 676 | Serial.printf(F("ERROR (LedArrayInterface::source_change_interrupt): PSU Monitoring not supported on this device."), SERIAL_LINE_ENDING); 677 | } 678 | 679 | float LedArrayInterface::get_power_source_voltage() 680 | { 681 | return -1.0; 682 | } 683 | 684 | bool LedArrayInterface::get_power_source_monitoring_state() 685 | { 686 | return false; 687 | } 688 | 689 | int16_t LedArrayInterface::get_device_power_sensing_capability() 690 | { 691 | return NO_PSU_SENSING; 692 | } 693 | 694 | void LedArrayInterface::set_power_source_monitoring_state(int new_state) 695 | { 696 | Serial.printf(F("ERROR (LedArrayInterface::set_power_source_monitoring_state): PSU Monitoring not supported on this device."), SERIAL_LINE_ENDING); 697 | } 698 | 699 | bool LedArrayInterface::is_power_source_plugged_in() 700 | { 701 | return true; 702 | } 703 | 704 | uint8_t LedArrayInterface::get_device_command_count() 705 | { 706 | return (LedArrayInterface::device_command_count); 707 | } 708 | 709 | const char * LedArrayInterface::get_device_command_name_short(int device_command_index) 710 | { 711 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 712 | return (LedArrayInterface::device_commandNamesShort[device_command_index]); 713 | else 714 | { 715 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 716 | return (""); 717 | } 718 | } 719 | 720 | const char * LedArrayInterface::get_device_command_name_long(int device_command_index) 721 | { 722 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 723 | return (LedArrayInterface::device_commandNamesLong[device_command_index]); 724 | else 725 | { 726 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 727 | return (""); 728 | } 729 | } 730 | 731 | uint32_t LedArrayInterface::get_device_command_led_list_size(int device_command_index) 732 | { 733 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 734 | { 735 | // Get stored pattern cound and led per pattern for this command 736 | uint16_t pattern_count = LedArrayInterface::device_command_pattern_dimensions[device_command_index][0]; 737 | uint16_t leds_per_pattern = LedArrayInterface::device_command_pattern_dimensions[device_command_index][1]; 738 | 739 | // Concatenate these two into 32-bit unsigned integer 740 | uint32_t concatenated = ((uint32_t)pattern_count) << 16 | leds_per_pattern; 741 | return (concatenated); 742 | } 743 | else 744 | { 745 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 746 | return 0; 747 | } 748 | } 749 | 750 | uint16_t LedArrayInterface::get_device_command_led_list_element(int device_command_index, uint16_t pattern_index, uint16_t led_index) 751 | { 752 | if ((device_command_index >= 0) && (device_command_index < LedArrayInterface::device_command_count)) 753 | { 754 | uint32_t concatenated = get_device_command_led_list_size(device_command_index); 755 | uint16_t pattern_count = (uint16_t)(concatenated >> 16); 756 | uint16_t leds_per_pattern = (uint16_t)concatenated; 757 | 758 | if ((pattern_index < pattern_count) && (led_index < leds_per_pattern)) 759 | { 760 | // if (device_command_index == 0) 761 | // return (uint16_t)pgm_read_word(&(hole_led_list[pattern_index][led_index])); 762 | // else if (device_command_index == 1) 763 | // return (uint16_t)pgm_read_word(&(uv_led_list[pattern_index][led_index])); 764 | // else 765 | return 0; 766 | 767 | } 768 | else 769 | { 770 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid pattern index (%d) / led index (%d)"), pattern_index, led_index, SERIAL_LINE_ENDING); 771 | return 0; 772 | } 773 | } 774 | else 775 | { 776 | Serial.printf(F("ERROR (LedArrayInterface::get_device_command_led_list_size): Invalid device command index (%d)"), device_command_index, SERIAL_LINE_ENDING); 777 | return 0; 778 | } 779 | } 780 | 781 | void LedArrayInterface::set_gsclk_frequency(uint32_t gsclk_frequency) 782 | { 783 | tlc.set_gsclk_frequency(gsclk_frequency); 784 | } 785 | 786 | uint32_t LedArrayInterface::get_gsclk_frequency() 787 | { 788 | return tlc.get_gsclk_frequency(); 789 | } 790 | 791 | void LedArrayInterface::set_sclk_baud_rate(uint32_t new_baud_rate) 792 | { 793 | tlc.set_sclk_frequency(new_baud_rate); 794 | } 795 | 796 | uint32_t LedArrayInterface::get_sclk_baud_rate() 797 | { 798 | return tlc.get_sclk_frequency(); 799 | } 800 | 801 | int8_t LedArrayInterface::set_register(uint32_t address, int8_t value) 802 | { 803 | EEPROM.write(address, value); 804 | return NO_ERROR; 805 | } 806 | 807 | int8_t LedArrayInterface::get_register(uint32_t address) 808 | { 809 | return EEPROM.read(address); 810 | } 811 | 812 | 813 | #endif 814 | --------------------------------------------------------------------------------