Initial commit

This commit is contained in:
Tomas Rezucha 2021-11-19 10:18:28 +01:00
commit 4acb852557
14 changed files with 2332 additions and 0 deletions

4
pid_ctrl/CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
set(srcs "src/pid_ctrl.c")
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "include")

202
pid_ctrl/LICENSE Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@ -0,0 +1,4 @@
version: "0.1.0"
description: Proportional-integral-derivative controller
dependencies:
idf: ">=4.3"

100
pid_ctrl/include/pid_ctrl.h Normal file
View File

@ -0,0 +1,100 @@
/*
* 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

140
pid_ctrl/src/pid_ctrl.c Normal file
View File

@ -0,0 +1,140 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdbool.h>
#include <sys/param.h>
#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;
}

3
qrcode/CMakeLists.txt Normal file
View File

@ -0,0 +1,3 @@
idf_component_register(SRCS "esp_qrcode_main.c" "esp_qrcode_wrapper.c" "qrcodegen.c"
INCLUDE_DIRS "include"
)

202
qrcode/LICENSE Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

7
qrcode/README.md Normal file
View File

@ -0,0 +1,7 @@
# QR Code generator component
This component contains a QR code generator 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](https://github.com/espressif/esp-idf/tree/master/examples/wifi/wifi_easy_connect/dpp-enrollee).
To learn more about how to use this component, please check API Documentation from header file [qrcode.h](https://github.com/espressif/esp-bsp/tree/master/qrcode/include/qrcode.h).

113
qrcode/esp_qrcode_main.c Normal file
View File

@ -0,0 +1,113 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <esp_err.h>
#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;
}

View File

@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <esp_err.h>
#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);
}

4
qrcode/idf_component.yml Normal file
View File

@ -0,0 +1,4 @@
version: "0.1.0"
description: QR Code generator
dependencies:
idf: ">=4.3"

97
qrcode/include/qrcode.h Normal file
View File

@ -0,0 +1,97 @@
/*
* 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 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

1124
qrcode/qrcodegen.c Normal file

File diff suppressed because it is too large Load Diff

311
qrcode/qrcodegen.h Normal file
View File

@ -0,0 +1,311 @@
/*
* 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 <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#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