From a19475e7e6843c86ff35c66597a921b02d82af15 Mon Sep 17 00:00:00 2001 From: Oliver Atkinson Date: Wed, 15 Jan 2025 15:12:17 -0700 Subject: [PATCH] init --- .gitignore | 5 ++ .vscode/extensions.json | 10 +++ include/README | 39 +++++++++++ lib/README | 46 +++++++++++++ platformio.ini | 16 +++++ src/cmd/cmd.cpp | 140 ++++++++++++++++++++++++++++++++++++++ src/cmd/write.h | 146 ++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 26 +++++++ test/README | 11 +++ test/test.cpp | 33 +++++++++ 10 files changed, 472 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 include/README create mode 100644 lib/README create mode 100644 platformio.ini create mode 100644 src/cmd/cmd.cpp create mode 100644 src/cmd/write.h create mode 100644 src/main.cpp create mode 100644 test/README create mode 100644 test/test.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..d9d590c --- /dev/null +++ b/platformio.ini @@ -0,0 +1,16 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:nanoatmega328] +platform = atmelavr +board = nanoatmega328 +framework = arduino +test_framework = unity +; build_flags = "-D UBRR1H" diff --git a/src/cmd/cmd.cpp b/src/cmd/cmd.cpp new file mode 100644 index 0000000..3c1da04 --- /dev/null +++ b/src/cmd/cmd.cpp @@ -0,0 +1,140 @@ +#include +#include "write.h" + +Addr::Addr(InfoCommands cmd) +{ + device_address = 0x36; + class_address = 0x74; + rw_flag = 0x01; + + switch (cmd) + { + case Model: + subclass_address = 0x02; + break; + case FPGA_Ver: + subclass_address = 0x03; + break; + case FPGA_Comp_Time: + subclass_address = 0x04; + break; + case Module_Software_Ver: + subclass_address = 0x05; + break; + case Module_Software_Comp_Time: + subclass_address = 0x06; + break; + case Camera_Calibration_Ver_Time: + subclass_address = 0x0B; + break; + case ISP_Parameter_Ver: + subclass_address = 0x0C; + break; + case Init_State: + // TODO why is this one so different? + class_address = 0x7D; + subclass_address = 0x06; + rw_flag = 0x00; + } +} + +Addr::Addr(FuncCommands cmd) +{ + device_address = 0x36; + rw_flag = 0x00; + + switch (cmd) + { + case Manual_Shutter_Calibration: + class_address = 0x7C; + subclass_address = 0x02; + break; + case Manual_Background_Correction: + class_address = 0x7C; + subclass_address = 0x03; + break; + case Automatic_Shutter_Control: + class_address = 0x7C; + subclass_address = 0x04; + break; + case Automatic_Shutter_Switching_Interval: + class_address = 0x7C; + subclass_address = 0x05; + break; + case Vignetting_Correction: + class_address = 0x7C; + subclass_address = 0x0C; + break; + case Brightness: + class_address = 0x78; + subclass_address = 0x02; + break; + case Contrast: + class_address = 0x78; + subclass_address = 0x03; + break; + case Digital_Enhancement: + class_address = 0x78; + subclass_address = 0x10; + break; + case Static_De_Noising: + class_address = 0x78; + subclass_address = 0x15; + break; + case Dynamic_De_Noising: + class_address = 0x78; + subclass_address = 0x16; + break; + case Defective_Pixel_Correction: + class_address = 0x78; + subclass_address = 0x1A; + break; + case Palette_Setting: + class_address = 0x78; + subclass_address = 0x20; + break; + case Factory_Reset: + class_address = 0x74; + subclass_address = 0x0F; + break; + case Save_Settings: + class_address = 0x74; + subclass_address = 0x10; + break; + case Mirroring: + class_address = 0x70; + subclass_address = 0x11; + break; + } +} + +void command(Addr cmd, uint8_t data_in[], int data_len, uint8_t buffer[]) +{ + char begin = 0xF0; + char size = data_len + 4; + char end = 0xFF; + + // GET CHECKSUM ////////////////////////////// + // add all addresses + rw_flag + data and take the last 8 bits as the checksum + int all_data = 0; + all_data += cmd.device_address; + all_data += cmd.class_address; + all_data += cmd.subclass_address; + all_data += cmd.rw_flag; + for (int i = 0; i < data_len; i++) + all_data += data_in[i]; + char checksum = all_data & 0xFF; + // /////////////////////////////////////////// + + // CREATE OUTPUT BUFFER ////////////////////// + buffer[0] = begin; + buffer[1] = size; + buffer[2] = cmd.device_address; + buffer[3] = cmd.class_address; + buffer[4] = cmd.subclass_address; + buffer[5] = cmd.rw_flag; + for (int i = 0; i < data_len; i++) // copy in the data to this array + buffer[i + 6] = data_in[i]; + buffer[6 + data_len] = checksum; + buffer[7 + data_len] = end; +} diff --git a/src/cmd/write.h b/src/cmd/write.h new file mode 100644 index 0000000..8d4634d --- /dev/null +++ b/src/cmd/write.h @@ -0,0 +1,146 @@ + +// Table 3-1, Information query commands +// Default data needs to be set to "none": `0x00` +enum InfoCommands +{ + // Note on time: + // 0x20170101 indicates the time is January 1, 2017. + + // Returns 5 bytes - Convert to ascii + Model, + // Returns 3 bytes - 0x011420 means v1.14.20 + FPGA_Ver, + // Returns 4 bytes - Big endian time + FPGA_Comp_Time, + // Returns 3 bytes - 0x010410 means v1.4.10 + Module_Software_Ver, + // Returns 4 bytes - Big endian time + Module_Software_Comp_Time, + // Returns 4 bytes - Big endian time + Camera_Calibration_Ver_Time, + // Returns 4 bytes + ISP_Parameter_Ver, + // Returns 1 byte - Loading: `0x00`, or Streaming: `0x01` + Init_State, +}; + +// Table 3-2, Function setting commands +enum FuncCommands +{ + // TODO write only? + // Data none? + Manual_Shutter_Calibration, + // TODO write only? + // Data none? + Manual_Background_Correction, + // @brief Set shutter control. Data: + // + // `0x00` Automatic control off + // + // `0x01` Automatic switching, timing control + // + // `0x02` Automatic switching, temperature difference control + // + // `0x03` (Default) Full-automatic control + Automatic_Shutter_Control, + // Setting the shutter interval in minutes, 2 bytes. + // Default, 10min: `0x00 0x0A` "Not recommended for users to modify" + Automatic_Shutter_Switching_Interval, + // TODO + Vignetting_Correction, + // 1 byte, default: `0x32` (50), range: 0~100. + Brightness, + // 1 byte, default: `0x32` (50), range: 0~100. + Contrast, + // 1 byte, default: `0x32` (50), range: 0~100. + Digital_Enhancement, + // 1 byte, default: `0x32` (50), range: 0~100. + Static_De_Noising, + // 1 byte, default: `0x32` (50), range: 0~100. + Dynamic_De_Noising, + // `0x00`: Turn off the cursor display + // + // `0x0F`: Turn on the cursor display + // + // `0x02`: Cursor up + // + // `0x03`: Cursor down + // + // `0x04`: Cursor shifted left + // + // `0x05`: Cursor shifted right + // + // `0x06`: Cursor to the center + // + // `0x0D`: Add the pixel to the defective pixel table. + // + // `0x0E`: Remove the pixel from the defective pixel table. + // + // `0x2N`: Cursor up for N pixels (N: 0x1~0xF) + // + // `0x3N`: Cursor down for N pixels (N: 0x1~0xF) + // + // `0x4N`: Cursor shifted left for N pixels (N: 0x1~0xF) + // + // `0x5N`: Cursor shifted right for N pixels (N: 0x1~0xF) + Defective_Pixel_Correction, + // `0x00`: White Hot (Default) + // + // `0x01`: Black Hot + // + // `0x02`: Fusion 1 + // + // `0x03`: Rainbow + // + // `0x04`: Fusion 2 + // + // `0x05`: Iron Red 1 + // + // `0x06`: Iron Red 2 + // + // `0x07`: Dark Brown + // + // `0x08`: Color 1 + // + // `0x09`: Color 2 + // + // `0x0A`: Ice Fire + // + // `0x0B`: Rain + // + // `0x0C`: Green Hot + // + // `0x0D`: Red Hot + // + // `0x0E`: Deep Blue + Palette_Setting, + // Send `0x00` as data (default)(none) + Factory_Reset, + // Send `0x00` as data (default)(none) + Save_Settings, + // `0x00`: No mirroring. + // + // `0x01`: Central mirroring. + // + // `0x02`: Left and right mirroring. + // + // `0x03`: Up and down mirroring. + Mirroring, +}; + +class Addr +{ + +public: + uint8_t device_address, class_address, subclass_address, rw_flag; + + explicit Addr(FuncCommands cmd); + explicit Addr(InfoCommands cmd); +}; + +/// @brief Sets up command to send to camera. +/// @param cmd Addr object of the command you want to send. +/// @param data_in Any data that should go along with it. If there is no data then send [0x00] +/// @param data_len Length of data array. +/// @param buffer Buffer to output into. This should be 8 larger than the data array. +void command(Addr cmd, uint8_t data_in[], int data_len, uint8_t buffer[]); diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..fc3a53a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,26 @@ +#include +#include +#include +#include "cmd/write.h" + +SoftwareSerial cam_serial(3, 2); + +void setup() +{ + Serial.begin(115200); + cam_serial.begin(115200); + cam_serial.listen(); // this isn't strictly nsessray +} + +void loop() +{ + uint8_t buf[9]; + for (unsigned char i = 0; i < 100; i++) + { + uint8_t data[] = {i}; + command(*new Addr(FuncCommands::Brightness), data, 1, buf); + cam_serial.write(buf, 9); // software serial automatically flushes + + delay(100); + } +} diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html diff --git a/test/test.cpp b/test/test.cpp new file mode 100644 index 0000000..5f39fe1 --- /dev/null +++ b/test/test.cpp @@ -0,0 +1,33 @@ +#include "unity.h" +#include "cmd/write.h" + +void setUp() {} +void tearDown() {} + +void test_byte_ordering() { + + uint8_t expected[9] = { + 0xF0, // Begin + 0x05, // size ({data bytes}+4) + 0x36, // dev addr + 0x78, // class addr + 0x02, // subclass addr + 0x00, // r/w flag (0 = write, 1 = read) + 0x64, // data + 0x14, // Checksum (dev addr + sub addr + class addr + rw flag + data) & 0xFF + 0xFF, // End + }; + + Addr cmd = *new Addr(FuncCommands::Brightness); + uint8_t data[] = {0x64}; + uint8_t buf[1+8]; + command(cmd, data, 1, buf); + + TEST_ASSERT_EQUAL(expected, buf); +} + +int main() { + UNITY_BEGIN(); + RUN_TEST(test_byte_ordering); + return UNITY_END(); +}