From 4dde197ccaaa53f38c2944750de68396c7629fd7 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Wed, 4 May 2022 13:01:10 +0200 Subject: [PATCH] examples: Use components from idf-extra-components repository --- .../common_components/pcap/CMakeLists.txt | 2 - .../common_components/pcap/include/pcap.h | 128 --- examples/common_components/pcap/src/pcap.c | 224 ---- .../common_components/pid_ctrl/CMakeLists.txt | 4 - .../pid_ctrl/include/pid_ctrl.h | 100 -- .../common_components/pid_ctrl/src/pid_ctrl.c | 140 --- .../common_components/qrcode/CMakeLists.txt | 3 - examples/common_components/qrcode/README.md | 9 - .../qrcode/esp_qrcode_main.c | 121 -- .../qrcode/esp_qrcode_wrapper.c | 29 - .../common_components/qrcode/include/qrcode.h | 104 -- examples/common_components/qrcode/qrcodegen.c | 1022 ----------------- examples/common_components/qrcode/qrcodegen.h | 311 ----- .../network/simple_sniffer/CMakeLists.txt | 2 - .../simple_sniffer/main/idf_component.yml | 2 + .../mcpwm_bdc_speed_control/CMakeLists.txt | 2 - .../main/idf_component.yml | 2 + .../provisioning/wifi_prov_mgr/CMakeLists.txt | 2 +- .../wifi_prov_mgr/main/idf_component.yml | 2 + .../dpp-enrollee/CMakeLists.txt | 2 - .../dpp-enrollee/main/idf_component.yml | 2 + tools/ci/check_copyright_ignore.txt | 7 - 22 files changed, 9 insertions(+), 2211 deletions(-) delete mode 100644 examples/common_components/pcap/CMakeLists.txt delete mode 100644 examples/common_components/pcap/include/pcap.h delete mode 100644 examples/common_components/pcap/src/pcap.c delete mode 100644 examples/common_components/pid_ctrl/CMakeLists.txt delete mode 100644 examples/common_components/pid_ctrl/include/pid_ctrl.h delete mode 100644 examples/common_components/pid_ctrl/src/pid_ctrl.c delete mode 100644 examples/common_components/qrcode/CMakeLists.txt delete mode 100644 examples/common_components/qrcode/README.md delete mode 100644 examples/common_components/qrcode/esp_qrcode_main.c delete mode 100644 examples/common_components/qrcode/esp_qrcode_wrapper.c delete mode 100644 examples/common_components/qrcode/include/qrcode.h delete mode 100644 examples/common_components/qrcode/qrcodegen.c delete mode 100644 examples/common_components/qrcode/qrcodegen.h create mode 100644 examples/network/simple_sniffer/main/idf_component.yml create mode 100644 examples/peripherals/mcpwm/mcpwm_bdc_speed_control/main/idf_component.yml create mode 100644 examples/provisioning/wifi_prov_mgr/main/idf_component.yml create mode 100644 examples/wifi/wifi_easy_connect/dpp-enrollee/main/idf_component.yml diff --git a/examples/common_components/pcap/CMakeLists.txt b/examples/common_components/pcap/CMakeLists.txt deleted file mode 100644 index 21b6fac3a0..0000000000 --- a/examples/common_components/pcap/CMakeLists.txt +++ /dev/null @@ -1,2 +0,0 @@ -idf_component_register(SRCS "src/pcap.c" - INCLUDE_DIRS "include") diff --git a/examples/common_components/pcap/include/pcap.h b/examples/common_components/pcap/include/pcap.h deleted file mode 100644 index 2bb9d5f775..0000000000 --- a/examples/common_components/pcap/include/pcap.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define PCAP_DEFAULT_VERSION_MAJOR 0x02 /*!< Major Version */ -#define PCAP_DEFAULT_VERSION_MINOR 0x04 /*!< Minor Version */ -#define PCAP_DEFAULT_TIME_ZONE_GMT 0x00 /*!< Time Zone */ - -/** - * @brief Type of pcap file handle - * - */ -typedef struct pcap_file_t *pcap_file_handle_t; - -/** -* @brief Link layer Type Definition, used for Pcap reader to decode payload -* -*/ -typedef enum { - PCAP_LINK_TYPE_LOOPBACK = 0, /*!< Loopback devices, except for later OpenBSD */ - PCAP_LINK_TYPE_ETHERNET = 1, /*!< Ethernet, and Linux loopback devices */ - PCAP_LINK_TYPE_TOKEN_RING = 6, /*!< 802.5 Token Ring */ - PCAP_LINK_TYPE_ARCNET = 7, /*!< ARCnet */ - PCAP_LINK_TYPE_SLIP = 8, /*!< SLIP */ - PCAP_LINK_TYPE_PPP = 9, /*!< PPP */ - PCAP_LINK_TYPE_FDDI = 10, /*!< FDDI */ - PCAP_LINK_TYPE_ATM = 100, /*!< LLC/SNAP encapsulated ATM */ - PCAP_LINK_TYPE_RAW_IP = 101, /*!< Raw IP, without link */ - PCAP_LINK_TYPE_BSD_SLIP = 102, /*!< BSD/OS SLIP */ - PCAP_LINK_TYPE_BSD_PPP = 103, /*!< BSD/OS PPP */ - PCAP_LINK_TYPE_CISCO_HDLC = 104, /*!< Cisco HDLC */ - PCAP_LINK_TYPE_802_11 = 105, /*!< 802.11 */ - PCAP_LINK_TYPE_BSD_LOOPBACK = 108, /*!< OpenBSD loopback devices(with AF_value in network byte order) */ - PCAP_LINK_TYPE_LOCAL_TALK = 114 /*!< LocalTalk */ -} pcap_link_type_t; - -/** -* @brief Pcap configuration Type Definition -* -*/ -typedef struct { - FILE *fp; /*!< Pointer to a standard file handle */ - unsigned int major_version; /*!< Pcap version: major */ - unsigned int minor_version; /*!< Pcap version: minor */ - unsigned int time_zone; /*!< Pcap timezone code */ - struct { - unsigned int little_endian: 1; /*!< Whether the pcap file is recored in little endian format */ - } flags; -} pcap_config_t; - -/** - * @brief Create a new pcap session, and returns pcap file handle - * - * @note This function won't create the low level FILE* object, the user should take care of the creation of the File Stream. - * - * @param[in] config pcap file configuration - * @param[out] ret_pcap Returned pcap file handle - * @return - * - ESP_OK: Create pcap file successfully - * - ESP_ERR_INVALID_ARG: Create pcap file failed because of invalid argument - * - ESP_ERR_NO_MEM: Create pcap file failed because out of memory - * - ESP_FAIL: Create pcap file failed - */ -esp_err_t pcap_new_session(const pcap_config_t *config, pcap_file_handle_t *ret_pcap); - -/** - * @brief Delete the pcap session, and close the File Stream - * - * @param[in] pcap pcap file handle created by `pcap_new_session()` - * @return - * - ESP_OK: Delete pcap session successfully - * - ESP_ERR_INVALID_ARG: Delete pcap session failed because of invalid argument - * - ESP_FAIL: Delete pcap session failed - */ -esp_err_t pcap_del_session(pcap_file_handle_t pcap); - -/** - * @brief Write pcap file header - * - * @param[in] pcap pcap file handle created by `pcap_new_session()` - * @param[in] link_type Network link layer type - * @return - * - ESP_OK: Write pcap file header successfully - * - ESP_ERR_INVALID_ARG: Write pcap file header failed because of invalid argument - * - ESP_FAIL: Write pcap file header failed - */ -esp_err_t pcap_write_header(pcap_file_handle_t pcap, pcap_link_type_t link_type); - -/** - * @brief Capture one packet into pcap file - * - * @param[in] pcap pcap file handle created by `pcap_new_session()` - * @param[in] payload pointer of the captured data buffer - * @param[in] length length of captured data buffer - * @param[in] seconds second of capture time - * @param[in] microseconds microsecond of capture time - * @return - * - ESP_OK: Write network packet into pcap file successfully - * - ESP_ERR_INVALID_ARG: Write network packet into pcap file failed because of invalid argument - * - ESP_FAIL: Write network packet into pcap file failed - */ -esp_err_t pcap_capture_packet(pcap_file_handle_t pcap, void *payload, uint32_t length, uint32_t seconds, uint32_t microseconds); - -/** - * @brief Print the summary of pcap file into stream - * - * @param[in] pcap pcap file handle created by `pcap_new_session()` - * @param[in] print_file the file stream to save the summary - * @return - * - ESP_OK: Print pcap file summary successfully - * - ESP_ERR_INVALID_ARG: Print pcap file summary failed because of invalid argument - * - ESP_FAIL: Print pcap file summary failed - */ -esp_err_t pcap_print_summary(pcap_file_handle_t pcap, FILE *print_file); - -#ifdef __cplusplus -} -#endif diff --git a/examples/common_components/pcap/src/pcap.c b/examples/common_components/pcap/src/pcap.c deleted file mode 100644 index a3efae7c3f..0000000000 --- a/examples/common_components/pcap/src/pcap.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include "esp_log.h" -#include "esp_check.h" -#include "pcap.h" - -static const char *TAG = "pcap"; - -#define PCAP_MAGIC_BIG_ENDIAN 0xA1B2C3D4 /*!< Big-Endian */ -#define PCAP_MAGIC_LITTLE_ENDIAN 0xD4C3B2A1 /*!< Little-Endian */ - -typedef struct pcap_file_t pcap_file_t; - -/** - * @brief Pcap File Header - * - */ -typedef struct { - uint32_t magic; /*!< Magic Number */ - uint16_t major; /*!< Major Version */ - uint16_t minor; /*!< Minor Version */ - uint32_t zone; /*!< Time Zone Offset */ - uint32_t sigfigs; /*!< Timestamp Accuracy */ - uint32_t snaplen; /*!< Max Length to Capture */ - uint32_t link_type; /*!< Link Layer Type */ -} pcap_file_header_t; - -/** - * @brief Pcap Packet Header - * - */ -typedef struct { - uint32_t seconds; /*!< Number of seconds since January 1st, 1970, 00:00:00 GMT */ - uint32_t microseconds; /*!< Number of microseconds when the packet was captured (offset from seconds) */ - uint32_t capture_length; /*!< Number of bytes of captured data, no longer than packet_length */ - uint32_t packet_length; /*!< Actual length of current packet */ -} pcap_packet_header_t; - -/** - * @brief Pcap Runtime Handle - * - */ -struct pcap_file_t { - FILE *file; /*!< File handle */ - pcap_link_type_t link_type; /*!< Pcap Link Type */ - unsigned int major_version; /*!< Pcap version: major */ - unsigned int minor_version; /*!< Pcap version: minor */ - unsigned int time_zone; /*!< Pcap timezone code */ - uint32_t endian_magic; /*!< Magic value related to endian format */ -}; - -esp_err_t pcap_new_session(const pcap_config_t *config, pcap_file_handle_t *ret_pcap) -{ - esp_err_t ret = ESP_OK; - pcap_file_t *pcap = NULL; - ESP_GOTO_ON_FALSE(config && ret_pcap, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - ESP_GOTO_ON_FALSE(config->fp, ESP_ERR_INVALID_ARG, err, TAG, "pcap file handle can't be NULL"); - pcap = calloc(1, sizeof(pcap_file_t)); - ESP_GOTO_ON_FALSE(pcap, ESP_ERR_NO_MEM, err, TAG, "no mem for pcap file object"); - pcap->file = config->fp; - pcap->major_version = config->major_version; - pcap->minor_version = config->minor_version; - pcap->endian_magic = config->flags.little_endian ? PCAP_MAGIC_LITTLE_ENDIAN : PCAP_MAGIC_BIG_ENDIAN; - pcap->time_zone = config->time_zone; - *ret_pcap = pcap; - return ret; -err: - if (pcap) { - free(pcap); - } - return ret; -} - -esp_err_t pcap_del_session(pcap_file_handle_t pcap) -{ - ESP_RETURN_ON_FALSE(pcap, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - if (pcap->file) { - fclose(pcap->file); - pcap->file = NULL; - } - free(pcap); - return ESP_OK; -} - -esp_err_t pcap_write_header(pcap_file_handle_t pcap, pcap_link_type_t link_type) -{ - ESP_RETURN_ON_FALSE(pcap, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - /* Write Pcap File header */ - pcap_file_header_t header = { - .magic = pcap->endian_magic, - .major = pcap->major_version, - .minor = pcap->minor_version, - .zone = pcap->time_zone, - .sigfigs = 0, - .snaplen = 0x40000, - .link_type = link_type, - }; - size_t real_write = fwrite(&header, sizeof(header), 1, pcap->file); - ESP_RETURN_ON_FALSE(real_write == 1, ESP_FAIL, TAG, "write pcap file header failed"); - /* Save the link type to pcap file object */ - pcap->link_type = link_type; - /* Flush content in the buffer into device */ - fflush(pcap->file); - return ESP_OK; -} - -esp_err_t pcap_capture_packet(pcap_file_handle_t pcap, void *payload, uint32_t length, uint32_t seconds, uint32_t microseconds) -{ - ESP_RETURN_ON_FALSE(pcap && payload, ESP_ERR_INVALID_ARG, TAG, "invalid argumnet"); - size_t real_write = 0; - pcap_packet_header_t header = { - .seconds = seconds, - .microseconds = microseconds, - .capture_length = length, - .packet_length = length - }; - real_write = fwrite(&header, sizeof(header), 1, pcap->file); - ESP_RETURN_ON_FALSE(real_write == 1, ESP_FAIL, TAG, "write packet header failed"); - real_write = fwrite(payload, sizeof(uint8_t), length, pcap->file); - ESP_RETURN_ON_FALSE(real_write == length, ESP_FAIL, TAG, "write packet payload failed"); - /* Flush content in the buffer into device */ - fflush(pcap->file); - return ESP_OK; -} - -esp_err_t pcap_print_summary(pcap_file_handle_t pcap, FILE *print_file) -{ - esp_err_t ret = ESP_OK; - long size = 0; - char *packet_payload = NULL; - ESP_RETURN_ON_FALSE(pcap && print_file, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - // get file size - fseek(pcap->file, 0L, SEEK_END); - size = ftell(pcap->file); - fseek(pcap->file, 0L, SEEK_SET); - // file empty is allowed, so return ESP_OK - ESP_RETURN_ON_FALSE(size, ESP_OK, TAG, "pcap file is empty"); - // packet index (by bytes) - uint32_t index = 0; - pcap_file_header_t file_header; - size_t real_read = fread(&file_header, sizeof(pcap_file_header_t), 1, pcap->file); - ESP_RETURN_ON_FALSE(real_read == 1, ESP_FAIL, TAG, "read pcap file header failed"); - index += sizeof(pcap_file_header_t); - //print pcap header information - fprintf(print_file, "------------------------------------------------------------------------\n"); - fprintf(print_file, "Pcap packet Head:\n"); - fprintf(print_file, "------------------------------------------------------------------------\n"); - fprintf(print_file, "Magic Number: %x\n", file_header.magic); - fprintf(print_file, "Major Version: %d\n", file_header.major); - fprintf(print_file, "Minor Version: %d\n", file_header.minor); - fprintf(print_file, "SnapLen: %d\n", file_header.snaplen); - fprintf(print_file, "LinkType: %d\n", file_header.link_type); - fprintf(print_file, "------------------------------------------------------------------------\n"); - uint32_t packet_num = 0; - pcap_packet_header_t packet_header; - while (index < size) { - real_read = fread(&packet_header, sizeof(pcap_packet_header_t), 1, pcap->file); - ESP_GOTO_ON_FALSE(real_read == 1, ESP_FAIL, err, TAG, "read pcap packet header failed"); - // print packet header information - fprintf(print_file, "Packet %d:\n", packet_num); - fprintf(print_file, "Timestamp (Seconds): %d\n", packet_header.seconds); - fprintf(print_file, "Timestamp (Microseconds): %d\n", packet_header.microseconds); - fprintf(print_file, "Capture Length: %d\n", packet_header.capture_length); - fprintf(print_file, "Packet Length: %d\n", packet_header.packet_length); - size_t payload_length = packet_header.capture_length; - packet_payload = malloc(payload_length); - ESP_GOTO_ON_FALSE(packet_payload, ESP_ERR_NO_MEM, err, TAG, "no mem to save packet payload"); - real_read = fread(packet_payload, payload_length, 1, pcap->file); - ESP_GOTO_ON_FALSE(real_read == 1, ESP_FAIL, err, TAG, "read payload error"); - // print packet information - if (file_header.link_type == PCAP_LINK_TYPE_802_11) { - // Frame Control Field is coded as LSB first - fprintf(print_file, "Frame Type: %2x\n", (packet_payload[0] >> 2) & 0x03); - fprintf(print_file, "Frame Subtype: %2x\n", (packet_payload[0] >> 4) & 0x0F); - fprintf(print_file, "Destination: "); - for (int j = 0; j < 5; j++) { - fprintf(print_file, "%2x ", packet_payload[4 + j]); - } - fprintf(print_file, "%2x\n", packet_payload[9]); - fprintf(print_file, "Source: "); - for (int j = 0; j < 5; j++) { - fprintf(print_file, "%2x ", packet_payload[10 + j]); - } - fprintf(print_file, "%2x\n", packet_payload[15]); - fprintf(print_file, "------------------------------------------------------------------------\n"); - } else if (file_header.link_type == PCAP_LINK_TYPE_ETHERNET){ - fprintf(print_file, "Destination: "); - for (int j = 0; j < 5; j++) { - fprintf(print_file, "%2x ", packet_payload[j]); - } - fprintf(print_file, "%2x\n", packet_payload[5]); - fprintf(print_file, "Source: "); - for (int j = 0; j < 5; j++) { - fprintf(print_file, "%2x ", packet_payload[6 + j]); - } - fprintf(print_file, "%2x\n", packet_payload[11]); - fprintf(print_file, "Type: 0x%x\n", packet_payload[13] | (packet_payload[12] << 8)); - fprintf(print_file, "------------------------------------------------------------------------\n"); - } - else { - fprintf(print_file, "Unknown link type:%d\n", file_header.link_type); - fprintf(print_file, "------------------------------------------------------------------------\n"); - } - free(packet_payload); - packet_payload = NULL; - index += packet_header.capture_length + sizeof(pcap_packet_header_t); - packet_num ++; - } - fprintf(print_file, "Pcap packet Number: %d\n", packet_num); - fprintf(print_file, "------------------------------------------------------------------------\n"); - return ret; -err: - if (packet_payload) { - free(packet_payload); - } - return ret; -} diff --git a/examples/common_components/pid_ctrl/CMakeLists.txt b/examples/common_components/pid_ctrl/CMakeLists.txt deleted file mode 100644 index 544820d5d7..0000000000 --- a/examples/common_components/pid_ctrl/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -set(srcs "src/pid_ctrl.c") - -idf_component_register(SRCS "${srcs}" - INCLUDE_DIRS "include") diff --git a/examples/common_components/pid_ctrl/include/pid_ctrl.h b/examples/common_components/pid_ctrl/include/pid_ctrl.h deleted file mode 100644 index 5aa26df7b6..0000000000 --- a/examples/common_components/pid_ctrl/include/pid_ctrl.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#pragma once - -#include "esp_err.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief PID calculation type - * - */ -typedef enum { - PID_CAL_TYPE_INCREMENTAL, /*!< Incremental PID control */ - PID_CAL_TYPE_POSITIONAL, /*!< Positional PID control */ -} pid_calculate_type_t; - -/** - * @brief Type of PID control block handle - * - */ -typedef struct pid_ctrl_block_t *pid_ctrl_block_handle_t; - -/** - * @brief PID control parameters - * - */ -typedef struct { - float kp; // PID Kp parameter - float ki; // PID Ki parameter - float kd; // PID Kd parameter - float max_output; // PID maximum output limitation - float min_output; // PID minimum output limitation - float max_integral; // PID maximum integral value limitation - float min_integral; // PID minimum integral value limitation - pid_calculate_type_t cal_type; // PID calculation type -} pid_ctrl_parameter_t; - -/** - * @brief PID control configuration - * - */ -typedef struct { - pid_ctrl_parameter_t init_param; // Initial parameters -} pid_ctrl_config_t; - -/** - * @brief Create a new PID control session, returns the handle of control block - * - * @param[in] config PID control configuration - * @param[out] ret_pid Returned PID control block handle - * @return - * - ESP_OK: Created PID control block successfully - * - ESP_ERR_INVALID_ARG: Created PID control block failed because of invalid argument - * - ESP_ERR_NO_MEM: Created PID control block failed because out of memory - */ -esp_err_t pid_new_control_block(const pid_ctrl_config_t *config, pid_ctrl_block_handle_t *ret_pid); - -/** - * @brief Delete the PID control block - * - * @param[in] pid PID control block handle, created by `pid_new_control_block()` - * @return - * - ESP_OK: Delete PID control block successfully - * - ESP_ERR_INVALID_ARG: Delete PID control block failed because of invalid argument - */ -esp_err_t pid_del_control_block(pid_ctrl_block_handle_t pid); - -/** - * @brief Update PID parameters - * - * @param[in] pid PID control block handle, created by `pid_new_control_block()` - * @param[in] params PID parameters - * @return - * - ESP_OK: Update PID parameters successfully - * - ESP_ERR_INVALID_ARG: Update PID parameters failed because of invalid argument - */ -esp_err_t pid_update_parameters(pid_ctrl_block_handle_t pid, const pid_ctrl_parameter_t *params); - -/** - * @brief Input error and get PID control result - * - * @param[in] pid PID control block handle, created by `pid_new_control_block()` - * @param[in] input_error error data that feed to the PID controller - * @param[out] ret_result result after PID calculation - * @return - * - ESP_OK: Run a PID compute successfully - * - ESP_ERR_INVALID_ARG: Run a PID compute failed because of invalid argument - */ -esp_err_t pid_compute(pid_ctrl_block_handle_t pid, float input_error, float *ret_result); - -#ifdef __cplusplus -} -#endif diff --git a/examples/common_components/pid_ctrl/src/pid_ctrl.c b/examples/common_components/pid_ctrl/src/pid_ctrl.c deleted file mode 100644 index 4b51177b41..0000000000 --- a/examples/common_components/pid_ctrl/src/pid_ctrl.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include "esp_check.h" -#include "esp_log.h" -#include "pid_ctrl.h" - -static const char *TAG = "pid_ctrl"; - -typedef struct pid_ctrl_block_t pid_ctrl_block_t; -typedef float (*pid_cal_func_t)(pid_ctrl_block_t *pid, float error); - -struct pid_ctrl_block_t { - float Kp; // PID Kp value - float Ki; // PID Ki value - float Kd; // PID Kd value - float previous_err1; // e(k-1) - float previous_err2; // e(k-2) - float integral_err; // Sum of error - float last_output; // PID output in last control period - float max_output; // PID maximum output limitation - float min_output; // PID minimum output limitation - float max_integral; // PID maximum integral value limitation - float min_integral; // PID minimum integral value limitation - pid_cal_func_t calculate_func; // calculation function, depends on actual PID type set by user -}; - -static float pid_calc_positional(pid_ctrl_block_t *pid, float error) -{ - float output = 0; - /* Add current error to the integral error */ - pid->integral_err += error; - /* If the integral error is out of the range, it will be limited */ - pid->integral_err = MIN(pid->integral_err, pid->max_integral); - pid->integral_err = MAX(pid->integral_err, pid->min_integral); - - /* Calculate the pid control value by location formula */ - /* u(k) = e(k)*Kp + (e(k)-e(k-1))*Kd + integral*Ki */ - output = error * pid->Kp + - (error - pid->previous_err1) * pid->Kd + - pid->integral_err * pid->Ki; - - /* If the output is out of the range, it will be limited */ - output = MIN(output, pid->max_output); - output = MAX(output, pid->min_output); - - /* Update previous error */ - pid->previous_err1 = error; - - return output; -} - -static float pid_calc_incremental(pid_ctrl_block_t *pid, float error) -{ - float output = 0; - - /* Calculate the pid control value by increment formula */ - /* du(k) = (e(k)-e(k-1))*Kp + (e(k)-2*e(k-1)+e(k-2))*Kd + e(k)*Ki */ - /* u(k) = du(k) + u(k-1) */ - output = (error - pid->previous_err1) * pid->Kp + - (error - 2 * pid->previous_err1 + pid->previous_err2) * pid->Kd + - error * pid->Ki + - pid->last_output; - - /* If the output is beyond the range, it will be limited */ - output = MIN(output, pid->max_output); - output = MAX(output, pid->min_output); - - /* Update previous error */ - pid->previous_err2 = pid->previous_err1; - pid->previous_err1 = error; - - /* Update last output */ - pid->last_output = output; - - return output; -} - -esp_err_t pid_new_control_block(const pid_ctrl_config_t *config, pid_ctrl_block_handle_t *ret_pid) -{ - esp_err_t ret = ESP_OK; - pid_ctrl_block_t *pid = NULL; - /* Check the input pointer */ - ESP_GOTO_ON_FALSE(config && ret_pid, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - - pid = calloc(1, sizeof(pid_ctrl_block_t)); - ESP_GOTO_ON_FALSE(pid, ESP_ERR_NO_MEM, err, TAG, "no mem for PID control block"); - ESP_GOTO_ON_ERROR(pid_update_parameters(pid, &config->init_param), err, TAG, "init PID parameters failed"); - *ret_pid = pid; - return ret; - -err: - if (pid) { - free(pid); - } - return ret; -} - -esp_err_t pid_del_control_block(pid_ctrl_block_handle_t pid) -{ - ESP_RETURN_ON_FALSE(pid, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - free(pid); - return ESP_OK; -} - -esp_err_t pid_compute(pid_ctrl_block_handle_t pid, float input_error, float *ret_result) -{ - ESP_RETURN_ON_FALSE(pid && ret_result, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - *ret_result = pid->calculate_func(pid, input_error); - return ESP_OK; -} - -esp_err_t pid_update_parameters(pid_ctrl_block_handle_t pid, const pid_ctrl_parameter_t *params) -{ - ESP_RETURN_ON_FALSE(pid && params, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); - pid->Kp = params->kp; - pid->Ki = params->ki; - pid->Kd = params->kd; - pid->max_output = params->max_output; - pid->min_output = params->min_output; - pid->max_integral = params->max_integral; - pid->min_integral = params->min_integral; - /* Set the calculate function according to the PID type */ - switch (params->cal_type) { - case PID_CAL_TYPE_INCREMENTAL: - pid->calculate_func = pid_calc_incremental; - break; - case PID_CAL_TYPE_POSITIONAL: - pid->calculate_func = pid_calc_positional; - break; - default: - ESP_RETURN_ON_FALSE(false, ESP_ERR_INVALID_ARG, TAG, "invalid PID calculation type:%d", params->cal_type); - } - return ESP_OK; -} diff --git a/examples/common_components/qrcode/CMakeLists.txt b/examples/common_components/qrcode/CMakeLists.txt deleted file mode 100644 index fa3bd8e418..0000000000 --- a/examples/common_components/qrcode/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -idf_component_register(SRCS "esp_qrcode_main.c" "esp_qrcode_wrapper.c" "qrcodegen.c" - INCLUDE_DIRS "include" - ) diff --git a/examples/common_components/qrcode/README.md b/examples/common_components/qrcode/README.md deleted file mode 100644 index 16bb27c06b..0000000000 --- a/examples/common_components/qrcode/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# QR Code generator component - -This directory contains a QR code generator component written in C. This component is based on [QR-Code-generator](https://github.com/nayuki/QR-Code-generator). -This component is used as part of the following ESP-IDF examples: -- [DPP Enrollee Example](../../wifi/wifi_easy_connect/dpp-enrollee/). - -To learn more about how to use this component, please check API Documentation from header file [qrcode.h](./include/qrcode.h). - -Please note that this component is not considered to be a part of ESP-IDF stable API. It may change and may be removed in the future releases. diff --git a/examples/common_components/qrcode/esp_qrcode_main.c b/examples/common_components/qrcode/esp_qrcode_main.c deleted file mode 100644 index 7b03d5d4f4..0000000000 --- a/examples/common_components/qrcode/esp_qrcode_main.c +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include -#include "esp_log.h" - -#include "qrcodegen.h" -#include "qrcode.h" - -static const char *TAG = "QRCODE"; - -static const char *lt[] = { - /* 0 */ " ", - /* 1 */ "\u2580 ", - /* 2 */ " \u2580", - /* 3 */ "\u2580\u2580", - /* 4 */ "\u2584 ", - /* 5 */ "\u2588 ", - /* 6 */ "\u2584\u2580", - /* 7 */ "\u2588\u2580", - /* 8 */ " \u2584", - /* 9 */ "\u2580\u2584", - /* 10 */ " \u2588", - /* 11 */ "\u2580\u2588", - /* 12 */ "\u2584\u2584", - /* 13 */ "\u2588\u2584", - /* 14 */ "\u2584\u2588", - /* 15 */ "\u2588\u2588", -}; - -void esp_qrcode_print_console(esp_qrcode_handle_t qrcode) -{ - int size = qrcodegen_getSize(qrcode); - int border = 2; - unsigned char num = 0; - - for (int y = -border; y < size + border; y+=2) { - for (int x = -border; x < size + border; x+=2) { - num = 0; - if (qrcodegen_getModule(qrcode, x, y)) { - num |= 1 << 0; - } - if ((x < size + border) && qrcodegen_getModule(qrcode, x+1, y)) { - num |= 1 << 1; - } - if ((y < size + border) && qrcodegen_getModule(qrcode, x, y+1)) { - num |= 1 << 2; - } - if ((x < size + border) && (y < size + border) && qrcodegen_getModule(qrcode, x+1, y+1)) { - num |= 1 << 3; - } - printf("%s", lt[num]); - } - printf("\n"); - } - printf("\n"); -} - -esp_err_t esp_qrcode_generate(esp_qrcode_config_t *cfg, const char *text) -{ - enum qrcodegen_Ecc ecc_lvl; - uint8_t *qrcode, *tempbuf; - esp_err_t err = ESP_FAIL; - - qrcode = calloc(1, qrcodegen_BUFFER_LEN_FOR_VERSION(cfg->max_qrcode_version)); - if (!qrcode) { - return ESP_ERR_NO_MEM; - } - - tempbuf = calloc(1, qrcodegen_BUFFER_LEN_FOR_VERSION(cfg->max_qrcode_version)); - if (!tempbuf) { - free(qrcode); - return ESP_ERR_NO_MEM; - } - - switch(cfg->qrcode_ecc_level) { - case ESP_QRCODE_ECC_LOW: - ecc_lvl = qrcodegen_Ecc_LOW; - break; - case ESP_QRCODE_ECC_MED: - ecc_lvl = qrcodegen_Ecc_MEDIUM; - break; - case ESP_QRCODE_ECC_QUART: - ecc_lvl = qrcodegen_Ecc_QUARTILE; - break; - case ESP_QRCODE_ECC_HIGH: - ecc_lvl = qrcodegen_Ecc_HIGH; - break; - default: - ecc_lvl = qrcodegen_Ecc_LOW; - break; - } - - ESP_LOGI(TAG, "Encoding below text with ECC LVL %d & QR Code Version %d", - ecc_lvl, cfg->max_qrcode_version); - ESP_LOGI(TAG, "%s", text); - // Make and print the QR Code symbol - bool ok = qrcodegen_encodeText(text, tempbuf, qrcode, ecc_lvl, - qrcodegen_VERSION_MIN, cfg->max_qrcode_version, - qrcodegen_Mask_AUTO, true); - if (ok && cfg->display_func) { - cfg->display_func((esp_qrcode_handle_t)qrcode); - err = ESP_OK; - } - - free(qrcode); - free(tempbuf); - return err; -} diff --git a/examples/common_components/qrcode/esp_qrcode_wrapper.c b/examples/common_components/qrcode/esp_qrcode_wrapper.c deleted file mode 100644 index cde516586b..0000000000 --- a/examples/common_components/qrcode/esp_qrcode_wrapper.c +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include -#include - -#include "qrcodegen.h" -#include "qrcode.h" - -int esp_qrcode_get_size(esp_qrcode_handle_t qrcode) -{ - return qrcodegen_getSize(qrcode); -} - -bool esp_qrcode_get_module(esp_qrcode_handle_t qrcode, int x, int y) -{ - return qrcodegen_getModule(qrcode, x, y); -} diff --git a/examples/common_components/qrcode/include/qrcode.h b/examples/common_components/qrcode/include/qrcode.h deleted file mode 100644 index 75002c3e0e..0000000000 --- a/examples/common_components/qrcode/include/qrcode.h +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief QR Code handle used by the display function - */ -typedef const uint8_t * esp_qrcode_handle_t; - -/** - * @brief QR Code configuration options - */ -typedef struct { - void (*display_func)(esp_qrcode_handle_t qrcode); /**< Function called for displaying the QR Code after encoding is complete */ - int max_qrcode_version; /**< Max QR Code Version to be used. Range: 2 - 40 */ - int qrcode_ecc_level; /**< Error Correction Level for QR Code */ -} esp_qrcode_config_t; - -/** - * @brief Error Correction Level in a QR Code Symbol - */ -enum { - ESP_QRCODE_ECC_LOW, /**< QR Code Error Tolerance of 7% */ - ESP_QRCODE_ECC_MED, /**< QR Code Error Tolerance of 15% */ - ESP_QRCODE_ECC_QUART, /**< QR Code Error Tolerance of 25% */ - ESP_QRCODE_ECC_HIGH /**< QR Code Error Tolerance of 30% */ -}; - -/** - * @brief Encodes the given string into a QR Code and calls the display function - * - * @attention 1. Can successfully encode a UTF-8 string of up to 2953 bytes or an alphanumeric - * string of up to 4296 characters or any digit string of up to 7089 characters - * - * @param cfg Configuration used for QR Code encoding. - * @param text String to encode into a QR Code. - * - * @return - * - ESP_OK: succeed - * - ESP_FAIL: Failed to encode string into a QR Code - * - ESP_ERR_NO_MEM: Failed to allocate buffer for given max_qrcode_version - */ -esp_err_t esp_qrcode_generate(esp_qrcode_config_t *cfg, const char *text); - -/** - * @brief Displays QR Code on the console - * - * @param qrcode QR Code handle used by the display function. - */ -void esp_qrcode_print_console(esp_qrcode_handle_t qrcode); - -/** - * @brief Returns the side length of the given QR Code - * - * @param qrcode QR Code handle used by the display function. - * - * @return - * - val[21, 177]: Side length of QR Code - */ -int esp_qrcode_get_size(esp_qrcode_handle_t qrcode); - -/** - * @brief Returns the Pixel value for the given coordinates - * False indicates White and True indicates Black - * - * @attention 1. Coordinates for top left corner are (x=0, y=0) - * @attention 2. For out of bound coordinates false (White) is returned - * - * @param qrcode QR Code handle used by the display function. - * @param x X-Coordinate of QR Code module - * @param y Y-Coordinate of QR Code module - * - * @return - * - true: (x, y) Pixel is Black - * - false: (x, y) Pixel is White - */ -bool esp_qrcode_get_module(esp_qrcode_handle_t qrcode, int x, int y); - -#define ESP_QRCODE_CONFIG_DEFAULT() (esp_qrcode_config_t) { \ - .display_func = esp_qrcode_print_console, \ - .max_qrcode_version = 10, \ - .qrcode_ecc_level = ESP_QRCODE_ECC_LOW, \ -} - -#ifdef __cplusplus -} -#endif diff --git a/examples/common_components/qrcode/qrcodegen.c b/examples/common_components/qrcode/qrcodegen.c deleted file mode 100644 index 9fce6b0727..0000000000 --- a/examples/common_components/qrcode/qrcodegen.c +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * QR Code generator library (C) - * - * Copyright (c) Project Nayuki. (MIT License) - * https://www.nayuki.io/page/qr-code-generator-library - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - The Software is provided "as is", without warranty of any kind, express or - * implied, including but not limited to the warranties of merchantability, - * fitness for a particular purpose and noninfringement. In no event shall the - * authors or copyright holders be liable for any claim, damages or other - * liability, whether in an action of contract, tort or otherwise, arising from, - * out of or in connection with the Software or the use or other dealings in the - * Software. - */ - -#include -#include -#include -#include -#include "qrcodegen.h" - -#ifndef QRCODEGEN_TEST - #define testable static // Keep functions private -#else - #define testable // Expose private functions -#endif - - -/*---- Forward declarations for private functions ----*/ - -// Regarding all public and private functions defined in this source file: -// - They require all pointer/array arguments to be not null unless the array length is zero. -// - They only read input scalar/array arguments, write to output pointer/array -// arguments, and return scalar values; they are "pure" functions. -// - They don't read mutable global variables or write to any global variables. -// - They don't perform I/O, read the clock, print to console, etc. -// - They allocate a small and constant amount of stack memory. -// - They don't allocate or free any memory on the heap. -// - They don't recurse or mutually recurse. All the code -// could be inlined into the top-level public functions. -// - They run in at most quadratic time with respect to input arguments. -// Most functions run in linear time, and some in constant time. -// There are no unbounded loops or non-obvious termination conditions. -// - They are completely thread-safe if the caller does not give the -// same writable buffer to concurrent calls to these functions. - -testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen); - -testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); -testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); -testable int getNumRawDataModules(int ver); - -testable void reedSolomonComputeDivisor(int degree, uint8_t result[]); -testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, - const uint8_t generator[], int degree, uint8_t result[]); -testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y); - -testable void initializeFunctionModules(int version, uint8_t qrcode[]); -static void drawWhiteFunctionModules(uint8_t qrcode[], int version); -static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); -testable int getAlignmentPatternPositions(int version, uint8_t result[7]); -static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); - -static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); -static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); -static long getPenaltyScore(const uint8_t qrcode[]); -static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize); -static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize); -static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7]); - -testable bool getModule(const uint8_t qrcode[], int x, int y); -testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack); -testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack); -static bool getBit(int x, int i); - -testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); -testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); -static int numCharCountBits(enum qrcodegen_Mode mode, int version); - - - -/*---- Private tables of constants ----*/ - -// The set of all legal characters in alphanumeric mode, where each character -// value maps to the index in the string. For checking text and encoding segments. -static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; - -// For generating error correction codes. -testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low - {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium - {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile - {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High -}; - -#define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above - -// For generating error correction codes. -testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { - // Version: (note that index 0 is for padding, and is set to an illegal value) - //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level - {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low - {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium - {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile - {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High -}; - -// For automatic mask pattern selection. -static const int PENALTY_N1 = 3; -static const int PENALTY_N2 = 3; -static const int PENALTY_N3 = 40; -static const int PENALTY_N4 = 10; - - - -/*---- High-level QR Code encoding functions ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { - - size_t textLen = strlen(text); - if (textLen == 0) - return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); - size_t bufLen = (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); - - struct qrcodegen_Segment seg; - if (qrcodegen_isNumeric(text)) { - if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) - goto fail; - seg = qrcodegen_makeNumeric(text, tempBuffer); - } else if (qrcodegen_isAlphanumeric(text)) { - if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) - goto fail; - seg = qrcodegen_makeAlphanumeric(text, tempBuffer); - } else { - if (textLen > bufLen) - goto fail; - for (size_t i = 0; i < textLen; i++) - tempBuffer[i] = (uint8_t)text[i]; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, textLen); - if (seg.bitLength == -1) - goto fail; - seg.numChars = (int)textLen; - seg.data = tempBuffer; - } - return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); - -fail: - qrcode[0] = 0; // Set size to invalid value for safety - return false; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { - - struct qrcodegen_Segment seg; - seg.mode = qrcodegen_Mode_BYTE; - seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); - if (seg.bitLength == -1) { - qrcode[0] = 0; // Set size to invalid value for safety - return false; - } - seg.numChars = (int)dataLen; - seg.data = dataAndTemp; - return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); -} - - -// Appends the given number of low-order bits of the given value to the given byte-based -// bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. -testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) { - assert(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); - for (int i = numBits - 1; i >= 0; i--, (*bitLen)++) - buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); -} - - - -/*---- Low-level QR Code encoding functions ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, - enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) { - return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, - qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true, tempBuffer, qrcode); -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, - int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) { - assert(segs != NULL || len == 0); - assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); - assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); - - // Find the minimal version number to use - int version, dataUsedBits; - for (version = minVersion; ; version++) { - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available - dataUsedBits = getTotalBits(segs, len, version); - if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) - break; // This version number is found to be suitable - if (version >= maxVersion) { // All versions in the range could not fit the given data - qrcode[0] = 0; // Set size to invalid value for safety - return false; - } - } - assert(dataUsedBits != -1); - - // Increase the error correction level while the data still fits in the current version number - for (int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high - if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) - ecl = (enum qrcodegen_Ecc)i; - } - - // Concatenate all segments to create the data bit string - memset(qrcode, 0, (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); - int bitLen = 0; - for (size_t i = 0; i < len; i++) { - const struct qrcodegen_Segment *seg = &segs[i]; - appendBitsToBuffer((unsigned int)seg->mode, 4, qrcode, &bitLen); - appendBitsToBuffer((unsigned int)seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); - for (int j = 0; j < seg->bitLength; j++) { - int bit = (seg->data[j >> 3] >> (7 - (j & 7))) & 1; - appendBitsToBuffer((unsigned int)bit, 1, qrcode, &bitLen); - } - } - assert(bitLen == dataUsedBits); - - // Add terminator and pad up to a byte if applicable - int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; - assert(bitLen <= dataCapacityBits); - int terminatorBits = dataCapacityBits - bitLen; - if (terminatorBits > 4) - terminatorBits = 4; - appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); - appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); - assert(bitLen % 8 == 0); - - // Pad with alternating bytes until data capacity is reached - for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) - appendBitsToBuffer(padByte, 8, qrcode, &bitLen); - - // Draw function and data codeword modules - addEccAndInterleave(qrcode, version, ecl, tempBuffer); - initializeFunctionModules(version, qrcode); - drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); - drawWhiteFunctionModules(qrcode, version); - initializeFunctionModules(version, tempBuffer); - - // Handle masking - if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask - long minPenalty = LONG_MAX; - for (int i = 0; i < 8; i++) { - enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; - applyMask(tempBuffer, qrcode, msk); - drawFormatBits(ecl, msk, qrcode); - long penalty = getPenaltyScore(qrcode); - if (penalty < minPenalty) { - mask = msk; - minPenalty = penalty; - } - applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR - } - } - assert(0 <= (int)mask && (int)mask <= 7); - applyMask(tempBuffer, qrcode, mask); - drawFormatBits(ecl, mask, qrcode); - return true; -} - - - -/*---- Error correction code generation functions ----*/ - -// Appends error correction bytes to each block of the given data array, then interleaves -// bytes from the blocks and stores them in the result array. data[0 : dataLen] contains -// the input data. data[dataLen : rawCodewords] is used as a temporary work area and will -// be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. -testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) { - // Calculate parameter numbers - assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); - int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; - int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; - int rawCodewords = getNumRawDataModules(version) / 8; - int dataLen = getNumDataCodewords(version, ecl); - int numShortBlocks = numBlocks - rawCodewords % numBlocks; - int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; - - // Split data into blocks, calculate ECC, and interleave - // (not concatenate) the bytes into a single sequence - uint8_t rsdiv[qrcodegen_REED_SOLOMON_DEGREE_MAX]; - reedSolomonComputeDivisor(blockEccLen, rsdiv); - const uint8_t *dat = data; - for (int i = 0; i < numBlocks; i++) { - int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); - uint8_t *ecc = &data[dataLen]; // Temporary storage - reedSolomonComputeRemainder(dat, datLen, rsdiv, blockEccLen, ecc); - for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data - if (j == shortBlockDataLen) - k -= numShortBlocks; - result[k] = dat[j]; - } - for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) // Copy ECC - result[k] = ecc[j]; - dat += datLen; - } -} - - -// Returns the number of 8-bit codewords that can be used for storing data (not ECC), -// for the given version number and error correction level. The result is in the range [9, 2956]. -testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) { - int v = version, e = (int)ecl; - assert(0 <= e && e < 4); - return getNumRawDataModules(v) / 8 - - ECC_CODEWORDS_PER_BLOCK [e][v] - * NUM_ERROR_CORRECTION_BLOCKS[e][v]; -} - - -// Returns the number of data bits that can be stored in a QR Code of the given version number, after -// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. -// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. -testable int getNumRawDataModules(int ver) { - assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); - int result = (16 * ver + 128) * ver + 64; - if (ver >= 2) { - int numAlign = ver / 7 + 2; - result -= (25 * numAlign - 10) * numAlign - 55; - if (ver >= 7) - result -= 36; - } - assert(208 <= result && result <= 29648); - return result; -} - - - -/*---- Reed-Solomon ECC generator functions ----*/ - -// Computes a Reed-Solomon ECC generator polynomial for the given degree, storing in result[0 : degree]. -// This could be implemented as a lookup table over all possible parameter values, instead of as an algorithm. -testable void reedSolomonComputeDivisor(int degree, uint8_t result[]) { - assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); - // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. - // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. - memset(result, 0, (size_t)degree * sizeof(result[0])); - result[degree - 1] = 1; // Start off with the monomial x^0 - - // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), - // drop the highest monomial term which is always 1x^degree. - // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). - uint8_t root = 1; - for (int i = 0; i < degree; i++) { - // Multiply the current product by (x - r^i) - for (int j = 0; j < degree; j++) { - result[j] = reedSolomonMultiply(result[j], root); - if (j + 1 < degree) - result[j] ^= result[j + 1]; - } - root = reedSolomonMultiply(root, 0x02); - } -} - - -// Computes the Reed-Solomon error correction codeword for the given data and divisor polynomials. -// The remainder when data[0 : dataLen] is divided by divisor[0 : degree] is stored in result[0 : degree]. -// All polynomials are in big endian, and the generator has an implicit leading 1 term. -testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, - const uint8_t generator[], int degree, uint8_t result[]) { - assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); - memset(result, 0, (size_t)degree * sizeof(result[0])); - for (int i = 0; i < dataLen; i++) { // Polynomial division - uint8_t factor = data[i] ^ result[0]; - memmove(&result[0], &result[1], (size_t)(degree - 1) * sizeof(result[0])); - result[degree - 1] = 0; - for (int j = 0; j < degree; j++) - result[j] ^= reedSolomonMultiply(generator[j], factor); - } -} - -#undef qrcodegen_REED_SOLOMON_DEGREE_MAX - - -// Returns the product of the two given field elements modulo GF(2^8/0x11D). -// All inputs are valid. This could be implemented as a 256*256 lookup table. -testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y) { - // Russian peasant multiplication - uint8_t z = 0; - for (int i = 7; i >= 0; i--) { - z = (uint8_t)((z << 1) ^ ((z >> 7) * 0x11D)); - z ^= ((y >> i) & 1) * x; - } - return z; -} - - - -/*---- Drawing function modules ----*/ - -// Clears the given QR Code grid with white modules for the given -// version's size, then marks every function module as black. -testable void initializeFunctionModules(int version, uint8_t qrcode[]) { - // Initialize QR Code - int qrsize = version * 4 + 17; - memset(qrcode, 0, (size_t)((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); - qrcode[0] = (uint8_t)qrsize; - - // Fill horizontal and vertical timing patterns - fillRectangle(6, 0, 1, qrsize, qrcode); - fillRectangle(0, 6, qrsize, 1, qrcode); - - // Fill 3 finder patterns (all corners except bottom right) and format bits - fillRectangle(0, 0, 9, 9, qrcode); - fillRectangle(qrsize - 8, 0, 8, 9, qrcode); - fillRectangle(0, qrsize - 8, 9, 8, qrcode); - - // Fill numerous alignment patterns - uint8_t alignPatPos[7]; - int numAlign = getAlignmentPatternPositions(version, alignPatPos); - for (int i = 0; i < numAlign; i++) { - for (int j = 0; j < numAlign; j++) { - // Don't draw on the three finder corners - if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) - fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); - } - } - - // Fill version blocks - if (version >= 7) { - fillRectangle(qrsize - 11, 0, 3, 6, qrcode); - fillRectangle(0, qrsize - 11, 6, 3, qrcode); - } -} - - -// Draws white function modules and possibly some black modules onto the given QR Code, without changing -// non-function modules. This does not draw the format bits. This requires all function modules to be previously -// marked black (namely by initializeFunctionModules()), because this may skip redrawing black function modules. -static void drawWhiteFunctionModules(uint8_t qrcode[], int version) { - // Draw horizontal and vertical timing patterns - int qrsize = qrcodegen_getSize(qrcode); - for (int i = 7; i < qrsize - 7; i += 2) { - setModule(qrcode, 6, i, false); - setModule(qrcode, i, 6, false); - } - - // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) - for (int dy = -4; dy <= 4; dy++) { - for (int dx = -4; dx <= 4; dx++) { - int dist = abs(dx); - if (abs(dy) > dist) - dist = abs(dy); - if (dist == 2 || dist == 4) { - setModuleBounded(qrcode, 3 + dx, 3 + dy, false); - setModuleBounded(qrcode, qrsize - 4 + dx, 3 + dy, false); - setModuleBounded(qrcode, 3 + dx, qrsize - 4 + dy, false); - } - } - } - - // Draw numerous alignment patterns - uint8_t alignPatPos[7]; - int numAlign = getAlignmentPatternPositions(version, alignPatPos); - for (int i = 0; i < numAlign; i++) { - for (int j = 0; j < numAlign; j++) { - if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) - continue; // Don't draw on the three finder corners - for (int dy = -1; dy <= 1; dy++) { - for (int dx = -1; dx <= 1; dx++) - setModule(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); - } - } - } - - // Draw version blocks - if (version >= 7) { - // Calculate error correction code and pack bits - int rem = version; // version is uint6, in the range [7, 40] - for (int i = 0; i < 12; i++) - rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); - long bits = (long)version << 12 | rem; // uint18 - assert(bits >> 18 == 0); - - // Draw two copies - for (int i = 0; i < 6; i++) { - for (int j = 0; j < 3; j++) { - int k = qrsize - 11 + j; - setModule(qrcode, k, i, (bits & 1) != 0); - setModule(qrcode, i, k, (bits & 1) != 0); - bits >>= 1; - } - } - } -} - - -// Draws two copies of the format bits (with its own error correction code) based -// on the given mask and error correction level. This always draws all modules of -// the format bits, unlike drawWhiteFunctionModules() which might skip black modules. -static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) { - // Calculate error correction code and pack bits - assert(0 <= (int)mask && (int)mask <= 7); - static const int table[] = {1, 0, 3, 2}; - int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 - int rem = data; - for (int i = 0; i < 10; i++) - rem = (rem << 1) ^ ((rem >> 9) * 0x537); - int bits = (data << 10 | rem) ^ 0x5412; // uint15 - assert(bits >> 15 == 0); - - // Draw first copy - for (int i = 0; i <= 5; i++) - setModule(qrcode, 8, i, getBit(bits, i)); - setModule(qrcode, 8, 7, getBit(bits, 6)); - setModule(qrcode, 8, 8, getBit(bits, 7)); - setModule(qrcode, 7, 8, getBit(bits, 8)); - for (int i = 9; i < 15; i++) - setModule(qrcode, 14 - i, 8, getBit(bits, i)); - - // Draw second copy - int qrsize = qrcodegen_getSize(qrcode); - for (int i = 0; i < 8; i++) - setModule(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); - for (int i = 8; i < 15; i++) - setModule(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); - setModule(qrcode, 8, qrsize - 8, true); // Always black -} - - -// Calculates and stores an ascending list of positions of alignment patterns -// for this version number, returning the length of the list (in the range [0,7]). -// Each position is in the range [0,177), and are used on both the x and y axes. -// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. -testable int getAlignmentPatternPositions(int version, uint8_t result[7]) { - if (version == 1) - return 0; - int numAlign = version / 7 + 2; - int step = (version == 32) ? 26 : - (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; - for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) - result[i] = (uint8_t)pos; - result[0] = 6; - return numAlign; -} - - -// Sets every pixel in the range [left : left + width] * [top : top + height] to black. -static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) { - for (int dy = 0; dy < height; dy++) { - for (int dx = 0; dx < width; dx++) - setModule(qrcode, left + dx, top + dy, true); - } -} - - - -/*---- Drawing data modules and masking ----*/ - -// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of -// the QR Code to be black at function modules and white at codeword modules (including unused remainder bits). -static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) { - int qrsize = qrcodegen_getSize(qrcode); - int i = 0; // Bit index into the data - // Do the funny zigzag scan - for (int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair - if (right == 6) - right = 5; - for (int vert = 0; vert < qrsize; vert++) { // Vertical counter - for (int j = 0; j < 2; j++) { - int x = right - j; // Actual x coordinate - bool upward = ((right + 1) & 2) == 0; - int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate - if (!getModule(qrcode, x, y) && i < dataLen * 8) { - bool black = getBit(data[i >> 3], 7 - (i & 7)); - setModule(qrcode, x, y, black); - i++; - } - // If this QR Code has any remainder bits (0 to 7), they were assigned as - // 0/false/white by the constructor and are left unchanged by this method - } - } - } - assert(i == dataLen * 8); -} - - -// XORs the codeword modules in this QR Code with the given mask pattern. -// The function modules must be marked and the codeword bits must be drawn -// before masking. Due to the arithmetic of XOR, calling applyMask() with -// the same mask value a second time will undo the mask. A final well-formed -// QR Code needs exactly one (not zero, two, etc.) mask applied. -static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) { - assert(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO - int qrsize = qrcodegen_getSize(qrcode); - for (int y = 0; y < qrsize; y++) { - for (int x = 0; x < qrsize; x++) { - if (getModule(functionModules, x, y)) - continue; - bool invert; - switch ((int)mask) { - case 0: invert = (x + y) % 2 == 0; break; - case 1: invert = y % 2 == 0; break; - case 2: invert = x % 3 == 0; break; - case 3: invert = (x + y) % 3 == 0; break; - case 4: invert = (x / 3 + y / 2) % 2 == 0; break; - case 5: invert = x * y % 2 + x * y % 3 == 0; break; - case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; - case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; - default: assert(false); return; - } - bool val = getModule(qrcode, x, y); - setModule(qrcode, x, y, val ^ invert); - } - } -} - - -// Calculates and returns the penalty score based on state of the given QR Code's current modules. -// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. -static long getPenaltyScore(const uint8_t qrcode[]) { - int qrsize = qrcodegen_getSize(qrcode); - long result = 0; - - // Adjacent modules in row having same color, and finder-like patterns - for (int y = 0; y < qrsize; y++) { - bool runColor = false; - int runX = 0; - int runHistory[7] = {0}; - int padRun = qrsize; // Add white border to initial run - for (int x = 0; x < qrsize; x++) { - if (getModule(qrcode, x, y) == runColor) { - runX++; - if (runX == 5) - result += PENALTY_N1; - else if (runX > 5) - result++; - } else { - finderPenaltyAddHistory(runX + padRun, runHistory); - padRun = 0; - if (!runColor) - result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; - runColor = getModule(qrcode, x, y); - runX = 1; - } - } - result += finderPenaltyTerminateAndCount(runColor, runX + padRun, runHistory, qrsize) * PENALTY_N3; - } - // Adjacent modules in column having same color, and finder-like patterns - for (int x = 0; x < qrsize; x++) { - bool runColor = false; - int runY = 0; - int runHistory[7] = {0}; - int padRun = qrsize; // Add white border to initial run - for (int y = 0; y < qrsize; y++) { - if (getModule(qrcode, x, y) == runColor) { - runY++; - if (runY == 5) - result += PENALTY_N1; - else if (runY > 5) - result++; - } else { - finderPenaltyAddHistory(runY + padRun, runHistory); - padRun = 0; - if (!runColor) - result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; - runColor = getModule(qrcode, x, y); - runY = 1; - } - } - result += finderPenaltyTerminateAndCount(runColor, runY + padRun, runHistory, qrsize) * PENALTY_N3; - } - - // 2*2 blocks of modules having same color - for (int y = 0; y < qrsize - 1; y++) { - for (int x = 0; x < qrsize - 1; x++) { - bool color = getModule(qrcode, x, y); - if ( color == getModule(qrcode, x + 1, y) && - color == getModule(qrcode, x, y + 1) && - color == getModule(qrcode, x + 1, y + 1)) - result += PENALTY_N2; - } - } - - // Balance of black and white modules - int black = 0; - for (int y = 0; y < qrsize; y++) { - for (int x = 0; x < qrsize; x++) { - if (getModule(qrcode, x, y)) - black++; - } - } - int total = qrsize * qrsize; // Note that size is odd, so black/total != 1/2 - // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% - int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1; - result += k * PENALTY_N4; - return result; -} - - -// Can only be called immediately after a white run is added, and -// returns either 0, 1, or 2. A helper function for getPenaltyScore(). -static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize) { - int n = runHistory[1]; - assert(n <= qrsize * 3); - bool core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n; - // The maximum QR Code size is 177, hence the black run length n <= 177. - // Arithmetic is promoted to int, so n*4 will not overflow. - return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) - + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0); -} - - -// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). -static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize) { - if (currentRunColor) { // Terminate black run - finderPenaltyAddHistory(currentRunLength, runHistory); - currentRunLength = 0; - } - currentRunLength += qrsize; // Add white border to final run - finderPenaltyAddHistory(currentRunLength, runHistory); - return finderPenaltyCountPatterns(runHistory, qrsize); -} - - -// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). -static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7]) { - memmove(&runHistory[1], &runHistory[0], 6 * sizeof(runHistory[0])); - runHistory[0] = currentRunLength; -} - - - -/*---- Basic QR Code information ----*/ - -// Public function - see documentation comment in header file. -int qrcodegen_getSize(const uint8_t qrcode[]) { - assert(qrcode != NULL); - int result = qrcode[0]; - assert((qrcodegen_VERSION_MIN * 4 + 17) <= result - && result <= (qrcodegen_VERSION_MAX * 4 + 17)); - return result; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) { - assert(qrcode != NULL); - int qrsize = qrcode[0]; - return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModule(qrcode, x, y); -} - - -// Gets the module at the given coordinates, which must be in bounds. -testable bool getModule(const uint8_t qrcode[], int x, int y) { - int qrsize = qrcode[0]; - assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); - int index = y * qrsize + x; - return getBit(qrcode[(index >> 3) + 1], index & 7); -} - - -// Sets the module at the given coordinates, which must be in bounds. -testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack) { - int qrsize = qrcode[0]; - assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); - int index = y * qrsize + x; - int bitIndex = index & 7; - int byteIndex = (index >> 3) + 1; - if (isBlack) - qrcode[byteIndex] |= 1 << bitIndex; - else - qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; -} - - -// Sets the module at the given coordinates, doing nothing if out of bounds. -testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack) { - int qrsize = qrcode[0]; - if (0 <= x && x < qrsize && 0 <= y && y < qrsize) - setModule(qrcode, x, y, isBlack); -} - - -// Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. -static bool getBit(int x, int i) { - return ((x >> i) & 1) != 0; -} - - - -/*---- Segment handling ----*/ - -// Public function - see documentation comment in header file. -bool qrcodegen_isAlphanumeric(const char *text) { - assert(text != NULL); - for (; *text != '\0'; text++) { - if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) - return false; - } - return true; -} - - -// Public function - see documentation comment in header file. -bool qrcodegen_isNumeric(const char *text) { - assert(text != NULL); - for (; *text != '\0'; text++) { - if (*text < '0' || *text > '9') - return false; - } - return true; -} - - -// Public function - see documentation comment in header file. -size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) { - int temp = calcSegmentBitLength(mode, numChars); - if (temp == -1) - return SIZE_MAX; - assert(0 <= temp && temp <= INT16_MAX); - return ((size_t)temp + 7) / 8; -} - - -// Returns the number of data bits needed to represent a segment -// containing the given number of characters using the given mode. Notes: -// - Returns -1 on failure, i.e. numChars > INT16_MAX or -// the number of needed bits exceeds INT16_MAX (i.e. 32767). -// - Otherwise, all valid results are in the range [0, INT16_MAX]. -// - For byte mode, numChars measures the number of bytes, not Unicode code points. -// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. -// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. -testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) { - // All calculations are designed to avoid overflow on all platforms - if (numChars > (unsigned int)INT16_MAX) - return -1; - long result = (long)numChars; - if (mode == qrcodegen_Mode_NUMERIC) - result = (result * 10 + 2) / 3; // ceil(10/3 * n) - else if (mode == qrcodegen_Mode_ALPHANUMERIC) - result = (result * 11 + 1) / 2; // ceil(11/2 * n) - else if (mode == qrcodegen_Mode_BYTE) - result *= 8; - else if (mode == qrcodegen_Mode_KANJI) - result *= 13; - else if (mode == qrcodegen_Mode_ECI && numChars == 0) - result = 3 * 8; - else { // Invalid argument - assert(false); - return -1; - } - assert(result >= 0); - if (result > INT16_MAX) - return -1; - return (int)result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) { - assert(data != NULL || len == 0); - struct qrcodegen_Segment result; - result.mode = qrcodegen_Mode_BYTE; - result.bitLength = calcSegmentBitLength(result.mode, len); - assert(result.bitLength != -1); - result.numChars = (int)len; - if (len > 0) - memcpy(buf, data, len * sizeof(buf[0])); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) { - assert(digits != NULL); - struct qrcodegen_Segment result; - size_t len = strlen(digits); - result.mode = qrcodegen_Mode_NUMERIC; - int bitLen = calcSegmentBitLength(result.mode, len); - assert(bitLen != -1); - result.numChars = (int)len; - if (bitLen > 0) - memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); - result.bitLength = 0; - - unsigned int accumData = 0; - int accumCount = 0; - for (; *digits != '\0'; digits++) { - char c = *digits; - assert('0' <= c && c <= '9'); - accumData = accumData * 10 + (unsigned int)(c - '0'); - accumCount++; - if (accumCount == 3) { - appendBitsToBuffer(accumData, 10, buf, &result.bitLength); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 or 2 digits remaining - appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); - assert(result.bitLength == bitLen); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) { - assert(text != NULL); - struct qrcodegen_Segment result; - size_t len = strlen(text); - result.mode = qrcodegen_Mode_ALPHANUMERIC; - int bitLen = calcSegmentBitLength(result.mode, len); - assert(bitLen != -1); - result.numChars = (int)len; - if (bitLen > 0) - memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); - result.bitLength = 0; - - unsigned int accumData = 0; - int accumCount = 0; - for (; *text != '\0'; text++) { - const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); - assert(temp != NULL); - accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); - accumCount++; - if (accumCount == 2) { - appendBitsToBuffer(accumData, 11, buf, &result.bitLength); - accumData = 0; - accumCount = 0; - } - } - if (accumCount > 0) // 1 character remaining - appendBitsToBuffer(accumData, 6, buf, &result.bitLength); - assert(result.bitLength == bitLen); - result.data = buf; - return result; -} - - -// Public function - see documentation comment in header file. -struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) { - struct qrcodegen_Segment result; - result.mode = qrcodegen_Mode_ECI; - result.numChars = 0; - result.bitLength = 0; - if (assignVal < 0) - assert(false); - else if (assignVal < (1 << 7)) { - memset(buf, 0, 1 * sizeof(buf[0])); - appendBitsToBuffer((unsigned int)assignVal, 8, buf, &result.bitLength); - } else if (assignVal < (1 << 14)) { - memset(buf, 0, 2 * sizeof(buf[0])); - appendBitsToBuffer(2, 2, buf, &result.bitLength); - appendBitsToBuffer((unsigned int)assignVal, 14, buf, &result.bitLength); - } else if (assignVal < 1000000L) { - memset(buf, 0, 3 * sizeof(buf[0])); - appendBitsToBuffer(6, 3, buf, &result.bitLength); - appendBitsToBuffer((unsigned int)(assignVal >> 10), 11, buf, &result.bitLength); - appendBitsToBuffer((unsigned int)(assignVal & 0x3FF), 10, buf, &result.bitLength); - } else - assert(false); - result.data = buf; - return result; -} - - -// Calculates the number of bits needed to encode the given segments at the given version. -// Returns a non-negative number if successful. Otherwise returns -1 if a segment has too -// many characters to fit its length field, or the total bits exceeds INT16_MAX. -testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) { - assert(segs != NULL || len == 0); - long result = 0; - for (size_t i = 0; i < len; i++) { - int numChars = segs[i].numChars; - int bitLength = segs[i].bitLength; - assert(0 <= numChars && numChars <= INT16_MAX); - assert(0 <= bitLength && bitLength <= INT16_MAX); - int ccbits = numCharCountBits(segs[i].mode, version); - assert(0 <= ccbits && ccbits <= 16); - if (numChars >= (1L << ccbits)) - return -1; // The segment's length doesn't fit the field's bit width - result += 4L + ccbits + bitLength; - if (result > INT16_MAX) - return -1; // The sum might overflow an int type - } - assert(0 <= result && result <= INT16_MAX); - return (int)result; -} - - -// Returns the bit width of the character count field for a segment in the given mode -// in a QR Code at the given version number. The result is in the range [0, 16]. -static int numCharCountBits(enum qrcodegen_Mode mode, int version) { - assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); - int i = (version + 7) / 17; - switch (mode) { - case qrcodegen_Mode_NUMERIC : { static const int temp[] = {10, 12, 14}; return temp[i]; } - case qrcodegen_Mode_ALPHANUMERIC: { static const int temp[] = { 9, 11, 13}; return temp[i]; } - case qrcodegen_Mode_BYTE : { static const int temp[] = { 8, 16, 16}; return temp[i]; } - case qrcodegen_Mode_KANJI : { static const int temp[] = { 8, 10, 12}; return temp[i]; } - case qrcodegen_Mode_ECI : return 0; - default: assert(false); return -1; // Dummy value - } -} diff --git a/examples/common_components/qrcode/qrcodegen.h b/examples/common_components/qrcode/qrcodegen.h deleted file mode 100644 index f76be204f2..0000000000 --- a/examples/common_components/qrcode/qrcodegen.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * QR Code generator library (C) - * - * Copyright (c) Project Nayuki. (MIT License) - * https://www.nayuki.io/page/qr-code-generator-library - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - The Software is provided "as is", without warranty of any kind, express or - * implied, including but not limited to the warranties of merchantability, - * fitness for a particular purpose and noninfringement. In no event shall the - * authors or copyright holders be liable for any claim, damages or other - * liability, whether in an action of contract, tort or otherwise, arising from, - * out of or in connection with the Software or the use or other dealings in the - * Software. - */ - -#pragma once - -#include -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * This library creates QR Code symbols, which is a type of two-dimension barcode. - * Invented by Denso Wave and described in the ISO/IEC 18004 standard. - * A QR Code structure is an immutable square grid of black and white cells. - * The library provides functions to create a QR Code from text or binary data. - * The library covers the QR Code Model 2 specification, supporting all versions (sizes) - * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. - * - * Ways to create a QR Code object: - * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). - * - Low level: Custom-make the list of segments and call - * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced(). - * (Note that all ways require supplying the desired error correction level and various byte buffers.) - */ - - -/*---- Enum and struct types----*/ - -/* - * The error correction level in a QR Code symbol. - */ -enum qrcodegen_Ecc { - // Must be declared in ascending order of error protection - // so that an internal qrcodegen function works properly - qrcodegen_Ecc_LOW = 0 , // The QR Code can tolerate about 7% erroneous codewords - qrcodegen_Ecc_MEDIUM , // The QR Code can tolerate about 15% erroneous codewords - qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords - qrcodegen_Ecc_HIGH , // The QR Code can tolerate about 30% erroneous codewords -}; - - -/* - * The mask pattern used in a QR Code symbol. - */ -enum qrcodegen_Mask { - // A special value to tell the QR Code encoder to - // automatically select an appropriate mask pattern - qrcodegen_Mask_AUTO = -1, - // The eight actual mask patterns - qrcodegen_Mask_0 = 0, - qrcodegen_Mask_1, - qrcodegen_Mask_2, - qrcodegen_Mask_3, - qrcodegen_Mask_4, - qrcodegen_Mask_5, - qrcodegen_Mask_6, - qrcodegen_Mask_7, -}; - - -/* - * Describes how a segment's data bits are interpreted. - */ -enum qrcodegen_Mode { - qrcodegen_Mode_NUMERIC = 0x1, - qrcodegen_Mode_ALPHANUMERIC = 0x2, - qrcodegen_Mode_BYTE = 0x4, - qrcodegen_Mode_KANJI = 0x8, - qrcodegen_Mode_ECI = 0x7, -}; - - -/* - * A segment of character/binary/control data in a QR Code symbol. - * The mid-level way to create a segment is to take the payload data - * and call a factory function such as qrcodegen_makeNumeric(). - * The low-level way to create a segment is to custom-make the bit buffer - * and initialize a qrcodegen_Segment struct with appropriate values. - * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. - * Any segment longer than this is meaningless for the purpose of generating QR Codes. - * Moreover, the maximum allowed bit length is 32767 because - * the largest QR Code (version 40) has 31329 modules. - */ -struct qrcodegen_Segment { - // The mode indicator of this segment. - enum qrcodegen_Mode mode; - - // The length of this segment's unencoded data. Measured in characters for - // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. - // Always zero or positive. Not the same as the data's bit length. - int numChars; - - // The data bits of this segment, packed in bitwise big endian. - // Can be null if the bit length is zero. - uint8_t *data; - - // The number of valid data bits used in the buffer. Requires - // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. - // The character count (numChars) must agree with the mode and the bit buffer length. - int bitLength; -}; - - - -/*---- Macro constants and functions ----*/ - -#define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard -#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard - -// Calculates the number of bytes needed to store any QR Code up to and including the given version number, -// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' -// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16). -// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX. -#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1) - -// The worst-case number of bytes needed to store one QR Code, up to and including -// version 40. This value equals 3918, which is just under 4 kilobytes. -// Use this more convenient value to avoid calculating tighter memory bounds for buffers. -#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) - - - -/*---- Functions (high level) to generate QR Codes ----*/ - -/* - * Encodes the given text string to a QR Code, returning true if encoding succeeded. - * If the data is too long to fit in any version in the given range - * at the given ECC level, then false is returned. - * - The input text must be encoded in UTF-8 and contain no NULs. - * - The variables ecl and mask must correspond to enum constant values. - * - Requires 1 <= minVersion <= maxVersion <= 40. - * - The arrays tempBuffer and qrcode must each have a length - * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). - * - After the function returns, tempBuffer contains no useful data. - * - If successful, the resulting QR Code may use numeric, - * alphanumeric, or byte mode to encode the text. - * - In the most optimistic case, a QR Code at version 40 with low ECC - * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string - * up to 4296 characters, or any digit string up to 7089 characters. - * These numbers represent the hard upper limit of the QR Code standard. - * - Please consult the QR Code specification for information on - * data capacities per version, ECC level, and text encoding mode. - */ -bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); - - -/* - * Encodes the given binary data to a QR Code, returning true if encoding succeeded. - * If the data is too long to fit in any version in the given range - * at the given ECC level, then false is returned. - * - The input array range dataAndTemp[0 : dataLen] should normally be - * valid UTF-8 text, but is not required by the QR Code standard. - * - The variables ecl and mask must correspond to enum constant values. - * - Requires 1 <= minVersion <= maxVersion <= 40. - * - The arrays dataAndTemp and qrcode must each have a length - * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). - * - After the function returns, the contents of dataAndTemp may have changed, - * and does not represent useful data anymore. - * - If successful, the resulting QR Code will use byte mode to encode the data. - * - In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte - * sequence up to length 2953. This is the hard upper limit of the QR Code standard. - * - Please consult the QR Code specification for information on - * data capacities per version, ECC level, and text encoding mode. - */ -bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], - enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); - - -/*---- Functions (low level) to generate QR Codes ----*/ - -/* - * Renders a QR Code representing the given segments at the given error correction level. - * The smallest possible QR Code version is automatically chosen for the output. Returns true if - * QR Code creation succeeded, or false if the data is too long to fit in any version. The ECC level - * of the result may be higher than the ecl argument if it can be done without increasing the version. - * This function allows the user to create a custom sequence of segments that switches - * between modes (such as alphanumeric and byte) to encode text in less space. - * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). - * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will - * result in them being clobbered, but the QR Code output will still be correct. - * But the qrcode array must not overlap tempBuffer or any segment's data buffer. - */ -bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, - enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); - - -/* - * Renders a QR Code representing the given segments with the given encoding parameters. - * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions. - * The smallest possible QR Code version within the given range is automatically - * chosen for the output. Iff boostEcl is true, then the ECC level of the result - * may be higher than the ecl argument if it can be done without increasing the - * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or - * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). - * This function allows the user to create a custom sequence of segments that switches - * between modes (such as alphanumeric and byte) to encode text in less space. - * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). - * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will - * result in them being clobbered, but the QR Code output will still be correct. - * But the qrcode array must not overlap tempBuffer or any segment's data buffer. - */ -bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, - int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); - - -/* - * Tests whether the given string can be encoded as a segment in alphanumeric mode. - * A string is encodable iff each character is in the following set: 0 to 9, A to Z - * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. - */ -bool qrcodegen_isAlphanumeric(const char *text); - - -/* - * Tests whether the given string can be encoded as a segment in numeric mode. - * A string is encodable iff each character is in the range 0 to 9. - */ -bool qrcodegen_isNumeric(const char *text); - - -/* - * Returns the number of bytes (uint8_t) needed for the data buffer of a segment - * containing the given number of characters using the given mode. Notes: - * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or - * the number of needed bits exceeds INT16_MAX (i.e. 32767). - * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096. - * - It is okay for the user to allocate more bytes for the buffer than needed. - * - For byte mode, numChars measures the number of bytes, not Unicode code points. - * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned. - * An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. - */ -size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); - - -/* - * Returns a segment representing the given binary data encoded in - * byte mode. All input byte arrays are acceptable. Any text string - * can be converted to UTF-8 bytes and encoded as a byte mode segment. - */ -struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); - - -/* - * Returns a segment representing the given string of decimal digits encoded in numeric mode. - */ -struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); - - -/* - * Returns a segment representing the given text string encoded in alphanumeric mode. - * The characters allowed are: 0 to 9, A to Z (uppercase only), space, - * dollar, percent, asterisk, plus, hyphen, period, slash, colon. - */ -struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); - - -/* - * Returns a segment representing an Extended Channel Interpretation - * (ECI) designator with the given assignment value. - */ -struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); - - -/*---- Functions to extract raw data from QR Codes ----*/ - -/* - * Returns the side length of the given QR Code, assuming that encoding succeeded. - * The result is in the range [21, 177]. Note that the length of the array buffer - * is related to the side length - every 'uint8_t qrcode[]' must have length at least - * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1). - */ -int qrcodegen_getSize(const uint8_t qrcode[]); - - -/* - * Returns the color of the module (pixel) at the given coordinates, which is false - * for white or true for black. The top left corner has the coordinates (x=0, y=0). - * If the given coordinates are out of bounds, then false (white) is returned. - */ -bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); - - -#ifdef __cplusplus -} -#endif diff --git a/examples/network/simple_sniffer/CMakeLists.txt b/examples/network/simple_sniffer/CMakeLists.txt index 130c6c262e..f0b768c241 100644 --- a/examples/network/simple_sniffer/CMakeLists.txt +++ b/examples/network/simple_sniffer/CMakeLists.txt @@ -2,7 +2,5 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/common_components/pcap") - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(simple_sniffer) diff --git a/examples/network/simple_sniffer/main/idf_component.yml b/examples/network/simple_sniffer/main/idf_component.yml new file mode 100644 index 0000000000..c407c54eb4 --- /dev/null +++ b/examples/network/simple_sniffer/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + pcap: "^1.0.0" diff --git a/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/CMakeLists.txt index 8590f5e1eb..a4baf8b40c 100644 --- a/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/CMakeLists.txt +++ b/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/CMakeLists.txt @@ -2,7 +2,5 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/examples/common_components/pid_ctrl") - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(mcpwm_brushed_dc_control) diff --git a/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/main/idf_component.yml b/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/main/idf_component.yml new file mode 100644 index 0000000000..7d51337b61 --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_bdc_speed_control/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + pid_ctrl: "^0.1.1" diff --git a/examples/provisioning/wifi_prov_mgr/CMakeLists.txt b/examples/provisioning/wifi_prov_mgr/CMakeLists.txt index 3bd8174c6c..b036d9ce60 100644 --- a/examples/provisioning/wifi_prov_mgr/CMakeLists.txt +++ b/examples/provisioning/wifi_prov_mgr/CMakeLists.txt @@ -1,6 +1,6 @@ # The following lines of boilerplate have to be in your project's CMakeLists # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/qrcode) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(wifi_prov_mgr) diff --git a/examples/provisioning/wifi_prov_mgr/main/idf_component.yml b/examples/provisioning/wifi_prov_mgr/main/idf_component.yml new file mode 100644 index 0000000000..15aa094a22 --- /dev/null +++ b/examples/provisioning/wifi_prov_mgr/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + qrcode: "^0.1.0" diff --git a/examples/wifi/wifi_easy_connect/dpp-enrollee/CMakeLists.txt b/examples/wifi/wifi_easy_connect/dpp-enrollee/CMakeLists.txt index 2d4a908a8e..2a59359cfc 100644 --- a/examples/wifi/wifi_easy_connect/dpp-enrollee/CMakeLists.txt +++ b/examples/wifi/wifi_easy_connect/dpp-enrollee/CMakeLists.txt @@ -2,7 +2,5 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) -set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/qrcode) - include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(dpp-enrollee) diff --git a/examples/wifi/wifi_easy_connect/dpp-enrollee/main/idf_component.yml b/examples/wifi/wifi_easy_connect/dpp-enrollee/main/idf_component.yml new file mode 100644 index 0000000000..15aa094a22 --- /dev/null +++ b/examples/wifi/wifi_easy_connect/dpp-enrollee/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + qrcode: "^0.1.0" diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 5b802b1e38..8678cae92d 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1963,11 +1963,6 @@ examples/common_components/protocol_examples_common/connect.c examples/common_components/protocol_examples_common/include/addr_from_stdin.h examples/common_components/protocol_examples_common/include/protocol_examples_common.h examples/common_components/protocol_examples_common/stdin_out.c -examples/common_components/qrcode/esp_qrcode_main.c -examples/common_components/qrcode/esp_qrcode_wrapper.c -examples/common_components/qrcode/include/qrcode.h -examples/common_components/qrcode/qrcodegen.c -examples/common_components/qrcode/qrcodegen.h examples/custom_bootloader/bootloader_hooks/bootloader_components/my_boot_hooks/hooks.c examples/custom_bootloader/bootloader_hooks/example_test.py examples/custom_bootloader/bootloader_hooks/main/bootloader_hooks_example_main.c @@ -2025,8 +2020,6 @@ examples/mesh/manual_networking/main/mesh_light.c examples/mesh/manual_networking/main/mesh_main.c examples/network/network_tests/main/stdinout.c examples/network/network_tests/main/stdinout.h -examples/network/simple_sniffer/components/pcap/pcap.c -examples/network/simple_sniffer/components/pcap/pcap.h examples/network/simple_sniffer/main/cmd_sniffer.c examples/network/simple_sniffer/main/cmd_sniffer.h examples/network/simple_sniffer/main/simple_sniffer_example_main.c