Refactor: Rename NanoKVM to BatchuKVM and update server URL

This commit is contained in:
2025-12-09 20:35:38 +09:00
commit 8cf674c9e5
396 changed files with 54380 additions and 0 deletions

26
support/sg2002/README.md Normal file
View File

@@ -0,0 +1,26 @@
# NanoKVM Support Instructions
## Environment Preparation
1. NanoKVM-Lite/Full/PCIe is based on the SG2002 as the main control chip. The projects in the support section are compiled under the [MaixCDK](https://github.com/sipeed/MaixCDK) framework. Before compiling, please ensure that the `MaixCDK` environment is correctly configured. For configuration instructions, click [here](https://github.com/sipeed/MaixCDK/blob/main/docs/doc_zh/README.md).
## kvm_system Compilation Instructions
> The `kvm_system` is responsible for monitoring the NanoKVM system status, system updates, screen key drivers, and a few system functions, compiled with MaixCDK.
1. Before compiling, please ensure that the above-mentioned `MaixCDK` environment is correctly configured.
2. Modify the paths of `MAIXCDK_PATH` and `NanoKVM_PATH` in `./build`.
3. Execute `./build kvm_system` to compile `kvm_system`.
4. Use `scp ./kvm_system/dist/kvm_system_release/kvm_system root@192.168.x.x:/kvmapp/kvm_system` to copy it to NanoKVM for testing.
5. Use `./build add_to_kvmapp` to place the executable file into the `/kvmapp` installation package.
6. Use `./build kvm_system clean` to clean the compilation of `kvm_system`.
## kvm_vision Compilation Instructions
> `kvm_vision` refers to the image acquisition and encoding subsystem of NanoKVM, compiled with MaixCDK to produce dynamic libraries for Go calls. Use `kvm_vision_test` to compile and test the dynamic library.
1. Before compiling, please ensure that the above-mentioned `MaixCDK` environment is correctly configured.
2. Modify the paths of `MAIXCDK_PATH` and `NanoKVM_PATH` in `./build`.
3. Execute `./build kvm_vision` to compile `kvm_vision_test`.
4. You can test the dynamic libraries in `kvm_vision_test/dist/kvm_vision_test_release/dl_lib/`.
5. Use `./build add_to_kvmapp` to place the dynamic libraries into the `/kvmapp` installation package.
6. Use `./build kvm_vision clean` to clean the compilation of `kvm_vision`.

View File

@@ -0,0 +1,26 @@
# NanoKVM support 说明
## 环境准备
1. NanoKVM-Lite/Full/PCIe 以SG2002为主控芯片support 部分的工程在[MaixCDK](https://github.com/sipeed/MaixCDK) 框架下编译。编译前,请保证`MaixCDK`环境已正确配置,配置教程点击[这里](https://github.com/sipeed/MaixCDK/blob/main/docs/doc_zh/README.md)
## kvm_system 编译说明
> `kvm_system` 负责 NanoKVM 系统状态监控、系统更新、屏幕按键驱动和少部分的系统功能,借助 MaixCDK 编译
1. 编译前,请保证上述 1.`MaixCDK`环境已正确配置
2. 修改 `./build``MAIXCDK_PATH``NanoKVM_PATH`的路径
3. 执行 `./build kvm_system` 编译 kvm_system
4. 使用 `scp ./kvm_system/dist/kvm_system_release/kvm_system root@192.168.x.x:/kvmapp/kvm_system` 拷贝入 NanoKVM 测试
5. 使用 `./build add_to_kvmapp` 可以将可执行文件放入 `/kvmapp` 安装包内
6. 使用 `./build kvm_system clean` 可以清除 kvm_system 的编译
## kvm_vision 编译说明
> `kvm_vision` 是 NanoKVM 图像获取编码子系统的统称使用MaixCDK编译出动态库供Go调用使用 `kvm_vision_test` 编译和测试动态库
1. 编译前,请保证上述 1.`MaixCDK`环境已正确配置
2. 修改 `./build``MAIXCDK_PATH``NanoKVM_PATH`的路径
3. 执行 `./build kvm_vision` 编译 kvm_vision_test
4. 可使用 `kvm_vision_test/dist/kvm_vision_test_release/dl_lib/` 中的动态库测试
5. 使用 `./build add_to_kvmapp` 可以将动态库放入 `/kvmapp` 安装包内
6. 使用 `./build kvm_vision clean` 可以清除 kvm_system 的编译

View File

@@ -0,0 +1,6 @@
list(APPEND ADD_REQUIREMENTS vision basic peripheral)
list(APPEND ADD_INCLUDE "include")
append_srcs_dir(ADD_SRCS "src")
register_component(DYNAMIC)

View File

View File

@@ -0,0 +1,82 @@
#ifndef KVM_VISION_H_
#define KVM_VISION_H_
#include "kvm_mmf.hpp"
#include "maix_camera.hpp"
#include "maix_basic.hpp"
#include "maix_i2c.hpp"
#ifdef __cplusplus
extern "C" {
#endif
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <pthread.h>
#include <time.h>
// #include "kvm_mmf.hpp"
#define IMG_BUFFER_FULL -3
#define IMG_VENC_ERROR -2
#define IMG_NOT_EXIST -1
#define IMG_MJPEG_TYPE 0
#define IMG_H264_TYPE_SPS 1
#define IMG_H264_TYPE_PPS 2
#define IMG_H264_TYPE_IF 3
#define IMG_H264_TYPE_PF 4
#define NORMAL_RES 0
#define NEW_RES 1
#define UNSUPPORT_RES 2
#define UNKNOWN_RES 3
#define ERROR_RES 4
void kvmv_init(uint8_t _debug_info_en = 0);
void set_venc_auto_recyc(uint8_t _enable);
/**********************************************************************************
* @name kvmv_read_img
* @author Sipeed BuGu
* @date 2024/10/25
* @version R1.0
* @brief Acquire the encoded image with auto init
* @param _width @input: Output image width
* @param _height @input: Output image height
* @param _type @input: Encode type
* @param _qlty @input: MJPEG: (50-100) | H264: (500-10000)
* @param _pp_kvm_data @output: Encode data
* @param _p_kvmv_data_size @output: Encode data size
* @return
-7: HDMI INPUT RES ERROR
-6: Unsupported resolution, please modify it in the host settings.
-5: Retrieving image, please wait
-4: Modifying image resolution, please wait
-3: img buffer full
-2: VENC Errorl
-1: No images were acquired
0: Acquire MJPEG encoded images
1: Acquire H264 encoded images(SPS)[Deprecated]
2: Acquire H264 encoded images(PPS)[Deprecated]
3: Acquire H264 encoded images(I)
4: Acquire H264 encoded images(P)
5: IMG not changed
**********************************************************************************/
int kvmv_read_img(uint16_t _width, uint16_t _height, uint8_t _type, uint16_t _qlty, uint8_t** _pp_kvm_data, uint32_t* _p_kvmv_data_size);
int free_kvmv_data(uint8_t ** _pp_kvm_data);
void free_all_kvmv_data();
void set_h264_gop(uint8_t _gop);
void set_frame_detact(uint8_t _frame_detact);
void kvmv_deinit();
uint8_t kvmv_hdmi_control(uint8_t _en);
#ifdef __cplusplus
}
#endif
#endif // KVM_VISION_H_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
list(APPEND ADD_REQUIREMENTS basic ini)
list(APPEND ADD_INCLUDE "include")
# sophgo-middleware
set(middleware_src_path "${CMAKE_CURRENT_SOURCE_DIR}/../3rd_party/sophgo-middleware/sophgo-middleware")
set(source_dir "src")
append_srcs_dir(ADD_SRCS "${source_dir}")
# middleware
set(middleware_include_dir .
${middleware_src_path}/v2/component/panel/${CONFIG_SOPHGO_MIDDLEWARE_CHIP}
${middleware_src_path}/v2/include
${middleware_src_path}/v2/include/isp/${CONFIG_SOPHGO_MIDDLEWARE_CHIP}
${middleware_src_path}/v2/sample/common
${middleware_src_path}/v2/uapi
${middleware_src_path}/v2/3rdparty/inih
${middleware_src_path}/v2/modules/ive/include/
)
list(APPEND ADD_INCLUDE ${middleware_include_dir})
set_property(SOURCE ${middleware_include_dir} PROPERTY GENERATED 1)
append_srcs_dir(middleware_src_dir ${middleware_src_path}/v2/sample/common
${middleware_src_path}/v2/component/isp/sensor/sg200x/lontium_lt6911
)
list(APPEND ADD_SRCS ${middleware_src_dir}
"${source_dir}/kvm_mmf.cpp")
set_property(SOURCE ${middleware_src_dir} PROPERTY GENERATED 1)
set(middleware_static_lib_file "")
list(APPEND ADD_STATIC_LIB ${middleware_static_lib_file})
set_property(SOURCE ${middleware_static_lib_file} PROPERTY GENERATED 1)
set(mmf_lib_dir ${middleware_src_path}/v2/lib)
if(CONFIG_SOPHGO_MIDDLEWARE_C_LIBRARY STREQUAL "musl")
set(middleware_dynamic_lib_file ${mmf_lib_dir}/libcvi_bin.so
${mmf_lib_dir}/libae.so
${mmf_lib_dir}/libaf.so
${mmf_lib_dir}/libawb.so
${mmf_lib_dir}/libcvi_bin_isp.so
${mmf_lib_dir}/libisp_algo.so
${mmf_lib_dir}/libisp.so
${mmf_lib_dir}/libsys.so
${mmf_lib_dir}/libvdec.so
${mmf_lib_dir}/libvenc.so
${mmf_lib_dir}/libvpu.so
${mmf_lib_dir}/3rd/libini.so)
elseif(CONFIG_SOPHGO_MIDDLEWARE_C_LIBRARY STREQUAL "glibc")
set(middleware_dynamic_lib_file ${mmf_lib_dir}/libcvi_vb.so
${mmf_lib_dir}/libcvi_sys.so
${mmf_lib_dir}/libcvi_debug.so
)
else()
message(FATAL_ERROR "No sophgo middleware c library support, please check menuoconfig to select c library")
endif()
list(APPEND ADD_DYNAMIC_LIB ${middleware_dynamic_lib_file})
set_property(SOURCE ${middleware_dynamic_lib_file} PROPERTY GENERATED 1)
list(APPEND ADD_DEFINITIONS_PRIVATE -DSENSOR_LONTIUM_LT6911
-DSENSOR2_TYPE=LONTIUM_LT6911_2M_60FPS_8BIT)
register_component(DYNAMIC)

View File

@@ -0,0 +1,32 @@
# sophgo middleware version major minor patch
menu "sophgo middleware version"
config SOPHGO_MIDDLEWARE_CHIP
string "sophgo chip"
default "cv181x"
help
sophgo chip. cv180x or cv181x
config SOPHGO_MIDDLEWARE_C_LIBRARY
string "sophgo c standard library"
default "musl"
help
sophgo c standard library. glibc or musl
config SOPHGO_MIDDLEWARE_VERSION_MAJOR
int "sophgo middleware package major version"
default 0
help
sophgo middleware package major version, 0 means auto select according to board
config SOPHGO_MIDDLEWARE_VERSION_MINOR
int "sophgo middleware package minor version"
default 0
help
sophgo middleware package minor version
config SOPHGO_MIDDLEWARE_VERSION_PATCH
int "sophgo middleware package patch version"
default 4
help
sophgo middleware package patch version
endmenu

View File

@@ -0,0 +1,68 @@
#ifndef __KVM_MMF_HPP__
#define __KVM_MMF_HPP__
#include "stdint.h"
typedef struct {
uint8_t *data[8];
int data_size[8];
int count;
} mmf_stream_t;
typedef struct {
uint8_t type; // 0, jpg; 1, h265; 2, h264
int w;
int h;
int fmt;
uint8_t jpg_quality; // jpeg
int gop; // h264
int intput_fps; // h264
int output_fps; // h264
int bitrate; // h264
} mmf_venc_cfg_t;
// init sys
int mmf_init(void);
int mmf_deinit(void);
int mmf_try_deinit(bool force);
bool mmf_is_init(void);
// manage vi channels(vi->vpssgroup->vpss->frame)
int mmf_get_vi_unused_channel(void);
int mmf_vi_init(void);
int mmf_vi_deinit(void);
int mmf_add_vi_channel_with_enc(int ch, int width, int height, int format);
int mmf_add_vi_channel(int ch, int width, int height, int format);
int mmf_del_vi_channel(int ch);
int mmf_del_vi_channel_all(void);
int mmf_reset_vi_channel(int ch, int width, int height, int format);
bool mmf_vi_chn_is_open(int ch);
int mmf_vi_aligned_width(int ch);
void mmf_set_vi_hmirror(int ch, bool en);
void mmf_set_vi_vflip(int ch, bool en);
void mmf_get_vi_hmirror(int ch, bool *en);
void mmf_get_vi_vflip(int ch, bool *en);
// get vi frame
int mmf_vi_frame_pop(int ch, void **data, int *len, int *width, int *height, int *format);
void mmf_vi_frame_free(int ch);
// invert format
int mmf_invert_format_to_maix(int mmf_format);
int mmf_invert_format_to_mmf(int maix_format);
// venc
int mmf_enc_jpg_init(int ch, int w, int h, int format, int quality);
int mmf_enc_jpg_deinit(int ch);
int mmf_enc_jpg_push(int ch, uint8_t *data, int w, int h, int format);
int mmf_enc_jpg_push_with_quality(int ch, uint8_t *data, int w, int h, int format, int quality);
int mmf_enc_jpg_pop(int ch, uint8_t **data, int *size);
int mmf_enc_jpg_free(int ch);
int mmf_add_venc_channel(int ch, mmf_venc_cfg_t *cfg);
int mmf_del_venc_channel(int ch);
int mmf_del_venc_channel_all();
int mmf_venc_push(int ch, uint8_t *data, int w, int h, int format);
int mmf_venc_pop(int ch, mmf_stream_t *stream);
int mmf_venc_free(int ch);
#endif // __KVM_MMF_HPP__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,322 @@
/**
* @author neucrack@sipeed, lxowalle@sipeed
* @copyright Sipeed Ltd 2023-
* @license Apache 2.0
* @update 2023.9.8: Add framework, create this file.
*/
#include "maix_i2c.hpp"
#include "maix_basic.hpp"
#include "cstdio"
#include <fcntl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#define DEV_PATH "/dev/i2c-%d"
namespace maix::peripheral::i2c
{
std::vector<int> list_devices()
{
std::vector<int> data;
// list all files in /dev, find i2c-*
std::vector<std::string> *files = fs::listdir("/dev");
for (auto &file : *files)
{
if (file.find("i2c-") != std::string::npos)
{
try
{
data.push_back(std::stoi(file.substr(4)));
}
catch (const std::exception &e)
{
log::error("i2c bus id %s format error", file.c_str());
}
}
}
delete files;
return data;
}
I2C::I2C(int id, i2c::Mode mode, int freq, i2c::AddrSize addr_size)
{
char buf[32];
snprintf(buf, sizeof(buf), DEV_PATH, id);
if(access(buf, F_OK) == 0){
if (mode == i2c::SLAVE)
{
throw err::Exception(err::Err::ERR_NOT_IMPL, "i2c::SLAVE mode not implemented");
}
if (addr_size != i2c::SEVEN_BIT)
{
throw err::Exception(err::Err::ERR_NOT_IMPL, "addr_size " + std::to_string(addr_size) + " not support");
}
int fd = ::open(buf, O_RDWR);
if (fd < 0)
{
throw err::Exception(err::Err::ERR_IO, "open " + std::string(buf) + " failed");
}
_fd = fd;
_freq = freq;
_mode = mode;
_addr_size = addr_size;
} else {
printf("not exit i2c\r\n");
}
}
I2C::~I2C()
{
if (_fd > 0)
{
::close(_fd);
}
}
std::vector<int> I2C::scan(int addr)
{
std::vector<int> data;
int addr_start = 0x08;
int addr_end = 0x77;
if(addr > 0)
{
addr_start = addr;
addr_end = addr;
}
if (_mode != i2c::Mode::MASTER)
{
log::error("Only for master mode");
return data;
}
switch (_addr_size)
{
case i2c::AddrSize::SEVEN_BIT:
for (int address = addr_start; address <= addr_end; ++address)
{
if (::ioctl(_fd, I2C_SLAVE, address) < 0)
{
continue;
}
unsigned char buffer[1];
if (::read(_fd, buffer, sizeof(buffer)) >= 0)
{
data.push_back(address);
}
}
break;
default:
log::error("bit %d not support", _addr_size);
return data;
}
return data;
}
int I2C::writeto(int addr, const uint8_t *data, int len)
{
if (_mode != i2c::Mode::MASTER)
{
log::error("Only for master mode");
return (int)-err::Err::ERR_NOT_PERMIT;
}
if (0 != ioctl(_fd, I2C_SLAVE, addr))
{
// log::error("set slave address failed");
return (int)-err::Err::ERR_IO;
}
if (len != ::write(_fd, data, len))
{
log::error("write failed");
return (int)-err::Err::ERR_IO;
}
return len;
}
int I2C::writeto(int addr, const std::vector<unsigned char> data)
{
return writeto(addr, data.data(), (int)data.size());
}
int I2C::writeto(int addr, const Bytes &data)
{
return writeto(addr, data.data, (int)data.size());
}
Bytes* I2C::readfrom(int addr, int len)
{
Bytes *data = new Bytes(nullptr, len);
if (_mode != i2c::Mode::MASTER)
{
log::error("Only for master mode");
return nullptr;
}
if (0 != ioctl(_fd, I2C_SLAVE, addr))
{
// log::error("set slave address failed");
return nullptr;
}
if (len != ::read(_fd, data->data, len))
{
log::error("read failed");
delete data;
return nullptr;
}
return data;
}
int I2C::writeto_mem(int addr, int mem_addr, const uint8_t *data, int len, int mem_addr_size, bool mem_addr_le)
{
if (_mode != i2c::Mode::MASTER)
{
log::error("Only for master mode");
return (int)-err::Err::ERR_NOT_PERMIT;
}
if(mem_addr_size % 8 != 0)
{
log::error("mem_addr_size must be multiple of 8");
return (int)-err::Err::ERR_IO;
}
if (0 != ioctl(_fd, I2C_SLAVE, addr))
{
// log::error("set slave address failed");
return (int)-err::Err::ERR_IO;
}
std::vector<unsigned char> data_final;
if(mem_addr_size == 8)
{
data_final.push_back((unsigned char)mem_addr);
}
else
{
if(mem_addr_le)
{
for(int i = 0; i < mem_addr_size / 8; i++)
{
data_final.push_back((unsigned char)(mem_addr & 0xff));
mem_addr >>= 8;
}
}
else
{
for(int i = 0; i < mem_addr_size / 8; i++)
{
data_final.push_back((unsigned char)(mem_addr >> (8 * (mem_addr_size / 8 - i - 1))));
}
}
}
for(int i = 0; i < len; i++)
{
data_final.push_back(data[i]);
}
int write_len = ::write(_fd, data_final.data(), data_final.size());
if (data_final.size() != (size_t)write_len)
{
log::error("write failed, write_len: %d", write_len);
return (int)-err::Err::ERR_IO;
}
return len;
}
int I2C::writeto_mem(int addr, int mem_addr, const std::vector<unsigned char> data, int mem_addr_size, bool mem_addr_le)
{
return writeto_mem(addr, mem_addr, data.data(), (int)data.size(), mem_addr_size, mem_addr_le);
}
int I2C::writeto_mem(int addr, int mem_addr, const Bytes &data, int mem_addr_size, bool mem_addr_le)
{
return writeto_mem(addr, mem_addr, data.data, (int)data.size(), mem_addr_size, mem_addr_le);
}
Bytes* I2C::readfrom_mem(int addr, int mem_addr, int len, int mem_addr_size, bool mem_addr_le)
{
// write mem_addr and restart to read
if (_mode != i2c::Mode::MASTER)
{
log::error("Only for master mode");
return nullptr;
}
if(mem_addr_size % 8 != 0)
{
log::error("mem_addr_size must be multiple of 8");
return nullptr;
}
// write mem_addr first and restart to read
if (0 != ioctl(_fd, I2C_SLAVE, addr))
{
// log::error("set slave address failed");
return nullptr;
}
std::vector<unsigned char> data_final;
if(mem_addr_size == 8)
{
data_final.push_back((unsigned char)mem_addr);
}
else
{
if(mem_addr_le)
{
for(int i = 0; i < mem_addr_size / 8; i++)
{
data_final.push_back((unsigned char)(mem_addr & 0xff));
mem_addr >>= 8;
}
}
else
{
for(int i = 0; i < mem_addr_size / 8; i++)
{
data_final.push_back((unsigned char)(mem_addr >> (8 * (mem_addr_size / 8 - i - 1))));
}
}
}
// write read with I2C_RDWR
struct i2c_msg msgs[2];
msgs[0].addr = addr;
msgs[0].flags = 0;
msgs[0].len = data_final.size();
msgs[0].buf = data_final.data();
Bytes *data = new Bytes(nullptr, len);
msgs[1].addr = addr;
msgs[1].flags = I2C_M_RD;
msgs[1].len = len;
msgs[1].buf = data->data;
struct i2c_rdwr_ioctl_data msgset;
msgset.msgs = msgs;
msgset.nmsgs = 2;
int read_len = ioctl(_fd, I2C_RDWR, &msgset);
if (read_len != 2)
{
log::error("read failed");
delete data;
return nullptr;
}
return data;
}
}

View File

@@ -0,0 +1,77 @@
# Config enable component2 or not in Kconfig
################# Add include #################
list(APPEND ADD_INCLUDE "include"
"include/base"
)
if(PLATFORM_LINUX)
list(APPEND ADD_PRIVATE_INCLUDE "port/linux")
elseif(PLATFORM_MAIXCAM)
list(APPEND ADD_PRIVATE_INCLUDE "port/maixcam")
endif()
list(APPEND ADD_PRIVATE_INCLUDE "include_private")
###############################################
############## Add source files ###############
# list(APPEND ADD_SRCS "src/lib2.c"
# )
# FILE(GLOB_RECURSE EXTRA_SRC "src/*.c")
# FILE(GLOB EXTRA_SRC "src/*.c")
# list(APPEND ADD_SRCS ${EXTRA_SRC})
# aux_source_directory(src ADD_SRCS) # collect all source file in src dir, will set var ADD_SRCS
append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS
if(PLATFORM_LINUX)
append_srcs_dir(ADD_SRCS "port/linux")
elseif(PLATFORM_MAIXCAM)
append_srcs_dir(ADD_SRCS "port/maixcam")
endif()
# list(REMOVE_ITEM COMPONENT_SRCS "src/test.c")
# set(ADD_ASM_SRCS "src/asm.S")
# list(APPEND ADD_SRCS ${ADD_ASM_SRCS})
# SET_PROPERTY(SOURCE ${ADD_ASM_SRCS} PROPERTY LANGUAGE C) # set .S ASM file as C language
# SET_SOURCE_FILES_PROPERTIES(${ADD_ASM_SRCS} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp -D BBBBB")
###############################################
###### Add required/dependent components ######
list(APPEND ADD_REQUIREMENTS basic opencv opencv_freetype websocket peripheral)
list(APPEND ADD_REQUIREMENTS omv)
list(APPEND ADD_REQUIREMENTS kvm_mmf)
###############################################
###### Add link search path for requirements/libs ######
# list(APPEND ADD_LINK_SEARCH_PATH "${CONFIG_TOOLCHAIN_PATH}/lib")
# list(APPEND ADD_REQUIREMENTS pthread m) # add system libs, pthread and math lib for example here
# set (OpenCV_DIR opencv/lib/cmake/opencv4)
# find_package(OpenCV REQUIRED)
###############################################
############ Add static libs ##################
# list(APPEND ADD_STATIC_LIB "lib/libtest.a")
###############################################
############ Add dynamic libs ##################
# list(APPEND ADD_DYNAMIC_LIB "lib/arch/v831/libmaix_nn.so"
# "lib/arch/v831/libmaix_cam.so"
# )
###############################################
#### Add compile option for this component ####
#### Just for this component, won't affect other
#### modules, including component that depend
#### on this component
# list(APPEND ADD_DEFINITIONS_PRIVATE -DAAAAA=1)
#### Add compile option for this component
#### and components denpend on this component
# list(APPEND ADD_DEFINITIONS -DAAAAA222=1
# -DAAAAA333=1)
###############################################
############ Add static libs ##################
#### Update parent's variables like CMAKE_C_LINK_FLAGS
# set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group libmaix/libtest.a -ltest2 -Wl,--end-group" PARENT_SCOPE)
###############################################
# register component, DYNAMIC or SHARED flags will make component compiled to dynamic(shared) lib
register_component()

View File

View File

@@ -0,0 +1,109 @@
/**
* @file maix_camera_base.hpp
* @brief Maix camera SDL implementation
* @author neucrack@sipeed.com
* @license Apache 2.0 Sipeed Ltd
* @update date 2023-10-23 Create by neucrack
*/
#pragma once
#include <vector>
#include "maix_image.hpp"
#include "maix_err.hpp"
namespace maix::camera
{
class CameraBase
{
public:
/**
* @brief Construct a new Camera object
* @param device camera device name, you can get devices by list_devices method, by default(value is NULL(None in MaixPy)) means the first device
* @param width camera width, by default(value is -1) means auto detect,
* if width > max device supported width, will auto set to max device supported width
* @param height camera height, by default(value is -1) means auto detect,
* if height > max device supported height, will auto set to max device supported height
* @param format camera format, by default(value is FMT_RGB888)
* @param buff_num camera buffer number, by default(value is 3)
*/
CameraBase(const char *device = nullptr, int width = -1, int height = -1, image::Format format = image::Format::FMT_RGB888, int buff_num = 3){};
/**
* @brief Judge if the given format is supported by the camera
*/
virtual bool is_support_format(image::Format format) = 0;
/**
* @brief open camera device
* @param width camera width, by default(value is -1) means auto detect,
* if width > max device supported width, will auto set to max device supported width
* @param height camera height, by default(value is -1) means auto detect,
* if height > max device supported height, will auto set to max device supported height
* @param format camera format, by default(value is FMT_RGB888)
* @param buff_num camera buffer number, by default(value is 3)
* @return error code
*/
virtual err::Err open(int width = -1, int height = -1, image::Format format = image::Format::FMT_RGB888, int buff_num = 3) = 0;
/**
* @brief read a frame from camera
* @param buff buffer to store image data, if NULL, will alloc a new buffer
* @return image data
*/
virtual image::Image *read(void *buff = NULL, size_t buff_size = 0) = 0;
/**
* @brief close camera device
* @return none
*/
virtual void close() = 0;
/**
* Add a new channel and return a new Camera object, you can use close() to close this channel.
* @param width camera width, default is -1, means auto, mostly means max width of camera support
* @param height camera height, default is -1, means auto, mostly means max height of camera support
* @param format camera output format, default is RGB888
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
* more than one buffer will accelerate image read speed, but will cost more memory.
* @return new Camera object
*/
virtual camera::CameraBase *add_channel(int width = -1, int height = -1, image::Format format = image::FMT_RGB888, int buff_num = 3) = 0;
/**
* @brief clear all buffer
* @return none
*/
virtual void clear_buff() = 0;
/**
* @brief check camera device is opened or not
* @return opened or not, bool type
*/
virtual bool is_opened() = 0;
/**
* Get camera supported channels(layers)
*/
virtual int get_ch_nums() = 0;
/**
* Get channel number of camera.
*/
virtual int get_channel() = 0;
/**
* Set/Get camera mirror
* @param en enable/disable mirror
*/
virtual int hmirror(int en) = 0;
/**
* Set/Get camera flip
* @param en enable/disable flip
*/
virtual int vflip(int en) = 0;
};
}

View File

@@ -0,0 +1,305 @@
/**
* @author neucrack@sipeed, lxowalle@sipeed
* @copyright Sipeed Ltd 2023-
* @license Apache 2.0
* @update 2023.9.8: Add framework, create this file.
*/
#pragma once
#include "maix_tensor.hpp"
#include "maix_log.hpp"
#include "maix_image.hpp"
#include "maix_err.hpp"
#include "maix_camera_base.hpp"
#include <stdlib.h>
#include <map>
#include <stdexcept>
#include <vector>
#include <opencv2/opencv.hpp>
/**
* @brief maix.camera module, access camera device and get image from it
* @maixpy maix.camera
*/
namespace maix::camera
{
/**
* List all supported camera devices.
* @return Returns the path to the camera device.
* @maixpy maix.camera.list_devices
*/
std::vector<std::string> list_devices();
/**
* Enable set camera registers, default is false, if set to true, will not set camera registers, you can manually set registers by write_reg API.
* @param enable enable/disable set camera registers
* @maixpy maix.camera.set_regs_enable
*/
void set_regs_enable(bool enable = true);
/**
* Camera class
* @maixpy maix.camera.Camera
*/
class Camera
{
public:
/**
* @brief Construct a new Camera object.
* Maximum resolution support 2560x1440.
* @param width camera width, default is -1, means auto, mostly means max width of camera support
* @param height camera height, default is -1, means auto, mostly means max height of camera support
* @param format camera output format, default is image.Format.FMT_RGB888
* @param device camera device path, you can get devices by list_devices method, by default(value is NULL(None in MaixPy)) means the first device
* @param fps camera fps, default is -1, means auto, mostly means max fps of camera support
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
* more than one buffer will accelerate image read speed, but will cost more memory.
* @param open If true, camera will automatically call open() after creation. default is true.
* @maixpy maix.camera.Camera.__init__
* @maixcdk maix.camera.Camera.Camera
*/
Camera(int width = -1, int height = -1, image::Format format = image::FMT_RGB888, const char *device = nullptr, int fps = -1, int buff_num = 3, bool open = true);
/**
* @brief Construct a new Camera object.
* @attention CameraBase * parameter need to be set manually, otherwise the operation of this object will be invalid.
* @param device camera device path, you can get devices by list_devices method, by default(value is NULL(None in MaixPy)) means the first device
* @param base basic operation objects.
* @param width camera width, default is -1, means auto, mostly means max width of camera support
* @param height camera height, default is -1, means auto, mostly means max height of camera support
* @param format camera output format, default is image.Format.FMT_RGB888
* @param fps camera fps, default is -1, means auto, mostly means max fps of camera support
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
* more than one buffer will accelerate image read speed, but will cost more memory.
* @param open If true, camera will automatically call open() after creation. default is true.
* @maixcdk maix.camera.Camera.Camera
*/
Camera(const char *device, CameraBase *base, int width = -1, int height = -1, image::Format format = image::FMT_RGB888, int fps = -1, int buff_num = -1, bool open = true);
~Camera();
void restart(int width = -1, int height = -1, image::Format format = image::FMT_RGB888, const char *device = nullptr, int fps = -1, int buff_num = 3, bool open = true);
/**
* Get the number of channels supported by the camera.
* @return Returns the maximum number of channels.
* @maixpy maix.camera.Camera.get_ch_nums
*/
int get_ch_nums();
/**
* Open camera and run
* @param width camera width, default is -1, means auto, mostly means max width of camera support
* @param height camera height, default is -1, means auto, mostly means max height of camera support
* @param format camera output format, default same as the constructor's format argument
* @param fps camera fps, default is -1, means auto, mostly means max fps of camera support
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
* more than one buffer will accelerate image read speed, but will cost more memory.
* @return error code, err::ERR_NONE means success, others means failed
* @maixpy maix.camera.Camera.open
*/
err::Err open(int width = -1, int height = -1, image::Format format = image::FMT_INVALID, int fps = -1, int buff_num = -1);
/**
* Get one frame image from camera buffer, must call open method before read.
* If open method not called, will call it automatically, if open failed, will throw exception!
* So call open method before read is recommended.
* @param buff buffer to store image data, if buff is nullptr, will alloc memory automatically.
* In MaixPy, default to None, you can create a image.Image object, then pass img.data() to buff.
* @param block block read, default is true, means block util read image successfully,
* if set to false, will return nullptr if no image in buffer
* @return image::Image object, if failed, return nullptr, you should delete if manually in C++
* @maixpy maix.camera.Camera.read
*/
image::Image *read(void *buff = nullptr, size_t buff_size = 0, bool block = true);
/**
* Clear buff to ensure the next read image is the latest image
* @maixpy maix.camera.Camera.clear_buff
*/
void clear_buff();
/**
* Read some frames and drop, this is usually used avoid read not stable image when camera just opened.
* @param num number of frames to read and drop
* @maixpy maix.camera.Camera.skip_frames
*/
void skip_frames(int num);
/**
* Close camera
* @maixpy maix.camera.Camera.close
*/
void close();
/**
* Add a new channel and return a new Camera object, you can use close() to close this channel.
* @param width camera width, default is -1, means auto, mostly means max width of camera support
* @param height camera height, default is -1, means auto, mostly means max height of camera support
* @param format camera output format, default is RGB888
* @param fps camera fps, default is -1, means auto, mostly means max fps of camera support
* @param buff_num camera buffer number, default is 3, means 3 buffer, one used by user, one used for cache the next frame,
* more than one buffer will accelerate image read speed, but will cost more memory.
* @param open If true, camera will automatically call open() after creation. default is true.
* @return new Camera object
* @maixpy maix.camera.Camera.add_channel
*/
camera::Camera *add_channel(int width = -1, int height = -1, image::Format format = image::FMT_RGB888, int fps = -1, int buff_num = 3, bool open = true);
/**
* Check if camera is opened
* @return true if camera is opened, false if not
* @maixpy maix.camera.Camera.is_opened
*/
bool is_opened();
/**
* @brief check camera device is closed or not
* @return closed or not, bool type
* @maixpy maix.camera.Camera.is_closed
*/
bool is_closed() { return !is_opened();}
/**
* Get camera width
* @return camera width
* @maixpy maix.camera.Camera.width
*/
int width()
{
return _width;
}
/**
* Get camera height
* @return camera height
* @maixpy maix.camera.Camera.height
*/
int height()
{
return _height;
}
/**
* Get camera fps
* @return camera fps
* @maixpy maix.camera.Camera.fps
*/
int fps()
{
return _fps;
}
/**
* Get camera output format
* @return camera output format, image::Format object
* @maixpy maix.camera.Camera.format
*/
image::Format format()
{
return _format;
}
/**
* Get camera buffer number
* @return camera buffer number
* @maixpy maix.camera.Camera.buff_num
*/
int buff_num()
{
return _buff_num;
}
/**
* Set/Get camera horizontal mirror
* @return camera horizontal mirror
* @maixpy maix.camera.Camera.hmirror
*/
int hmirror(int value = -1);
/**
* Set/Get camera vertical flip
* @return camera vertical flip
* @maixpy maix.camera.Camera.vflip
*/
int vflip(int value = -1);
/**
* Get camera device path
* @return camera device path
* @maixpy maix.camera.Camera.device
*/
std::string device()
{
return _device;
}
/**
* Write camera register
* @param addr register address
* @param data register data
* @param bit_width register data bit width, default is 8
* @return error code, err::ERR_NONE means success, others means failed
* @maixpy maix.camera.Camera.write_reg
*/
err::Err write_reg(int addr, int data, int bit_width = 8)
{
return err::ERR_NONE;
}
/**
* Read camera register
* @param addr register address
* @return register data, -1 means failed
* @param bit_width register data bit width, default is 8
* @maixpy maix.camera.Camera.read_reg
*/
int read_reg(int addr, int bit_width = 8)
{
return -1;
}
/**
* Camera output color bar image for test
* @param enable enable/disable color bar
* @return error code, err::ERR_NONE means success, others means failed
* @maixpy maix.camera.Camera.show_colorbar
*/
err::Err show_colorbar(bool enable);
/**
* Get channel of camera
* @return channel number
* @maixpy maix.camera.Camera.get_channel
*/
int get_channel();
/**
* Set camera resolution
* @param width new width
* @param height new height
* @return error code, err::ERR_NONE means success, others means failed
* @maixpy maix.camera.Camera.set_resolution
*/
err::Err set_resolution(int width, int height);
private:
std::string _device;
int _ch;
int _width;
int _height;
int _fps;
int _buff_num;
image::Format _format;
image::Format _format_impl; // used by implement code and need convert to _format
int _hmirror;
int _vflip;
float _exposure;
float _gain;
bool _show_colorbar;
bool _open_set_regs;
CameraBase *_impl; // used by implement code
bool _check_format(image::Format format);
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,296 @@
/**
* @author neucrack@sipeed, lxowalle@sipeed
* @copyright Sipeed Ltd 2023-
* @license Apache 2.0
* @update 2023.9.8: Add framework, create this file.
*/
#pragma once
#include "maix_image_def.hpp"
#include "maix_log.hpp"
namespace maix::image
{
/**
* Color class
* @maixpy maix.image.Color
*/
class Color
{
public:
/**
* Color constructor
* @param alpha alpha channel, value range: 0 ~ 1
* @maixpy maix.image.Color.__init__
*/
Color(uint8_t ch1, uint8_t ch2 = 0, uint8_t ch3 = 0, float alpha = 0, image::Format format = image::FMT_GRAYSCALE)
{
if(alpha > 1 || alpha < 0)
throw std::runtime_error("alpha value range: 0 ~ 1");
this->format = format;
switch (format)
{
case image::FMT_RGB888:
r = ch1;
g = ch2;
b = ch3;
this->alpha = 1;
break;
case image::FMT_BGR888:
b = ch1;
g = ch2;
r = ch3;
this->alpha = 1;
break;
case image::FMT_GRAYSCALE:
gray = ch1;
break;
case image::FMT_BGRA8888:
b = ch1;
g = ch2;
r = ch3;
this->alpha = alpha;
break;
case image::FMT_RGBA8888:
r = ch1;
g = ch2;
b = ch3;
this->alpha = alpha;
break;
default:
throw std::runtime_error("not support format");
break;
}
}
/**
* Color red channel
* @maixpy maix.image.Color.r
*/
uint8_t r;
/**
* Color green channel
* @maixpy maix.image.Color.g
*/
uint8_t g;
/**
* Color blue channel
* @maixpy maix.image.Color.b
*/
uint8_t b;
/**
* Color alpha channel, value from 0.0 to 1.0, float value
* @maixpy maix.image.Color.alpha
*/
float alpha;
/**
* Color gray channel
* @maixpy maix.image.Color.gray
*/
uint8_t gray;
/**
* Color format
* @maixpy maix.image.Color.format
*/
image::Format format;
/**
* Get color's hex value
* @maixpy maix.image.Color.hex
*/
uint32_t hex()
{
uint32_t hex = 0;
switch (format)
{
case image::FMT_RGB888:
hex = r | (g << 8) | (b << 16);
break;
case image::FMT_BGR888:
hex = b | (g << 8) | (r << 16);
break;
case image::FMT_GRAYSCALE:
hex = gray;
break;
case image::FMT_BGRA8888:
hex = b | (g << 8) | (r << 16) | ((uint8_t)(alpha*255) << 24);
break;
case image::FMT_RGBA8888:
hex = r | (g << 8) | (b << 16) | ((uint8_t)(alpha*255) << 24);
break;
default:
throw std::runtime_error("not support format");
break;
}
return hex;
}
/**
* Create Color object from RGB channels
* @maixpy maix.image.Color.from_rgb
*/
static image::Color from_rgb(uint8_t r, uint8_t g, uint8_t b)
{
return Color(r, g, b, 1, image::Format::FMT_RGB888);
}
/**
* Create Color object from BGR channels
* @maixpy maix.image.Color.from_bgr
*/
static image::Color from_bgr(uint8_t b, uint8_t g, uint8_t r)
{
return Color(b, g, r, 1, image::Format::FMT_BGR888);
}
/**
* Create Color object from gray channel
* @maixpy maix.image.Color.from_gray
*/
static image::Color from_gray(uint8_t gray)
{
return Color(gray);
}
/**
* Create Color object from RGBA channels
* @param alpha alpha channel, float value, value range: 0 ~ 1
* @maixpy maix.image.Color.from_rgba
*/
static image::Color from_rgba(uint8_t r, uint8_t g, uint8_t b, float alpha)
{
return Color(r, g, b, alpha, image::Format::FMT_RGBA8888);
}
/**
* Create Color object from BGRA channels
* * @param alpha alpha channel, float value, value range: 0 ~ 1
* @maixpy maix.image.Color.from_bgra
*/
static image::Color from_bgra(uint8_t b, uint8_t g, uint8_t r, float alpha)
{
return Color(b, g, r, alpha, image::Format::FMT_BGRA8888);
}
/**
* Create Color object from hex value
* @param hex hex value, e.g. 0x0000FF00, lower address if first channel
* @param format color format, @see image::Format
* @maixpy maix.image.Color.from_hex
*/
static image::Color from_hex(uint32_t hex, image::Format &format)
{
return Color(hex & 0xFF, hex & 0xFF00, hex & 0xFF0000, (hex & 0xFF000000)/255.0, format);
}
/**
* Convert Color format
* @param format format want to convert to, @see image::Format, only support RGB888, BGR888, RGBA8888, BGRA8888, GRAYSCALE.
* @maixpy maix.image.Color.to_format
*/
void to_format(const image::Format &format)
{
if(!(format == image::FMT_RGB888 || format == image::FMT_BGR888 ||
format == image::FMT_RGBA8888 || format == image::FMT_BGRA8888 ||
format == image::FMT_GRAYSCALE))
{
log::error("convert format failed, not support format %d\n", format);
return;
}
if(this->format == format)
return;
if((this->format == image::FMT_RGB888 || this->format == image::FMT_BGR888) &&
(format == image::FMT_RGBA8888 || format == image::FMT_BGRA8888))
{
this->alpha = 1;
}
else if(this->format == image::FMT_GRAYSCALE && format != image::FMT_GRAYSCALE)
{
this->r = this->gray;
this->g = this->gray;
this->b = this->gray;
this->alpha = 1;
}
else if((this->format == image::FMT_RGBA8888 || this->format == image::FMT_BGRA8888) &&
(format == image::FMT_RGB888 || format == image::FMT_BGR888))
{
this->alpha = 0;
}
else if(this->format != image::FMT_GRAYSCALE && format == image::FMT_GRAYSCALE)
{
this->gray = (this->r + this->g + this->b) / 3;
this->r = this->gray;
this->g = this->gray;
this->b = this->gray;
this->alpha = 0;
}
this->format = format;
}
/**
* Convert color format and return a new Color object
* @param format format want to convert to, @see image::Format, only support RGB888, BGR888, RGBA8888, BGRA8888, GRAYSCALE.
* @return new Color object, you need to delete it manually in C++.
* @maixpy maix.image.Color.to_format2
*/
image::Color *to_format2(const image::Format &format)
{
image::Color *color = new image::Color(*this);
color->to_format(format);
return color;
}
};
/**
* Predefined color white
* @maixpy maix.image.COLOR_WHITE
*/
const image::Color COLOR_WHITE = image::Color::from_rgb(255, 255, 255);
/**
* Predefined color black
* @maixpy maix.image.COLOR_BLACK
*/
const image::Color COLOR_BLACK = image::Color::from_rgb(0, 0, 0);
/**
* Predefined color red
* @maixpy maix.image.COLOR_RED
*/
const image::Color COLOR_RED = image::Color::from_rgb(255, 0, 0);
/**
* Predefined color green
* @maixpy maix.image.COLOR_GREEN
*/
const image::Color COLOR_GREEN = image::Color::from_rgb(0, 255, 0);
/**
* Predefined color blue
* @maixpy maix.image.COLOR_BLUE
*/
const image::Color COLOR_BLUE = image::Color::from_rgb(0, 0, 255);
/**
* Predefined color yellow
* @maixpy maix.image.COLOR_YELLOW
*/
const image::Color COLOR_YELLOW = image::Color::from_rgb(255, 255, 0);
/**
* Predefined color purple
* @maixpy maix.image.COLOR_PURPLE
*/
const image::Color COLOR_PURPLE = image::Color::from_rgb(143, 0, 255);
/**
* Predefined color orange
* @maixpy maix.image.COLOR_ORANGE
*/
const image::Color COLOR_ORANGE = image::Color::from_rgb(255, 127, 0);
/**
* Predefined color gray
* @maixpy maix.image.COLOR_GRAY
*/
const image::Color COLOR_GRAY = image::Color::from_rgb(127, 127, 127);
}

View File

@@ -0,0 +1,313 @@
/**
* @author neucrack@sipeed, lxowalle@sipeed
* @copyright Sipeed Ltd 2023-
* @license Apache 2.0
* @update 2023.9.8: Add framework, create this file.
*/
#pragma once
#include <vector>
#include <string>
#include <map>
#include <stdint.h>
#include <stdexcept>
namespace maix::image
{
/**
* Image formats
* @attention for MaixPy firmware developers, update this enum will also need to update the fmt_size and fmt_names too !!!
* @maixpy maix.image.Format
*/
enum Format
{
FMT_RGB888 = 0, // RGBRGB...RGB, R at the lowest address
FMT_BGR888, // BGRBGR...BGR, B at the lowest address
FMT_RGBA8888, // RGBARGBA...RGBA, R at the lowest address
FMT_BGRA8888, // BGRABGRA...BGRA, B at the lowest address
FMT_RGB565,
FMT_BGR565,
FMT_YUV422SP, // YYY...UVUVUV...UVUV
FMT_YUV422P, // YYY...UUU...VVV
FMT_YVU420SP, // YYY...VUVUVU...VUVU, NV21
FMT_YUV420SP, // YYY...UVUVUV...UVUV, NV12
FMT_YVU420P, // YYY...VVV...UUU
FMT_YUV420P, // YYY...UUU...VVV
FMT_GRAYSCALE,
FMT_BGGR6, // 6-bit Bayer format with a BGGR pattern.
FMT_GBRG6, // 6-bit Bayer format with a GBRG pattern.
FMT_GRBG6, // 6-bit Bayer format with a GRBG pattern.
FMT_RGGB6, // 6-bit Bayer format with a RGGB pattern.
FMT_BGGR8, // 8-bit Bayer format with a BGGR pattern.
FMT_GBRG8, // 8-bit Bayer format with a GBRG pattern.
FMT_GRBG8, // 8-bit Bayer format with a GRBG pattern.
FMT_RGGB8, // 8-bit Bayer format with a RGGB pattern.
FMT_BGGR10, // 10-bit Bayer format with a BGGR pattern.
FMT_GBRG10, // 10-bit Bayer format with a GBRG pattern.
FMT_GRBG10, // 10-bit Bayer format with a GRBG pattern.
FMT_RGGB10, // 10-bit Bayer format with a RGGB pattern.
FMT_BGGR12, // 12-bit Bayer format with a BGGR pattern.
FMT_GBRG12, // 12-bit Bayer format with a GBRG pattern.
FMT_GRBG12, // 12-bit Bayer format with a GRBG pattern.
FMT_RGGB12, // 12-bit Bayer format with a RGGB pattern.
FMT_UNCOMPRESSED_MAX,
// compressed format below, not compressed should define upper
FMT_COMPRESSED_MIN,
FMT_JPEG,
FMT_PNG,
FMT_COMPRESSED_MAX,
FMT_INVALID = 0xFF // format not valid
}; // !!!! update this section please update fmt_size and fmt_names too !!!!
/**
* Image format size in bytes
* @attention It's a copy of this variable in MaixPy,
* so change it in C++ (e.g. update var in hello function) will not take effect the var inMaixPy.
* So we add const for this var to avoid this mistake.
* @maixpy maix.image.fmt_size
*/
const std::vector<float> fmt_size = {
3,
3,
4,
4,
2,
2,
2,
2,
1.5,
1.5,
1.5,
1.5,
1, // grayscale
0.75, // 6-bit Bayer format
0.75, // 6-bit Bayer format
0.75, // 6-bit Bayer format
0.75, // 6-bit Bayer format
1, // 8-bit Bayer format
1, // 8-bit Bayer format
1, // 8-bit Bayer format
1, // 8-bit Bayer format
1.25, // 10-bit Bayer format
1.25, // 10-bit Bayer format
1.25, // 10-bit Bayer format
1.25, // 10-bit Bayer format
1.5, // 12-bit Bayer format
1.5, // 12-bit Bayer format
1.5, // 12-bit Bayer format
1.5, // 12-bit Bayer format
0, // uncompereed_max
0, // compressed_min
1, // jpeg
1, // png
0, // compressed_max
0 // invalid
};
/**
* Image format string
* @maixpy maix.image.fmt_names
*/
const std::vector<std::string> fmt_names = {
"RGB888",
"BGR888",
"RGBA8888",
"BGRA8888",
"RGB565",
"BGR565",
"YUV422SP",
"YUV422P",
"YVU420SP",
"YUV420SP",
"YVU420P",
"YUV420P",
"GRAYSCALE",
"BGGR6",
"GBRG6",
"GRBG6",
"RG6B6",
"BGGR8",
"GBRG8",
"GRBG8",
"RG6B8",
"BGGR10",
"GBRG10",
"GRBG10",
"RG6B10",
"BGGR12",
"GBRG12",
"GRBG12",
"RG6B12",
"UNCOMPRESSED_MAX",
"COMPRESSED_MIN",
"JPEG",
"PNG",
"COMPRESSED_MAX",
"INVALID"
};
/**
* Image size type
* @maixpy maix.image.Size
*/
class Size
{
public:
/**
* Construct a new Size object
* @param width image width
* @param height image height
* @maixpy maix.image.Size.__init__
*/
Size(int width = 0, int height = 0)
{
this->_width = width;
this->_height = height;
}
/**
* width of size
* @param width set new width, if not set, only return current width
* @maixpy maix.image.Size.width
*/
int width(int width = -1)
{
if(width != -1)
{
this->_width = width;
}
return this->_width;
}
/**
* height of size
* @param height set new height, if not set, only return current height
* @maixpy maix.image.Size.height
*/
int height(int height = -1)
{
if(height != -1)
{
this->_height = height;
}
return this->_height;
}
/**
* Subscript operator
* @param index 0 for width, 1 for height
* @return int& width or height
* @maixpy maix.image.Size.__getitem__
* @maixcdk maix.image.Size.operator[]
*/
int &operator[](int index)
{
if (index == 0)
return _width;
else if (index == 1)
return _height;
else
throw std::out_of_range("Size index out of range");
}
/**
* to string
* @maixpy maix.image.Size.__str__
*/
std::string __str__()
{
return "Size(" + std::to_string(_width) + "x" + std::to_string(_height) + ")";
}
private:
int _width;
int _height;
};
/**
* Object fit method
* @maixpy maix.image.Fit
*/
enum Fit
{
FIT_NONE = -1, // no object fit, keep original
FIT_FILL = 0, // width to new width, height to new height, may be stretch
FIT_CONTAIN, // keep aspect ratio, fill blank area with black color
FIT_COVER, // keep aspect ratio, crop image to fit new size
FIT_MAX
};
/**
* Resize method
* @maixpy maix.image.ResizeMethod
*/
enum ResizeMethod
{
NEAREST = 0,
BILINEAR,
BICUBIC,
AREA,
LANCZOS,
HAMMING,
RESIZE_METHOD_MAX
};
/**
* Family of apriltag
* @maixpy maix.image.ApriltagFamilies
*/
enum ApriltagFamilies
{
TAG16H5 = 1,
TAG25H7 = 2,
TAG25H9 = 4,
TAG36H10 = 8,
TAG36H11 = 16,
ARTOOLKIT = 32
};
/**
* Template match method
* @maixpy maix.image.TemplateMatch
*/
enum TemplateMatch
{
SEARCH_EX, // Exhaustive search
SEARCH_DS, // Diamond search
};
/**
* CornerDetector class
* @maixpy maix.image.CornerDetector
*/
enum CornerDetector
{
CORNER_FAST,
CORNER_AGAST
};
/**
* EdgeDetector class
* @maixpy maix.image.EdgeDetector
*/
enum EdgeDetector
{
EDGE_CANNY,
EDGE_SIMPLE,
};
/**
* FlipDir
* @maixpy maix.image.FlipDir
*/
enum class FlipDir
{
X,
Y,
XY
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,4 @@
#include "maix_image.hpp"
#include "maix_display.hpp"
#include "maix_camera.hpp"
#include "maix_video.hpp"

View File

@@ -0,0 +1,17 @@
#pragma once
#include "maix_image.hpp"
#include "omv.hpp"
namespace maix::image
{
/**
* Convert image to openmv image format
* @param image image
* @param imlib_image openmv image
* @return
*/
extern void convert_to_imlib_image(image::Image *image, image_t *imlib_image);
extern void _convert_to_lab_thresholds(std::vector<std::vector<int>> &in, list_t *out);
}

View File

@@ -0,0 +1,317 @@
/**
* @author lxowalle@sipeed
* @copyright Sipeed Ltd 2023-
* @license Apache 2.0
* @update 2023.9.8: Add framework, create this file.
*/
#pragma once
#include <stdint.h>
#include "maix_err.hpp"
#include "maix_basic.hpp"
#include "maix_log.hpp"
#include "maix_image.hpp"
#include "maix_time.hpp"
#include "maix_camera_base.hpp"
#include "kvm_mmf.hpp"
#include <signal.h>
static void try_deinit_mmf()
{
static uint8_t is_called = 0;
if (!is_called) {
mmf_try_deinit(true);
is_called = 1;
}
}
static void signal_handle(int signal)
{
const char *signal_msg = NULL;
switch (signal) {
case SIGILL: signal_msg = "SIGILL"; break;
case SIGTRAP: signal_msg = "SIGTRAP"; break;
case SIGABRT: signal_msg = "SIGABRT"; break;
case SIGBUS: signal_msg = "SIGBUS"; break;
case SIGFPE: signal_msg = "SIGFPE"; break;
case SIGKILL: signal_msg = "SIGKILL"; break;
case SIGSEGV: signal_msg = "SIGSEGV"; break;
default: signal_msg = "UNKNOWN"; break;
}
maix::log::error("Trigger signal, code:%s(%d)!\r\n", signal_msg, signal);
try_deinit_mmf();
exit(1);
}
// FIXME: move this function to port/maix_vision_maixcam.cpp ?
static __attribute__((constructor)) void maix_vision_register_signal(void)
{
signal(SIGILL, signal_handle);
signal(SIGTRAP, signal_handle);
signal(SIGABRT, signal_handle);
signal(SIGBUS, signal_handle);
signal(SIGFPE, signal_handle);
signal(SIGKILL, signal_handle);
signal(SIGSEGV, signal_handle);
maix::util::register_exit_function(try_deinit_mmf);
}
namespace maix::camera
{
class CameraCviMmf final : public CameraBase
{
public:
CameraCviMmf(const std::string device, int width, int height, image::Format format, int buff_num)
{
this->device = device;
this->format = format;
this->width = width;
this->height = height;
this->buffer_num = buff_num;
this->ch = -1;
if (0 != mmf_init()) {
err::check_raise(err::ERR_RUNTIME, "mmf init failed");
}
if (0 != mmf_vi_init()) {
err::check_raise(err::ERR_RUNTIME, "mmf vi init failed");
}
}
CameraCviMmf(const std::string device, int ch, int width, int height, image::Format format, int buff_num)
{
this->device = device;
this->format = format;
this->width = width;
this->height = height;
this->buffer_num = buff_num;
this->ch = ch;
if (0 != mmf_init()) {
err::check_raise(err::ERR_RUNTIME, "mmf init failed");
}
if (0 != mmf_vi_init()) {
err::check_raise(err::ERR_RUNTIME, "mmf vi init failed");
}
}
~CameraCviMmf()
{
mmf_del_vi_channel(this->ch);
if (0 != mmf_vi_deinit()) {
err::check_raise(err::ERR_RUNTIME, "mmf vi init failed");
}
mmf_try_deinit(true);
}
err::Err open(int width, int height, image::Format format, int buff_num)
{
if (format == image::FMT_GRAYSCALE) {
format = image::FMT_YVU420SP;
}
int ch = mmf_get_vi_unused_channel();
if (ch < 0) {
log::error("camera open: mmf get vi channel failed");
return err::ERR_RUNTIME;
}
if (0 != mmf_add_vi_channel(ch, width, height, mmf_invert_format_to_mmf(format))) {
log::error("camera open: mmf add vi channel failed");
return err::ERR_RUNTIME;
}
this->ch = ch;
this->width = (width == -1) ? this->width : width;
this->height = (height == -1) ? this->height : height;
this->align_width = mmf_vi_aligned_width(this->ch);
this->align_need = (this->width % this->align_width == 0) ? false : true; // Width need align only
return err::ERR_NONE;
} // open
bool is_support_format(image::Format format)
{
if(format == image::Format::FMT_RGB888 || format == image::Format::FMT_BGR888
|| format == image::Format::FMT_YVU420SP|| format == image::Format::FMT_GRAYSCALE)
return true;
return false;
}
void close()
{
if (mmf_vi_chn_is_open(this->ch) == true) {
if (0 != mmf_del_vi_channel(this->ch)) {
log::error("mmf del vi channel failed");
}
}
} // close
// read
image::Image *read(void *buff = NULL, size_t buff_size = 0)
{
// printf("Func: maix_image.cpp read\r\n");
image::Image *img = NULL;
void *buffer = NULL;
int buffer_len = 0, width = 0, height = 0, format = 0;
if (0 == mmf_vi_frame_pop(this->ch, &buffer, &buffer_len, &width, &height, &format)) {
if (buffer == NULL) {
mmf_vi_frame_free(this->ch);
printf("mmf_vi_frame_free error\r\n");
return NULL;
}
if(buff)
{
if(buff_size < (size_t)buffer_len)
{
log::error("camera read: buff size not enough, need %d, but %d", buffer_len, buff_size);
mmf_vi_frame_free(this->ch);
return NULL;
}
img = new image::Image(width, height, this->format, (uint8_t*)buff, buff_size, false);
}
else
{
img = new image::Image(this->width, this->height, this->format);
}
void *image_data = img->data();
switch (img->format()) {
case image::Format::FMT_GRAYSCALE:
if (this->align_need) {
for (int h = 0; h < this->height; h ++) {
memcpy((uint8_t *)image_data + h * this->width, (uint8_t *)buffer + h * width, this->width);
}
} else {
memcpy(image_data, buffer, this->width * this->height);
}
break;
case image::Format::FMT_BGR888: // fall through
case image::Format::FMT_RGB888:
if (this->align_need) {
for (int h = 0; h < this->height; h++) {
memcpy((uint8_t *)image_data + h * this->width * 3, (uint8_t *)buffer + h * width * 3, this->width * 3);
}
} else {
memcpy(image_data, buffer, this->width * this->height * 3);
}
break;
case image::Format::FMT_YVU420SP:
if (this->align_need) {
for (int h = 0; h < this->height * 3 / 2; h ++) {
memcpy((uint8_t *)image_data + h * this->width, (uint8_t *)buffer + h * width, this->width);
}
} else {
memcpy(image_data, buffer, this->width * this->height * 3 / 2);
}
break;
default:
printf("unknown format\n");
delete img;
mmf_vi_frame_free(this->ch);
printf("switch (img->format()\r\n");
return NULL;
}
mmf_vi_frame_free(this->ch);
// printf("mmf_vi_frame_free\r\n");
return img;
}
return img;
} // read
camera::CameraCviMmf *add_channel(int width, int height, image::Format format, int buff_num)
{
int new_channel = mmf_get_vi_unused_channel();
if (new_channel < 0) {
log::error("Support not more channel!\r\n");
return NULL;
}
return new camera::CameraCviMmf(this->device, new_channel, width, height, format, buff_num);
}
void clear_buff()
{
}
bool is_opened() {
return mmf_vi_chn_is_open(this->ch);
}
int get_ch_nums() {
return 1;
}
int get_channel() {
return this->ch;
}
int hmirror(int en)
{
bool out;
if (en == -1) {
mmf_get_vi_hmirror(this->ch, &out);
} else {
bool need_open = false;
if (this->is_opened()) {
this->close();
need_open = true;
}
mmf_set_vi_hmirror(this->ch, en);
if (need_open) {
err::check_raise(this->open(this->width, this->height, this->format, this->buffer_num), "Open failed");
}
out = en;
}
return out;
}
int vflip(int en)
{
bool out;
if (en == -1) {
mmf_get_vi_vflip(this->ch, &out);
} else {
bool need_open = false;
if (this->is_opened()) {
this->close();
need_open = true;
}
mmf_set_vi_vflip(this->ch, en);
if (need_open) {
err::check_raise(this->open(this->width, this->height, this->format, this->buffer_num), "Open failed");
}
out = en;
}
return out;
}
private:
std::string device;
image::Format format;
int fd;
int ch;
uint32_t raw_format;
std::vector<void*> buffers;
std::vector<int> buffers_len;
int buffer_num;
int queue_id; // user directly used buffer id
int width;
int height;
void *buff;
bool buff_alloc;
int align_width;
bool align_need;
};
} // namespace maix::camera

View File

@@ -0,0 +1,425 @@
/**
* @author neucrack@sipeed, lxowalle@sipeed
* @copyright Sipeed Ltd 2023-
* @license Apache 2.0
* @update 2023.9.8: Add framework, create this file.
*/
#include "maix_camera.hpp"
#include <dirent.h>
#ifdef PLATFORM_LINUX
#include "maix_camera_v4l2.hpp"
#endif
#ifdef PLATFORM_MAIXCAM
#include "maix_camera_mmf.hpp"
#endif
namespace maix::camera
{
static bool set_regs_flag = false;
std::vector<std::string> list_devices()
{
// find to /dev/video*
std::vector<std::string> devices;
std::string path = "/dev";
DIR *dir = opendir(path.c_str());
if (dir == NULL)
{
return devices;
}
struct dirent *ptr;
while ((ptr = readdir(dir)) != NULL)
{
if (ptr->d_type == DT_CHR)
{
std::string name = ptr->d_name;
if (name.find("video") != std::string::npos)
{
devices.push_back( path + "/" + name );
}
}
}
closedir(dir);
// sort devices with name
std::sort(devices.begin(), devices.end());
// print devices
for (size_t i = 0; i < devices.size(); i++)
{
log::debug("find device: %s\n", devices[i].c_str());
}
return devices;
}
void set_regs_enable(bool enable) {
set_regs_flag = enable;
}
err::Err Camera::show_colorbar(bool enable)
{
// only set variable now
// should control camera to show colorbar
_show_colorbar = enable;
return err::ERR_NONE;
}
static void generate_colorbar(image::Image &img)
{
int width = img.width();
int height = img.height();
int step = width / 8;
int color_step = 255 / 7;
int color = 0;
uint8_t colors[8][3] = {
{255, 255, 255},
{255, 0, 0},
{255, 127, 0},
{255, 255, 0},
{0, 255, 0},
{0, 0, 255},
{143, 0, 255},
{0, 0, 0},
};
for (int i = 0; i < 8; i++)
{
image::Color _color(colors[i][0], colors[i][1], colors[i][2], 0, image::FMT_RGB888);
img.draw_rect(i * step, 0, step, height, _color, -1);
color += color_step;
}
}
#ifdef PLATFORM_LINUX
static char * _get_device(const char *device)
{
if (device)
{
return (char *)device;
}
else
{
std::vector<std::string> devices = list_devices();
err::check_bool_raise(devices.size() > 0, "No camera device");
return (char *)devices[0].c_str();
}
}
#endif
Camera::Camera(int width, int height, image::Format format, const char *device, int fps, int buff_num, bool open)
{
err::Err e;
err::check_bool_raise(_check_format(format), "Format not support");
if (format == image::Format::FMT_RGB888 && width * height * 3 > 640 * 640 * 3) {
log::warn("Note that we do not recommend using large resolution RGB888 images, which can take up a lot of memory!\r\n");
}
_width = (width == -1) ? 640 : width;
_height = (height == -1) ? 480 : height;
_format = format;
_fps = (fps == -1) ? 30 : fps;
_buff_num = buff_num;
_show_colorbar = false;
_open_set_regs = set_regs_flag;
_impl = NULL;
#ifdef PLATFORM_LINUX
_device = _get_device(device);
_impl = new CameraV4L2(_device, _width, _height, _format, _buff_num);
#endif
#ifdef PLATFORM_MAIXCAM
_device = "";
_impl = new CameraCviMmf(_device, _width, _height, _format, _buff_num);
#endif
if (open) {
e = this->open(_width, _height, _format, _buff_num);
// err::check_raise(e, "camera open failed");
}
}
Camera::Camera(const char *device, CameraBase *base, int width, int height, image::Format format, int fps, int buff_num, bool open)
{
err::Err e;
err::check_bool_raise(_check_format(format), "Format not support");
_width = (width == -1) ? 640 : width;
_height = (height == -1) ? 480 : height;
_format = format;
_fps = (fps == -1) ? 30 : fps;
_buff_num = buff_num;
_show_colorbar = false;
_open_set_regs = set_regs_flag;
_impl = base;
if (open) {
e = this->open(_width, _height, _format, _buff_num);
err::check_raise(e, "camera open failed");
}
}
Camera::~Camera()
{
if (this->is_opened()) {
this->close();
}
#ifdef PLATFORM_LINUX
delete (CameraV4L2*)_impl;
#endif
#ifdef PLATFORM_MAIXCAM
delete (CameraCviMmf*)_impl;
#endif
}
void Camera::restart(int width, int height, image::Format format, const char *device, int fps, int buff_num, bool open)
{
if (this->is_opened()) {
this->close();
}
#ifdef PLATFORM_LINUX
delete (CameraV4L2*)_impl;
#endif
#ifdef PLATFORM_MAIXCAM
delete (CameraCviMmf*)_impl;
#endif
err::Err e;
err::check_bool_raise(_check_format(format), "Format not support");
if (format == image::Format::FMT_RGB888 && width * height * 3 > 640 * 640 * 3) {
log::warn("Note that we do not recommend using large resolution RGB888 images, which can take up a lot of memory!\r\n");
}
_width = (width == -1) ? 640 : width;
_height = (height == -1) ? 480 : height;
_format = format;
_fps = (fps == -1) ? 30 : fps;
_buff_num = buff_num;
_show_colorbar = false;
_open_set_regs = set_regs_flag;
_impl = NULL;
#ifdef PLATFORM_LINUX
_device = _get_device(device);
_impl = new CameraV4L2(_device, _width, _height, _format, _buff_num);
#endif
#ifdef PLATFORM_MAIXCAM
_device = "";
_impl = new CameraCviMmf(_device, _width, _height, _format, _buff_num);
#endif
if (open) {
e = this->open(_width, _height, _format, _buff_num);
// err::check_raise(e, "camera open failed");
}
}
int Camera::get_ch_nums()
{
return 2;
}
int Camera::get_channel()
{
if (_impl == NULL)
return err::ERR_NOT_INIT;
if (!this->is_opened()) {
return err::ERR_NOT_OPEN;
}
return _impl->get_channel();
}
bool Camera::_check_format(image::Format format) {
if (format == image::FMT_RGB888 || format == image::FMT_BGR888
|| format == image::FMT_RGBA8888 || format == image::FMT_BGRA8888
|| format == image::FMT_YVU420SP || format == image::FMT_GRAYSCALE) {
return true;
} else {
return false;
}
}
err::Err Camera::open(int width, int height, image::Format format, int fps, int buff_num)
{
if (_impl == NULL)
return err::Err::ERR_RUNTIME;
int width_tmp = (width == -1) ? _width : width;
int height_tmp = (height == -1) ? _height : height;
image::Format format_tmp = (format == image::FMT_INVALID) ? _format : format;
int fps_tmp = (fps == -1) ? 30 : fps;
int buff_num_tmp =( buff_num == -1) ? _buff_num : buff_num;
err::check_bool_raise(_check_format(format_tmp), "Format not support");
if (this->is_opened()) {
if (width == width_tmp && height == height_tmp && format == format_tmp && fps == fps_tmp && buff_num == buff_num_tmp) {
return err::ERR_NONE;
}
this->close(); // Get new param, close and reopen
}
_width = width_tmp;
_height = height_tmp;
_fps = fps_tmp;
_buff_num = buff_num_tmp;
_format = format_tmp;
_format_impl = _format;
if(!_impl->is_support_format(_format))
{
if(_impl->is_support_format(image::FMT_RGB888))
_format_impl = image::FMT_RGB888;
else if(_impl->is_support_format(image::FMT_BGR888))
_format_impl = image::FMT_BGR888;
else if(_impl->is_support_format(image::FMT_YVU420SP))
_format_impl = image::FMT_YVU420SP;
else if(_impl->is_support_format(image::FMT_YUV420SP))
_format_impl = image::FMT_YUV420SP;
else if(_impl->is_support_format(image::FMT_RGBA8888))
_format_impl = image::FMT_RGBA8888;
else if(_impl->is_support_format(image::FMT_BGRA8888))
_format_impl = image::FMT_BGRA8888;
else if(_impl->is_support_format(image::FMT_GRAYSCALE))
_format_impl = image::FMT_GRAYSCALE;
else
return err::ERR_ARGS;
}
return _impl->open(_width, _height, _format_impl, _buff_num);;
}
void Camera::close()
{
if (this->is_closed())
return;
_impl->close();
}
camera::Camera *Camera::add_channel(int width, int height, image::Format format, int fps, int buff_num, bool open)
{
err::check_bool_raise(_check_format(format), "Format not support");
int width_tmp = (width == -1) ? _width : width;
int height_tmp = (height == -1) ? _height : height;
image::Format format_tmp = (format == image::Format::FMT_INVALID) ? _format : format;
int fps_tmp = (fps == -1) ? _fps : fps;
int buff_num_tmp = buff_num == -1 ? _buff_num : buff_num;
Camera *cam = NULL;
if (_impl) {
CameraBase *cam_base = _impl->add_channel(width_tmp, height_tmp, format_tmp, buff_num);
err::check_bool_raise(cam_base, "Unable to add a new channel. Please check the maximum number of supported channels.");
cam = new Camera(_device.c_str(), cam_base, width_tmp, height_tmp, format_tmp, fps_tmp, buff_num_tmp, open);
}
return cam;
}
bool Camera::is_opened()
{
if (_impl == NULL)
return false;
return _impl->is_opened();
}
image::Image *Camera::read(void *buff, size_t buff_size, bool block)
{
if (!this->is_opened()) {
// err::Err e = open(_width, _height, _format, _buff_num);
// err::check_raise(e, "open camera failed");
return NULL;
}
if (_show_colorbar) {
image::Image *img = new image::Image(_width, _height);
generate_colorbar(*img);
err::check_null_raise(img, "camera read failed");
return img;
} else {
// it's better all done by impl to faster read, but if impl not support, we have to convert it
if(_format_impl == _format)
{
image::Image *img = _impl->read(buff, buff_size);
// err::check_null_raise(img, "camera read failed");
return img;
}
else
{
image::Image *img = _impl->read();
image::Image *img2 = img->to_format(_format, buff, buff_size);
delete img;
// err::check_null_raise(img2, "camera read failed");
return img2;
}
}
}
void Camera::clear_buff()
{
if (_impl == NULL)
return;
_impl->clear_buff();
}
void Camera::skip_frames(int num)
{
if (_impl == NULL)
return;
for(int i = 0; i < num; i++)
{
image::Image *img = _impl->read();
delete img;
}
}
err::Err Camera::set_resolution(int width, int height)
{
err::Err e;
if (_impl == NULL)
return err::ERR_NOT_INIT;
if (this->is_opened()) {
this->close();
}
_width = width;
_height = height;
e = this->open(_width, _height, _format, _buff_num);
err::check_raise(e, "camera open failed");
return err::ERR_NONE;
}
int Camera::hmirror(int value) {
if (_impl == NULL)
return err::ERR_NOT_INIT;
if (!this->is_opened()) {
return err::ERR_NOT_OPEN;
}
return _impl->hmirror(value);
}
int Camera::vflip(int value) {
if (_impl == NULL)
return err::ERR_NOT_INIT;
if (!this->is_opened()) {
return err::ERR_NOT_OPEN;
}
return _impl->vflip(value);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

178
support/sg2002/build Normal file
View File

@@ -0,0 +1,178 @@
#!/bin/bash
export MAIXCDK_PATH=~/MaixCDK
export NanoKVM_PATH=~/NanoKVM
Project_Name="None"
Project_PATH="None"
Project_Action="None"
KVMAPP_PATH="$NanoKVM_PATH/kvmapp"
maixcdk_build() {
local input_value="$1"
DIST_PATH="./dist"
rm -rf $DIST_PATH
if [ "$input_value" = "from_zero" ]
then
maixcdk build <<EOF
2
EOF
else
maixcdk build
fi
}
chack_build(){
DIST_PATH="./dist"
if [ -d "$DIST_PATH" ]
then
echo "SUCCESS"
else
echo "FAILURE"
fi
}
maixcdk_clean(){
maixcdk distclean
maixcdk clean
}
case "$1" in
update_lib)
cp -rf $NanoKVM_PATH/support/sg2002/additional/kvm $MAIXCDK_PATH/components
cp -rf $NanoKVM_PATH/support/sg2002/additional/kvm_mmf $MAIXCDK_PATH/components
cp -rf $NanoKVM_PATH/support/sg2002/additional/vision $MAIXCDK_PATH/components
cp -f $NanoKVM_PATH/support/sg2002/additional/peripheral/port/maixcam/maix_i2c.cpp $MAIXCDK_PATH/components/peripheral/port/maixcam/maix_i2c.cpp
cp -f $NanoKVM_PATH/support/sg2002/additional/sophgo-middleware/v2/sample/common/sample_common_sensor.c $MAIXCDK_PATH/components/3rd_party/sophgo-middleware/sophgo-middleware/v2/sample/common/
echo -e "\e[36m[build] \e[32mupdate_lib ok!\e[0m"
exit 1
;;
kvm_system)
Project_Name="kvm_system"
Project_PATH="$NanoKVM_PATH/support/sg2002/kvm_system"
echo -e "\e[36m[build] \e[32mProject: kvm_system \e[0m"
;;
kvm_vision)
Project_Name="kvm_vision"
Project_PATH="$NanoKVM_PATH/support/sg2002/kvm_vision_test"
echo -e "\e[36m[build] \e[32mProject: kvm_system \e[0m"
;;
*)
echo -e "\e[36m[build] \e[31mInvalid project name \e[0m"
echo -e "\e[36m[build] \e[32mPlease select a project:\e[0m"
echo -e "0: kvm_system"
echo -e "1: kvm_vision"
while true; do
read -p "Please enter 0 or 1 : " input
if [[ "$input" -eq 0 ]]
then
Project_Name="kvm_system"
Project_PATH="$NanoKVM_PATH/support/sg2002/kvm_system"
break
elif [[ "$input" -eq 1 ]]
then
Project_Name="kvm_vision"
Project_PATH="$NanoKVM_PATH/support/sg2002/kvm_vision_test"
break
else
echo -e "\e[36m[build] \e[31mInvalid Index \e[0m"
fi
done
esac
if [ -z "$2" ]
then
Project_Action="build"
else
Project_Action=$2
fi
if [ ! "$Project_Name" = "None" ]
then
case "$Project_Action" in
build)
# echo -e "\e[36m[build] \e[32mStart using MaixCDK to compile kvm_system...\e[0m"
JSON_PATH="$Project_PATH/build/config/project_vars.json"
Platform_Char="\"PLATFORM\": \"maixcam\""
if [ ! -e "$MAIXCDK_PATH/components/kvm" ]
then
echo -e "\e[36m[build] \e[32mDetected that the library has not been modified; first, move the library\e[0m"
mkdir $NanoKVM_PATH/support/sg2002/additional/original
mv -f $MAIXCDK_PATH/components/vision $NanoKVM_PATH/support/sg2002/additional/original
# mv $MAIXCDK_PATH/components/maixcam_lib $NanoKVM_PATH/support/sg2002/additional/original
mv -f $MAIXCDK_PATH/components/peripheral/port/maixcam/maix_i2c.cpp $NanoKVM_PATH/support/sg2002/additional/original
mv -f $MAIXCDK_PATH/components/3rd_party/sophgo-middleware/sophgo-middleware/v2/sample/common/sample_common_sensor.c $NanoKVM_PATH/support/sg2002/additional/original
cp -rf $NanoKVM_PATH/support/sg2002/additional/kvm $MAIXCDK_PATH/components
cp -rf $NanoKVM_PATH/support/sg2002/additional/kvm_mmf $MAIXCDK_PATH/components
cp -rf $NanoKVM_PATH/support/sg2002/additional/vision $MAIXCDK_PATH/components
cp -f $NanoKVM_PATH/support/sg2002/additional/peripheral/port/maixcam/maix_i2c.cpp $MAIXCDK_PATH/components/peripheral/port/maixcam/maix_i2c.cpp
cp -f $NanoKVM_PATH/support/sg2002/additional/sophgo-middleware/v2/sample/common/sample_common_sensor.c $MAIXCDK_PATH/components/3rd_party/sophgo-middleware/sophgo-middleware/v2/sample/common/
echo -e "\e[36m[build] \e[32mMove the library completed!\e[0m"
fi
cd $Project_PATH
if [ -f $JSON_PATH ]
then
if grep -q $Platform_Char $JSON_PATH; then
maixcdk_build
else
maixcdk_clean
maixcdk_build "from_zero"
fi
else
maixcdk_build "from_zero"
fi
RES=$(chack_build)
if [ "$RES" = "SUCCESS" ]
then
echo -e "\e[36m[build] \e[32mBuild completed! Use \e[34m./build $Project_Name add_to_kvmapp\e[32m to add it to kvmapp.\e[0m"
else
echo -e "\e[36m[build] \e[31mBuild Error!\e[0m"
fi
;;
clean)
cd $Project_PATH
maixcdk_clean
echo -e "\e[36m[build] \e[32m$Project_Name cleanup completed!\e[0m"
;;
add_to_kvmapp)
if [ "$Project_Name" = "kvm_system" ]
then
SOURCE_PATH="$Project_PATH/dist/kvm_system_release/kvm_system"
TARGET_PATH="$KVMAPP_PATH/kvm_system"
chmod +x $SOURCE_PATH
else
SOURCE_PATH="$Project_PATH/dist/kvm_vision_test_release/dl_lib"
TARGET_PATH="$KVMAPP_PATH/server/"
fi
if [ ! -d $TARGET_PATH ]
then
mkdir -p $TARGET_PATH
fi
if [ -e $SOURCE_PATH ]
then
cp -rf $SOURCE_PATH $TARGET_PATH
echo -e "\e[36m[build] \e[32mkvm_system has been moved to kvmapp.\e[0m"
else
echo -e "\e[36m[build] \e[31mThe source file does not exist. Please compile using \e[34m./build kvm_system \e[31mfirst.\e[0m"
fi
;;
*)
echo -e "\e[36m[build] \e[31mInvalid Action: \e[34m$2 \e[0m"
echo -e "\e[36m[build] \e[31mUsage: $0 [Project Name]{kvm_system|kvm_vision} [Action]{-/build|clean|add_to_kvmapp} e.g. \e[34m./build kvm_system clean \e[0m"
exit 1
esac
else
echo -e "\e[36m[build] \e[31mInvalid Name \e[0m"
exit 1
fi

View File

@@ -0,0 +1,28 @@
list(APPEND ADD_INCLUDE
"include"
"lib/libqr"
"lib/system_ctrl"
"lib/system_state"
"lib/system_init"
"lib/oled_ctrl"
"lib/oled_ui"
"lib/hdmi"
)
list(APPEND ADD_PRIVATE_INCLUDE "")
append_srcs_dir(ADD_SRCS
"src"
"lib/libqr"
"lib/system_ctrl"
"lib/system_state"
"lib/system_init"
"lib/oled_ctrl"
"lib/oled_ui"
"lib/hdmi"
) # append source file in src dir to var ADD_SRCS
list(APPEND ADD_REQUIREMENTS basic peripheral)
register_component()

View File

View File

@@ -0,0 +1,104 @@
#ifndef CONFIG_H_
#define CONFIG_H_
#include "maix_basic.hpp"
#include "maix_time.hpp"
#include "maix_gpio.hpp"
#include "maix_pinmap.hpp"
#include "maix_i2c.hpp"
#include "maix_uart.hpp"
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/poll.h>
#include <fstream>
#include <linux/input.h>
#include "qr.h"
#include "system_ctrl.h"
#include "system_state.h"
#include "system_init.h"
#include "oled_ctrl.h"
#include "oled_ui.h"
#include "hdmi.h"
#define IP_Change_time 5000
#define QR_Change_time 5000
#define STATE_DELAY 1000
#define OLED_DELAY 1000
#define KEY_DELAY 100
#define KEY_LONG_PRESS 1500
#define KEY_LONGLONG_PRESS 9000
#define WIFI_CONNECTION_DELAY 5000
#define OLED_SLEEP_DELAY_MIN 10
#define OLED_SLEEP_DELAY_DEFAULT 30
#define KVM_WD_COUNT_MAX 10
#define RM_Watchdog_times 60
typedef struct {
int8_t page = 0;
int8_t sub_page = 0;
uint8_t eth_route[16] = {0}; // route ip
uint8_t wifi_route[16] = {0}; // route ip
uint8_t eth_addr[16] = {0}; // ETH ip
uint8_t wifi_addr[16] = {0}; // WiFi ip
uint8_t tail_addr[16] = {0}; // Tailscale ip
uint8_t rndis_addr[16] = {0}; // RNDIS ip
int8_t eth_state = -1; // cat /sys/class/net/eth0/carrier
int8_t wifi_state = -1; // cat /sys/class/net/wlan0/carrier
int8_t tail_state = -1; // ifconfig tailscale0 | grep 'inet addr' | awk '{print $2}'
int8_t hdmi_state = -1; // cat /proc/cvitek/vi_dbg | grep VIFPS | awk '{print $3}' (1s)
int8_t usb_state = -1; // cat /sys/class/udc/4340000.usb/state
int8_t hid_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/hid.GSn(n=012)
int8_t rndis_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/rndis.usb0
int8_t udisk_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/mass_storage.disk0
int8_t host_pwr_state = -1; // cat /sys/class/gpio/gpio504/value
int16_t hdmi_width = 0; // cat /kvmapp/kvm/width
int16_t hdmi_height = 0; // cat /kvmapp/kvm/height
int8_t type = 0; // cat /kvmapp/kvm/type
int8_t now_fps = 0; // cat /kvmapp/kvm/now_fps
int16_t qlty = 0; // cat /kvmapp/kvm/qlty
int8_t oled_thread_running = 0;
int8_t key_thread_running = 0;
int8_t sys_thread_running = 0;
int8_t wifi_config_process = -1; // 1:QR;2:Test;3:IP;
char wifi_ap_pass[9] = {0};
uint8_t oled_sleep_state = 0; // 0:wakeup; 1:sleep;
int8_t reconvery_update = 0; // 0:Undetected; 1:Needs Update; 2:Update finish; -1:not need to update
uint8_t ping_allow = 1;
} kvm_sys_state_t;
typedef struct {
int8_t page = -1;
int8_t sub_page = -1;
uint8_t eth_route[16] = {0}; // route ip
uint8_t wifi_route[16] = {0}; // route ip
uint8_t eth_addr[16] = {0}; // ETH ip
uint8_t wifi_addr[16] = {0}; // WiFi ip
uint8_t tail_addr[16] = {0}; // Tailscale ip
uint8_t rndis_addr[16] = {0}; // RNDIS ip
int8_t eth_state = -1; // cat /sys/class/net/eth0/carrier
int8_t wifi_state = -1; // cat /sys/class/net/wlan0/carrier
int8_t tail_state = -1; // ifconfig tailscale0 | grep inet\ addr | awk '{print $2}'
int8_t hdmi_state = -1; // cat /proc/cvitek/vi_dbg | grep VIFPS | awk '{print $3}' (1s)
int8_t usb_state = -1; // cat /sys/class/udc/4340000.usb/state
int8_t hid_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/hid.GSn(n=012)
int8_t rndis_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/rndis.usb0
int8_t udisk_state = -1; // (exist?) /sys/kernel/config/usb_gadget/g0/configs/c.1/mass_storage.disk0
int8_t host_pwr_state = -1; // cat /sys/class/gpio/gpio504/value
int16_t hdmi_width = -1; // cat /kvmapp/kvm/width
int16_t hdmi_height = -1; // cat /kvmapp/kvm/height
int8_t type = -1; // cat /kvmapp/kvm/type
int8_t now_fps = -1; // cat /kvmapp/kvm/now_fps
int16_t qlty = -1; // cat /kvmapp/kvm/qlty
uint8_t oled_sleep_param = 0;
uint8_t oled_sleep_state = 0; // 0:wakeup; 1:sleep;
uint64_t oled_sleep_start = 0;
uint64_t ue_patch_state = 0;
} kvm_oled_state_t;
#endif // CONFIG_H_

View File

@@ -0,0 +1,238 @@
#include "hdmi.h"
using namespace maix;
using namespace maix::sys;
using namespace maix::peripheral;
i2c::I2C LT6911_i2c(4, i2c::Mode::MASTER);
void lt6911_enable()
{
uint8_t buf[2];
buf[0] = 0xff;
buf[1] = 0x80;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
buf[0] = 0xee;
buf[1] = 0x01;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
}
void lt6911_disable()
{
uint8_t buf[2];
buf[0] = 0xff;
buf[1] = 0x80;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
buf[0] = 0xee;
buf[1] = 0x00;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
}
void lt6911_start()
{
uint8_t buf[2];
buf[0] = 0xff;
buf[1] = 0x80;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
buf[0] = 0x5A;
buf[1] = 0x80;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
}
void lt6911_stop()
{
uint8_t buf[2];
buf[0] = 0xff;
buf[1] = 0x80;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
buf[0] = 0x5A;
buf[1] = 0x88;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
}
void lt6911_reset()
{
lt6911_stop();
time::sleep_ms(1);
lt6911_start();
}
void lt6911_get_hdmi_errer()
{
uint8_t buf[6];
buf[0] = 0xff;
buf[1] = 0xC0;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
buf[0] = 0x20;
buf[1] = 0x01;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
time::sleep_ms(100);
buf[0] = 0x24;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat = LT6911_i2c.readfrom(LT6911_ADDR, 6);
buf[0] = 0x20;
buf[1] = 0x07;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
for(int i = 0; i < 6; i++){
buf[i] = (uint8_t)dat->data[i];
}
delete dat;
printf("hdmi_errer_code = %x, %x, %x, %x, %x, %x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
}
uint8_t lt6911_get_hdmi_res()
{
uint8_t buf[2];
uint8_t revbuf[4];
uint16_t Vactive;
uint16_t Hactive;
buf[0] = 0xff;
buf[1] = 0xd2;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
buf[0] = 0x83;
buf[1] = 0x11;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
time::sleep_ms(100);
// Vactive
buf[0] = 0x96;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 2);
// Hactive
buf[0] = 0x8b;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat1 = LT6911_i2c.readfrom(LT6911_ADDR, 2);
revbuf[0] = (uint8_t)dat0->data[0];
revbuf[1] = (uint8_t)dat0->data[1];
revbuf[2] = (uint8_t)dat1->data[0];
revbuf[3] = (uint8_t)dat1->data[1];
Vactive = (revbuf[0] << 8)|revbuf[1];
Hactive = (revbuf[2] << 8)|revbuf[3];
Hactive *= 2;
printf("HDMI res modification event\n");
printf("new res: %d * %d\n", Hactive, Vactive);
delete dat0;
delete dat1;
if (Vactive != 0 && Hactive != 0){
return 1;
} else {
return 0;
}
}
void lt6911_get_hdmi_clk()
{
uint8_t buf[2];
uint8_t revbuf[3];
uint32_t clk;
buf[0] = 0xff;
buf[1] = 0xa0;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
buf[0] = 0x34;
buf[1] = 0x0b;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
time::sleep_ms(50);
// clk
buf[0] = 0xff;
buf[1] = 0xb8;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
buf[0] = 0xb1;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 3);
revbuf[0] = (uint8_t)dat0->data[0];
revbuf[1] = (uint8_t)dat0->data[1];
revbuf[2] = (uint8_t)dat0->data[2];
revbuf[0] &= 0x07;
clk = revbuf[0];
clk <<= 8;
clk |= revbuf[1];
clk <<= 8;
clk |= revbuf[2];
printf("HDMI CLK = %d\n", clk);
delete dat0;
}
uint8_t lt6911_get_csi_res()
{
uint8_t ret = 0;
uint8_t buf[2];
uint8_t revbuf[4];
static uint16_t old_Vactive;
static uint16_t old_Hactive;
uint16_t Vactive;
uint16_t Hactive;
char Cmd[100]={0};
buf[0] = 0xff;
buf[1] = 0xc2;
LT6911_i2c.writeto(LT6911_ADDR, buf, 2);
// Vactive
buf[0] = 0x06;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat0 = LT6911_i2c.readfrom(LT6911_ADDR, 2);
// Hactive
buf[0] = 0x38;
LT6911_i2c.writeto(LT6911_ADDR, buf, 1);
maix::Bytes *dat1 = LT6911_i2c.readfrom(LT6911_ADDR, 2);
revbuf[0] = (uint8_t)dat0->data[0];
revbuf[1] = (uint8_t)dat0->data[1];
revbuf[2] = (uint8_t)dat1->data[0];
revbuf[3] = (uint8_t)dat1->data[1];
Vactive = (revbuf[0] << 8)|revbuf[1];
Hactive = (revbuf[2] << 8)|revbuf[3];
if(old_Hactive != Hactive || old_Vactive != Vactive){
old_Hactive = Hactive;
old_Vactive = Vactive;
ret = 1;
}
printf("CSI res: %d * %d\n", Hactive, Vactive);
// setenv("KVM_CSI_HEIGHT", to_string(Hactive).c_str(), 1);
// setenv("KVM_CSI_WIDTH", to_string(Vactive).c_str(), 1);
sprintf(Cmd, "echo %d > /kvmapp/kvm/width", Hactive);
system(Cmd);
sprintf(Cmd, "echo %d > /kvmapp/kvm/height", Vactive);
system(Cmd);
delete dat0;
delete dat1;
return ret;
}

View File

@@ -0,0 +1,29 @@
#ifndef HDMI_H_
#define HDMI_H_
#include "maix_basic.hpp"
#include "maix_time.hpp"
#include "maix_gpio.hpp"
#include "maix_pinmap.hpp"
#include "maix_i2c.hpp"
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#define LT6911_ADDR 0x2B
#define LT6911_READ 0xFF
#define LT6911_WRITE 0x00
void lt6911_enable();
void lt6911_disable();
void lt6911_start();
void lt6911_stop();
void lt6911_reset();
void lt6911_get_hdmi_errer();
uint8_t lt6911_get_hdmi_res();
void lt6911_get_hdmi_clk();
uint8_t lt6911_get_csi_res();
#endif // HDMI_H_

View File

@@ -0,0 +1,59 @@
project(qr)
cmake_minimum_required(VERSION 2.6.0)
set(QR_VERSION "1.0.0")
set(QR_SOVERSION "1")
set(QR_COMMAND_SOURCES qrcmd.c)
set(QR_LIBRARY_SOURCES
qr.c qrcnv.c qrcnv_bmp.c qrcnv_png.c qrcnv_svg.c qrcnv_tiff.c
)
set(QR_PUBLIC_HEADERS qr.h)
set(bindir bin)
set(incdir include)
set(libdir lib)
set(CMAKE_SKIP_BUILD_RPATH OFF)
set(CMAKE_BUILD_WITH_INSTALL_RPATH OFF)
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${libdir}")
set(CMAKE_INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${libdir}")
find_package(ZLIB)
add_definitions(-Wall -Wextra)
include_directories(${ZLIB_INCLUDE_DIRS})
add_executable(qrcmd ${QR_COMMAND_SOURCES})
add_executable(qrcmd_multi ${QR_COMMAND_SOURCES})
add_library(libqr_shared SHARED ${QR_LIBRARY_SOURCES})
add_library(libqr_static STATIC ${QR_LIBRARY_SOURCES})
target_link_libraries(qrcmd libqr_shared)
target_link_libraries(qrcmd_multi libqr_shared)
target_link_libraries(libqr_shared m ${ZLIB_LIBRARIES})
set_target_properties(qrcmd PROPERTIES
OUTPUT_NAME qr
)
set_target_properties(qrcmd_multi PROPERTIES
OUTPUT_NAME qrs
COMPILE_FLAGS -DQRCMD_STRUCTURED_APPEND
)
set_target_properties(libqr_shared PROPERTIES
OUTPUT_NAME qr
VERSION ${QR_VERSION}
SOVERSION ${QR_SOVERSION}
)
set_target_properties(libqr_static PROPERTIES
OUTPUT_NAME qr
)
install(TARGETS qrcmd qrcmd_multi libqr_shared libqr_static
RUNTIME DESTINATION ${bindir}
LIBRARY DESTINATION ${libdir}
ARCHIVE DESTINATION ${libdir}
)
install(FILES ${QR_PUBLIC_HEADERS} DESTINATION ${incdir})

View File

@@ -0,0 +1,19 @@
All rights reserved.
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.

View File

@@ -0,0 +1 @@
This is a C library and a command line tool to make a QR Code.

View File

@@ -0,0 +1,8 @@
TODO:
- test on Win32
- test on Cygwin (if I could)
- write tests
- write manpage of qr(1), qrs(1) and libqr(3)
- localization support by ICU4C
- pkg-config (.pc file) support
- rcfile support for command line tool

View File

@@ -0,0 +1,63 @@
/*
* This code is taken from:
* PNG (Portable Network Graphics) Specification, Version 1.1
* 15. Appendix: Sample CRC Code
* http://www.libpng.org/pub/png/spec/1.1/PNG-CRCAppendix.html
*/
#ifdef uint32_t
typedef uint32_t crc_t;
#else
typedef unsigned long crc_t;
#endif
/* Table of CRCs of all 8-bit messages. */
static crc_t crc_table[256];
/* Flag: has the table been computed? Initially false. */
static int crc_table_computed = 0;
/* Make the table for a fast CRC. */
static void make_crc_table(void)
{
crc_t c;
int n, k;
for (n = 0; n < 256; n++) {
c = (crc_t) n;
for (k = 0; k < 8; k++) {
if (c & 1) {
c = 0xedb88320L ^ (c >> 1);
} else {
c = c >> 1;
}
}
crc_table[n] = c;
}
crc_table_computed = 1;
}
/* Update a running CRC with the bytes buf[0..len-1]--the CRC
should be initialized to all 1's, and the transmitted value
is the 1's complement of the final running CRC (see the
crc() routine below)). */
static crc_t update_crc(crc_t crc, const unsigned char *buf, int len)
{
crc_t c = crc;
int n;
if (!crc_table_computed) {
make_crc_table();
}
for (n = 0; n < len; n++) {
c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
}
return c;
}
/* Return the CRC of the bytes buf[0..len-1]. */
static crc_t crc(const unsigned char *buf, int len)
{
return update_crc(0xffffffffL, buf, len) ^ 0xffffffffL;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,341 @@
/*
* QR Code Generator Library: Basic Header
*
* Core routines were originally written by Junn Ohta.
* Based on qr.c Version 0.1: 2004/4/3 (Public Domain)
*
* @package libqr
* @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
* @copyright 2006-2013 Ryusuke SEKIYAMA
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#ifndef _QR_H_
#define _QR_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <errno.h>
#include <stdio.h>
#if defined(WIN32) && !defined(QR_STATIC_BUILD)
#ifdef QR_DLL_BUILD
#define QR_API __declspec(dllexport)
#else
#define QR_API __declspec(dllimport)
#endif
#else
#define QR_API
#endif
/*
* ライブラリのバージョン
*/
#define LIBQR_VERSION "0.3.1"
/*
* エラーコード
*/
typedef enum {
/* 汎用エラーコード */
QR_ERR_NONE = 0,
QR_ERR_USAGE = 0x68,
QR_ERR_NOT_IMPL = 0x69,
QR_ERR_SEE_ERRNO = 0x6e,
QR_ERR_FOPEN = 0x6f,
QR_ERR_FREAD = 0x72,
QR_ERR_STATE = 0x73,
QR_ERR_UNKNOWN = 0x75,
QR_ERR_FWRITE = 0x77,
QR_ERR_MEMORY_EXHAUSTED = 0x78,
/* パラメータ用エラーコード */
QR_ERR_INVALID_ARG = 0x01,
QR_ERR_INVALID_VERSION = 0x02,
QR_ERR_INVALID_MODE = 0x03,
QR_ERR_INVALID_ECL = 0x04,
QR_ERR_INVALID_MPT = 0x05,
QR_ERR_INVALID_MAG = 0x06,
QR_ERR_INVALID_SEP = 0x07,
QR_ERR_INVALID_SIZE = 0x08,
QR_ERR_INVALID_FMT = 0x09,
QR_ERR_INVALID_OUT = 0x0a,
QR_ERR_INVALID_MAXNUM = 0x0b,
QR_ERR_UNSUPPORTED_FMT = 0x0c,
QR_ERR_EMPTY_PARAM = 0x0f,
/* 入力データ用エラーコード */
QR_ERR_EMPTY_SRC = 0x10,
QR_ERR_LARGE_SRC = 0x11,
QR_ERR_NOT_NUMERIC = 0x12,
QR_ERR_NOT_ALNUM = 0x13,
QR_ERR_NOT_KANJI = 0x14,
/* 画像処理用エラーコード */
QR_ERR_IMAGE_TOO_LARGE = 0x30,
QR_ERR_WIDTH_TOO_LARGE = 0x31,
QR_ERR_HEIGHT_TOO_LARGE = 0x32,
QR_ERR_IMAGECREATE = 0x33,
QR_ERR_IMAGEFORMAT = 0x34,
QR_ERR_IMAGEFRAME = 0x35,
/* zlib用エラーコード */
QR_ERR_DEFLATE = 0x40
} qr_err_t;
/*
* 内部状態
*/
#define QR_STATE_BEGIN 0
#define QR_STATE_SET 1
#define QR_STATE_FINAL 2
/*
* 符号化モード
*/
typedef enum {
QR_EM_AUTO = -1, /* 自動選択 */
QR_EM_NUMERIC = 0, /* 数字 */
QR_EM_ALNUM = 1, /* 英数字: 0-9 A-Z SP $%*+-./: */
QR_EM_8BIT = 2, /* 8ビットバイト */
QR_EM_KANJI = 3 /* 漢字 */
} qr_em_t;
/* モード総数 */
#define QR_EM_COUNT 4
/*
* 誤り訂正レベル
*/
typedef enum {
QR_ECL_L = 0, /* レベルL */
QR_ECL_M = 1, /* レベルM */
QR_ECL_Q = 2, /* レベルQ */
QR_ECL_H = 3 /* レベルH */
} qr_ecl_t;
/* レベル総数 */
#define QR_ECL_COUNT 4
/*
* 出力形式
*/
typedef enum {
QR_FMT_PNG = 0, /* PNG */
QR_FMT_BMP = 1, /* BMP */
QR_FMT_TIFF = 2, /* TIFF */
QR_FMT_PBM = 3, /* PBM */
QR_FMT_SVG = 4, /* SVG */
QR_FMT_JSON = 5, /* JSON */
QR_FMT_DIGIT = 6, /* 文字列 */
QR_FMT_ASCII = 7, /* アスキーアート */
QR_FMT_UNAVAILABLE = -1 /* 利用不可 */
} qr_format_t;
/* 出力形式総数 */
#define QR_FMT_COUNT 8
/*
* モジュール値のマスク
*/
#define QR_MM_DATA 0x01 /* 符号化データの黒モジュール */
#define QR_MM_BLACK 0x02 /* 印字される黒モジュール */
#define QR_MM_FUNC 0x04 /* 機能パターン領域(形式/型番情報を含む) */
/*
* 機能パターンの定数
*/
#define QR_DIM_SEP 4 /* 分離パターンの幅 */
#define QR_DIM_FINDER 7 /* 位置検出パターンの1辺の長さ */
#define QR_DIM_ALIGN 5 /* 位置合わせパターンの1辺の長さ */
#define QR_DIM_TIMING 6 /* タイミングパターンのオフセット位置 */
/*
* サイズ定数
*/
#define QR_SRC_MAX 7089 /* 入力データの最大長 */
#define QR_DIM_MAX 177 /* 1辺のモジュール数の最大値 */
#define QR_VER_MAX 40 /* 型番の最大値 */
#define QR_DWD_MAX 2956 /* データコード語の最大長(型番40/レベルL) */
#define QR_ECW_MAX 2430 /* 誤り訂正コード語の最大長(型番40/レベルH) */
#define QR_CWD_MAX 3706 /* コード語の最大長(型番40) */
#define QR_RSD_MAX 123 /* RSブロックデータコード語の最大長 */
#define QR_RSW_MAX 68 /* RSブロック誤り訂正コード語の最大長 */
#define QR_RSB_MAX 2 /* RSブロック種別の最大数 */
#define QR_MPT_MAX 8 /* マスクパターン種別総数 */
#define QR_APL_MAX 7 /* 位置合わせパターン座標の最大数 */
#define QR_FIN_MAX 15 /* 形式情報のビット数 */
#define QR_VIN_MAX 18 /* 型番情報のビット数 */
#define QR_MAG_MAX 16 /* ピクセル表示倍率の最大値 */
#define QR_SEP_MAX 16 /* 分離パターン幅の最大値 */
#define QR_ERR_MAX 1024 /* エラー情報の最大長 */
#define QR_STA_MAX 16 /* 構造的連接(分割/連結)の最大数 */
#define QR_STA_LEN 20 /* 構造的連接ヘッダのビット数 */
/*
* その他の定数
*/
#define NAV 0 /* 不使用(not available) */
#define PADWORD1 0xec /* 埋め草コード語1: 11101100 */
#define PADWORD2 0x11 /* 埋め草コード語2: 00010001 */
#define VERPOINT1 9 /* 文字数指示子のビット数が変わる直前の型番1 */
#define VERPOINT2 26 /* 文字数指示子のビット数が変わる直前の型番2 */
/*
* 8bitバイナリデータ型
*/
typedef unsigned char qr_byte_t;
/*
* RSブロックごとの情報
*/
typedef struct qr_rsblock_t {
int rsbnum; /* RSブロック数 */
int totalwords; /* RSブロック総コード語数 */
int datawords; /* RSブロックデータコード語数 */
int ecnum; /* RSブロック誤り訂正数(不使用) */
} qr_rsblock_t;
/*
* 誤り訂正レベルごとの情報
*/
typedef struct qr_eclevel_t {
int datawords; /* データコード語数(全RSブロック) */
int capacity[QR_EM_COUNT]; /* 符号化モードごとのデータ容量 */
int nrsb; /* RSブロックの種類(1または2) */
qr_rsblock_t rsb[QR_RSB_MAX]; /* RSブロックごとの情報 */
} qr_eclevel_t;
/*
* 型番ごとの情報
*/
typedef struct qr_vertable_t {
int version; /* 型番 */
int dimension; /* 1辺のモジュール数 */
int totalwords; /* 総コード語数 */
int remainedbits; /* 剰余ビット数 */
int nlen[QR_EM_COUNT]; /* 文字数指示子のビット数 */
qr_eclevel_t ecl[QR_ECL_COUNT]; /* 誤り訂正レベルごとの情報 */
int aplnum; /* 位置合わせパターン中心座標数 */
int aploc[QR_APL_MAX]; /* 位置合わせパターン中心座標 */
} qr_vertable_t;
/*
* 座標データ型
*/
typedef struct qr_coord_t { int ypos, xpos; } qr_coord_t;
/*
* パラメータ構造体
*/
typedef struct qr_param_t {
int version; /* 型番 */
int mode; /* 符号化モード */
int eclevel; /* 誤り訂正レベル */
int masktype; /* マスクパターン種別 */
} qr_param_t;
/*
* QRコードオブジェクト
*/
typedef struct qrcode_t {
qr_byte_t *dataword; /* データコード語領域のアドレス */
qr_byte_t *ecword; /* 誤り訂正コード語領域のアドレス */
qr_byte_t *codeword; /* シンボル配置用コード語領域のアドレス */
qr_byte_t *_symbol; /* シンボルデータ領域のアドレス */
qr_byte_t **symbol; /* シンボルデータの各行頭のアドレスのポインタ */
qr_byte_t *source; /* 入力データ領域のアドレス */
size_t srcmax; /* 入力データ領域の最大容量 */
size_t srclen; /* 入力データ領域の使用容量 */
int enclen; /* データコード語の総ビット長 */
int delta1, delta2; /* 型番自動選択の補助に使われるビット長差分 */
int dwpos; /* データコード語の追加バイト位置 */
int dwbit; /* データコード語の追加ビット位置 */
int xpos, ypos; /* モジュールを配置する座標位置 */
int xdir, ydir; /* モジュール配置の移動方向 */
int state; /* 処理の進行状況 */
int errcode; /* 最後に起こったエラーの番号 */
char errinfo[QR_ERR_MAX]; /* 最後に起こったエラーの詳細 */
qr_param_t param; /* 出力パラメータ */
} QRCode;
/*
* 構造的連接QRコードオブジェクト
*/
typedef struct qrcode_sa_t {
QRCode *qrs[QR_STA_MAX]; /* QRコードオブジェクトのポインタ配列 */
QRCode *cur; /* 値を入力する対象のQRコードオブジェクト */
int num; /* シンボル数 */
int max; /* 最大シンボル数 */
int parity; /* パリティ */
int state; /* 処理の進行状況 */
qr_param_t param; /* 出力パラメータ */
} QRStructured;
/*
* QRコード出力関数型
*/
typedef qr_byte_t *(*QRConverter)(QRCode *, int, int, int *);
typedef qr_byte_t *(*QRsConverter)(QRStructured *, int, int, int, int *);
#define qrIsBlacke(qr, i, j) (((qr)->symbol[(i)][(j)] & QR_MM_BLACK) != 0)
/*
* 基本関数のプロトタイプ
*/
QR_API QRCode *qrInit(int version, int mode, int eclevel, int masktype, int *errcode);
QR_API void qrDestroy(QRCode *qr);
QR_API int qrGetErrorCode(QRCode *qr);
QR_API char *qrGetErrorInfo(QRCode *qr);
QR_API int qrAddData(QRCode *qr, const qr_byte_t *source, int size);
QR_API int qrAddData2(QRCode *qr, const qr_byte_t *source, int size, int mode);
QR_API int qrFinalize(QRCode *qr);
QR_API int qrIsFinalized(const QRCode *qr);
QR_API int qrHasData(const QRCode *qr);
QR_API QRCode *qrClone(const QRCode *qr, int *errcode);
/*
* 構造的連接操作用関数のプロトタイプ
*/
QR_API QRStructured *qrsInit(int version, int mode, int eclevel, int masktype, int maxnum, int *errcode);
QR_API void qrsDestroy(QRStructured *st);
QR_API int qrsGetErrorCode(QRStructured *st);
QR_API char *qrsGetErrorInfo(QRStructured *st);
QR_API int qrsAddData(QRStructured *st, const qr_byte_t *source, int size);
QR_API int qrsAddData2(QRStructured *st, const qr_byte_t *source, int size, int mode);
QR_API int qrsFinalize(QRStructured *st);
QR_API int qrsIsFinalized(const QRStructured *st);
QR_API int qrsHasData(const QRStructured *st);
QR_API QRStructured *qrsClone(const QRStructured *st, int *errcode);
/*
* 出力用関数のプロトタイプ
*/
QR_API int qrOutputSymbol(QRCode *qr, FILE *fp, int fmt, int sep, int mag);
QR_API int qrOutputSymbol2(QRCode *qr, const char *pathname, int fmt, int sep, int mag);
QR_API qr_byte_t *qrGetSymbol(QRCode *qr, int fmt, int sep, int mag, int *size);
QR_API qr_byte_t *qrSymbolToDigit(QRCode *qr, int sep, int mag, int *size);
QR_API qr_byte_t *qrSymbolToASCII(QRCode *qr, int sep, int mag, int *size);
QR_API qr_byte_t *qrSymbolToJSON(QRCode *qr, int sep, int mag, int *size);
QR_API qr_byte_t *qrSymbolToPBM(QRCode *qr, int sep, int mag, int *size);
QR_API qr_byte_t *qrSymbolToBMP(QRCode *qr, int sep, int mag, int *size);
/*
* 構造的連接出力用関数のプロトタイプ
*/
QR_API int qrsOutputSymbols(QRStructured *st, FILE *fp, int fmt, int sep, int mag, int order);
QR_API int qrsOutputSymbols2(QRStructured *st, const char *pathname, int fmt, int sep, int mag, int order);
QR_API qr_byte_t *qrsGetSymbols(QRStructured *st, int fmt, int sep, int mag, int order, int *size);
QR_API qr_byte_t *qrsSymbolsToDigit(QRStructured *st, int sep, int mag, int order, int *size);
QR_API qr_byte_t *qrsSymbolsToASCII(QRStructured *st, int sep, int mag, int order, int *size);
QR_API qr_byte_t *qrsSymbolsToJSON(QRStructured *st, int sep, int mag, int order, int *size);
QR_API qr_byte_t *qrsSymbolsToPBM(QRStructured *st, int sep, int mag, int order, int *size);
QR_API qr_byte_t *qrsSymbolsToBMP(QRStructured *st, int sep, int mag, int order, int *size);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* _QR_H_ */

View File

@@ -0,0 +1,48 @@
static const short qr_dwtable_kanji[42][189] = {
{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,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,-1,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,120,121,122,123,124,125,126,127,-1,-1,-1,-1,-1,-1,-1,-1,136,137,138,139,140,141,142,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,-1,-1,-1,-1,-1,-1,-1,176,177,178,179,180,181,182,183,-1,-1,-1,-1,188},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,207,208,209,210,211,212,213,214,215,216,-1,-1,-1,-1,-1,-1,-1,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,-1,-1,-1,-1,-1,-1,-1,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,-1,-1,-1,-1,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,-1,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,-1,-1,-1,-1,-1,-1,-1,-1,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,-1,-1,-1,-1,-1,-1,-1,-1,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,-1,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
#ifdef QR_DISABLE_CP932_CHARACTER
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
#else
{1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,-1,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,-1,-1,-1,-1,-1,-1,-1,-1,1214,-1,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
#endif
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486,1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532},
{1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565,1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,-1,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724},
{1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,-1,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916},
{1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,-1,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108},
{2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,-1,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300},
{2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,-1,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418,2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492},
{2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,-1,2560,2561,2562,2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,2684},
{2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,-1,2752,2753,2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785,2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876},
{2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,-1,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068},
{3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,3134,-1,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184,3185,3186,3187,3188,3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260},
{3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,-1,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369,3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452},
{3456,3457,3458,3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,-1,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593,3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644},
{3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685,3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,-1,3712,3713,3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836},
{3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852,3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3902,-1,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028},
{4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,-1,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220},
{4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,-1,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,4349,4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401,4402,4403,4404,4405,4406,4407,4408,4409,4410,4411,4412},
{4416,4417,4418,4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,4604},
{4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,-1,4672,4673,4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,4709,4710,4711,4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796},
{4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,-1,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988},
{4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,-1,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,5114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180},
{5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,-1,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,5354,5355,5356,5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,5370,5371,5372},
{5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,5431,5432,5433,5434,5435,5436,5437,5438,-1,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564},
{5568,5569,5570,5571,5572,5573,5574,5575,5576,5577,5578,5579,5580,5581,5582,5583,5584,5585,5586,5587,5588,5589,5590,5591,5592,5593,5594,5595,5596,5597,5598,5599,5600,5601,5602,5603,5604,5605,5606,5607,5608,5609,5610,5611,5612,5613,5614,5615,5616,5617,5618,5619,5620,5621,5622,5623,5624,5625,5626,5627,5628,5629,5630,-1,5632,5633,5634,5635,5636,5637,5638,5639,5640,5641,5642,5643,5644,5645,5646,5647,5648,5649,5650,5651,5652,5653,5654,5655,5656,5657,5658,5659,5660,5661,5662,5663,5664,5665,5666,5667,5668,5669,5670,5671,5672,5673,5674,5675,5676,5677,5678,5679,5680,5681,5682,5683,5684,5685,5686,5687,5688,5689,5690,5691,5692,5693,5694,5695,5696,5697,5698,5699,5700,5701,5702,5703,5704,5705,5706,5707,5708,5709,5710,5711,5712,5713,5714,5715,5716,5717,5718,5719,5720,5721,5722,5723,5724,5725,5726,5727,5728,5729,5730,5731,5732,5733,5734,5735,5736,5737,5738,5739,5740,5741,5742,5743,5744,5745,5746,5747,5748,5749,5750,5751,5752,5753,5754,5755,5756},
{5760,5761,5762,5763,5764,5765,5766,5767,5768,5769,5770,5771,5772,5773,5774,5775,5776,5777,5778,5779,5780,5781,5782,5783,5784,5785,5786,5787,5788,5789,5790,5791,5792,5793,5794,5795,5796,5797,5798,5799,5800,5801,5802,5803,5804,5805,5806,5807,5808,5809,5810,5811,5812,5813,5814,5815,5816,5817,5818,5819,5820,5821,5822,-1,5824,5825,5826,5827,5828,5829,5830,5831,5832,5833,5834,5835,5836,5837,5838,5839,5840,5841,5842,5843,5844,5845,5846,5847,5848,5849,5850,5851,5852,5853,5854,5855,5856,5857,5858,5859,5860,5861,5862,5863,5864,5865,5866,5867,5868,5869,5870,5871,5872,5873,5874,5875,5876,5877,5878,5879,5880,5881,5882,5883,5884,5885,5886,5887,5888,5889,5890,5891,5892,5893,5894,5895,5896,5897,5898,5899,5900,5901,5902,5903,5904,5905,5906,5907,5908,5909,5910,5911,5912,5913,5914,5915,5916,5917,5918,5919,5920,5921,5922,5923,5924,5925,5926,5927,5928,5929,5930,5931,5932,5933,5934,5935,5936,5937,5938,5939,5940,5941,5942,5943,5944,5945,5946,5947,5948},
{5952,5953,5954,5955,5956,5957,5958,5959,5960,5961,5962,5963,5964,5965,5966,5967,5968,5969,5970,5971,5972,5973,5974,5975,5976,5977,5978,5979,5980,5981,5982,5983,5984,5985,5986,5987,5988,5989,5990,5991,5992,5993,5994,5995,5996,5997,5998,5999,6000,6001,6002,6003,6004,6005,6006,6007,6008,6009,6010,6011,6012,6013,6014,-1,6016,6017,6018,6019,6020,6021,6022,6023,6024,6025,6026,6027,6028,6029,6030,6031,6032,6033,6034,6035,6036,6037,6038,6039,6040,6041,6042,6043,6044,6045,6046,6047,6048,6049,6050,6051,6052,6053,6054,6055,6056,6057,6058,6059,6060,6061,6062,6063,6064,6065,6066,6067,6068,6069,6070,6071,6072,6073,6074,6075,6076,6077,6078,6079,6080,6081,6082,6083,6084,6085,6086,6087,6088,6089,6090,6091,6092,6093,6094,6095,6096,6097,6098,6099,6100,6101,6102,6103,6104,6105,6106,6107,6108,6109,6110,6111,6112,6113,6114,6115,6116,6117,6118,6119,6120,6121,6122,6123,6124,6125,6126,6127,6128,6129,6130,6131,6132,6133,6134,6135,6136,6137,6138,6139,6140},
{6144,6145,6146,6147,6148,6149,6150,6151,6152,6153,6154,6155,6156,6157,6158,6159,6160,6161,6162,6163,6164,6165,6166,6167,6168,6169,6170,6171,6172,6173,6174,6175,6176,6177,6178,6179,6180,6181,6182,6183,6184,6185,6186,6187,6188,6189,6190,6191,6192,6193,6194,6195,6196,6197,6198,6199,6200,6201,6202,6203,6204,6205,6206,-1,6208,6209,6210,6211,6212,6213,6214,6215,6216,6217,6218,6219,6220,6221,6222,6223,6224,6225,6226,6227,6228,6229,6230,6231,6232,6233,6234,6235,6236,6237,6238,6239,6240,6241,6242,6243,6244,6245,6246,6247,6248,6249,6250,6251,6252,6253,6254,6255,6256,6257,6258,6259,6260,6261,6262,6263,6264,6265,6266,6267,6268,6269,6270,6271,6272,6273,6274,6275,6276,6277,6278,6279,6280,6281,6282,6283,6284,6285,6286,6287,6288,6289,6290,6291,6292,6293,6294,6295,6296,6297,6298,6299,6300,6301,6302,6303,6304,6305,6306,6307,6308,6309,6310,6311,6312,6313,6314,6315,6316,6317,6318,6319,6320,6321,6322,6323,6324,6325,6326,6327,6328,6329,6330,6331,6332},
{6336,6337,6338,6339,6340,6341,6342,6343,6344,6345,6346,6347,6348,6349,6350,6351,6352,6353,6354,6355,6356,6357,6358,6359,6360,6361,6362,6363,6364,6365,6366,6367,6368,6369,6370,6371,6372,6373,6374,6375,6376,6377,6378,6379,6380,6381,6382,6383,6384,6385,6386,6387,6388,6389,6390,6391,6392,6393,6394,6395,6396,6397,6398,-1,6400,6401,6402,6403,6404,6405,6406,6407,6408,6409,6410,6411,6412,6413,6414,6415,6416,6417,6418,6419,6420,6421,6422,6423,6424,6425,6426,6427,6428,6429,6430,6431,6432,6433,6434,6435,6436,6437,6438,6439,6440,6441,6442,6443,6444,6445,6446,6447,6448,6449,6450,6451,6452,6453,6454,6455,6456,6457,6458,6459,6460,6461,6462,6463,6464,6465,6466,6467,6468,6469,6470,6471,6472,6473,6474,6475,6476,6477,6478,6479,6480,6481,6482,6483,6484,6485,6486,6487,6488,6489,6490,6491,6492,6493,6494,6495,6496,6497,6498,6499,6500,6501,6502,6503,6504,6505,6506,6507,6508,6509,6510,6511,6512,6513,6514,6515,6516,6517,6518,6519,6520,6521,6522,6523,6524},
{6528,6529,6530,6531,6532,6533,6534,6535,6536,6537,6538,6539,6540,6541,6542,6543,6544,6545,6546,6547,6548,6549,6550,6551,6552,6553,6554,6555,6556,6557,6558,6559,6560,6561,6562,6563,6564,6565,6566,6567,6568,6569,6570,6571,6572,6573,6574,6575,6576,6577,6578,6579,6580,6581,6582,6583,6584,6585,6586,6587,6588,6589,6590,-1,6592,6593,6594,6595,6596,6597,6598,6599,6600,6601,6602,6603,6604,6605,6606,6607,6608,6609,6610,6611,6612,6613,6614,6615,6616,6617,6618,6619,6620,6621,6622,6623,6624,6625,6626,6627,6628,6629,6630,6631,6632,6633,6634,6635,6636,6637,6638,6639,6640,6641,6642,6643,6644,6645,6646,6647,6648,6649,6650,6651,6652,6653,6654,6655,6656,6657,6658,6659,6660,6661,6662,6663,6664,6665,6666,6667,6668,6669,6670,6671,6672,6673,6674,6675,6676,6677,6678,6679,6680,6681,6682,6683,6684,6685,6686,6687,6688,6689,6690,6691,6692,6693,6694,6695,6696,6697,6698,6699,6700,6701,6702,6703,6704,6705,6706,6707,6708,6709,6710,6711,6712,6713,6714,6715,6716},
{6720,6721,6722,6723,6724,6725,6726,6727,6728,6729,6730,6731,6732,6733,6734,6735,6736,6737,6738,6739,6740,6741,6742,6743,6744,6745,6746,6747,6748,6749,6750,6751,6752,6753,6754,6755,6756,6757,6758,6759,6760,6761,6762,6763,6764,6765,6766,6767,6768,6769,6770,6771,6772,6773,6774,6775,6776,6777,6778,6779,6780,6781,6782,-1,6784,6785,6786,6787,6788,6789,6790,6791,6792,6793,6794,6795,6796,6797,6798,6799,6800,6801,6802,6803,6804,6805,6806,6807,6808,6809,6810,6811,6812,6813,6814,6815,6816,6817,6818,6819,6820,6821,6822,6823,6824,6825,6826,6827,6828,6829,6830,6831,6832,6833,6834,6835,6836,6837,6838,6839,6840,6841,6842,6843,6844,6845,6846,6847,6848,6849,6850,6851,6852,6853,6854,6855,6856,6857,6858,6859,6860,6861,6862,6863,6864,6865,6866,6867,6868,6869,6870,6871,6872,6873,6874,6875,6876,6877,6878,6879,6880,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890,6891,6892,6893,6894,6895,6896,6897,6898,6899,6900,6901,6902,6903,6904,6905,6906,6907,6908},
{6912,6913,6914,6915,6916,6917,6918,6919,6920,6921,6922,6923,6924,6925,6926,6927,6928,6929,6930,6931,6932,6933,6934,6935,6936,6937,6938,6939,6940,6941,6942,6943,6944,6945,6946,6947,6948,6949,6950,6951,6952,6953,6954,6955,6956,6957,6958,6959,6960,6961,6962,6963,6964,6965,6966,6967,6968,6969,6970,6971,6972,6973,6974,-1,6976,6977,6978,6979,6980,6981,6982,6983,6984,6985,6986,6987,6988,6989,6990,6991,6992,6993,6994,6995,6996,6997,6998,6999,7000,7001,7002,7003,7004,7005,7006,7007,7008,7009,7010,7011,7012,7013,7014,7015,7016,7017,7018,7019,7020,7021,7022,7023,7024,7025,7026,7027,7028,7029,7030,7031,7032,7033,7034,7035,7036,7037,7038,7039,7040,7041,7042,7043,7044,7045,7046,7047,7048,7049,7050,7051,7052,7053,7054,7055,7056,7057,7058,7059,7060,7061,7062,7063,7064,7065,7066,7067,7068,7069,7070,7071,7072,7073,7074,7075,7076,7077,7078,7079,7080,7081,7082,7083,7084,7085,7086,7087,7088,7089,7090,7091,7092,7093,7094,7095,7096,7097,7098,7099,7100},
{7104,7105,7106,7107,7108,7109,7110,7111,7112,7113,7114,7115,7116,7117,7118,7119,7120,7121,7122,7123,7124,7125,7126,7127,7128,7129,7130,7131,7132,7133,7134,7135,7136,7137,7138,7139,7140,7141,7142,7143,7144,7145,7146,7147,7148,7149,7150,7151,7152,7153,7154,7155,7156,7157,7158,7159,7160,7161,7162,7163,7164,7165,7166,-1,7168,7169,7170,7171,7172,7173,7174,7175,7176,7177,7178,7179,7180,7181,7182,7183,7184,7185,7186,7187,7188,7189,7190,7191,7192,7193,7194,7195,7196,7197,7198,7199,7200,7201,7202,7203,7204,7205,7206,7207,7208,7209,7210,7211,7212,7213,7214,7215,7216,7217,7218,7219,7220,7221,7222,7223,7224,7225,7226,7227,7228,7229,7230,7231,7232,7233,7234,7235,7236,7237,7238,7239,7240,7241,7242,7243,7244,7245,7246,7247,7248,7249,7250,7251,7252,7253,7254,7255,7256,7257,7258,7259,7260,7261,7262,7263,7264,7265,7266,7267,7268,7269,7270,7271,7272,7273,7274,7275,7276,7277,7278,7279,7280,7281,7282,7283,7284,7285,7286,7287,7288,7289,7290,7291,7292},
{7296,7297,7298,7299,7300,7301,7302,7303,7304,7305,7306,7307,7308,7309,7310,7311,7312,7313,7314,7315,7316,7317,7318,7319,7320,7321,7322,7323,7324,7325,7326,7327,7328,7329,7330,7331,7332,7333,7334,7335,7336,7337,7338,7339,7340,7341,7342,7343,7344,7345,7346,7347,7348,7349,7350,7351,7352,7353,7354,7355,7356,7357,7358,-1,7360,7361,7362,7363,7364,7365,7366,7367,7368,7369,7370,7371,7372,7373,7374,7375,7376,7377,7378,7379,7380,7381,7382,7383,7384,7385,7386,7387,7388,7389,7390,7391,7392,7393,7394,7395,7396,7397,7398,7399,7400,7401,7402,7403,7404,7405,7406,7407,7408,7409,7410,7411,7412,7413,7414,7415,7416,7417,7418,7419,7420,7421,7422,7423,7424,7425,7426,7427,7428,7429,7430,7431,7432,7433,7434,7435,7436,7437,7438,7439,7440,7441,7442,7443,7444,7445,7446,7447,7448,7449,7450,7451,7452,7453,7454,7455,7456,7457,7458,7459,7460,7461,7462,7463,7464,7465,7466,7467,7468,7469,7470,7471,7472,7473,7474,7475,7476,7477,7478,7479,7480,7481,7482,7483,7484},
{7488,7489,7490,7491,7492,7493,7494,7495,7496,7497,7498,7499,7500,7501,7502,7503,7504,7505,7506,7507,7508,7509,7510,7511,7512,7513,7514,7515,7516,7517,7518,7519,7520,7521,7522,7523,7524,7525,7526,7527,7528,7529,7530,7531,7532,7533,7534,7535,7536,7537,7538,7539,7540,7541,7542,7543,7544,7545,7546,7547,7548,7549,7550,-1,7552,7553,7554,7555,7556,7557,7558,7559,7560,7561,7562,7563,7564,7565,7566,7567,7568,7569,7570,7571,7572,7573,7574,7575,7576,7577,7578,7579,7580,7581,7582,7583,7584,7585,7586,7587,7588,7589,7590,7591,7592,7593,7594,7595,7596,7597,7598,7599,7600,7601,7602,7603,7604,7605,7606,7607,7608,7609,7610,7611,7612,7613,7614,7615,7616,7617,7618,7619,7620,7621,7622,7623,7624,7625,7626,7627,7628,7629,7630,7631,7632,7633,7634,7635,7636,7637,7638,7639,7640,7641,7642,7643,7644,7645,7646,7647,7648,7649,7650,7651,7652,7653,7654,7655,7656,7657,7658,7659,7660,7661,7662,7663,7664,7665,7666,7667,7668,7669,7670,7671,7672,7673,7674,7675,7676},
{7680,7681,7682,7683,7684,7685,7686,7687,7688,7689,7690,7691,7692,7693,7694,7695,7696,7697,7698,7699,7700,7701,7702,7703,7704,7705,7706,7707,7708,7709,7710,7711,7712,7713,7714,7715,7716,7717,7718,7719,7720,7721,7722,7723,7724,7725,7726,7727,7728,7729,7730,7731,7732,7733,7734,7735,7736,7737,7738,7739,7740,7741,7742,-1,7744,7745,7746,7747,7748,7749,7750,7751,7752,7753,7754,7755,7756,7757,7758,7759,7760,7761,7762,7763,7764,7765,7766,7767,7768,7769,7770,7771,7772,7773,7774,7775,7776,7777,7778,7779,7780,7781,7782,7783,7784,7785,7786,7787,7788,7789,7790,7791,7792,7793,7794,7795,7796,7797,7798,7799,7800,7801,7802,7803,7804,7805,7806,7807,7808,7809,7810,7811,7812,7813,7814,7815,7816,7817,7818,7819,7820,7821,7822,7823,7824,7825,7826,7827,7828,7829,7830,7831,7832,7833,7834,7835,7836,7837,7838,7839,7840,7841,7842,7843,7844,7845,7846,7847,7848,7849,7850,7851,7852,7853,7854,7855,7856,7857,7858,7859,7860,7861,7862,7863,7864,7865,7866,7867,7868},
{7872,7873,7874,7875,7876,7877,7878,7879,7880,7881,7882,7883,7884,7885,7886,7887,7888,7889,7890,7891,7892,7893,7894,7895,7896,7897,7898,7899,7900,7901,7902,7903,7904,7905,7906,7907,7908,7909,7910,7911,7912,7913,7914,7915,7916,7917,7918,7919,7920,7921,7922,7923,7924,7925,7926,7927,7928,7929,7930,7931,7932,7933,7934,-1,7936,7937,7938,7939,7940,7941,7942,7943,7944,7945,7946,7947,7948,7949,7950,7951,7952,7953,7954,7955,7956,7957,7958,7959,7960,7961,7962,7963,7964,7965,7966,7967,7968,7969,7970,7971,7972,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}
};

View File

@@ -0,0 +1,512 @@
/*
* QR Code Generator Library: Private Definitions
*
* Core routines were originally written by Junn Ohta.
* Based on qr.c Version 0.1: 2004/4/3 (Public Domain)
*
* @package libqr
* @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
* @copyright 2006-2013 Ryusuke SEKIYAMA
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#ifndef _QR_PRIVATE_H_
#define _QR_PRIVATE_H_
#include "qr.h"
#include <stdlib.h>
#include <string.h>
/*
* Booblean
*/
#ifdef TRUE
#undef TRUE
#endif
#ifdef FALSE
#undef FALSE
#endif
#define TRUE 1
#define FALSE 0
/*
* 型番データ表
*/
const qr_vertable_t qr_vertable[QR_VER_MAX+1] = {
{ NAV, NAV, NAV, NAV, { 0, 0, 0, 0 },
{{ NAV, { 0, 0, 0, 0 }, NAV, {{ 0, 0, 0, 0 }}},
{ NAV, { 0, 0, 0, 0 }, NAV, {{ 0, 0, 0, 0 }}},
{ NAV, { 0, 0, 0, 0 }, NAV, {{ 0, 0, 0, 0 }}},
{ NAV, { 0, 0, 0, 0 }, NAV, {{ 0, 0, 0, 0 }}}},
NAV, { NAV, NAV }},
{ 1, 21, 26, 0, { 10, 9, 8, 8 },
{{ 19, { 41, 25, 17, 10 }, 1, {{ 1, 26, 19, 2 }}},
{ 16, { 34, 20, 14, 8 }, 1, {{ 1, 26, 16, 4 }}},
{ 13, { 27, 16, 11, 7 }, 1, {{ 1, 26, 13, 6 }}},
{ 9, { 17, 10, 7, 4 }, 1, {{ 1, 26, 9, 8 }}}},
0, { NAV, NAV }},
{ 2, 25, 44, 7, { 10, 9, 8, 8 },
{{ 34, { 77, 47, 32, 20 }, 1, {{ 1, 44, 34, 4 }}},
{ 28, { 63, 38, 26, 16 }, 1, {{ 1, 44, 28, 8 }}},
{ 22, { 48, 29, 20, 12 }, 1, {{ 1, 44, 22, 11 }}},
{ 16, { 34, 20, 14, 8 }, 1, {{ 1, 44, 16, 14 }}}},
2, { 6, 18 }},
{ 3, 29, 70, 7, { 10, 9, 8, 8 },
{{ 55, { 127, 77, 53, 32 }, 1, {{ 1, 70, 55, 7 }}},
{ 44, { 101, 61, 42, 26 }, 1, {{ 1, 70, 44, 13 }}},
{ 34, { 77, 47, 32, 20 }, 1, {{ 2, 35, 17, 9 }}},
{ 26, { 58, 35, 24, 15 }, 1, {{ 2, 35, 13, 11 }}}},
2, { 6, 22 }},
{ 4, 33, 100, 7, { 10, 9, 8, 8 },
{{ 80, { 187, 114, 78, 48 }, 1, {{ 1, 100, 80, 10 }}},
{ 64, { 149, 90, 62, 38 }, 1, {{ 2, 50, 32, 9 }}},
{ 48, { 111, 67, 46, 28 }, 1, {{ 2, 50, 24, 13 }}},
{ 36, { 82, 50, 34, 21 }, 1, {{ 4, 25, 9, 8 }}}},
2, { 6, 26 }},
{ 5, 37, 134, 7, { 10, 9, 8, 8 },
{{ 108, { 255, 154, 106, 65 }, 1, {{ 1, 134, 108, 13 }}},
{ 86, { 202, 122, 84, 52 }, 1, {{ 2, 67, 43, 12 }}},
{ 62, { 144, 87, 60, 37 }, 2, {{ 2, 33, 15, 9 }, { 2, 34, 16, 9 }}},
{ 46, { 106, 64, 44, 27 }, 2, {{ 2, 33, 11, 11 }, { 2, 34, 12, 11 }}}},
2, { 6, 30 }},
{ 6, 41, 172, 7, { 10, 9, 8, 8 },
{{ 136, { 322, 195, 134, 82 }, 1, {{ 2, 86, 68, 9 }}},
{ 108, { 255, 154, 106, 65 }, 1, {{ 4, 43, 27, 8 }}},
{ 76, { 178, 108, 74, 45 }, 1, {{ 4, 43, 19, 12 }}},
{ 60, { 139, 84, 58, 36 }, 1, {{ 4, 43, 15, 14 }}}},
2, { 6, 34 }},
{ 7, 45, 196, 0, { 10, 9, 8, 8 },
{{ 156, { 370, 224, 154, 95 }, 1, {{ 2, 98, 78, 10 }}},
{ 124, { 293, 178, 122, 75 }, 1, {{ 4, 49, 31, 9 }}},
{ 88, { 207, 125, 86, 53 }, 2, {{ 2, 32, 14, 9 }, { 4, 33, 15, 9 }}},
{ 66, { 154, 93, 64, 39 }, 2, {{ 4, 39, 13, 13 }, { 1, 40, 14, 13 }}}},
3, { 6, 22, 38 }},
{ 8, 49, 242, 0, { 10, 9, 8, 8 },
{{ 194, { 461, 279, 192, 118 }, 1, {{ 2, 121, 97, 12 }}},
{ 154, { 365, 221, 152, 93 }, 2, {{ 2, 60, 38, 11 }, { 2, 61, 39, 11 }}},
{ 110, { 259, 157, 108, 66 }, 2, {{ 4, 40, 18, 11 }, { 2, 41, 19, 11 }}},
{ 86, { 202, 122, 84, 52 }, 2, {{ 4, 40, 14, 13 }, { 2, 41, 15, 13 }}}},
3, { 6, 24, 42 }},
{ 9, 53, 292, 0, { 10, 9, 8, 8 },
{{ 232, { 552, 335, 230, 141 }, 1, {{ 2, 146, 116, 15 }}},
{ 182, { 432, 262, 180, 111 }, 2, {{ 3, 58, 36, 11 }, { 2, 59, 37, 11 }}},
{ 132, { 312, 189, 130, 80 }, 2, {{ 4, 36, 16, 10 }, { 4, 37, 17, 10 }}},
{ 100, { 235, 143, 98, 60 }, 2, {{ 4, 36, 12, 12 }, { 4, 37, 13, 12 }}}},
3, { 6, 26, 46 }},
{ 10, 57, 346, 0, { 12, 11, 16, 10 },
{{ 274, { 652, 395, 271, 167 }, 2, {{ 2, 86, 68, 9 }, { 2, 87, 69, 9 }}},
{ 216, { 513, 311, 213, 131 }, 2, {{ 4, 69, 43, 13 }, { 1, 70, 44, 13 }}},
{ 154, { 364, 221, 151, 93 }, 2, {{ 6, 43, 19, 12 }, { 2, 44, 20, 12 }}},
{ 122, { 288, 174, 119, 74 }, 2, {{ 6, 43, 15, 14 }, { 2, 44, 16, 14 }}}},
3, { 6, 28, 50 }},
{ 11, 61, 404, 0, { 12, 11, 16, 10 },
{{ 324, { 772, 468, 321, 198 }, 1, {{ 4, 101, 81, 10 }}},
{ 254, { 604, 366, 251, 155 }, 2, {{ 1, 80, 50, 15 }, { 4, 81, 51, 15 }}},
{ 180, { 427, 259, 177, 109 }, 2, {{ 4, 50, 22, 14 }, { 4, 51, 23, 14 }}},
{ 140, { 331, 200, 137, 85 }, 2, {{ 3, 36, 12, 12 }, { 8, 37, 13, 12 }}}},
3, { 6, 30, 54 }},
{ 12, 65, 466, 0, { 12, 11, 16, 10 },
{{ 370, { 883, 535, 367, 226 }, 2, {{ 2, 116, 92, 12 }, { 2, 117, 93, 12 }}},
{ 290, { 691, 419, 287, 177 }, 2, {{ 6, 58, 36, 11 }, { 2, 59, 37, 11 }}},
{ 206, { 489, 296, 203, 125 }, 2, {{ 4, 46, 20, 13 }, { 6, 47, 21, 13 }}},
{ 158, { 374, 227, 155, 96 }, 2, {{ 7, 42, 14, 14 }, { 4, 43, 15, 14 }}}},
3, { 6, 32, 58 }},
{ 13, 69, 532, 0, { 12, 11, 16, 10 },
{{ 428, { 1022, 619, 425, 262 }, 1, {{ 4, 133, 107, 13 }}},
{ 334, { 796, 483, 331, 204 }, 2, {{ 8, 59, 37, 11 }, { 1, 60, 38, 11 }}},
{ 244, { 580, 352, 241, 149 }, 2, {{ 8, 44, 20, 12 }, { 4, 45, 21, 12 }}},
{ 180, { 427, 259, 177, 109 }, 2, {{ 12, 33, 11, 11 }, { 4, 34, 12, 11 }}}},
3, { 6, 34, 62 }},
{ 14, 73, 581, 3, { 12, 11, 16, 10 },
{{ 461, { 1101, 667, 458, 282 }, 2, {{ 3, 145, 115, 15 }, { 1, 146, 116, 15 }}},
{ 365, { 871, 528, 362, 223 }, 2, {{ 4, 64, 40, 12 }, { 5, 65, 41, 12 }}},
{ 261, { 621, 376, 258, 159 }, 2, {{ 11, 36, 16, 10 }, { 5, 37, 17, 10 }}},
{ 197, { 468, 283, 194, 120 }, 2, {{ 11, 36, 12, 12 }, { 5, 37, 13, 12 }}}},
4, { 6, 26, 46, 66 }},
{ 15, 77, 655, 3, { 12, 11, 16, 10 },
{{ 523, { 1250, 758, 520, 320 }, 2, {{ 5, 109, 87, 11 }, { 1, 110, 88, 11 }}},
{ 415, { 991, 600, 412, 254 }, 2, {{ 5, 65, 41, 12 }, { 5, 66, 42, 12 }}},
{ 295, { 703, 426, 292, 180 }, 2, {{ 5, 54, 24, 15 }, { 7, 55, 25, 15 }}},
{ 223, { 530, 321, 220, 136 }, 2, {{ 11, 36, 12, 12 }, { 7, 37, 13, 12 }}}},
4, { 6, 26, 48, 70 }},
{ 16, 81, 733, 3, { 12, 11, 16, 10 },
{{ 589, { 1408, 854, 586, 361 }, 2, {{ 5, 122, 98, 12 }, { 1, 123, 99, 12 }}},
{ 453, { 1082, 656, 450, 277 }, 2, {{ 7, 73, 45, 14 }, { 3, 74, 46, 14 }}},
{ 325, { 775, 470, 322, 198 }, 2, {{ 15, 43, 19, 12 }, { 2, 44, 20, 12 }}},
{ 253, { 602, 365, 250, 154 }, 2, {{ 3, 45, 15, 15 }, { 13, 46, 16, 15 }}}},
4, { 6, 26, 50, 74 }},
{ 17, 85, 815, 3, { 12, 11, 16, 10 },
{{ 647, { 1548, 938, 644, 397 }, 2, {{ 1, 135, 107, 14 }, { 5, 136, 108, 14 }}},
{ 507, { 1212, 734, 504, 310 }, 2, {{ 10, 74, 46, 14 }, { 1, 75, 47, 14 }}},
{ 367, { 876, 531, 364, 224 }, 2, {{ 1, 50, 22, 14 }, { 15, 51, 23, 14 }}},
{ 283, { 674, 408, 280, 173 }, 2, {{ 2, 42, 14, 14 }, { 17, 43, 15, 14 }}}},
4, { 6, 30, 54, 78 }},
{ 18, 89, 901, 3, { 12, 11, 16, 10 },
{{ 721, { 1725, 1046, 718, 442 }, 2, {{ 5, 150, 120, 15 }, { 1, 151, 121, 15 }}},
{ 563, { 1346, 816, 560, 345 }, 2, {{ 9, 69, 43, 13 }, { 4, 70, 44, 13 }}},
{ 397, { 948, 574, 394, 243 }, 2, {{ 17, 50, 22, 14 }, { 1, 51, 23, 14 }}},
{ 313, { 746, 452, 310, 191 }, 2, {{ 2, 42, 14, 14 }, { 19, 43, 15, 14 }}}},
4, { 6, 30, 56, 82 }},
{ 19, 93, 991, 3, { 12, 11, 16, 10 },
{{ 795, { 1903, 1153, 792, 488 }, 2, {{ 3, 141, 113, 14 }, { 4, 142, 114, 14 }}},
{ 627, { 1500, 909, 624, 384 }, 2, {{ 3, 70, 44, 13 }, { 11, 71, 45, 13 }}},
{ 445, { 1063, 644, 442, 272 }, 2, {{ 17, 47, 21, 13 }, { 4, 48, 22, 13 }}},
{ 341, { 813, 493, 338, 208 }, 2, {{ 9, 39, 13, 13 }, { 16, 40, 14, 13 }}}},
4, { 6, 30, 58, 86 }},
{ 20, 97, 1085, 3, { 12, 11, 16, 10 },
{{ 861, { 2061, 1249, 858, 528 }, 2, {{ 3, 135, 107, 14 }, { 5, 136, 108, 14 }}},
{ 669, { 1600, 970, 666, 410 }, 2, {{ 3, 67, 41, 13 }, { 13, 68, 42, 13 }}},
{ 485, { 1159, 702, 482, 297 }, 2, {{ 15, 54, 24, 15 }, { 5, 55, 25, 15 }}},
{ 385, { 919, 557, 382, 235 }, 2, {{ 15, 43, 15, 14 }, { 10, 44, 16, 14 }}}},
4, { 6, 34, 62, 90 }},
{ 21, 101, 1156, 4, { 12, 11, 16, 10 },
{{ 932, { 2232, 1352, 929, 572 }, 2, {{ 4, 144, 116, 14 }, { 4, 145, 117, 14 }}},
{ 714, { 1708, 1035, 711, 438 }, 1, {{ 17, 68, 42, 13 }}},
{ 512, { 1224, 742, 509, 314 }, 2, {{ 17, 50, 22, 14 }, { 6, 51, 23, 14 }}},
{ 406, { 969, 587, 403, 248 }, 2, {{ 19, 46, 16, 15 }, { 6, 47, 17, 15 }}}},
5, { 6, 28, 50, 72, 94 }},
{ 22, 105, 1258, 4, { 12, 11, 16, 10 },
{{ 1006, { 2409, 1460, 1003, 618 }, 2, {{ 2, 139, 111, 14 }, { 7, 140, 112, 14 }}},
{ 782, { 1872, 1134, 779, 480 }, 1, {{ 17, 74, 46, 14 }}},
{ 568, { 1358, 823, 565, 348 }, 2, {{ 7, 54, 24, 15 }, { 16, 55, 25, 15 }}},
{ 442, { 1056, 640, 439, 270 }, 1, {{ 34, 37, 13, 13 }}}},
5, { 6, 26, 50, 74, 98 }},
{ 23, 109, 1364, 4, { 12, 11, 16, 10 },
{{ 1094, { 2620, 1588, 1091, 672 }, 2, {{ 4, 151, 121, 15 }, { 5, 152, 122, 15 }}},
{ 860, { 2059, 1248, 857, 528 }, 2, {{ 4, 75, 47, 14 }, { 14, 76, 48, 14 }}},
{ 614, { 1468, 890, 611, 376 }, 2, {{ 11, 54, 24, 15 }, { 14, 55, 25, 15 }}},
{ 464, { 1108, 672, 461, 284 }, 2, {{ 16, 45, 15, 15 }, { 14, 46, 16, 15 }}}},
5, { 6, 30, 54, 78, 102 }},
{ 24, 113, 1474, 4, { 12, 11, 16, 10 },
{{ 1174, { 2812, 1704, 1171, 721 }, 2, {{ 6, 147, 117, 15 }, { 4, 148, 118, 15 }}},
{ 914, { 2188, 1326, 911, 561 }, 2, {{ 6, 73, 45, 14 }, { 14, 74, 46, 14 }}},
{ 664, { 1588, 963, 661, 407 }, 2, {{ 11, 54, 24, 15 }, { 16, 55, 25, 15 }}},
{ 514, { 1228, 744, 511, 315 }, 2, {{ 30, 46, 16, 15 }, { 2, 47, 17, 15 }}}},
5, { 6, 28, 54, 80, 106 }},
{ 25, 117, 1588, 4, { 12, 11, 16, 10 },
{{ 1276, { 3057, 1853, 1273, 784 }, 2, {{ 8, 132, 106, 13 }, { 4, 133, 107, 13 }}},
{ 1000, { 2395, 1451, 997, 614 }, 2, {{ 8, 75, 47, 14 }, { 13, 76, 48, 14 }}},
{ 718, { 1718, 1041, 715, 440 }, 2, {{ 7, 54, 24, 15 }, { 22, 55, 25, 15 }}},
{ 538, { 1286, 779, 535, 330 }, 2, {{ 22, 45, 15, 15 }, { 13, 46, 16, 15 }}}},
5, { 6, 32, 58, 84, 110 }},
{ 26, 121, 1706, 4, { 12, 11, 16, 10 },
{{ 1370, { 3283, 1990, 1367, 842 }, 2, {{ 10, 142, 114, 14 }, { 2, 143, 115, 14 }}},
{ 1062, { 2544, 1542, 1059, 652 }, 2, {{ 19, 74, 46, 14 }, { 4, 75, 47, 14 }}},
{ 754, { 1804, 1094, 751, 462 }, 2, {{ 28, 50, 22, 14 }, { 6, 51, 23, 14 }}},
{ 596, { 1425, 864, 593, 365 }, 2, {{ 33, 46, 16, 15 }, { 4, 47, 17, 15 }}}},
5, { 6, 30, 58, 86, 114 }},
{ 27, 125, 1828, 4, { 14, 13, 16, 12 },
{{ 1468, { 3517, 2132, 1465, 902 }, 2, {{ 8, 152, 122, 15 }, { 4, 153, 123, 15 }}},
{ 1128, { 2701, 1637, 1125, 692 }, 2, {{ 22, 73, 45, 14 }, { 3, 74, 46, 14 }}},
{ 808, { 1933, 1172, 805, 496 }, 2, {{ 8, 53, 23, 15 }, { 26, 54, 24, 15 }}},
{ 628, { 1501, 910, 625, 385 }, 2, {{ 12, 45, 15, 15 }, { 28, 46, 16, 15 }}}},
5, { 6, 34, 62, 90, 118 }},
{ 28, 129, 1921, 3, { 14, 13, 16, 12 },
{{ 1531, { 3669, 2223, 1528, 940 }, 2, {{ 3, 147, 117, 15 }, { 10, 148, 118, 15 }}},
{ 1193, { 2857, 1732, 1190, 732 }, 2, {{ 3, 73, 45, 14 }, { 23, 74, 46, 14 }}},
{ 871, { 2085, 1263, 868, 534 }, 2, {{ 4, 54, 24, 15 }, { 31, 55, 25, 15 }}},
{ 661, { 1581, 958, 658, 405 }, 2, {{ 11, 45, 15, 15 }, { 31, 46, 16, 15 }}}},
6, { 6, 26, 50, 74, 98, 122 }},
{ 29, 133, 2051, 3, { 14, 13, 16, 12 },
{{ 1631, { 3909, 2369, 1628, 1002 }, 2, {{ 7, 146, 116, 15 }, { 7, 147, 117, 15 }}},
{ 1267, { 3035, 1839, 1264, 778 }, 2, {{ 21, 73, 45, 14 }, { 7, 74, 46, 14 }}},
{ 911, { 2181, 1322, 908, 559 }, 2, {{ 1, 53, 23, 15 }, { 37, 54, 24, 15 }}},
{ 701, { 1677, 1016, 698, 430 }, 2, {{ 19, 45, 15, 15 }, { 26, 46, 16, 15 }}}},
6, { 6, 30, 54, 78, 102, 126 }},
{ 30, 137, 2185, 3, { 14, 13, 16, 12 },
{{ 1735, { 4158, 2520, 1732, 1066 }, 2, {{ 5, 145, 115, 15 }, { 10, 146, 116, 15 }}},
{ 1373, { 3289, 1994, 1370, 843 }, 2, {{ 19, 75, 47, 14 }, { 10, 76, 48, 14 }}},
{ 985, { 2358, 1429, 982, 604 }, 2, {{ 15, 54, 24, 15 }, { 25, 55, 25, 15 }}},
{ 745, { 1782, 1080, 742, 457 }, 2, {{ 23, 45, 15, 15 }, { 25, 46, 16, 15 }}}},
6, { 6, 26, 52, 78, 104, 130 }},
{ 31, 141, 2323, 3, { 14, 13, 16, 12 },
{{ 1843, { 4417, 2677, 1840, 1132 }, 2, {{ 13, 145, 115, 15 }, { 3, 146, 116, 15 }}},
{ 1455, { 3486, 2113, 1452, 894 }, 2, {{ 2, 74, 46, 14 }, { 29, 75, 47, 14 }}},
{ 1033, { 2473, 1499, 1030, 634 }, 2, {{ 42, 54, 24, 15 }, { 1, 55, 25, 15 }}},
{ 793, { 1897, 1150, 790, 486 }, 2, {{ 23, 45, 15, 15 }, { 28, 46, 16, 15 }}}},
6, { 6, 30, 56, 82, 108, 134 }},
{ 32, 145, 2465, 3, { 14, 13, 16, 12 },
{{ 1955, { 4686, 2840, 1952, 1201 }, 1, {{ 17, 145, 115, 15 }}},
{ 1541, { 3693, 2238, 1538, 947 }, 2, {{ 10, 74, 46, 14 }, { 23, 75, 47, 14 }}},
{ 1115, { 2670, 1618, 1112, 684 }, 2, {{ 10, 54, 24, 15 }, { 35, 55, 25, 15 }}},
{ 845, { 2022, 1226, 842, 518 }, 2, {{ 19, 45, 15, 15 }, { 35, 46, 16, 15 }}}},
6, { 6, 34, 60, 86, 112, 138 }},
{ 33, 149, 2611, 3, { 14, 13, 16, 12 },
{{ 2071, { 4965, 3009, 2068, 1273 }, 2, {{ 17, 145, 115, 15 }, { 1, 146, 116, 15 }}},
{ 1631, { 3909, 2369, 1628, 1002 }, 2, {{ 14, 74, 46, 14 }, { 21, 75, 47, 14 }}},
{ 1171, { 2805, 1700, 1168, 719 }, 2, {{ 29, 54, 24, 15 }, { 19, 55, 25, 15 }}},
{ 901, { 2157, 1307, 898, 553 }, 2, {{ 11, 45, 15, 15 }, { 46, 46, 16, 15 }}}},
6, { 6, 30, 58, 86, 114, 142 }},
{ 34, 153, 2761, 3, { 14, 13, 16, 12 },
{{ 2191, { 5253, 3183, 2188, 1347 }, 2, {{ 13, 145, 115, 15 }, { 6, 146, 116, 15 }}},
{ 1725, { 4134, 2506, 1722, 1060 }, 2, {{ 14, 74, 46, 14 }, { 23, 75, 47, 14 }}},
{ 1231, { 2949, 1787, 1228, 756 }, 2, {{ 44, 54, 24, 15 }, { 7, 55, 25, 15 }}},
{ 961, { 2301, 1394, 958, 590 }, 2, {{ 59, 46, 16, 15 }, { 1, 47, 17, 15 }}}},
6, { 6, 34, 62, 90, 118, 146 }},
{ 35, 157, 2876, 0, { 14, 13, 16, 12 },
{{ 2306, { 5529, 3351, 2303, 1417 }, 2, {{ 12, 151, 121, 15 }, { 7, 152, 122, 15 }}},
{ 1812, { 4343, 2632, 1809, 1113 }, 2, {{ 12, 75, 47, 14 }, { 26, 76, 48, 14 }}},
{ 1286, { 3081, 1867, 1283, 790 }, 2, {{ 39, 54, 24, 15 }, { 14, 55, 25, 15 }}},
{ 986, { 2361, 1431, 983, 605 }, 2, {{ 22, 45, 15, 15 }, { 41, 46, 16, 15 }}}},
7, { 6, 30, 54, 78, 102, 126, 150 }},
{ 36, 161, 3034, 0, { 14, 13, 16, 12 },
{{ 2434, { 5836, 3537, 2431, 1496 }, 2, {{ 6, 151, 121, 15 }, { 14, 152, 122, 15 }}},
{ 1914, { 4588, 2780, 1911, 1176 }, 2, {{ 6, 75, 47, 14 }, { 34, 76, 48, 14 }}},
{ 1354, { 3244, 1966, 1351, 832 }, 2, {{ 46, 54, 24, 15 }, { 10, 55, 25, 15 }}},
{ 1054, { 2524, 1530, 1051, 647 }, 2, {{ 2, 45, 15, 15 }, { 64, 46, 16, 15 }}}},
7, { 6, 24, 50, 76, 102, 128, 154 }},
{ 37, 165, 3196, 0, { 14, 13, 16, 12 },
{{ 2566, { 6153, 3729, 2563, 1577 }, 2, {{ 17, 152, 122, 15 }, { 4, 153, 123, 15 }}},
{ 1992, { 4775, 2894, 1989, 1224 }, 2, {{ 29, 74, 46, 14 }, { 14, 75, 47, 14 }}},
{ 1426, { 3417, 2071, 1423, 876 }, 2, {{ 49, 54, 24, 15 }, { 10, 55, 25, 15 }}},
{ 1096, { 2625, 1591, 1093, 673 }, 2, {{ 24, 45, 15, 15 }, { 46, 46, 16, 15 }}}},
7, { 6, 28, 54, 80, 106, 132, 158 }},
{ 38, 169, 3362, 0, { 14, 13, 16, 12 },
{{ 2702, { 6479, 3927, 2699, 1661 }, 2, {{ 4, 152, 122, 15 }, { 18, 153, 123, 15 }}},
{ 2102, { 5039, 3054, 2099, 1292 }, 2, {{ 13, 74, 46, 14 }, { 32, 75, 47, 14 }}},
{ 1502, { 3599, 2181, 1499, 923 }, 2, {{ 48, 54, 24, 15 }, { 14, 55, 25, 15 }}},
{ 1142, { 2735, 1658, 1139, 701 }, 2, {{ 42, 45, 15, 15 }, { 32, 46, 16, 15 }}}},
7, { 6, 32, 58, 84, 110, 136, 162 }},
{ 39, 173, 3532, 0, { 14, 13, 16, 12 },
{{ 2812, { 6743, 4087, 2809, 1729 }, 2, {{ 20, 147, 117, 15 }, { 4, 148, 118, 15 }}},
{ 2216, { 5313, 3220, 2213, 1362 }, 2, {{ 40, 75, 47, 14 }, { 7, 76, 48, 14 }}},
{ 1582, { 3791, 2298, 1579, 972 }, 2, {{ 43, 54, 24, 15 }, { 22, 55, 25, 15 }}},
{ 1222, { 2927, 1774, 1219, 750 }, 2, {{ 10, 45, 15, 15 }, { 67, 46, 16, 15 }}}},
7, { 6, 26, 54, 82, 110, 138, 166 }},
{ 40, 177, 3706, 0, { 14, 13, 16, 12 },
{{ 2956, { 7089, 4296, 2953, 1817 }, 2, {{ 19, 148, 118, 15 }, { 6, 149, 119, 15 }}},
{ 2334, { 5596, 3391, 2331, 1435 }, 2, {{ 18, 75, 47, 14 }, { 31, 76, 48, 14 }}},
{ 1666, { 3993, 2420, 1663, 1024 }, 2, {{ 34, 54, 24, 15 }, { 34, 55, 25, 15 }}},
{ 1276, { 3057, 1852, 1273, 784 }, 2, {{ 20, 45, 15, 15 }, { 61, 46, 16, 15 }}}},
7, { 6, 30, 58, 86, 114, 142, 170 }}
};
/*
* αのべき表現→多項式係数の整数表現
*/
static const unsigned char qr_exp2fac[256] = {
1, 2, 4, 8, 16, 32, 64,128, 29, 58,116,232,205,135, 19, 38,
76,152, 45, 90,180,117,234,201,143, 3, 6, 12, 24, 48, 96,192,
157, 39, 78,156, 37, 74,148, 53,106,212,181,119,238,193,159, 35,
70,140, 5, 10, 20, 40, 80,160, 93,186,105,210,185,111,222,161,
95,190, 97,194,153, 47, 94,188,101,202,137, 15, 30, 60,120,240,
253,231,211,187,107,214,177,127,254,225,223,163, 91,182,113,226,
217,175, 67,134, 17, 34, 68,136, 13, 26, 52,104,208,189,103,206,
129, 31, 62,124,248,237,199,147, 59,118,236,197,151, 51,102,204,
133, 23, 46, 92,184,109,218,169, 79,158, 33, 66,132, 21, 42, 84,
168, 77,154, 41, 82,164, 85,170, 73,146, 57,114,228,213,183,115,
230,209,191, 99,198,145, 63,126,252,229,215,179,123,246,241,255,
227,219,171, 75,150, 49, 98,196,149, 55,110,220,165, 87,174, 65,
130, 25, 50,100,200,141, 7, 14, 28, 56,112,224,221,167, 83,166,
81,162, 89,178,121,242,249,239,195,155, 43, 86,172, 69,138, 9,
18, 36, 72,144, 61,122,244,245,247,243,251,235,203,139, 11, 22,
44, 88,176,125,250,233,207,131, 27, 54,108,216,173, 71,142, 1
};
/*
* 多項式係数の整数表現→αのべき表現
*/
static const unsigned char qr_fac2exp[256] = {
NAV, 0, 1, 25, 2, 50, 26,198, 3,223, 51,238, 27,104,199, 75,
4,100,224, 14, 52,141,239,129, 28,193,105,248,200, 8, 76,113,
5,138,101, 47,225, 36, 15, 33, 53,147,142,218,240, 18,130, 69,
29,181,194,125,106, 39,249,185,201,154, 9,120, 77,228,114,166,
6,191,139, 98,102,221, 48,253,226,152, 37,179, 16,145, 34,136,
54,208,148,206,143,150,219,189,241,210, 19, 92,131, 56, 70, 64,
30, 66,182,163,195, 72,126,110,107, 58, 40, 84,250,133,186, 61,
202, 94,155,159, 10, 21,121, 43, 78,212,229,172,115,243,167, 87,
7,112,192,247,140,128, 99, 13,103, 74,222,237, 49,197,254, 24,
227,165,153,119, 38,184,180,124, 17, 68,146,217, 35, 32,137, 46,
55, 63,209, 91,149,188,207,205,144,135,151,178,220,252,190, 97,
242, 86,211,171, 20, 42, 93,158,132, 60, 57, 83, 71,109, 65,162,
31, 45, 67,216,183,123,164,118,196, 23, 73,236,127, 12,111,246,
108,161, 59, 82, 41,157, 85,170,251, 96,134,177,187,204, 62, 90,
203, 89, 95,176,156,169,160, 81, 11,245, 22,235,122,117, 44,215,
79,174,213,233,230,231,173,232,116,214,244,234,168, 80, 88,175
};
/*
* 誤り訂正生成多項式の第2項以降の係数表(べき表現)
*/
static const unsigned char qr_gftable[QR_RSW_MAX+1][QR_RSW_MAX] = {
{0},{0},{0},{0},{0},{0},{0},{87,229,146,149,238,102,21},
{0},{0},{251,67,46,61,118,70,64,94,32,45},
{0},{0},{74,152,176,100,86,100,106,104,130,218,206,140,78},
{0},{8,183,61,91,202,37,51,58,58,237,140,124,5,99,105},
{120,104,107,109,102,161,76,3,91,191,147,169,182,194,225,120},
{43,139,206,78,43,239,123,206,214,147,24,99,150,39,243,163,136},
{215,234,158,94,184,97,118,170,79,187,152,148,252,179,5,98,96,153},
{0},{17,60,79,50,61,163,26,187,202,180,221,225,83,239,156,164,212,212,188,190},
{0},{210,171,247,242,93,230,14,109,221,53,200,74,8,172,98,80,219,134,160,105,165,231},
{0},{229,121,135,48,211,117,251,126,159,180,169,152,192,226,228,218,111,0,117,232,87,96,227,21},
{0},{173,125,158,2,103,182,118,17,145,201,111,28,165,53,161,21,245,142,13,102,48,227,153,145,218,70},
{0},{168,223,200,104,224,234,108,180,110,190,195,147,205,27,232,201,21,43,245,87,42,195,212,119,242,37,9,123},
{0},{41,173,145,152,216,31,179,182,50,48,110,86,239,96,222,125,42,173,226,193,224,130,156,37,251,216,238,40,192,180},
{0},{10,6,106,190,249,167,4,67,209,138,138,32,242,123,89,27,120,185,80,156,38,69,171,60,28,222,80,52,254,185,220,241},
{0},{111,77,146,94,26,21,108,19,105,94,113,193,86,140,163,125,58,158,229,239,218,103,56,70,114,61,183,129,167,13,98,62,129,51},
{0},{200,183,98,16,172,31,246,234,60,152,115,0,167,152,113,248,238,107,18,63,218,37,87,210,105,177,120,74,121,196,117,251,113,233,30,120},
{0},{159,34,38,228,230,59,243,95,49,218,176,164,20,65,45,111,39,81,49,118,113,222,193,250,242,168,217,41,164,247,177,30,238,18,120,153,60,193},
{0},{59,116,79,161,252,98,128,205,128,161,247,57,163,56,235,106,53,26,187,174,226,104,170,7,175,35,181,114,88,41,47,163,125,134,72,20,232,53,35,15},
{0},{250,103,221,230,25,18,137,231,0,3,58,242,221,191,110,84,230,8,188,106,96,147,15,131,139,34,101,223,39,101,213,199,237,254,201,123,171,162,194,117,50,96},
{0},{190,7,61,121,71,246,69,55,168,188,89,243,191,25,72,123,9,145,14,247,1,238,44,78,143,62,224,126,118,114,68,163,52,194,217,147,204,169,37,130,113,102,73,181},
{0},{112,94,88,112,253,224,202,115,187,99,89,5,54,113,129,44,58,16,135,216,169,211,36,1,4,96,60,241,73,104,234,8,249,245,119,174,52,25,157,224,43,202,223,19,82,15},
{0},{228,25,196,130,211,146,60,24,251,90,39,102,240,61,178,63,46,123,115,18,221,111,135,160,182,205,107,206,95,150,120,184,91,21,247,156,140,238,191,11,94,227,84,50,163,39,34,108},
{0},{232,125,157,161,164,9,118,46,209,99,203,193,35,3,209,111,195,242,203,225,46,13,32,160,126,209,130,160,242,215,242,75,77,42,189,32,113,65,124,69,228,114,235,175,124,170,215,232,133,205},
{0},{116,50,86,186,50,220,251,89,192,46,86,127,124,19,184,233,151,215,22,14,59,145,37,242,203,134,254,89,190,94,59,65,124,113,100,233,235,121,22,76,86,97,39,242,200,220,101,33,239,254,116,51},
{0},{183,26,201,87,210,221,113,21,46,65,45,50,238,184,249,225,102,58,209,218,109,165,26,95,184,192,52,245,35,254,238,175,172,79,123,25,122,43,120,108,215,80,128,201,235,8,153,59,101,31,198,76,31,156},
{0},{106,120,107,157,164,216,112,116,2,91,248,163,36,201,202,229,6,144,254,155,135,208,170,209,12,139,127,142,182,249,177,174,190,28,10,85,239,184,101,124,152,206,96,23,163,61,27,196,247,151,154,202,207,20,61,10},
{0},{82,116,26,247,66,27,62,107,252,182,200,185,235,55,251,242,210,144,154,237,176,141,192,248,152,249,206,85,253,142,65,165,125,23,24,30,122,240,214,6,129,218,29,145,127,134,206,245,117,29,41,63,159,142,233,125,148,123},
{0},{107,140,26,12,9,141,243,197,226,197,219,45,211,101,219,120,28,181,127,6,100,247,2,205,198,57,115,219,101,109,160,82,37,38,238,49,160,209,121,86,11,124,30,181,84,25,194,87,65,102,190,220,70,27,209,16,89,7,33,240},
{0},{65,202,113,98,71,223,248,118,214,94,0,122,37,23,2,228,58,121,7,105,135,78,243,118,70,76,223,89,72,50,70,111,194,17,212,126,181,35,221,117,235,11,229,149,147,123,213,40,115,6,200,100,26,246,182,218,127,215,36,186,110,106},
{0},{45,51,175,9,7,158,159,49,68,119,92,123,177,204,187,254,200,78,141,149,119,26,127,53,160,93,199,212,29,24,145,156,208,150,218,209,4,216,91,47,184,146,47,140,195,195,125,242,238,63,99,108,140,230,242,31,204,11,178,243,217,156,213,231},
{0},{5,118,222,180,136,136,162,51,46,117,13,215,81,17,139,247,197,171,95,173,65,137,178,68,111,95,101,41,72,214,169,197,95,7,44,154,77,111,236,40,121,143,63,87,80,253,240,126,217,77,34,232,106,50,168,82,76,146,67,106,171,25,132,93,45,105},
{0},{247,159,223,33,224,93,77,70,90,160,32,254,43,150,84,101,190,205,133,52,60,202,165,220,203,151,93,84,15,84,253,173,160,89,227,52,199,97,95,231,52,177,41,125,137,241,166,225,118,2,54,32,82,215,175,198,43,238,235,27,101,184,127,3,5,8,163,238}
};
#define F0 QR_MM_FUNC
#define F1 (QR_MM_FUNC | QR_MM_BLACK)
/*
* 位置検出パターンのデータ
*/
static const qr_byte_t qr_finderpattern[QR_DIM_FINDER][QR_DIM_FINDER] = {
{ F1, F1, F1, F1, F1, F1, F1 },
{ F1, F0, F0, F0, F0, F0, F1 },
{ F1, F0, F1, F1, F1, F0, F1 },
{ F1, F0, F1, F1, F1, F0, F1 },
{ F1, F0, F1, F1, F1, F0, F1 },
{ F1, F0, F0, F0, F0, F0, F1 },
{ F1, F1, F1, F1, F1, F1, F1 }
};
/*
* 位置合わせパターンのデータ
*/
static const qr_byte_t qr_alignpattern[QR_DIM_ALIGN][QR_DIM_ALIGN] = {
{ F1, F1, F1, F1, F1 },
{ F1, F0, F0, F0, F1 },
{ F1, F0, F1, F0, F1 },
{ F1, F0, F0, F0, F1 },
{ F1, F1, F1, F1, F1 }
};
#undef F0
#undef F1
/*
* モード指示子(英字, 英数字, 8ビットバイト, 漢字)
*/
static const int qr_modeid[QR_EM_COUNT] = { 0x01, 0x02, 0x04, 0x08 };
/*
* 符号化モード名 (不使用)
*/
/*const char *qr_modename[QR_EM_COUNT] = {
"Numeric", "Alnum", "8bit-byte", "Kanji"
};*/
/*
* エラー訂正レベル名
*/
const char *qr_eclname[QR_ECL_COUNT] = { "L", "M", "Q", "H" };
/*
* 英数字モードの符号化表
*/
static const signed char qr_alnumtable[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
-1, 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, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
/*
* 形式情報(2箇所)の座標(下位ビットから)
* (負数は下端/右端からのオフセット)
*/
static const qr_coord_t qr_fmtinfopos[2][QR_FIN_MAX] = {
{{ 0, 8 }, { 1, 8 }, { 2, 8 }, { 3, 8 },
{ 4, 8 }, { 5, 8 }, { 7, 8 }, { 8, 8 },
{ -7, 8 }, { -6, 8 }, { -5, 8 }, { -4, 8 },
{ -3, 8 }, { -2, 8 }, { -1, 8 }},
{{ 8, -1 }, { 8, -2 }, { 8, -3 }, { 8, -4 },
{ 8, -5 }, { 8, -6 }, { 8, -7 }, { 8, -8 },
{ 8, 7 }, { 8, 5 }, { 8, 4 }, { 8, 3 },
{ 8, 2 }, { 8, 1 }, { 8, 0 }}
};
/*
* 形式情報の固定黒モジュール
*/
static const qr_coord_t qr_fmtblackpos = { -8, 8 };
/*
* 型番情報(2箇所)の座標(下位ビットから)
* (負数は下端/右端からのオフセット)
*/
static const qr_coord_t qr_verinfopos[2][QR_VIN_MAX] = {
{{ -11, 0 }, { -10, 0 }, { -9, 0 },
{ -11, 1 }, { -10, 1 }, { -9, 1 },
{ -11, 2 }, { -10, 2 }, { -9, 2 },
{ -11, 3 }, { -10, 3 }, { -9, 3 },
{ -11, 4 }, { -10, 4 }, { -9, 4 },
{ -11, 5 }, { -10, 5 }, { -9, 5 }},
{{ 0, -11 }, { 0, -10 }, { 0, -9 },
{ 1, -11 }, { 1, -10 }, { 1, -9 },
{ 2, -11 }, { 2, -10 }, { 2, -9 },
{ 3, -11 }, { 3, -10 }, { 3, -9 },
{ 4, -11 }, { 4, -10 }, { 4, -9 },
{ 5, -11 }, { 5, -10 }, { 5, -9 }}
};
/*
* 型番情報(型番7〜40について有効)
*/
static const long qr_verinfo[QR_VER_MAX+1] = {
-1L, -1L, -1L, -1L, -1L, -1L,
-1L, 0x07c94L, 0x085bcL, 0x09a99L, 0x0a4d3L, 0x0bbf6L,
0x0c762L, 0x0d847L, 0x0e60dL, 0x0f928L, 0x10b78L, 0x1145dL,
0x12a17L, 0x13532L, 0x149a6L, 0x15683L, 0x168c9L, 0x177ecL,
0x18ec4L, 0x191e1L, 0x1afabL, 0x1b08eL, 0x1cc1aL, 0x1d33fL,
0x1ed75L, 0x1f250L, 0x209d5L, 0x216f0L, 0x228baL, 0x2379fL,
0x24b0bL, 0x2542eL, 0x26a64L, 0x27541L, 0x28c69L
};
/*
* 一連の処理をする関数ポインタ型
*/
typedef int (*qr_funcs)(QRCode *);
/*
* 内部処理用関数のプロトタイプ
*/
static void qrAddDataBits(QRCode *qr, int n, int word);
static int qrInitDataWord(QRCode *qr);
static int qrEncodeDataWord(QRCode *qr, const qr_byte_t *source, int size, int mode);
static int qrFinalizeDataWord(QRCode *qr);
static int qrComputeECWord(QRCode *qr);
static int qrMakeCodeWord(QRCode *qr);
static int qrFillFunctionPattern(QRCode *qr);
static int qrFillCodeWord(QRCode *qr);
static void qrInitPosition(QRCode *qr);
static void qrNextPosition(QRCode *qr);
static int qrSelectMaskPattern(QRCode *qr);
static int qrApplyMaskPattern(QRCode *qr);
static int qrApplyMaskPattern2(QRCode *qr, int type);
static long qrEvaluateMaskPattern(QRCode *qr);
static int qrFillFormatInfo(QRCode *qr);
#endif /* _QR_PRIVATE_H_ */

View File

@@ -0,0 +1,87 @@
/*
* QR Code Generator Library: Header for Utility
*
* Core routines were originally written by Junn Ohta.
* Based on qr.c Version 0.1: 2004/4/3 (Public Domain)
*
* @package libqr
* @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
* @copyright 2006-2013 Ryusuke SEKIYAMA
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#ifndef _QR_UTIL_H_
#define _QR_UTIL_H_
#include "qr.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h>
/*
* Determine the module is a dark module or not.
*/
#define qrIsBlack(qr, i, j) (((qr)->symbol[(i)][(j)] & QR_MM_BLACK) != 0)
/*
* Deallocate and set to NULL.
*/
#define qrFree(ptr) { if ((ptr) != NULL) { free(ptr); (ptr) = NULL; } }
/*
* Current function name macro.
*/
QR_API extern const char *(*qrGetCurrentFunctionName)(void);
#if defined(__FUNCTION__)
#define _QR_FUNCTION ((qrGetCurrentFunctionName) ? qrGetCurrentFunctionName() : __FUNCTION__)
#elif defined(__func__)
#define _QR_FUNCTION ((qrGetCurrentFunctionName) ? qrGetCurrentFunctionName() : __func__)
#else
#define _QR_FUNCTION ((qrGetCurrentFunctionName) ? qrGetCurrentFunctionName() : "?")
#endif
/*
* Maximum length of filename extensions.
*/
#define QR_EXT_MAX_LEN 4
/*
* Constatns.
*/
extern QR_API const qr_vertable_t qr_vertable[];
/*extern QR_API const char *qr_modename[]; */
extern QR_API const char *qr_eclname[];
/*
* Functions for utility.
*/
QR_API const char *qrVersion(void);
QR_API const char *qrMimeType(int format);
QR_API const char *qrExtension(int format);
QR_API const char *qrStrError(int errcode);
QR_API void qrSetErrorInfo(QRCode *qr, int errnum, const char *param);
QR_API void qrSetErrorInfo2(QRCode *qr, int errnum, const char *param);
QR_API void qrSetErrorInfo3(QRCode *qr, int errnum, const char *fmt, ...);
QR_API int qrGetEncodedLength(QRCode *qr, int size);
QR_API int qrGetEncodedLength2(QRCode *qr, int size, int mode);
QR_API int qrGetEncodableLength(QRCode *qr, int size);
QR_API int qrGetEncodableLength2(QRCode *qr, int size, int mode);
QR_API int qrRemainedDataBits(QRCode *qr);
/*
* Functions for checking datatype.
*/
QR_API int qrDetectDataType(const qr_byte_t *source, int size);
QR_API int qrStrPosNotNumeric(const qr_byte_t *source, int size);
QR_API int qrStrPosNotAlnum(const qr_byte_t *source, int size);
QR_API int qrStrPosNotKanji(const qr_byte_t *source, int size);
QR_API int qrStrPosNot8bit(const qr_byte_t *source, int size);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* _QR_UTIL_H_ */

View File

@@ -0,0 +1,626 @@
/*
* QR Code Generator Library: Command Line Interface
*
* Core routines were originally written by Junn Ohta.
* Based on qr.c Version 0.1: 2004/4/3 (Public Domain)
*
* @package libqr
* @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
* @copyright 2006-2013 Ryusuke SEKIYAMA
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#include "qrcmd.h"
#ifdef WIN32
#define err(code, ...) { \
printf(__VA_ARGS__); \
printf(": %s\r\n", strerror(errno)); \
exit(code); \
}
#define errx(code, ...) { \
printf(__VA_ARGS__); \
printf("\r\n"); \
exit(code); \
}
#else
#include <err.h>
#endif
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <sys/fcntl.h>
#define writeln(msg) printf(msg "\r\n")
#define ewriteln(msg) printf(msg "\r\n")
#define writelnf(fmt, ...) printf(fmt "r\n", __VA_ARGS__)
#define ewritelnf(fmt, ...) printf(fmt "\r\n", __VA_ARGS__)
#else
#define writeln(msg) printf(msg "\n")
#define ewriteln(msg) fprintf(stderr, msg "\n")
#define writelnf(fmt, ...) printf(fmt "\n", __VA_ARGS__)
#define ewritelnf(fmt, ...) fprintf(stderr, fmt "\n", __VA_ARGS__)
#endif
/* {{{ main() */
int
main(int argc, char **argv)
{
QRCMD_PTR_TYPE *qr;
int mag = 1;
int sep = QR_DIM_SEP;
int fmt = QR_FMT_PBM;
QRCMD_EXTRA_PARAM_A
char output[PATH_MAX] = { '\0' };
char *ptr = &(output[0]);
int result = 0;
#ifdef WIN32
setmode(fileno(stdin), O_BINARY);
setmode(fileno(stdout), O_BINARY);
#endif
if (argc <= 1) {
writelnf("%s: QR Code Generator", argv[0]);
writelnf("try '%s --help' for more information", argv[0]);
return 1;
}
/*
* QRコードオブジェクトを生成し、コマンド行引数からパラメータと入力データを設定する
*/
qr = qrGetParameter(argc, argv, &fmt, &sep, &mag, QRCMD_EXTRA_PARAM_C &ptr);
/*
* データコード語をエンコードし、シンボルを配置する
*/
if (!qrCmdFinalize(qr)) {
ewritelnf("%s: %s", argv[0], qrCmdGetErrorInfo(qr));
qrCmdDestroy(qr);
return 1;
}
/*
* シンボルを出力する
*/
#ifdef QRCMD_STRUCTURED_APPEND
if (extra == -1) {
/*
* 連番出力
*/
int i;
for (i = 0; i < qr->num; i++) {
if (output[0] == '\0') {
result = qrOutputSymbol(qr->qrs[i], stdout, fmt, sep, mag);
} else {
char outputs[PATH_MAX] = { '\0' };
int written = 0;
written = snprintf(&(outputs[0]), PATH_MAX, "%s%02d.%s",
&(output[0]), i + 1, qrExtension(fmt));
if (written < 0 || written >= PATH_MAX) {
ewritelnf("%s: output pathname is too long", argv[0]);
qrCmdDestroy(qr);
return 1;
}
result = qrOutputSymbol2(qr->qrs[i], &(outputs[0]), fmt, sep, mag);
}
if (result == -1) {
ewritelnf("%s: QR Code #%d: %s", argv[0], i, qrCmdGetErrorInfo(qr));
qrCmdDestroy(qr);
return 1;
}
}
} else
#endif
if (output[0] == '\0') {
result = qrCmdOutputSymbol(qr, stdout, fmt, sep, mag QRCMD_EXTRA_PARAM_B);
} else {
result = qrCmdOutputSymbol2(qr, &(output[0]), fmt, sep, mag QRCMD_EXTRA_PARAM_B);
}
if (result == -1) {
ewritelnf("%s: %s", argv[0], qrCmdGetErrorInfo(qr));
qrCmdDestroy(qr);
return 1;
}
qrCmdDestroy(qr);
return 0;
}
/* }}} main() */
/* {{{ qrShowHelp() */
/*
* 使用方法を表示する
*/
void
qrShowHelp(void)
{
writeln("QR Code Generator");
writeln();
writeln("QR Code (R) is registered trademarks of DENSO WAVE INCORPORATED");
writeln("in JAPAN and other countries.");
writeln();
writelnf("usage: %s [options ...] [ [ [mode] [text | -i file] ] ...] ", QRCMD_PROG_NAME);
writeln();
writeln("input:");
writeln(" The data which is stored in QR Code Symbol (at least 1 character).");
writeln(" If it is not specified, read from stdin.");
writeln();
writeln("examples:");
writelnf(" %s -eM -x6 < input.txt > output.pbm", QRCMD_PROG_NAME);
writelnf(" %s -eM -x6 -o output.pbm -i input.txt", QRCMD_PROG_NAME);
writelnf(" %s -v2 -fBMP -o foobar.bmp -mA 'FOOBAR'", QRCMD_PROG_NAME);
writelnf(" %s -x3 -fSVG -o mixed.svg -mA 'ALNUM' -m8 ' ' -mN '001'", QRCMD_PROG_NAME);
writelnf(" %s -fAA 'Ascii Art'", QRCMD_PROG_NAME);
writeln();
writeln("options:");
writeln(" -V show program's version number and exit");
writeln(" -?, -h, --help show this help message and exit");
#ifdef QRCMD_STRUCTURED_APPEND
writeln(" -v, --version=NUM symbol version (1-40, default: 1)");
#else
writeln(" -v, --version=NUM symbol version (1-40, default: auto)");
#endif
writeln(" -m, --mode=MODE encoding mode (N,A,8,K,S, default: S)");
writeln(" N: numeric, A: uppercase alphabet and numeric,");
writeln(" 8: 8-bit byte, K: JIS X 0208 Kanji, S: auto");
writeln(" -e, --eclevel=LEVEL error correction level (L,M,Q,H, default: M)");
writeln(" L: 7%%, M: 15%%, Q: 25%%, H: 30%%");
writeln(" -p, --pattern=NUM mask pattern (0-7, default: auto)");
writeln(" -x, --magnify=NUM magnifying ratio (1-16, default: 1)");
writeln(" -s, --separator=NUM separator pattan width (0-16, default: 4)");
writeln(" '4' is the lower limit of the QR Code specification.");
writeln(" -f, --format=FORMAT output format (default: PBM)");
writeln(" Available formats are followings.");
writeln(" PNG, BMP, TIFF, PBM, SVG, JSON, DIGIT, ASCII");
writeln(" These are case-insensitive and some have aliases.");
writeln(" DIGIT -> 01");
writeln(" ASCII -> asciiart, aa");
writeln(" JSON -> javascript, js");
writeln(" TIFF -> tif");
#ifdef QRCMD_STRUCTURED_APPEND
writelnf(" -a, --maxnum=NUM maximum number of symbols (1-%d, default: %d)", QR_STA_MAX, QR_STA_MAX);
writeln(" -z, --order=NUM ordering method of symbols, in case NUM is ...");
writeln(" = 0 (default): order to square as possible");
writeln(" >= 1: order each NUM symbols to horizontal");
writeln(" <= -1: order each NUM symbols to vertical");
writeln(" --serial output as serial numbered images");
writeln(" Number and extension will be added to output pathname.");
writeln(" (default: output as a combined image)");
#endif
writeln(" -o, --output=PATH output pathname (default: write to stdout)");
writeln(" -i, --input=PATH input pathname (default: read from stdin)");
writeln(" To specify multiple files, set this option");
writeln(" before every filename. And the encoding mode");
writeln(" can be specified to each files.");
writeln(" (e.g. -mA -i file1 -mK -i file2 ...)");
}
/* }}} qrShowHelp() */
/* {{{ utilities for qrGetParameter() */
#define QR_SHORT_OPT(name) (d = 2, !strncmp(ptr, name, d))
#define QR_LONG_OPT(name) (d = sizeof(name), !strncmp(ptr, name "=", d))
#define QR_GETOPT_NEXT() { \
opt = ptr; \
ptr += d; \
if (d == 2 && *ptr == '\0') { \
i++; \
if (i == argc) { \
errx(1, "%s: %s", opt, qrStrError(QR_ERR_EMPTY_PARAM)); \
} \
ptr = argv[i]; \
} \
if (ptr == NULL || *ptr == '\0') { \
errx(1, "%s: %s", opt, qrStrError(QR_ERR_EMPTY_PARAM)); \
} \
}
/* }}} utilities for qrGetParameter() */
/* {{{ qrGetParameter() */
/*
* コマンド行引数からパラメータと入力データを設定し、出力ファイル名を取得する
*/
QRCMD_PTR_TYPE *
qrGetParameter(int argc, char **argv,
int *fmt, int *sep, int *mag, QRCMD_EXTRA_PARAM_D char **output)
{
QRCMD_PTR_TYPE *qr;
char *opt, *ptr;
int i;
size_t d;
int version = QRCMD_DEFAULT_VERSION;
int mode = QR_EM_AUTO;
int eclevel = QR_ECL_M;
int masktype = -1;
QRCMD_MAX_NUM_A
int errcode = QR_ERR_NONE;
int has_data = 0;
/*
* 引数のパラメータを取得する
*/
for (i = 1; i < argc; i++) {
ptr = argv[i];
if (!strcmp(ptr, "-?") || !strcasecmp(ptr, "-h") || !strcmp(ptr, "--help")) {
/*
* 使用方法
*/
qrShowHelp();
exit(1);
} else if (!strcmp(ptr, "-V")) {
/*
* バージョン
*/
writelnf("%s: QR Code Generator", QRCMD_PROG_NAME);
writelnf("qrcmd version: %s", QRCMD_PROG_VERSION);
writelnf("libqr version: %s", qrVersion());
exit(1);
} else if (QR_SHORT_OPT("-v") || QR_LONG_OPT("--version")) {
/*
* 型番
*/
QR_GETOPT_NEXT();
if (*ptr < '0' || *ptr > '9') {
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_VERSION));
}
version = atoi(ptr);
if (version <= 0 || version > QR_VER_MAX) {
errx(1, "%d: %s", version, qrStrError(QR_ERR_INVALID_VERSION));
}
} else if (QR_SHORT_OPT("-m") || QR_LONG_OPT("--mode")) {
/*
* 符号化モード
*/
QR_GETOPT_NEXT();
switch (*ptr) {
case 's':
case 'S':
mode = QR_EM_AUTO;
break;
case 'n':
case 'N':
mode = QR_EM_NUMERIC;
break;
case 'a':
case 'A':
mode = QR_EM_ALNUM;
break;
case '8':
case 'B':
mode = QR_EM_8BIT;
break;
case 'k':
case 'K':
mode = QR_EM_KANJI;
break;
default:
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MODE));
}
} else if (QR_SHORT_OPT("-e") || QR_LONG_OPT("--eclevel")) {
/*
* 誤り訂正レベル
*/
QR_GETOPT_NEXT();
switch (*ptr) {
case 'l':
case 'L':
eclevel = QR_ECL_L;
break;
case 'm':
case 'M':
eclevel = QR_ECL_M;
break;
case 'q':
case 'Q':
eclevel = QR_ECL_Q;
break;
case 'h':
case 'H':
eclevel = QR_ECL_H;
break;
default:
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_ECL));
}
} else if (QR_SHORT_OPT("-p") || QR_LONG_OPT("--pattern")) {
/*
* マスクパターン種別
*/
QR_GETOPT_NEXT();
if (*ptr < '0' || *ptr > '9') {
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MPT));
}
masktype = atoi(ptr);
if (masktype < 0 || masktype >= QR_MPT_MAX) {
errx(1, "%d: %s", masktype, qrStrError(QR_ERR_INVALID_MPT));
}
} else if (QR_SHORT_OPT("-x") || QR_LONG_OPT("--magnify")) {
/*
* ピクセル表示倍率
*/
QR_GETOPT_NEXT();
if (*ptr < '0' || *ptr > '9') {
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MAG));
}
*mag = atoi(ptr);
if (*mag < 0 || *mag > QR_MAG_MAX) {
errx(1, "%d: %s", *mag, qrStrError(QR_ERR_INVALID_MAG));
}
} else if (QR_SHORT_OPT("-s") || QR_LONG_OPT("--separator")) {
/*
* 分離パターン幅
*/
QR_GETOPT_NEXT();
if (*ptr < '0' || *ptr > '9') {
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_SEP));
}
*sep = atoi(ptr);
if (*sep < 0 || *sep > QR_SEP_MAX) {
errx(1, "%d: %s", *sep, qrStrError(QR_ERR_INVALID_SEP));
}
} else if (QR_SHORT_OPT("-f") || QR_LONG_OPT("--format")) {
/*
* 出力形式
*/
QR_GETOPT_NEXT();
if (!strcasecmp(ptr, "digit") || !strcasecmp(ptr, "01")) {
*fmt = QR_FMT_DIGIT;
} else if (!strcasecmp(ptr, "asciiart") ||
!strcasecmp(ptr, "ascii") ||
!strcasecmp(ptr, "aa"))
{
*fmt = QR_FMT_ASCII;
} else if (!strcasecmp(ptr, "javascript") ||
!strcasecmp(ptr, "json") ||
!strcasecmp(ptr, "js"))
{
*fmt = QR_FMT_JSON;
} else if (!strcasecmp(ptr, "pbm")) {
*fmt = QR_FMT_PBM;
} else if (!strcasecmp(ptr, "bmp")) {
*fmt = QR_FMT_BMP;
} else if (!strcasecmp(ptr, "svg")) {
*fmt = QR_FMT_SVG;
} else if (!strcasecmp(ptr, "tiff") | !strcasecmp(ptr, "tif")) {
#ifdef QR_ENABLE_TIFF
*fmt = QR_FMT_TIFF;
#else
#endif /* QR_ENABLE_TIFF */
#ifdef QR_ENABLE_PNG
} else if (!strcasecmp(ptr, "png")) {
*fmt = QR_FMT_PNG;
#endif /* QR_ENABLE_PNG */
} else {
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_FMT));
}
} else if (QR_SHORT_OPT("-o") || QR_LONG_OPT("--output")) {
/*
* 出力ファイル名
*/
QR_GETOPT_NEXT();
size_t pathlen;
pathlen = strlen(ptr);
if (pathlen >= PATH_MAX) {
errx(1, "argv[%d]: %s", i, strerror(ENAMETOOLONG));
}
if (*output[0] != '\0') {
errx(1, "%s: %s: Duplicated declaration of output pathname",
*output, ptr);
}
strncpy(*output, ptr, pathlen);
#ifdef QRCMD_STRUCTURED_APPEND
} else if (QR_SHORT_OPT("-a") || QR_LONG_OPT("--maxnum")) {
/*
* 最大シンボル数
*/
QR_GETOPT_NEXT();
if (*ptr < '0' || *ptr > '9') {
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MAXNUM));
}
maxnum = atoi(ptr);
if (maxnum < 2 || maxnum > QR_STA_MAX) {
errx(1, "%d: %s", maxnum, qrStrError(QR_ERR_INVALID_MAXNUM));
}
} else if (QR_SHORT_OPT("-z") || QR_LONG_OPT("--order")) {
/*
* 並べ方
*/
QR_GETOPT_NEXT();
if (*ptr != '-' && (*ptr < '0' || *ptr > '9')) {
/*errx(1, "%s: %s", ptr, qrStrError(QR_ERR_UNKNOWN));*/
continue;
}
*order = atoi(ptr);
} else if (!strcmp(ptr, "--serial")) {
/*
* 連番
*/
if (*extra != 0) {
errx(1, "Serial image output and GIF animation output are exclusive.");
}
*extra = -1;
} else if (!strcmp(ptr, "--animation") || !strncmp(ptr, "--animation=", 12)) {
/*
* GIFアニメ
*/
if (*extra != 0) {
errx(1, "Serial image output and GIF animation output are exclusive.");
}
if (strlen(ptr) == 11) {
*extra = 100;
} else {
double _f;
ptr += 12;
if (*ptr < '0' || *ptr > '9') {
errx(1, "%s: Invalid animation delay.", ptr);
}
_f = atof(ptr);
*extra = (int)(_f * 100);
if (*extra == 0) {
errx(1, "Zero animation delay.");
}
}
#endif /* QRCMD_STRUCTURED_APPEND */
} else {
break;
}
}
/*
* QRコードオブジェクトを初期化する
*/
qr = qrCmdInit(version, mode, eclevel, masktype, QRCMD_MAX_NUM_B &errcode);
if (qr == NULL) {
errx(1, "%s", qrStrError(errcode));
}
/*
* 入力データを取得する
*/
for (; i < argc; i++) {
ptr = argv[i];
if (QR_SHORT_OPT("-m") || QR_LONG_OPT("--mode")) {
/*
* 符号化モードを上書き
*/
QR_GETOPT_NEXT();
switch (*ptr) {
case 'n':
case 'N':
mode = QR_EM_NUMERIC;
break;
case 'a':
case 'A':
mode = QR_EM_ALNUM;
break;
case '8':
case 'B':
mode = QR_EM_8BIT;
break;
case 'k':
case 'K':
mode = QR_EM_KANJI;
break;
default:
qrCmdDestroy(qr);
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_MODE));
}
} else if (QR_SHORT_OPT("-i") || QR_LONG_OPT("--input")) {
qr_byte_t source[QRCMD_SRC_MAX];
int srclen = 0;
FILE *fp;
int c;
/*
* 入力データをファイルから読む
*/
QR_GETOPT_NEXT();
fp = fopen(ptr, "rb");
if (fp == NULL) {
qrCmdDestroy(qr);
err(1, "%s", ptr);
}
while ((c = fgetc(fp)) != EOF && srclen < QRCMD_SRC_MAX){
source[srclen++] = (qr_byte_t)c;
}
fclose(fp);
if (srclen == 0) {
qrCmdDestroy(qr);
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_EMPTY_SRC));
} else if (c != EOF) {
qrCmdDestroy(qr);
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_LARGE_SRC));
}
if (!qrCmdAddData2(qr, source, srclen, mode)) {
char errinfo[QR_ERR_MAX];
snprintf(&(errinfo[0]), QR_ERR_MAX, "%s: %s", ptr, qrCmdGetErrorInfo(qr));
qrCmdDestroy(qr);
errx(1, "%s", errinfo);
}
has_data++;
} else if (*ptr != '-') {
qr_byte_t source[QRCMD_SRC_MAX];
int srclen = 0;
/*
* 入力データを引数から得る
*/
srclen = strlen(ptr);
if (srclen == 0) {
qrCmdDestroy(qr);
errx(1, "argv[%d]: %s", i, qrStrError(QR_ERR_EMPTY_SRC));
} else if (srclen > QRCMD_SRC_MAX) {
qrCmdDestroy(qr);
errx(1, "argv[%d]: %s", i, qrStrError(QR_ERR_LARGE_SRC));
}
memcpy(&(source[0]), ptr, (size_t)srclen);
if (!qrCmdAddData2(qr, source, srclen, mode)) {
char errinfo[QR_ERR_MAX];
snprintf(&(errinfo[0]), QR_ERR_MAX, "argv[%d]: %s", i, qrCmdGetErrorInfo(qr));
qrCmdDestroy(qr);
errx(1, "%s", errinfo);
}
has_data++;
} else {
/*
* 未定義オプション
*/
qrCmdDestroy(qr);
errx(1, "%s: %s", ptr, qrStrError(QR_ERR_INVALID_ARG));
}
}
/*
* 入力データが空なら、標準入力から読む
*/
if (!has_data) {
qr_byte_t source[QRCMD_SRC_MAX];
int srclen = 0;
int c;
while ((c = getchar()) != EOF && srclen < QRCMD_SRC_MAX){
source[srclen++] = (qr_byte_t)c;
}
if (srclen == 0) {
qrCmdDestroy(qr);
errx(1, "-stdin: %s", qrStrError(QR_ERR_EMPTY_SRC));
}
if (c != EOF) {
qrCmdDestroy(qr);
errx(1, "-stdin: %s", qrStrError(QR_ERR_LARGE_SRC));
}
if (!qrCmdAddData2(qr, source, srclen, mode)) {
char errinfo[QR_ERR_MAX];
snprintf(&(errinfo[0]), QR_ERR_MAX, "%s", qrCmdGetErrorInfo(qr));
qrCmdDestroy(qr);
errx(1, "%s", errinfo);
}
}
return qr;
}
/* }}} qrGetParameter() */

View File

@@ -0,0 +1,110 @@
/*
* QR Code Generator Library: Header for Command Line Interface
*
* Core routines were originally written by Junn Ohta.
* Based on qr.c Version 0.1: 2004/4/3 (Public Domain)
*
* @package libqr
* @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
* @copyright 2006-2013 Ryusuke SEKIYAMA
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#ifndef _QRCMD_H_
#define _QRCMD_H_
/* {{{ include headers */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "qr.h"
#include "qr_util.h"
/* }}} */
/* {{{ version information */
#define QRCMD_PROG_VERSION "0.2.0"
/* }}} */
/* {{{ whether enable structured append or not */
#ifdef QRCMD_STRUCTURED_APPEND
/* {{{ enable structured append */
/* parameters */
#define QRCMD_PTR_TYPE QRStructured
#define QRCMD_EXTRA_PARAM_A int order = 0; int extra = 0;
#define QRCMD_EXTRA_PARAM_B , order
#define QRCMD_EXTRA_PARAM_C &order, &extra,
#define QRCMD_EXTRA_PARAM_D int *order, int *extra,
#define QRCMD_MAX_NUM_A int maxnum = QR_STA_MAX;
#define QRCMD_MAX_NUM_B maxnum,
#define QRCMD_DEFAULT_VERSION 1
/* functions */
#define qrCmdInit qrsInit
#define qrCmdDestroy qrsDestroy
#define qrCmdFinalize qrsFinalize
#define qrCmdGetErrorInfo qrsGetErrorInfo
#define qrCmdAddData qrsAddData
#define qrCmdAddData2 qrsAddData2
#define qrCmdOutputSymbol qrsOutputSymbols
#define qrCmdOutputSymbol2 qrsOutputSymbols2
/* others */
#ifndef QRCMD_PROG_NAME
#define QRCMD_PROG_NAME "qrs"
#endif
#ifndef QR_SA_SRC_MAX
#define QR_SA_SRC_MAX 112233
#endif
#define QRCMD_SRC_MAX QR_SA_SRC_MAX
/* }}} */
#else
/* {{{ disable structured append */
/* parameters */
#define QRCMD_PTR_TYPE QRCode
#define QRCMD_EXTRA_PARAM_A
#define QRCMD_EXTRA_PARAM_B
#define QRCMD_EXTRA_PARAM_C
#define QRCMD_EXTRA_PARAM_D
#define QRCMD_MAX_NUM_A
#define QRCMD_MAX_NUM_B
#define QRCMD_DEFAULT_VERSION -1
/* functions */
#define qrCmdInit qrInit
#define qrCmdDestroy qrDestroy
#define qrCmdFinalize qrFinalize
#define qrCmdGetErrorInfo qrGetErrorInfo
#define qrCmdAddData qrAddData
#define qrCmdAddData2 qrAddData2
#define qrCmdOutputSymbol qrOutputSymbol
#define qrCmdOutputSymbol2 qrOutputSymbol2
/* others */
#ifndef QRCMD_PROG_NAME
#define QRCMD_PROG_NAME "qr"
#endif
#define QRCMD_SRC_MAX QR_SRC_MAX
/* }}} */
#endif /* QRCMD_STRUCTURED_APPEND */
/* }}} */
/* {{{ function prototype declarations */
QRCMD_PTR_TYPE *
qrGetParameter(int argc, char **argv,
int *fmt, int *sep, int *mag, QRCMD_EXTRA_PARAM_D char **output);
void
qrShowHelp(void);
/* }}} */
#endif /* _QRCMD_H_ */

View File

@@ -0,0 +1,672 @@
/*
* QR Code Generator Library: Symbol Converters for Basic Output Formats
*
* Core routines were originally written by Junn Ohta.
* Based on qr.c Version 0.1: 2004/4/3 (Public Domain)
*
* @package libqr
* @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
* @copyright 2006-2013 Ryusuke SEKIYAMA
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#include "qrcnv.h"
/* {{{ utility macro */
#define repeat(m, n) for ((m) = 0; (m) < (n); (m)++)
/* }}} */
/* {{{ symbol writing macro */
#define qrInitRow(filler) { \
memset(rbuf, (filler), (size_t)rsize); \
rptr = rbuf; \
}
#define qrWriteRow(m, n) { \
wsize = (int)(rptr - rbuf); \
for ((m) = 0; (m) < (n); (m)++) { \
memcpy(sptr, rbuf, (size_t)wsize); \
sptr += wsize; \
} \
if (wsize < rsize) { \
*size -= (rsize - wsize) * (n); \
} \
}
/*
* シンボルを出力する際の定型作業をまとめたマクロ
*
* このマクロを呼び出す前に以下の4つのマクロをdefineし、
* 呼び出した後はundefする
* qrWriteBOR() 行頭を書き込む
* qrWriteEOR() 行末を書き込む
* qrWriteBLM(m, n) 明モジュールを書き込む
* qrWriteDKM(m, n) 暗モジュールを書き込む
*/
#define qrWriteSymbol(qr, filler) { \
/* 分離パターン (上) */ \
if (sepdim > 0) { \
qrInitRow(filler); \
qrWriteBOR(); \
qrWriteBLM(j, imgdim); \
qrWriteEOR(); \
qrWriteRow(i, sepdim); \
} \
for (i = 0; i < dim; i++) { \
/* 行を初期化 */ \
qrInitRow(filler); \
/* 行頭 */ \
qrWriteBOR(); \
/* 分離パターン (左) */ \
qrWriteBLM(j, sepdim); \
/* シンボル本体 */ \
for (j = 0; j < dim; j++) { \
if (qrIsBlack((qr), i, j)) { \
qrWriteDKM(jx, mag); \
} else { \
qrWriteBLM(jx, mag); \
} \
} \
/* 分離パターン (右) */ \
qrWriteBLM(j, sepdim); \
/* 行末 */ \
qrWriteEOR(); \
/* 行をmag回繰り返し書き込む */ \
qrWriteRow(ix, mag); \
} \
/* 分離パターン (下) */ \
if (sepdim > 0) { \
qrInitRow(filler); \
qrWriteBOR(); \
qrWriteBLM(j, imgdim); \
qrWriteEOR(); \
qrWriteRow(i, sepdim); \
} \
}
/* }}} */
/* {{{ Structured append symbol writing macro */
#define qrsWriteSymbols(st, filler) { \
for (k = 0; k < rows; k++) { \
/* 分離パターン (上) */ \
if (sepdim > 0) { \
qrInitRow(filler); \
qrWriteBOR(); \
qrWriteBLM(j, xdim); \
qrWriteEOR(); \
qrWriteRow(i, sepdim); \
} \
for (i = 0; i < dim; i++) { \
/* 行を初期化 */ \
qrInitRow(filler); \
/* 行頭 */ \
qrWriteBOR(); \
for (kx = 0; kx < cols; kx++) { \
/* 分離パターン (左) */ \
qrWriteBLM(j, sepdim); \
/* シンボル本体 */ \
if (order < 0) { \
pos = k + rows * kx; \
} else { \
pos = cols * k + kx; \
} \
if (pos < (st)->num) { \
for (j = 0; j < dim; j++) { \
if (qrIsBlack((st)->qrs[pos], i, j)) { \
qrWriteDKM(jx, mag); \
} else { \
qrWriteBLM(jx, mag); \
} \
} \
} else { \
qrWriteBLM(j, zdim); \
} \
} \
/* 分離パターン (右) */ \
qrWriteBLM(j, sepdim); \
/* 行末 */ \
qrWriteEOR(); \
/* 行をmag回繰り返し書き込む */ \
qrWriteRow(ix, mag); \
} \
} \
/* 分離パターン (下) */ \
if (sepdim > 0) { \
qrInitRow(filler); \
qrWriteBOR(); \
qrWriteBLM(j, xdim); \
qrWriteEOR(); \
qrWriteRow(i, sepdim); \
} \
}
/* }}} */
/* {{{ Digit formatted symbol writing macro */
#define qrWriteBOR_Digit()
#define qrWriteEOR_Digit() { *rptr++ = ' '; }
#define qrWriteBLM_Digit(m, n) { rptr += (n); }
#define qrWriteDKM_Digit(m, n) { repeat(m, n) { *rptr++ = '1'; } }
/* }}} */
/* {{{ Ascii art formatted symbol writing macro */
#define qrWriteBOR_ASCII()
#ifdef WIN32
#define qrWriteEOR_ASCII() { *rptr++ = '\r'; *rptr++ = '\n'; }
#else
#define qrWriteEOR_ASCII() { *rptr++ = '\n'; }
#endif
#ifdef _QRCNV_AA_STYLE_U2588
#define QRCNV_AA_UNIT 3
#define qrWriteBLM_ASCII(m, n) { rptr += (n) * 2; }
#define qrWriteDKM_ASCII(m, n) { repeat(m, n) { *rptr++ = 0xe2; *rptr++ = 0x96; *rptr++ = 0x88; } }
#else
#define QRCNV_AA_UNIT 2
#define qrWriteBLM_ASCII(m, n) { rptr += (n) * 2; }
#define qrWriteDKM_ASCII(m, n) { repeat(m, n) { *rptr++ = 'X'; *rptr++ = 'X'; } }
#endif
/* }}} */
/* {{{ JSON formatted symbol writing macro */
#define qrWriteBOR_JSON() { *rptr++ = '['; }
#define qrWriteEOR_JSON() { rptr--; *rptr++ = ']'; rptr++; }
#ifdef _QR_JSON_STYLE_BOOLELAN
#define QRCNV_JSON_UNIT 6
#define qrWriteBLM_JSON(m, n) { repeat(m, n) { memcpy(rptr, "false", 5); rptr += 6; } }
#define qrWriteDKM_JSON(m, n) { repeat(m, n) { memcpy(rptr, "true", 4); rptr += 5; } }
#else
#define QRCNV_JSON_UNIT 2
#define qrWriteBLM_JSON(m, n) { repeat(m, n) { *rptr++ = '0'; rptr++; } }
#define qrWriteDKM_JSON(m, n) { repeat(m, n) { *rptr++ = '1'; rptr++; } }
#endif
/* }}} */
/* {{{ PBM formatted symbol writing macro */
#define qrWriteBOR_PBM()
#define qrWriteEOR_PBM() { *rptr++ = '\n'; }
#define qrWriteBLM_PBM(m, n) { repeat(m, n) { rptr++; *rptr++ = '0'; } }
#define qrWriteDKM_PBM(m, n) { repeat(m, n) { rptr++; *rptr++ = '1'; } }
/* }}} */
/* {{{ qrSymbolToDigit() */
/*
* 生成されたQRコードシンボルを0,1と空白で構成される文字列に変換する
*/
QR_API qr_byte_t *
qrSymbolToDigit(QRCode *qr, int sep, int mag, int *size)
{
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, wsize;
int i, j, ix, jx, dim, imgdim, sepdim;
QRCNV_CHECK_STATE();
QRCNV_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
rsize = imgdim + 1;
*size = rsize * imgdim - 1;
QRCNV_MALLOC(rsize, *size + 1);
sptr = sbuf;
#define qrWriteBOR qrWriteBOR_Digit
#define qrWriteEOR qrWriteEOR_Digit
#define qrWriteBLM qrWriteBLM_Digit
#define qrWriteDKM qrWriteDKM_Digit
/*
* シンボルを書き込む
*/
qrWriteSymbol(qr, '0');
/*
* 最後の文字(スペース)を終端文字に置換する
*/
*(--sptr) = '\0';
#undef qrWriteBOR
#undef qrWriteEOR
#undef qrWriteBLM
#undef qrWriteDKM
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrSymbolToASCII() */
/*
* 生成されたQRコードシンボルを0,1と空白で構成される文字列に変換する
*/
QR_API qr_byte_t *
qrSymbolToASCII(QRCode *qr, int sep, int mag, int *size)
{
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, wsize;
int i, j, ix, jx, dim, imgdim, sepdim;
QRCNV_CHECK_STATE();
QRCNV_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
rsize = imgdim * QRCNV_AA_UNIT + QRCNV_EOL_SIZE;
*size = rsize * imgdim;
QRCNV_MALLOC(rsize, *size + 1);
sptr = sbuf;
#define qrWriteBOR qrWriteBOR_ASCII
#define qrWriteEOR qrWriteEOR_ASCII
#define qrWriteBLM qrWriteBLM_ASCII
#define qrWriteDKM qrWriteDKM_ASCII
/*
* シンボルを書き込む
*/
qrWriteSymbol(qr, ' ');
/*
* 終端文字を書き込む
*/
*sptr = '\0';
#undef qrWriteBOR
#undef qrWriteEOR
#undef qrWriteBLM
#undef qrWriteDKM
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrSymbolToJSON() */
/*
* 生成されたQRコードシンボルをJSON形式の文字列に変換する
* JSONをデコードすると二次元配列が得られる
*/
QR_API qr_byte_t *
qrSymbolToJSON(QRCode *qr, int sep, int mag, int *size)
{
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, wsize;
int i, j, ix, jx, dim, imgdim, sepdim;
QRCNV_CHECK_STATE();
QRCNV_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
rsize = 1 + imgdim * QRCNV_JSON_UNIT + 1;
*size = 1 + rsize * imgdim - 1 + 1;
QRCNV_MALLOC(rsize, *size + 1);
sptr = sbuf;
#define qrWriteBOR qrWriteBOR_JSON
#define qrWriteEOR qrWriteEOR_JSON
#define qrWriteBLM qrWriteBLM_JSON
#define qrWriteDKM qrWriteDKM_JSON
/*
* ヘッダを書き込む
*/
*sptr++ = '[';
/*
* シンボルを書き込む
*/
qrWriteSymbol(qr, ',');
/*
* フッタと終端文字を書き込む
*/
sptr--;
*sptr++ = ']';
*sptr = '\0';
#undef qrWriteBOR
#undef qrWriteEOR
#undef qrWriteBLM
#undef qrWriteDKM
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrSymbolToPBM() */
/*
* 生成されたQRコードシンボルをモクロ2値の
* アスキー形式Portable Bitmap(PBM)に変換する
*/
QR_API qr_byte_t *
qrSymbolToPBM(QRCode *qr, int sep, int mag, int *size)
{
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, wsize;
int i, j, ix, jx, dim, imgdim, sepdim;
char header[64];
int hsize;
QRCNV_CHECK_STATE();
QRCNV_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
hsize = snprintf(&(header[0]), sizeof(header), "P1\n%d %d\n", imgdim, imgdim);
if (hsize == -1 || header[hsize - 1] != '\n') {
QRCNV_RETURN_FAILURE(QR_ERR_UNKNOWN, _QR_FUNCTION);
}
rsize = imgdim * 2 + 1;
*size = hsize + rsize * imgdim;
QRCNV_MALLOC(rsize, *size + 1);
sptr = sbuf;
#define qrWriteBOR qrWriteBOR_PBM
#define qrWriteEOR qrWriteEOR_PBM
#define qrWriteBLM qrWriteBLM_PBM
#define qrWriteDKM qrWriteDKM_PBM
/*
* ヘッダを書き込む
*/
memcpy(sptr, header, (size_t)hsize);
sptr += hsize;
/*
* シンボルを書き込む
*/
qrWriteSymbol(qr, ' ');
/*
* 終端文字を書き込む
*/
*sptr = '\0';
#undef qrWriteBOR
#undef qrWriteEOR
#undef qrWriteBLM
#undef qrWriteDKM
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrsSymbolsToDigit() */
/*
* 構造的連接用qrSymbolToDigit()
* order は無視される
*/
QR_API qr_byte_t *
qrsSymbolsToDigit(QRStructured *st, int sep, int mag, int order, int *size)
{
QRCode *qr = st->cur;
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, wsize;
int i, j, k, ix, jx;
int cols, rows, xdim, ydim, zdim;
int dim, imgdim, sepdim;
QRCNV_SA_CHECK_STATE();
QRCNV_SA_IF_ONE(qrSymbolToDigit);
QRCNV_SA_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
rsize = imgdim + 1;
*size = rsize * imgdim * st->num - 1;
QRCNV_MALLOC(rsize, *size + 1);
sptr = sbuf;
#define qrWriteBOR qrWriteBOR_Digit
#define qrWriteEOR qrWriteEOR_Digit
#define qrWriteBLM qrWriteBLM_Digit
#define qrWriteDKM qrWriteDKM_Digit
/*
* シンボルを書き込む
*/
for (k = 0; k < st->num; k++) {
qrWriteSymbol(st->qrs[k], '0');
*(--sptr) = '\n';
sptr++;
}
/*
* 最後の文字(LF)を終端文字に置換する
*/
*(--sptr) = '\0';
#undef qrWriteBOR
#undef qrWriteEOR
#undef qrWriteBLM
#undef qrWriteDKM
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrsSymbolsToASCII() */
/*
* 構造的連接用qrSymbolToASCII()
*/
QR_API qr_byte_t *
qrsSymbolsToASCII(QRStructured *st, int sep, int mag, int order, int *size)
{
QRCode *qr = st->cur;
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, wsize;
int i, j, k, ix, jx, kx;
int cols, rows, pos, xdim, ydim, zdim;
int dim, imgdim, sepdim;
QRCNV_SA_CHECK_STATE();
QRCNV_SA_IF_ONE(qrSymbolToASCII);
QRCNV_SA_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
rsize = xdim * QRCNV_AA_UNIT + QRCNV_EOL_SIZE;
*size = rsize * ydim;
QRCNV_MALLOC(rsize, *size + 1);
sptr = sbuf;
#define qrWriteBOR qrWriteBOR_ASCII
#define qrWriteEOR qrWriteEOR_ASCII
#define qrWriteBLM qrWriteBLM_ASCII
#define qrWriteDKM qrWriteDKM_ASCII
/*
* シンボルを書き込む
*/
qrsWriteSymbols(st, ' ');
/*
* 終端文字を書き込む
*/
*sptr = '\0';
#undef qrWriteBOR
#undef qrWriteEOR
#undef qrWriteBLM
#undef qrWriteDKM
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrsSymbolsToJSON() */
/*
* 構造的連接用qrSymbolToJSON()
* order は無視される
*/
QR_API qr_byte_t *
qrsSymbolsToJSON(QRStructured *st, int sep, int mag, int order, int *size)
{
QRCode *qr = st->cur;
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, wsize;
int i, j, k, ix, jx;
int cols, rows, xdim, ydim, zdim;
int dim, imgdim, sepdim;
QRCNV_SA_CHECK_STATE();
/*QRCNV_SA_IF_ONE(qrSymbolToJSON);*/
QRCNV_SA_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
rsize = 1 + imgdim * QRCNV_JSON_UNIT + 1;
*size = 1 + (1 + rsize * imgdim + 1) * st->num - 1 + 1;
QRCNV_MALLOC(rsize, *size + 1);
sptr = sbuf;
#define qrWriteBOR qrWriteBOR_JSON
#define qrWriteEOR qrWriteEOR_JSON
#define qrWriteBLM qrWriteBLM_JSON
#define qrWriteDKM qrWriteDKM_JSON
/*
* ヘッダを書き込む
*/
*sptr++ = '[';
/*
* シンボルを書き込む
*/
for (k = 0; k < st->num; k++) {
*sptr++ = '[';
qrWriteSymbol(st->qrs[k], ',');
sptr--;
*sptr++ = ']';
*sptr++ = ',';
}
/*
* フッタと終端文字を書き込む
*/
sptr--;
*sptr++ = ']';
*sptr = '\0';
#undef qrWriteBOR
#undef qrWriteEOR
#undef qrWriteBLM
#undef qrWriteDKM
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrsSymbolsToPBM() */
/*
* 構造的連接用qrSymbolToPBM()
*/
QR_API qr_byte_t *
qrsSymbolsToPBM(QRStructured *st, int sep, int mag, int order, int *size)
{
QRCode *qr = st->cur;
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, wsize;
int i, j, k, ix, jx, kx;
int cols, rows, pos, xdim, ydim, zdim;
int dim, imgdim, sepdim;
char header[64];
int hsize;
QRCNV_SA_CHECK_STATE();
QRCNV_SA_IF_ONE(qrSymbolToPBM);
QRCNV_SA_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
hsize = snprintf(&(header[0]), 64, "P1\n%d %d\n", xdim, ydim);
if (hsize >= 64) {
QRCNV_RETURN_FAILURE(QR_ERR_UNKNOWN, _QR_FUNCTION);
}
rsize = xdim * 2 + 1;
*size = hsize + rsize * ydim;
QRCNV_MALLOC(rsize, *size + 1);
sptr = sbuf;
#define qrWriteBOR qrWriteBOR_PBM
#define qrWriteEOR qrWriteEOR_PBM
#define qrWriteBLM qrWriteBLM_PBM
#define qrWriteDKM qrWriteDKM_PBM
/*
* ヘッダを書き込む
*/
memcpy(sptr, header, (size_t)hsize);
sptr += hsize;
/*
* シンボルを書き込む
*/
qrsWriteSymbols(st, ' ');
/*
* 終端文字を付加する
*/
*sptr = '\0';
#undef qrWriteBOR
#undef qrWriteEOR
#undef qrWriteBLM
#undef qrWriteDKM
free(rbuf);
return sbuf;
}
/* }}} */

View File

@@ -0,0 +1,165 @@
/*
* QR Code Generator Library: Private Definitions for Symbol Converters
*
* Core routines were originally written by Junn Ohta.
* Based on qr.c Version 0.1: 2004/4/3 (Public Domain)
*
* @package libqr
* @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
* @copyright 2006-2013 Ryusuke SEKIYAMA
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#ifndef _QRCNV_H_
#define _QRCNV_H_
/* {{{ include headers */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "qr.h"
#include "qr_util.h"
#include <math.h>
#include <stdlib.h>
#include <string.h>
/* }}} */
/* {{{ determine EOL size (CR+LF or LF) */
#ifdef WIN32
#define QRCNV_EOL_SIZE 2
#else
#define QRCNV_EOL_SIZE 1
#endif
/* }}} */
/* {{{ error handlers */
#define QRCNV_RETURN_FAILURE(e, p) { \
qrSetErrorInfo(qr, (e), (p)); \
if (size) { \
*size = -1; \
} \
return NULL; \
}
#define QRCNV_RETURN_FAILURE2(e, p) { \
qrSetErrorInfo2(qr, (e), (p)); \
if (size) { \
*size = -1; \
} \
return NULL; \
}
#define QRCNV_RETURN_FAILURE3(e, p, ...) { \
qrSetErrorInfo3(qr, (e), (p), __VA_ARGS__); \
if (size) { \
*size = -1; \
} \
return NULL; \
}
/* }}} */
/* {{{ allocate memory for the working rowl and the symbo */
#define QRCNV_MALLOC(rsize, ssize) { \
rbuf = (qr_byte_t *)malloc((size_t)(rsize)); \
if (rbuf == NULL) { \
QRCNV_RETURN_FAILURE2(QR_ERR_MEMORY_EXHAUSTED, _QR_FUNCTION); \
} \
sbuf = (qr_byte_t *)malloc((size_t)(ssize)); \
if (sbuf == NULL) { \
free(rbuf); \
QRCNV_RETURN_FAILURE2(QR_ERR_MEMORY_EXHAUSTED, _QR_FUNCTION); \
} \
}
/* }}} */
/* {{{ check the state and the parameters */
#define QRCNV_CHECK_STATE() { \
if (qr->state < QR_STATE_FINAL) { \
QRCNV_RETURN_FAILURE(QR_ERR_STATE, _QR_FUNCTION); \
} \
}
#define QRCNV_GET_SIZE() { \
if (sep != -1 && (sep < 0 || mag > QR_SEP_MAX)) { \
QRCNV_RETURN_FAILURE3(QR_ERR_INVALID_SEP, ": %d", sep); \
} \
if (mag <= 0 || mag > QR_MAG_MAX) { \
QRCNV_RETURN_FAILURE3(QR_ERR_INVALID_MAG, ": %d", mag); \
} \
dim = qr_vertable[qr->param.version].dimension; \
if (sep == -1) { \
sepdim = QR_DIM_SEP * mag; \
} else { \
sepdim = sep * mag; \
} \
imgdim = dim * mag + sepdim * 2; \
}
/* }}} */
/* {{{ check the state and the parameters (structured append) */
#define QRCNV_SA_CHECK_STATE() { \
if (st->state < QR_STATE_FINAL) { \
QRCNV_RETURN_FAILURE(QR_ERR_STATE, _QR_FUNCTION); \
} \
}
#define QRCNV_SA_GET_SIZE() { \
if (sep != -1 && (sep < 0 || mag > QR_SEP_MAX)) { \
QRCNV_RETURN_FAILURE3(QR_ERR_INVALID_SEP, ": %d", sep); \
} \
if (mag <= 0 || mag > QR_MAG_MAX) { \
QRCNV_RETURN_FAILURE3(QR_ERR_INVALID_MAG, ": %d", mag); \
} \
dim = qr_vertable[st->param.version].dimension; \
if (sep == -1) { \
sepdim = QR_DIM_SEP * mag; \
} else { \
sepdim = sep * mag; \
} \
zdim = dim * mag; \
imgdim = zdim + sepdim * 2; \
if (order > 0) { \
if (st->num > order) { \
cols = order; \
rows = (st->num + order - 1) / cols; \
} else { \
cols = st->num; \
rows = 1; \
} \
} else if (order < 0) { \
int _a; \
_a = abs(order); \
if (st->num > _a) { \
rows = _a; \
cols = (st->num + _a - 1) / rows; \
} else { \
cols = 1; \
rows = st->num; \
} \
} else { \
double _r; \
_r = sqrt((double)st->num); \
cols = (int)ceil(_r); \
rows = (int)floor(_r); \
if (cols * rows < st->num) { \
rows = (int)ceil(_r); \
} \
} \
xdim = (zdim + sepdim) * cols + sepdim; \
ydim = (zdim + sepdim) * rows + sepdim; \
}
#define QRCNV_SA_IF_ONE(func) { \
if (st->num == 1) { \
return (func)(st->qrs[0], sep, mag, size); \
} \
}
#endif /* _QRCNV_H_ */

View File

@@ -0,0 +1,324 @@
/*
* QR Code Generator Library: Symbol Converters for Windows Bitmap
*
* Core routines were originally written by Junn Ohta.
* Based on qr.c Version 0.1: 2004/4/3 (Public Domain)
*
* @package libqr
* @author Ryusuke SEKIYAMA <rsky0711@gmail.com>
* @copyright 2006-2013 Ryusuke SEKIYAMA
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
#include "qrcnv.h"
#if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)
#include <stdint.h>
#endif
/* {{{ size constants */
#define QRCNV_BMP_BISIZE 40 /* Windows Bitmap */
#define QRCNV_BMP_OFFBITS 62 /* 14(bf) + 40(bi) + 4(rgbq) + 4(rgbq) */
#define QRCNV_BMP_PPM 3780 /* 96 dpi ~= 3780 ppm */
/* 72 dpi ~= 2835 ppm */
/* }}} */
/* {{{ utility macro */
#if defined(__BIG_ENDIAN__)
#define qrBmpWriteShort(ptr, n) { \
uint16_t us = (uint16_t)((n) & 0xffffU); \
qr_byte_t *tmp = (qr_byte_t *)&us; \
*(ptr)++ = tmp[1]; \
*(ptr)++ = tmp[0]; \
}
#elif defined(__LITTLE_ENDIAN__)
#define qrBmpWriteShort(ptr, n) { \
uint16_t us = (uint16_t)((n) & 0xffffU); \
qr_byte_t *tmp = (qr_byte_t *)&us; \
*(ptr)++ = tmp[0]; \
*(ptr)++ = tmp[1]; \
}
#else
#define qrBmpWriteShort(ptr, n) { \
*(ptr)++ = (n) & 0xffU; \
*(ptr)++ = ((n) >> 8) & 0xffU; \
}
#endif
#if defined(__BIG_ENDIAN__)
#define qrBmpWriteLong(ptr, n) { \
uint32_t ul = (uint32_t)(n); \
qr_byte_t *tmp = (qr_byte_t *)&ul; \
*(ptr)++ = tmp[3]; \
*(ptr)++ = tmp[2]; \
*(ptr)++ = tmp[1]; \
*(ptr)++ = tmp[0]; \
}
#elif defined(__LITTLE_ENDIAN__)
#define qrBmpWriteLong(ptr, n) { \
uint32_t ul = (uint32_t)(n); \
qr_byte_t *tmp = (qr_byte_t *)&ul; \
*(ptr)++ = tmp[0]; \
*(ptr)++ = tmp[1]; \
*(ptr)++ = tmp[2]; \
*(ptr)++ = tmp[3]; \
}
#else
#define qrBmpWriteLong(ptr, n) { \
*(ptr)++ = (n) & 0xffU; \
*(ptr)++ = ((n) >> 8) & 0xffU; \
*(ptr)++ = ((n) >> 16) & 0xffU; \
*(ptr)++ = ((n) >> 24) & 0xffU; \
}
#endif
#define qrBmpNextPixel() { \
if (pxshift == 0) { \
rptr++; \
pxshift = 7; \
} else { \
pxshift--; \
} \
}
/* }}} */
/* {{{ function prototypes */
static qr_byte_t *
qrBmpWriteHeader(qr_byte_t *bof, int size, int width, int height, int imagesize);
/* }}} */
/* {{{ qrSymbolToBMP() */
/*
* 生成されたQRコードシンボルをモクロ2値の
* Windows Bitmap(BMP)に変換する
*/
QR_API qr_byte_t *
qrSymbolToBMP(QRCode *qr, int sep, int mag, int *size)
{
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, rmod, imgsize;
int sepskips, pxshift;
int i, j, ix, jx, dim, imgdim, sepdim;
QRCNV_CHECK_STATE();
QRCNV_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
rsize = (imgdim + 7) / 8;
if ((rmod = (rsize % 4)) != 0) {
rsize += 4 - rmod;
}
imgsize = rsize * imgdim;
*size = QRCNV_BMP_OFFBITS + imgsize;
QRCNV_MALLOC(rsize, *size);
/*
* ヘッダを書き込む
*/
sptr = qrBmpWriteHeader(sbuf, *size, imgdim, imgdim, imgsize);
/*
* シンボルを書き込む
*/
sepskips = rsize * sepdim;
/* 分離パターン (下) */
if (sepskips) {
memset(sptr, 0, (size_t)sepskips);
sptr += sepskips;
}
for (i = dim - 1; i >= 0; i--) {
memset(rbuf, 0, (size_t)rsize);
pxshift = 7;
rptr = rbuf;
/* 分離パターン (左) */
for (j = 0; j < sepdim; j++) {
qrBmpNextPixel();
}
/* シンボル本体 */
for (j = 0; j < dim; j++) {
if (qrIsBlack(qr, i, j)) {
for (jx = 0; jx < mag; jx++) {
*rptr |= 1 << pxshift;
qrBmpNextPixel();
}
} else {
for (jx = 0; jx < mag; jx++) {
qrBmpNextPixel();
}
}
}
/* 行をmag回繰り返し書き込む */
for (ix = 0; ix < mag; ix++) {
memcpy(sptr, rbuf, (size_t)rsize);
sptr += rsize;
}
}
/* 分離パターン (上) */
if (sepskips) {
memset(sptr, 0, (size_t)sepskips);
sptr += sepskips;
}
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrsSymbolsToBMP() */
/*
* 構造的連接用qrSymbolToBMP()
*/
QR_API qr_byte_t *
qrsSymbolsToBMP(QRStructured *st, int sep, int mag, int order, int *size)
{
QRCode *qr = st->cur;
qr_byte_t *rbuf, *rptr;
qr_byte_t *sbuf, *sptr;
int rsize, rmod, imgsize;
int sepskips, pxshift;
int i, j, k, ix, jx, kx;
int cols, rows, pos, xdim, ydim, zdim;
int dim, imgdim, sepdim;
QRCNV_SA_CHECK_STATE();
QRCNV_SA_IF_ONE(qrSymbolToBMP);
QRCNV_SA_GET_SIZE();
/*
* 変換後のサイズを計算し、メモリを確保する
*/
rsize = (xdim + 7) / 8;
if ((rmod = (rsize % 4)) != 0) {
rsize += 4 - rmod;
}
imgsize = rsize * ydim;
*size = QRCNV_BMP_OFFBITS + imgsize;
QRCNV_MALLOC(rsize, *size);
/*
* ヘッダを書き込む
*/
sptr = qrBmpWriteHeader(sbuf, *size, xdim, ydim, imgsize);
/*
* シンボルを書き込む
*/
sepskips = rsize * sepdim;
for (k = rows - 1; k >= 0; k--) {
/* 分離パターン (下) */
if (sepskips) {
memset(sptr, 0, (size_t)sepskips);
sptr += sepskips;
}
for (i = dim - 1; i >= 0; i--) {
memset(rbuf, 0, (size_t)rsize);
pxshift = 7;
rptr = rbuf;
for (kx = 0; kx < cols; kx++) {
/* 分離パターン (左) */
for (j = 0; j < sepdim; j++) {
qrBmpNextPixel();
}
/* シンボル本体 */
if (order < 0) {
pos = k + rows * kx;
} else {
pos = cols * k + kx;
}
if (pos >= st->num) {
break;
}
for (j = 0; j < dim; j++) {
if (qrIsBlack(st->qrs[pos], i, j)) {
for (jx = 0; jx < mag; jx++) {
*rptr |= 1 << pxshift;
qrBmpNextPixel();
}
} else {
for (jx = 0; jx < mag; jx++) {
qrBmpNextPixel();
}
}
}
}
/* 行をmag回繰り返し書き込む */
for (ix = 0; ix < mag; ix++) {
memcpy(sptr, rbuf, (size_t)rsize);
sptr += rsize;
}
}
}
/* 分離パターン (上) */
if (sepskips) {
memset(sptr, 0, (size_t)sepskips);
sptr += sepskips;
}
free(rbuf);
return sbuf;
}
/* }}} */
/* {{{ qrBmpWriteHeader() */
static qr_byte_t *
qrBmpWriteHeader(qr_byte_t *bof, int size, int width, int height, int imagesize)
{
qr_byte_t *ptr;
ptr = bof;
/*
* BITMAPFILEHEADER
*/
*ptr++ = 'B'; /* bfType */
*ptr++ = 'M'; /* bfType */
qrBmpWriteLong(ptr, size); /* bfSize */
qrBmpWriteShort(ptr, 0); /* bfReserved1 */
qrBmpWriteShort(ptr, 0); /* bfReserved2 */
qrBmpWriteLong(ptr, QRCNV_BMP_OFFBITS); /* bfOffBits */
/*
* BMPINFOHEADER
*/
qrBmpWriteLong(ptr, QRCNV_BMP_BISIZE); /* biSize */
qrBmpWriteLong(ptr, width); /* biWidth */
qrBmpWriteLong(ptr, height); /* biHeight */
qrBmpWriteShort(ptr, 1); /* biPlanes */
qrBmpWriteShort(ptr, 1); /* biBitCount - 1 bit per pixel */
qrBmpWriteLong(ptr, 0); /* biCopmression - BI_RGB */
qrBmpWriteLong(ptr, imagesize); /* biSizeImage */
qrBmpWriteLong(ptr, QRCNV_BMP_PPM); /* biXPixPerMeter */
qrBmpWriteLong(ptr, QRCNV_BMP_PPM); /* biYPixPerMeter */
qrBmpWriteLong(ptr, 2); /* biClrUsed */
qrBmpWriteLong(ptr, 2); /* biCirImportant */
/*
* RGBQUAD - white
*/
*ptr++ = 255; /* rgbBlue */
*ptr++ = 255; /* rgbGreen */
*ptr++ = 255; /* rgbRed */
*ptr++ = 0; /* rgbReserved */
/*
*RGBQUAD - black
*/
*ptr++ = 0; /* rgbBlue */
*ptr++ = 0; /* rgbGreen */
*ptr++ = 0; /* rgbRed */
*ptr++ = 0; /* rgbReserved */
return ptr;
}
/* }}} */

View File

@@ -0,0 +1,682 @@
#include "oled_ctrl.h"
using namespace maix;
using namespace maix::sys;
using namespace maix::peripheral;
i2c::I2C oled_alpha(1, i2c::Mode::MASTER);
i2c::I2C oled_beta(5, i2c::Mode::MASTER);
uint8_t OLED_state = 0;
uint8_t kvm_hw_ver = 0;
/* mode = OLED_CMD
* = OLED_DATA */
void oled_write_register(uint8_t mode, uint8_t data)
{
if(OLED_state){
uint8_t buf[2];
buf[0] = mode;
buf[1] = data;
if(kvm_hw_ver == 0){
if(oled_alpha.writeto(OLED_ADDR, buf, 2) == (int)-err::Err::ERR_IO){
return;
}
} else if(kvm_hw_ver == 1){
if(oled_beta.writeto(OLED_ADDR, buf, 2) == (int)-err::Err::ERR_IO){
return;
}
} else if(kvm_hw_ver == 2){
if(oled_beta.writeto(OLED_PCIe_ADDR, buf, 2) == (int)-err::Err::ERR_IO){
return;
}
}
return;
}
return;
}
int oled_exist(void)
{
// gpio::GPIO oled_rst("GPIOP19", gpio::Mode::OUT, gpio::Pull::PULL_UP);
// oled_rst.high();
// system("devmem 0x030010D4 32 0x3");
// system("devmem 0x030010D0 32 0x2");
// system("devmem 0x030010DC 32 0x2");
if(access("/etc/kvm/hw", F_OK) == 0){
uint8_t RW_Data[2];
FILE *fp = fopen("/etc/kvm/hw", "r");
fread(RW_Data, sizeof(char), 2, fp);
fclose(fp);
if(RW_Data[0] == 'b') kvm_hw_ver = 1;
else if(RW_Data[0] == 'p') kvm_hw_ver = 2;
}
uint8_t buf[2];
buf[0] = OLED_CMD;
buf[1] = 0xAE;
if(kvm_hw_ver == 0){
if(oled_alpha.writeto(OLED_ADDR, buf, 2) == (int)-err::Err::ERR_IO){
return 0;
}
} else if(kvm_hw_ver == 1){
printf("beta\r\n");
if(oled_beta.writeto(OLED_ADDR, buf, 2) == (int)-err::Err::ERR_IO){
return 0;
}
} else if(kvm_hw_ver == 2){
printf("PCIe\r\n");
if(oled_beta.writeto(OLED_PCIe_ADDR, buf, 2) == (int)-err::Err::ERR_IO){
return 0;
}
}
return 1;
}
// 坐标设置
void OLED_Set_Pos(uint8_t x, uint8_t y)
{
// oled_write_register(OLED_CMD, 0xb0+y);
// oled_write_register(OLED_CMD, ((x&0xf0)>>4)|0x10);
// oled_write_register(OLED_CMD, (x&0x0f));
if(kvm_hw_ver == 2){
x += 32;
y += 8;
}
oled_write_register(OLED_CMD, 0xb0+y);
oled_write_register(OLED_CMD, ((x&0xf0)>>4)|0x10);
oled_write_register(OLED_CMD, (x&0x0f));
}
//开启OLED显示
void OLED_Display_On()
{
oled_write_register(OLED_CMD, 0X8D);
oled_write_register(OLED_CMD, 0X14);
oled_write_register(OLED_CMD, 0XAF);
}
//关闭OLED显示
void OLED_Display_Off()
{
oled_write_register(OLED_CMD, 0X8D);
oled_write_register(OLED_CMD, 0X10);
oled_write_register(OLED_CMD, 0XAE);
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
oled_write_register(OLED_CMD, 0xb0+i);
oled_write_register(OLED_CMD, 0x00);
oled_write_register(OLED_CMD, 0x10);
for(n=0;n<128;n++)oled_write_register(OLED_DATA, 0x00);
} //更新显示
}
void OLED_Fill(void)
{
uint8_t i,n;
for(i=0;i<8;i++)
{
oled_write_register(OLED_CMD, 0xb0+i);
oled_write_register(OLED_CMD, 0x00);
oled_write_register(OLED_CMD, 0x10);
for(n=0;n<128;n++)oled_write_register(OLED_DATA, 0xFF);
} //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//sizey:选择字体 6x8 8x16
void OLED_ShowChar(uint8_t x,uint8_t y,char chr,uint8_t sizey)
{
uint8_t c=0,sizex=sizey/2;
uint16_t i=0,size1;
if(sizey==8)size1=6;
else if(sizey==4)size1=4;
else size1=(sizey/8+((sizey%8)?1:0))*(sizey/2);
c=chr-' ';//得到偏移后的值
OLED_Set_Pos(x, y);
for(i=0; i<size1; i++)
{
if(i%sizex==0&&sizey==16) OLED_Set_Pos(x, y++);
if(sizey==8) oled_write_register(OLED_DATA, oled_asc2_0806[c][i]); //6X8字号
else if(sizey==16) oled_write_register(OLED_DATA, oled_asc2_1608[c][i]);//8x16字号
else if(sizey==4) oled_write_register(OLED_DATA, oled_asc2_0804[c][i]);//8x4字号
else return;
}
}
void OLED_ShowCharTurn(uint8_t x,uint8_t y,char chr,uint8_t sizey)
{
uint8_t c=0,sizex=sizey/2;
uint16_t i=0,size1;
if(sizey==8)size1=6;
else size1=(sizey/8+((sizey%8)?1:0))*(sizey/2);
c=chr-' ';//得到偏移后的值
OLED_Set_Pos(x, y);
for(i=0; i<size1; i++)
{
if(i%sizex==0&&sizey!=8) OLED_Set_Pos(x, y++);
if(sizey==8) oled_write_register(OLED_DATA, ~oled_asc2_0806[c][i]); //6X8字号
else if(sizey==16) oled_write_register(OLED_DATA, ~oled_asc2_1608[c][i]);//8x16字号
else return;
}
}
void OLED_ShowError(uint8_t x,uint8_t y,uint8_t _state)
{
uint8_t i;
if(_state){
OLED_Set_Pos(x, y);
for(i=0; i<6; i++)
{
oled_write_register(OLED_DATA, etherror[i]);
}
} else {
OLED_ShowString(28, 3, " ", 8);
}
}
uint32_t oled_pow(uint8_t m,uint8_t n)
{
uint32_t result=1;
while(n--)result*=m;
return result;
}
//显示数字
//x,y :起点坐标
//num:要显示的数字
//len :数字的位数
//sizey:字体大小
void OLED_ShowNum(uint8_t x, uint8_t y, uint8_t num, uint8_t len, uint8_t sizey)
{
uint8_t t, temp, m = 0;
uint8_t enshow = 0;
if(sizey == 8) m = 2;
for(t=0; t<len; t++)
{
temp = (num / oled_pow(10,len-t-1)) % 10;
if(enshow == 0 && t < (len-1))
{
if(temp == 0)
{
OLED_ShowChar(x+(sizey/2+m)*t, y, ' ',sizey);
continue;
} else enshow=1;
}
OLED_ShowChar(x+(sizey/2+m)*t, y, temp+'0', sizey);
}
}
//显示一个字符号串
void OLED_ShowString(uint8_t x, uint8_t y, char *chr, uint8_t sizey)
{
uint8_t j=0;
while (chr[j]!='\0')
{
OLED_ShowChar(x, y, chr[j++], sizey);
if(sizey==8)x+=6;
else if(sizey==4)x+=4;
else x+=sizey/2;
}
}
//反显一个字符号串
void OLED_ShowStringTurn(uint8_t x, uint8_t y, char *chr, uint8_t sizey)
{
uint8_t j=0;
while (chr[j]!='\0')
{
OLED_ShowCharTurn(x, y, chr[j++], sizey);
if(sizey==8)x+=6;
else x+=sizey/2;
}
}
//反显函数
void OLED_ColorTurn(uint8_t i)
{
if(i==0)
{
oled_write_register(OLED_CMD, 0xA6); //正常显示
}
if(i==1)
{
oled_write_register(OLED_CMD, 0xA7);//反色显示
}
}
//屏幕旋转180度
void OLED_DisplayTurn(uint8_t i)
{
if(i==0)
{
oled_write_register(OLED_CMD, 0xC8);//正常显示
oled_write_register(OLED_CMD, 0xA1);
}
if(i==1)
{
oled_write_register(OLED_CMD, 0xC0);//反转显示
oled_write_register(OLED_CMD, 0xA0);
}
}
//初始化
void OLED_Init(void)
{
// pinmap::set_pin_function("A19", "GPIOP19");
// OLED_RES_Clr();
// delay_ms(200);
// OLED_RES_Set();
oled_write_register(OLED_CMD, 0xAE);//--turn off oled_alpha panel
oled_write_register(OLED_CMD, 0x00);//---set low column address
oled_write_register(OLED_CMD, 0x10);//---set high column address
oled_write_register(OLED_CMD, 0x40);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)
oled_write_register(OLED_CMD, 0x81);//--set contrast control register
oled_write_register(OLED_CMD, 0xCF);// Set SEG Output Current Brightness
oled_write_register(OLED_CMD, 0xA1);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常
oled_write_register(OLED_CMD, 0xC8);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常
oled_write_register(OLED_CMD, 0xA6);//--set normal display
oled_write_register(OLED_CMD, 0xA8);//--set multiplex ratio(1 to 64)
oled_write_register(OLED_CMD, 0x3f);//--1/64 duty
oled_write_register(OLED_CMD, 0xD3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
oled_write_register(OLED_CMD, 0x00);//-not offset
oled_write_register(OLED_CMD, 0xd5);//--set display clock divide ratio/oscillator frequency
oled_write_register(OLED_CMD, 0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
oled_write_register(OLED_CMD, 0xD9);//--set pre-charge period
oled_write_register(OLED_CMD, 0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
oled_write_register(OLED_CMD, 0xDA);//--set com pins hardware configuration
oled_write_register(OLED_CMD, 0x12);//
oled_write_register(OLED_CMD, 0xDB);//--set vcomh
oled_write_register(OLED_CMD, 0x40);//Set VCOM Deselect Level
oled_write_register(OLED_CMD, 0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
oled_write_register(OLED_CMD, 0x02);//
oled_write_register(OLED_CMD, 0x8D);//--set Charge Pump enable/disable
oled_write_register(OLED_CMD, 0x14);//--set(0x10) disable
oled_write_register(OLED_CMD, 0xA4);// Disable Entire Display On (0xa4/0xa5)
oled_write_register(OLED_CMD, 0xA6);// Disable Inverse Display On (0xa6/a7)
OLED_Clear();
oled_write_register(OLED_CMD, 0xAF); /*display ON*/
}
void OLED_ShowStringtoend(uint8_t x, uint8_t y, char *chr, uint8_t sizey, uint8_t end)
{
uint8_t j=0;
while (chr[j] != end)
{
OLED_ShowChar(x, y, chr[j++], sizey);
if(sizey==8)x+=6;
else x+=sizey/2;
}
}
void OLED_ROW(uint8_t _EN)
{
if(_EN){
oled_write_register(OLED_CMD, 0x2e); //关闭滚动
oled_write_register(OLED_CMD, 0x27); //水平向左或者右滚动 26/27
oled_write_register(OLED_CMD, 0x00); //虚拟字节
oled_write_register(OLED_CMD, 0x00); //起始页 0
oled_write_register(OLED_CMD, 0x07); //滚动时间间隔
oled_write_register(OLED_CMD, 0x07); //终止页 7
oled_write_register(OLED_CMD, 0x0f); //虚拟字节
oled_write_register(OLED_CMD, 0x7f); //虚拟字节
oled_write_register(OLED_CMD, 0x2f); //开启滚动
} else {
oled_write_register(OLED_CMD, 0x2e); //关闭滚动
}
}
void OLED_ShowState(uint8_t x,uint8_t y,char chr,uint8_t size)
{
uint16_t i=0;
OLED_Set_Pos(x, y);
for(i=0; i<size; i++)
{
oled_write_register(OLED_DATA, oled_kvm_0621[chr][i]);
}
}
void OLED_ShowLogo()
{
uint16_t i=0;
uint8_t x = 20;
uint8_t y = 0;
for(i=0; i<116; i++)
{
if(i%2==0){
x++;
y = 0;
} else {
y = 1;
}
OLED_Set_Pos(x, y);
oled_write_register(OLED_DATA, oled_kvm_logo[i]);
}
}
void OLED_Showline_1()
{
uint16_t i=0;
uint8_t x = 17;
uint8_t y = 0;
for(i=112; i<116; i++)
{
if(i%2==0){
x++;
y = 0;
} else {
y = 1;
}
OLED_Set_Pos(x, y);
oled_write_register(OLED_DATA, oled_kvm_logo[i]);
}
}
void OLED_ShowSipeedLogo()
{
uint16_t i=0;
uint8_t x = 0;
uint8_t y = 0;
uint8_t start_position = 0;
if(kvm_hw_ver == 2) start_position = 4;
for(i = start_position; i < 32; i++)
{
if(i%2==0){
x++;
y = 0;
} else {
y = 1;
}
OLED_Set_Pos(x, y);
oled_write_register(OLED_DATA, oled_sipeed_logo[i]);
}
}
void OLED_Showline()
{
uint8_t x = 3;
uint8_t y = 2;
for(y = 2; y < 8; y++){
OLED_Set_Pos(x, y);
if(y == 2){
oled_write_register(OLED_DATA, 0xC0);
oled_write_register(OLED_DATA, 0xC0);
oled_write_register(OLED_DATA, 0xC0);
} else {
oled_write_register(OLED_DATA, 0xFF);
oled_write_register(OLED_DATA, 0xFF);
oled_write_register(OLED_DATA, 0xFF);
}
}
}
void OLED_ShowString_AlignRight(uint8_t x_end, uint8_t y, char *chr, uint8_t size)
{
uint8_t j = 0;
uint8_t x = x_end;
while(chr[j] != '\0'){
j ++;
}
while (j)
{
if(size == 8) x -= 6;
else x -= 4;
OLED_ShowChar(x, y, chr[j-1], size);
j --;
}
}
void OLED_Revolve(void)
{
oled_write_register(OLED_CMD, 0xA0);
oled_write_register(OLED_CMD, 0xC0);
}
void OLED_ShowIMG(uint8_t x,uint8_t y,char *chr,uint8_t width,uint8_t height)
{
uint16_t size = width * height;
for(int count = 0; count < size; count++){
if(count%width == 0){
OLED_Set_Pos(x, y+(count/width));
}
oled_write_register(OLED_DATA, chr[count]);
}
}
void OLED_ShowKVMStreamState(uint8_t kvm_state_s, void* pdata)
{
switch(kvm_state_s){
case KVM_INIT:
if(kvm_hw_ver != 2){
OLED_ShowString(10, 3, "IP: ", 8);
OLED_ShowString(10, 4, "RES: ", 8);
OLED_ShowString(10, 5, "TYPE: ", 8);
OLED_ShowString(10, 6, "STREAM: ", 8);
OLED_ShowString(10, 7, "QUALITY: ", 8);
}
break;
case KVM_ETH_IP:
if(kvm_hw_ver != 2)
OLED_ShowString(10, 3, "IP: ", 8);
// OLED_ShowString(10, 3, "ETH: ", 8);
else
OLED_ShowString_AlignRight(AlignRightEND_P, 2, " ", 4);
if(*(char*)pdata != 0){
if(kvm_hw_ver != 2)
OLED_ShowString_AlignRight(AlignRightEND, 3, (char*)pdata, 8);
else{
OLED_ShowString(0, 2, "E", 4);
OLED_ShowString_AlignRight(AlignRightEND_P, 2, (char*)pdata, 4);
}
} else {
if(kvm_hw_ver != 2)
OLED_ShowString_AlignRight(AlignRightEND, 3, "--", 8);
else{
OLED_ShowString(0, 2, "E", 4);
OLED_ShowString_AlignRight(AlignRightEND_P, 2, "--", 4);
}
}
break;
case KVM_WIFI_IP:
if(kvm_hw_ver != 2)
OLED_ShowString(10, 3, "W: ", 8);
else
OLED_ShowString_AlignRight(AlignRightEND_P, 2, " ", 4);
if(*(char*)pdata != 0){
if(kvm_hw_ver != 2)
OLED_ShowString_AlignRight(AlignRightEND, 3, (char*)pdata, 8);
else{
OLED_ShowString(0, 2, "W", 4);
OLED_ShowString_AlignRight(AlignRightEND_P, 2, (char*)pdata, 4);
}
} else {
if(kvm_hw_ver != 2)
OLED_ShowString_AlignRight(AlignRightEND, 3, "--", 8);
else {
OLED_ShowString(0, 2, "W", 4);
OLED_ShowString_AlignRight(AlignRightEND_P, 2, "--", 4);
}
}
break;
case KVM_HDMI_RES:
break;
// if(kvm_hw_ver != 2){
// OLED_ShowString(10, 4, "RES: ", 8);
// switch (*(uint8_t*)pdata)
// {
// case KVM_RES_none:
// OLED_ShowString_AlignRight(AlignRightEND, 4, "--", 8);
// break;
// case KVM_RES_480P:
// OLED_ShowString_AlignRight(AlignRightEND, 4, "480P", 8);
// break;
// case KVM_RES_600P:
// OLED_ShowString_AlignRight(AlignRightEND, 4, "600P", 8);
// break;
// case KVM_RES_720P:
// OLED_ShowString_AlignRight(AlignRightEND, 4, "720P", 8);
// break;
// case KVM_RES_1080P:
// OLED_ShowString_AlignRight(AlignRightEND, 4, "1080P", 8);
// break;
// default:
// OLED_ShowString_AlignRight(AlignRightEND, 4, "--", 8);
// break;
// }
// }
break;
case KVM_STEAM_TYPE:
if(kvm_hw_ver != 2){
OLED_ShowString(10, 5, "TYPE: ", 8);
switch (*(uint8_t*)pdata)
{
case KVM_TYPE_MJPG:
OLED_ShowString_AlignRight(AlignRightEND, 5, "MJPG", 8);
break;
case KVM_TYPE_H264:
OLED_ShowString_AlignRight(AlignRightEND, 5, "H264", 8);
break;
default:
OLED_ShowString_AlignRight(AlignRightEND, 5, "--", 8);
break;
}
}
break;
case KVM_STEAM_FPS:
// OLED_ShowString(10, 6, "STREAM: ", 8);
if(kvm_hw_ver != 2){
OLED_ShowString_AlignRight(AlignRightEND, 6, "FPS", 8);
OLED_ShowNum(88, 6, *(uint8_t*)pdata, 3, 8);
} else {
OLED_ShowString_AlignRight(AlignRightEND_P, 3, " FPS", 4);
OLED_ShowNum(42, 3, *(uint8_t*)pdata, 3, 4);
char fps_num[10];
sprintf(fps_num, "%d", *(uint8_t*)pdata);
OLED_ShowString_AlignRight(AlignRightEND_P-13, 3, fps_num, 4);
}
break;
case KVM_JPG_QLTY:
if(kvm_hw_ver != 2){
OLED_ShowString(10, 7, "QUALITY: ", 8);
// OLED_ShowString_AlignRight(AlignRightEND, 7, "%", 8);
// OLED_ShowNum(AlignRightEND - 26, 7, *(uint8_t*)pdata, 3, 8);
switch (*(uint8_t*)pdata)
{
// LOW Middle HIGH EXTRA
case 0:
OLED_ShowString_AlignRight(AlignRightEND, 7, "--", 8);
break;
case 1:
OLED_ShowString_AlignRight(AlignRightEND, 7, "LOW", 8);
break;
case 2:
OLED_ShowString_AlignRight(AlignRightEND, 7, "Middle", 8);
break;
case 3:
OLED_ShowString_AlignRight(AlignRightEND, 7, "HIGH", 8);
break;
case 4:
OLED_ShowString_AlignRight(AlignRightEND, 7, "EXTRA", 8);
break;
default:
OLED_ShowString_AlignRight(AlignRightEND, 7, "--", 8);
break;
}
}
break;
case KVM_CPU_IDLE:
if(kvm_hw_ver != 2){
OLED_ShowString(10, 7, "CPU IDLE: ", 8);
OLED_ShowString_AlignRight(AlignRightEND, 7, "%", 8);
OLED_ShowNum(AlignRightEND - 26, 7, *(uint8_t*)pdata, 3, 8);
}
break;
}
}
void OLED_Show_Res(uint16_t _w, uint16_t _h)
{
// PCIe
if(_w != 0 || _h != 0){
char res_char[20]={0};
sprintf(res_char,"%d*%d", _w, _h);
if(kvm_hw_ver != 2){
// cube
OLED_ShowString(10, 4, "RES: ", 8);
OLED_ShowString_AlignRight(AlignRightEND, 4, res_char, 8);
} else {
// pcie
res_char[10]=0;
OLED_ShowString_AlignRight(36, 3, " ", 4);
OLED_ShowString_AlignRight(36, 3, res_char, 4);
}
} else {
if(kvm_hw_ver != 2){
// cube
OLED_ShowString(10, 4, "RES: --", 8);
} else {
// pcie
OLED_ShowString_AlignRight(36, 3, " ", 4);
}
}
}
void OLED_ShowKVMState(uint8_t _Interface, int8_t _EN)
{
uint8_t x0 = 84;
uint8_t x1 = 104;
if(kvm_hw_ver == 2){
x0 -= 60;
x1 -= 61;
}
if(_Interface & HDMI_STATE){
if(_EN) OLED_ShowState(x1, 1, 1, 21);
else OLED_ShowState(x1, 1, 0, 21);
}
if(_Interface & HID_STATE){
if(_EN) OLED_ShowState(x0, 1, 3, 15);
else OLED_ShowState(x0, 1, 2, 15);
}
if(_Interface & ETH_STATE){
if(_EN) OLED_ShowState(x0, 0, 5, 15);
else OLED_ShowState(x0, 0, 4, 15);
}
if(_Interface & WIFI_STATE){
if(_EN == 1) OLED_ShowState(x1, 0, 7, 15);
else if(_EN == 0) OLED_ShowState(x1, 0, 6, 15);
else OLED_ShowString(x1, 0, " -- ", 4);
}
}
void OLED_Show_Network_Error(uint8_t _state)
{
if(_state){
if(kvm_hw_ver != 2)
OLED_ShowError(28, 3, 1); // [!]
// else
// OLED_ShowString_AlignRight(5, 2, "!", 4);
} else {
if(kvm_hw_ver != 2)
OLED_ShowError(28, 3, 0);
// else
// OLED_ShowString_AlignRight(5, 2, " ", 4);
}
}

View File

@@ -0,0 +1,369 @@
#ifndef OLED_CTRL_H_
#define OLED_CTRL_H_
#include "maix_basic.hpp"
#include "maix_time.hpp"
#include "maix_gpio.hpp"
#include "maix_pinmap.hpp"
#include "maix_i2c.hpp"
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#define OLED_DISABLE 0
#define OLED_ENABLE 1
#define OLED_ADDR 0x3D
#define OLED_PCIe_ADDR 0x3C
#define OLED_CMD 0x00
#define OLED_DATA 0x40
#define HDMI_STATE 0x01
#define HID_STATE 0x02
#define ETH_STATE 0x04
#define WIFI_STATE 0x08
#define KVM_INIT 0x00
#define KVM_ETH_IP 0x01
#define KVM_WIFI_IP 0x02
#define KVM_HDMI_STATE 0x03
#define KVM_HDMI_RES 0x04
#define KVM_STEAM_TYPE 0x05
#define KVM_STEAM_FPS 0x06
#define KVM_JPG_QLTY 0x07
#define KVM_CPU_IDLE 0x08
#define KVM_RES_none 0x00
#define KVM_RES_480P 0x01
#define KVM_RES_600P 0x02
#define KVM_RES_720P 0x03
#define KVM_RES_1080P 0x04
#define KVM_TYPE_none 0x00
#define KVM_TYPE_MJPG 0x01
#define KVM_TYPE_H264 0x02
#define AlignRightEND 127
#define AlignRightEND_P 63
extern uint8_t OLED_state;
extern uint8_t kvm_hw_ver;
/************************************6*8的点阵************************************/
const uint8_t oled_asc2_0806[][6] ={
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// sp
{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00},// !
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00},// "
{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14},// #
{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12},// $
{0x00, 0x23, 0x13, 0x08, 0x64, 0x62},// %
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50},// &
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00},// '
{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00},// (
{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00},// )
// {0x00, 0x14, 0x08, 0x3E, 0x08, 0x14},// *
{0x00, 0x00, 0x28, 0x10, 0x28, 0x00},// *->x
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08},// +
{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00},// ,
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08},// -
{0x00, 0x00, 0x60, 0x60, 0x00, 0x00},// .
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02},// /
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E},// 0
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00},// 1
{0x00, 0x42, 0x61, 0x51, 0x49, 0x46},// 2
{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31},// 3
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10},// 4
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39},// 5
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30},// 6
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03},// 7
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36},// 8
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E},// 9
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00},// :
{0x00, 0x00, 0x56, 0x36, 0x00, 0x00},// ;
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00},// <
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14},// =
{0x00, 0x00, 0x41, 0x22, 0x14, 0x08},// >
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06},// ?
{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E},// @
{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C},// A
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36},// B
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22},// C
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C},// D
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41},// E
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01},// F
{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A},// G
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F},// H
{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00},// I
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01},// J
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41},// K
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40},// L
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F},// M
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F},// N
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E},// O
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06},// P
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E},// Q
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46},// R
{0x00, 0x46, 0x49, 0x49, 0x49, 0x31},// S
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01},// T
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F},// U
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F},// V
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F},// W
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63},// X
{0x00, 0x07, 0x08, 0x70, 0x08, 0x07},// Y
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43},// Z
{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00},// [
{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55},// 55
{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00},// ]
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04},// ^
{0x00, 0x40, 0x40, 0x40, 0x40, 0x40},// _
{0x00, 0x00, 0x01, 0x02, 0x04, 0x00},// '
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78},// a
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38},// b
{0x00, 0x38, 0x44, 0x44, 0x44, 0x20},// c
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F},// d
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18},// e
{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02},// f
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C},// g
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78},// h
{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00},// i
{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00},// j
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00},// k
{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00},// l
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78},// m
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78},// n
{0x00, 0x38, 0x44, 0x44, 0x44, 0x38},// o
{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18},// p
{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC},// q
{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08},// r
{0x00, 0x48, 0x54, 0x54, 0x54, 0x20},// s
{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20},// t
{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C},// u
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C},// v
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C},// w
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44},// x
{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C},// y
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44},// z
{0x14, 0x14, 0x14, 0x14, 0x14, 0x14},// horiz lines
};
const uint8_t oled_asc2_0804[][4] ={
{0x00,0x00,0x00,0x00},// sp
{0x7c,0x52,0x7c,0x00},// !
{0x00,0x0c,0x00,0x0c},// "
{0x00,0x7c,0x28,0x7c},// #
{0x00,0x5c,0x5e,0x74},// $
{0x6c,0x30,0x18,0x6c},// %
{0x00,0x68,0x54,0x68},// &
{0x00,0x00,0x0c,0x00},// '
{0x00,0x38,0x44,0x00},// (
{0x00,0x44,0x38,0x00},// )
{0x00,0x00,0x30,0x00},// *
{0x00,0x10,0x38,0x10},// +
{0x00,0x00,0x60,0x00},// ,
{0x00,0x10,0x10,0x10},// -
{0x00,0x00,0x40,0x00},// .
{0x00,0x40,0x38,0x04},// /
{0x00,0x7c,0x44,0x7c},// 0
{0x00,0x44,0x7c,0x40},// 1
{0x00,0x74,0x54,0x5c},// 2
{0x00,0x54,0x54,0x7c},// 3
{0x00,0x1c,0x10,0x7c},// 4
{0x00,0x5c,0x54,0x74},// 5
{0x00,0x7c,0x54,0x74},// 6
{0x00,0x04,0x04,0x7c},// 7
{0x00,0x7c,0x54,0x7c},// 8
{0x00,0x5c,0x54,0x7c},// 9
{0x00,0x00,0x28,0x00},// :
{0x00,0x40,0x28,0x00},// ;
{0x00,0x10,0x28,0x44},// <
{0x00,0x28,0x28,0x28},// =
{0x00,0x44,0x28,0x10},// >
{0x00,0x04,0x54,0x0c},// ?
{0x38,0x64,0x54,0x78},// @
{0x00,0x78,0x14,0x78},// A
{0x00,0x7c,0x54,0x38},// B
{0x00,0x38,0x44,0x44},// C
{0x00,0x7c,0x44,0x38},// D
{0x00,0x7c,0x54,0x54},// E
{0x00,0x7c,0x14,0x14},// F
{0x00,0x6c,0x54,0x74},// G
{0x00,0x7c,0x10,0x7c},// H
{0x00,0x44,0x7c,0x44},// I
{0x00,0x44,0x7c,0x04},// J
{0x00,0x7c,0x10,0x6c},// K
{0x00,0x7c,0x40,0x40},// L
{0x00,0x7c,0x18,0x7c},// M
{0x00,0x6c,0x18,0x74},// N
{0x00,0x38,0x44,0x38},// O
{0x00,0x7c,0x14,0x1c},// P
{0x00,0x3c,0x24,0x7c},// Q
{0x00,0x7c,0x14,0x6c},// R
{0x00,0x58,0x54,0x64},// S
{0x00,0x04,0x7c,0x04},// T
{0x00,0x3c,0x40,0x7c},// U
{0x00,0x3c,0x60,0x3c},// V
{0x00,0x7c,0x30,0x7c},// W
{0x00,0x6c,0x10,0x6c},// X
{0x00,0x0c,0x70,0x0c},// Y
{0x00,0x64,0x54,0x4c},// Z
{0x00,0x7c,0x44,0x00},// [
{0x28,0x54,0x28,0x54},// 55
{0x00,0x44,0x7c,0x00},// ]
};
//16*16 ASCII字符集点阵
const uint8_t oled_asc2_1608[][16]={
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/
{0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00},/*"!",1*/
{0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/
{0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00},/*"#",3*/
{0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00},/*"$",4*/
{0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00},/*"%",5*/
{0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10},/*"&",6*/
{0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/
{0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00},/*"(",8*/
{0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00},/*")",9*/
{0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00},/*"*",10*/
{0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00},/*"+",11*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00},/*",",12*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01},/*"-",13*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},/*".",14*/
{0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00},/*"/",15*/
{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},/*"0",16*/
{0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"1",17*/
{0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},/*"2",18*/
{0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},/*"3",19*/
{0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00},/*"4",20*/
{0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00},/*"5",21*/
{0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00},/*"6",22*/
{0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00},/*"7",23*/
{0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},/*"8",24*/
{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00},/*"9",25*/
{0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00},/*":",26*/
{0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00},/*";",27*/
{0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00},/*"<",28*/
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00},/*"=",29*/
{0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00},/*">",30*/
{0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00},/*"?",31*/
{0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00},/*"@",32*/
{0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20},/*"A",33*/
{0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},/*"B",34*/
{0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},/*"C",35*/
{0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},/*"D",36*/
{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},/*"E",37*/
{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},/*"F",38*/
{0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},/*"G",39*/
{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},/*"H",40*/
{0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"I",41*/
{0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},/*"J",42*/
{0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},/*"K",43*/
{0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},/*"L",44*/
{0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00},/*"M",45*/
{0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},/*"N",46*/
{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},/*"O",47*/
{0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},/*"P",48*/
{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00},/*"Q",49*/
{0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},/*"R",50*/
{0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},/*"S",51*/
{0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"T",52*/
{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"U",53*/
{0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},/*"V",54*/
{0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00},/*"W",55*/
{0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},/*"X",56*/
{0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"Y",57*/
{0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},/*"Z",58*/
{0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00},/*"[",59*/
{0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00},/*"\",60*/
{0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00},/*"]",61*/
{0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},/*"_",63*/
{0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/
{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20},/*"a",65*/
{0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},/*"b",66*/
{0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},/*"c",67*/
{0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20},/*"d",68*/
{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00},/*"e",69*/
{0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"f",70*/
{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},/*"g",71*/
{0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"h",72*/
{0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"i",73*/
{0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},/*"j",74*/
{0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00},/*"k",75*/
{0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"l",76*/
{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},/*"m",77*/
{0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"n",78*/
{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"o",79*/
{0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00},/*"p",80*/
{0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80},/*"q",81*/
{0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},/*"r",82*/
{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},/*"s",83*/
{0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00},/*"t",84*/
{0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},/*"u",85*/
{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00},/*"v",86*/
{0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00},/*"w",87*/
{0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00},/*"x",88*/
{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00},/*"y",89*/
{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},/*"z",90*/
{0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40},/*"{",91*/
{0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00},/*"|",92*/
{0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00},/*"}",93*/
{0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/
};
// [!]
const uint8_t etherror[6]
{0x00,0x3e,0x7f,0x51,0x7f,0x3e}; // [!]
//6*xx 图标点阵
const uint8_t oled_kvm_0621[][21]{
{0x00,0x3e,0x08,0x08,0x3e,0x00,0x3e,0x22,0x22,0x1c,0x00,0x3c,0x02,0x0c,0x02,0x3c,0x00,0x22,0x3e,0x22,0x00},/*"HDMI=0",0*,21*/
{0x3e,0x41,0x77,0x77,0x41,0x7f,0x41,0x5d,0x5d,0x63,0x7f,0x43,0x7d,0x73,0x7d,0x43,0x7f,0x5d,0x41,0x5d,0x3e},/*"HDMI=1",0*,21*/
{0x00,0x3e,0x08,0x08,0x3e,0x00,0x22,0x3e,0x20,0x00,0x3e,0x22,0x22,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"USB=0",0, 15*/
{0x3e,0x41,0x77,0x77,0x41,0x7f,0x5d,0x41,0x5f,0x7f,0x41,0x5d,0x5d,0x63,0x3e,0x00,0x00,0x00,0x00,0x00,0x00},/*"USB=1",1, 15*/
{0x00,0x3e,0x2a,0x2a,0x22,0x00,0x02,0x3e,0x02,0x00,0x3e,0x08,0x08,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"ETH=0",1, 15*/
{0x3e,0x41,0x55,0x55,0x5d,0x7f,0x7d,0x41,0x7d,0x7f,0x41,0x77,0x77,0x41,0x3e,0x00,0x00,0x00,0x00,0x00,0x00},/*"ETH=1",1, 15*/
{0x00,0x1e,0x20,0x18,0x20,0x1e,0x00,0x3a,0x00,0x3e,0x0a,0x0a,0x00,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"WiFi=0",1, 15*/
{0x3e,0x61,0x5f,0x67,0x5f,0x61,0x7f,0x45,0x7f,0x41,0x75,0x75,0x7f,0x45,0x3e,0x00,0x00,0x00,0x00,0x00,0x00},/*"WiFi=1",1, 15*/
};
const uint8_t oled_kvm_logo[116] =
{
0xf8,0x1f,0xfc,0x3f,0xf6,0x67,0x06,0x60,0xce,0x6f,0x3e,0x7f,0xfe,0x7c,0xf6,0x73,0x06,0x60,0xe6,0x6f,
0xfe,0x7f,0xfe,0x71,0xfe,0x6e,0xfe,0x6e,0xfe,0x61,0xfe,0x7f,0xfe,0x60,0xfe,0x7e,0xfe,0x7e,0xfe,0x60,
0xfe,0x7f,0xfe,0x71,0xfe,0x6e,0xfe,0x6e,0xfe,0x71,0xfe,0x7f,0xf6,0x6f,0x06,0x60,0x76,0x6f,0x3e,0x7e,
0x8e,0x79,0xe6,0x63,0xfe,0x6f,0xf6,0x7f,0x06,0x7f,0x7e,0x78,0xfe,0x63,0xfe,0x79,0x3e,0x7e,0x86,0x7f,
0xf6,0x6f,0x7e,0x60,0x86,0x6f,0x86,0x7f,0x7e,0x7c,0x86,0x7f,0x86,0x6f,0x7e,0x60,0xfe,0x6f,0xfc,0x3f,
0xf8,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0x3f,0xfc,0x3f
};
const uint8_t oled_sipeed_logo[32] = {
0x00,0x00,0xf8,0x1f,0xfc,0x3f,0xf6,0x7f,0xb2,0x7f,0x1e,0x67,0x0e,0x66,0x66,0x66,
0x66,0x66,0x66,0x66,0x66,0x70,0xfe,0x78,0xfe,0x7d,0xfc,0x3f,0xf8,0x1f,0x00,0x00
};
int oled_exist(void);
void OLED_Clear(void);
void OLED_Fill(void);
void OLED_Init(void);
void OLED_Revolve(void);
void OLED_ShowState(uint8_t x,uint8_t y,char chr,uint8_t size);
void OLED_DisplayTurn(uint8_t i);
void OLED_ColorTurn(uint8_t i);
void OLED_ShowError(uint8_t x,uint8_t y,uint8_t _state);
void OLED_ShowCharTurn(uint8_t x,uint8_t y,char chr,uint8_t sizey);
void OLED_ShowNum(uint8_t x, uint8_t y, uint8_t num, uint8_t len, uint8_t sizey);
void OLED_ShowString(uint8_t x, uint8_t y, char *chr, uint8_t sizey);
void OLED_ShowStringTurn(uint8_t x, uint8_t y, char *chr, uint8_t sizey);
void OLED_ShowStringtoend(uint8_t x, uint8_t y, char *chr, uint8_t sizey, uint8_t end);
void OLED_ShowString_AlignRight(uint8_t x_end, uint8_t y, char *chr, uint8_t size);
void OLED_ROW(uint8_t _EN);
void OLED_ShowLogo();
void OLED_ShowSipeedLogo();
void OLED_Showline();
void OLED_Showline_1();
void OLED_ShowIMG(uint8_t x,uint8_t y,char *chr,uint8_t width,uint8_t height);
void OLED_ShowKVMStreamState(uint8_t kvm_state_s, void* pdata);
void OLED_Show_Res(uint16_t _w, uint16_t _h);
void OLED_ShowKVMState(uint8_t _Interface, int8_t _EN);
void OLED_Show_Network_Error(uint8_t _state);
#endif // OLED_CTRL_H_

View File

@@ -0,0 +1,542 @@
#include "oled_ui.h"
using namespace maix;
using namespace maix::sys;
extern kvm_sys_state_t kvm_sys_state;
extern kvm_oled_state_t kvm_oled_state;
void kvm_init_cube_ui(void)
{
uint8_t temp;
char* str_temp = "192.168.1.243";
OLED_Clear();
// OLED_Revolve();
OLED_ShowLogo();
OLED_ShowSipeedLogo();
OLED_ShowKVMState(HDMI_STATE, 0);
OLED_ShowKVMState(HID_STATE, 0);
OLED_ShowKVMState(ETH_STATE, 0);
OLED_ShowKVMState(WIFI_STATE, 0);
OLED_Showline();
OLED_ShowKVMStreamState(KVM_INIT, &temp);
temp = 0;
OLED_ShowKVMStreamState(KVM_ETH_IP, &temp);
temp = KVM_RES_none;
OLED_ShowKVMStreamState(KVM_HDMI_RES, &temp);
temp = KVM_TYPE_none;
OLED_ShowKVMStreamState(KVM_STEAM_TYPE, &temp);
temp = 0;
OLED_ShowKVMStreamState(KVM_STEAM_FPS, &temp);
temp = 80;
OLED_ShowKVMStreamState(KVM_JPG_QLTY, &temp);
}
void kvm_init_pcie_ui(void)
{
OLED_Revolve();
OLED_Showline_1();
OLED_ShowSipeedLogo();
OLED_ShowKVMState(HDMI_STATE, 0);
OLED_ShowKVMState(HID_STATE, 0);
OLED_ShowKVMState(ETH_STATE, 0);
OLED_ShowKVMState(WIFI_STATE, 0);
// OLED_ShowString(0, 2, "!192.168.222.197", 4);
// OLED_ShowString(1, 2, " 192.168.2.197", 4);
// OLED_ShowString(1, 3, "1920*1080", 4);
// OLED_ShowString(41, 3, " FPS", 4);
// OLED_ShowString_AlignRight(AlignRightEND_P, 2, "192.168.0.69", 4);
// OLED_ShowString_AlignRight(37, 3, "1920*1080", 4);
OLED_ShowString_AlignRight(AlignRightEND_P, 3, " FPS", 4);
// OLED_ShowString(0, 3, "\"ABCDEFGHIJKLMMN\'", 4);
// OLED_ShowString(5, 2, "1", 4);
}
void kvm_init_ui(void)
{
if(kvm_hw_ver != 2){
kvm_init_cube_ui();
} else {
kvm_init_pcie_ui();
}
}
void qrcode_to_oled(QRCode *qr)
{
char *p_oled_data;
uint16_t count = 0;
uint8_t bit;
uint8_t begin_x = 2;
uint8_t begin_y = 2;
p_oled_data = (char *)malloc( 132 * sizeof(char));
if(p_oled_data != NULL){
// fill
for(int i = 0; i < 132; i++){
p_oled_data[i] = 0xFF;
}
// i | ; j -
for(int i = 0; i < 29; i++){
for(int j = 0; j < 29; j++){
if(qrIsBlacke(qr, i, j)){
// 敲黑点
uint16_t data_index = ((i+begin_y)/8)*33+(j+begin_x);
uint8_t mask = ~(0x01 << ((i+begin_y)%8));
p_oled_data[data_index] &= mask;
}
}
}
OLED_Fill();
OLED_ShowIMG(29, 0, p_oled_data, 33, 4);
free(p_oled_data);
}
}
int qrencode(char *string)
{
// test: qrencode("WIFI:T:WPA2;S:NanoKVM;P:12345678;;");
int errcode = QR_ERR_NONE;
QRCode* p = qrInit(3, QR_EM_8BIT, 1, 4, &errcode);
if (p == NULL) {
printf("error\n");
return -1;
}
qrAddData(p, (const qr_byte_t*)string, strlen(string));
if (!qrFinalize(p)) {
printf("finalize error\n");
return -1;
}
qrcode_to_oled(p);
if(string[0] == 'W'){
OLED_ShowStringTurn(3, 1, "WiFi", 8);
OLED_ShowStringTurn(3, 2, "AP:", 8);
} else if(string[0] == 'h'){
if(string[7] == '1'){
OLED_ShowStringTurn(3, 1, "Web:", 8);
} else if(string[8] == 'w'){
OLED_ShowStringTurn(3, 1, "WiKi", 8);
}
}
int size = 0;
// width = height = qr_vertable[version] * mag + sep * mag * 2
qr_byte_t * buffer = qrSymbolToBMP(p, 5, 5, &size);
if (buffer == NULL) {
printf("error %s", qrGetErrorInfo(p));
return -1;
}
// output qrcode to file
// ofstream f("/etc/kvm/wifi_config.bmp");
// if (f.fail()) {
// return -1;
// }
// f.write((const char *)buffer, size);
// f.close();
return 0;
}
ip_addr_t show_which_ip(void)
{
if(kvm_sys_state.wifi_state == -2) return ETH_IP;
if(kvm_oled_state.eth_state == 3 && kvm_oled_state.wifi_state != 1) return ETH_IP;
if(kvm_oled_state.eth_state != 3 && kvm_oled_state.wifi_state == 1) return WiFi_IP;
static uint8_t run_count = 0;
static ip_addr_t ip_type = ETH_IP;
run_count++;
if(run_count > IP_Change_time/STATE_DELAY){
run_count = 0;
switch(ip_type){
case ETH_IP:
ip_type = WiFi_IP;
break;
case WiFi_IP:
ip_type = ETH_IP;
break;
default:
ip_type = ETH_IP;
}
}
// printf("show_which_ip? %d\n", ip_type);
return ip_type;
}
uint8_t ip_changed(ip_addr_t ip_type)
{
uint8_t *kvm_sys_ip;
uint8_t *kvm_oled_ip;
uint8_t ret;
if(ip_type == ETH_IP){
kvm_sys_ip = kvm_sys_state.eth_addr;
kvm_oled_ip = kvm_oled_state.eth_addr;
} else if(ip_type == WiFi_IP){
kvm_sys_ip = kvm_sys_state.wifi_addr;
kvm_oled_ip = kvm_oled_state.wifi_addr;
} else ret = 0;
for (int i = 0; i < 16; i++){
if(kvm_sys_ip[i] == 0) ret = 0;
if(kvm_sys_ip[i] != kvm_oled_ip[i]) ret = 1;
}
if(ret == 1){
memcpy(kvm_oled_ip, kvm_sys_ip, 16);
}
return ret;
}
uint8_t kvm_state_is_changed()
{
if( (kvm_sys_state.eth_state != kvm_oled_state.eth_state) ||
(kvm_sys_state.wifi_state != kvm_oled_state.wifi_state) ||
(kvm_sys_state.usb_state != kvm_oled_state.usb_state) ||
(kvm_sys_state.hdmi_state != kvm_oled_state.hdmi_state) ||
/* (kvm_sys_state.now_fps != kvm_oled_state.now_fps) || */
(kvm_sys_state.hdmi_width != kvm_oled_state.hdmi_width) ||
(kvm_sys_state.hdmi_height != kvm_oled_state.hdmi_height) ||
(kvm_sys_state.type != kvm_oled_state.type) ||
(kvm_sys_state.qlty != kvm_oled_state.qlty) )
return 1;
else
return 0;
}
void kvm_eth_state_disp(ip_addr_t _ip_type, uint8_t first_disp)
{
static ip_addr_t _ip_type_old = NULL_IP;
uint8_t temp;
// printf("[kvmd]eth_state = %d\n", kvm_sys_state.eth_state);
if( (kvm_oled_state.eth_state != kvm_sys_state.eth_state) ||
(_ip_type_old != _ip_type) ||
first_disp || ip_changed(ETH_IP))
{
kvm_oled_state.eth_state = kvm_sys_state.eth_state;
_ip_type_old = _ip_type;
switch(kvm_oled_state.eth_state){
case -1:
case 0:
temp = 0;
OLED_ShowKVMState(ETH_STATE, 0);
if(_ip_type == ETH_IP)
OLED_ShowKVMStreamState(KVM_ETH_IP, &temp);
break;
case 1:
OLED_ShowKVMState(ETH_STATE, 1);
if(_ip_type == ETH_IP)
OLED_ShowKVMStreamState(KVM_ETH_IP, &temp);
break;
case 2:
OLED_Show_Network_Error(1);
case 3:
OLED_Show_Network_Error(0);
OLED_ShowKVMState(ETH_STATE, 1);
if(_ip_type == ETH_IP)
OLED_ShowKVMStreamState(KVM_ETH_IP, kvm_sys_state.eth_addr);
break;
}
}
}
void kvm_wifi_state_disp(ip_addr_t _ip_type, uint8_t first_disp)
{
static ip_addr_t _ip_type_old = NULL_IP;
uint8_t temp;
// printf("[kvmd]wifi_state = %d\n", kvm_sys_state.wifi_state);
if( (kvm_oled_state.wifi_state != kvm_sys_state.wifi_state) ||
(_ip_type_old != _ip_type) ||
first_disp || ip_changed(WiFi_IP))
{
kvm_oled_state.wifi_state = kvm_sys_state.wifi_state;
_ip_type_old = _ip_type;
switch(kvm_oled_state.wifi_state){
case -2:
OLED_ShowKVMState(WIFI_STATE, -1);
break;
case -1:
case 0:
temp = 0;
OLED_ShowKVMState(WIFI_STATE, 0);
if(_ip_type == WiFi_IP)
OLED_ShowKVMStreamState(KVM_WIFI_IP, &temp);
break;
case 1:
OLED_ShowKVMState(WIFI_STATE, 1);
if(_ip_type == WiFi_IP){
OLED_ShowKVMStreamState(KVM_WIFI_IP, kvm_sys_state.wifi_addr);
}
break;
}
}
}
void kvm_usb_state_disp(uint8_t first_disp)
{
if((kvm_oled_state.usb_state != kvm_sys_state.usb_state) || first_disp){
kvm_oled_state.usb_state = kvm_sys_state.usb_state;
switch(kvm_oled_state.usb_state){
case -1:
case 0:
OLED_ShowKVMState(HID_STATE, 0);
break;
case 1:
OLED_ShowKVMState(HID_STATE, 1);
break;
}
}
}
void kvm_hdmi_state_disp(uint8_t first_disp)
{
if((kvm_oled_state.hdmi_state != kvm_sys_state.hdmi_state) || first_disp){
kvm_oled_state.hdmi_state = kvm_sys_state.hdmi_state;
switch(kvm_oled_state.hdmi_state){
case -1:
case 0:
OLED_ShowKVMState(HDMI_STATE, 0);
break;
case 1:
OLED_ShowKVMState(HDMI_STATE, 1);
break;
}
}
}
void kvm_fps_disp(uint8_t first_disp)
{
if((kvm_oled_state.now_fps != kvm_sys_state.now_fps) || first_disp){
kvm_oled_state.now_fps = kvm_sys_state.now_fps;
OLED_ShowKVMStreamState(KVM_STEAM_FPS, &kvm_oled_state.now_fps);
}
}
void kvm_res_disp(uint8_t first_disp)
{
if( (kvm_oled_state.hdmi_width != kvm_sys_state.hdmi_width) || \
(kvm_oled_state.hdmi_height != kvm_sys_state.hdmi_height) || \
first_disp ){
kvm_oled_state.hdmi_width = kvm_sys_state.hdmi_width;
kvm_oled_state.hdmi_height = kvm_sys_state.hdmi_height;
OLED_Show_Res(kvm_sys_state.hdmi_width, kvm_sys_state.hdmi_height);
}
}
void kvm_type_disp(uint8_t first_disp)
{
if( (kvm_oled_state.type != kvm_sys_state.type) || first_disp){
kvm_oled_state.type = kvm_sys_state.type;
OLED_ShowKVMStreamState(KVM_STEAM_TYPE, &kvm_oled_state.type);
}
}
void kvm_qlty_disp(uint8_t first_disp)
{
if( (kvm_oled_state.qlty != kvm_sys_state.qlty) || first_disp){
kvm_oled_state.qlty = kvm_sys_state.qlty;
OLED_ShowKVMStreamState(KVM_JPG_QLTY, &kvm_sys_state.qlty);
}
}
void kvm_main_disp(uint8_t first_disp)
{
if(first_disp){
OLED_Clear();
kvm_init_ui();
}
}
void kvm_oled_clear(uint8_t subpage_changed)
{
if(subpage_changed){
OLED_Clear();
}
}
void kvm_main_ui_disp(uint8_t first_disp, uint8_t subpage_changed)
{
ip_addr_t now_ip_type;
// if(kvm_oled_state.sub_page == 0)
// if(kvm_oled_state.oled_sleep_state == 1){
// Any operation will update the OLED sleep time
if (kvm_state_is_changed())
oled_auto_sleep_time_update();
if(kvm_oled_state.sub_page == 1){
// main page (oled sleep)
kvm_oled_clear(first_disp || subpage_changed);
kvm_oled_state.oled_sleep_state = 1;
} else {
// main page
kvm_oled_state.oled_sleep_state = 0;
now_ip_type = show_which_ip();
kvm_main_disp(first_disp || subpage_changed);
kvm_eth_state_disp(now_ip_type, first_disp || subpage_changed);
kvm_wifi_state_disp(now_ip_type, first_disp || subpage_changed);
kvm_usb_state_disp(first_disp || subpage_changed);
kvm_hdmi_state_disp(first_disp || subpage_changed);
kvm_fps_disp(first_disp || subpage_changed);
kvm_res_disp(first_disp || subpage_changed);
kvm_type_disp(first_disp || subpage_changed);
kvm_qlty_disp(first_disp || subpage_changed);
}
}
uint8_t show_which_page()
{
static uint8_t run_count = 0xfe;
static uint8_t show_type = 0; // 0 不动 1 QRcode; 2 text
if(sta_connect_ap()){
if(ssid_pass_ok()){
//
}
}
run_count++;
if(run_count > QR_Change_time/STATE_DELAY){
run_count = 0;
if(show_type == 1) show_type = 2;
else show_type = 1;
return show_type;
}
return 0;
}
void show_text_wifi_config(char *ap_ssid)
{
OLED_Clear();
OLED_ShowString(0, 0, "SSID:", 8);
OLED_ShowString_AlignRight(63, 1, "NanoKVM", 8);
OLED_ShowString(0, 2, "PASS:", 8);
OLED_ShowString_AlignRight(63, 3, ap_ssid, 8);
}
void show_wifi_config_ip(void)
{
OLED_Clear();
get_ip_addr(WiFi_IP);
OLED_ShowString(0, 1, "Config IP:", 8);
OLED_ShowString_AlignRight(63, 2, (char*)kvm_sys_state.wifi_addr, 4);
}
void show_wifi_config_QR(void)
{
static char cmd[70];
OLED_Clear();
get_ip_addr(WiFi_IP);
printf("http://%s/#/wifi\n", kvm_sys_state.wifi_addr);
sprintf(cmd, "http://%s/#/wifi", kvm_sys_state.wifi_addr);
qrencode(cmd);
}
void show_wifi_starting(void)
{
OLED_Clear();
OLED_ShowString(0, 1, "WiFi AP is", 8);
OLED_ShowString(0, 2, "Starting..", 8);
}
void show_wifi_connecting(void)
{
OLED_Clear();
OLED_ShowString(0, 1, "WiFi", 8);
OLED_ShowString(0, 2, "Connect...", 8);
}
void kvm_wifi_config_ui_disp(uint8_t first_disp, uint8_t subpage_changed)
{
static char cmd[70];
// printf("[kvmd]kvm_wifi_config_ui_disp %d | %d\n", first_disp, subpage_changed);
if(first_disp) kvm_start_wifi_config_process(); // 略有不妥,就这样吧
if(first_disp || subpage_changed){
switch(kvm_oled_state.sub_page){
case 0: // wifi ap is starting
show_wifi_starting();
break;
case 1: // QRcode
printf("WIFI:T:WPA2;S:NanoKVM;P:%s;;\n", kvm_sys_state.wifi_ap_pass);
sprintf(cmd, "WIFI:T:WPA2;S:NanoKVM;P:%s;;", kvm_sys_state.wifi_ap_pass);
qrencode(cmd);
break;
case 2: // Textcode
show_text_wifi_config(kvm_sys_state.wifi_ap_pass);
break;
case 3: // open IP with QR Code
show_wifi_config_QR();
break;
case 4: // open IP
show_wifi_config_ip();
break;
case 5: // Connecting...
show_wifi_connecting();
break;
}
}
// switch(show_which_page())
}
void oled_auto_sleep_time_update(void)
{
kvm_oled_state.oled_sleep_start = time::time_ms();
}
void oled_auto_sleep(void)
{
uint8_t tmp8;
uint8_t sleep_close_signal = 0;
FILE *fp;
int file_size;
uint8_t RW_Data[10];
if(access("/etc/kvm/oled_sleep", F_OK) == 0){
fp = fopen("/etc/kvm/oled_sleep", "r");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(RW_Data, sizeof(char), file_size, fp);
fclose(fp);
if(file_size != 0){
tmp8 = atoi((char*)RW_Data);
} else {
tmp8 = OLED_SLEEP_DELAY_DEFAULT;
}
if(tmp8 != kvm_oled_state.oled_sleep_param){
// printf("/etc/kvm/oled_sleep = %d\n", tmp8);
kvm_oled_state.oled_sleep_param = tmp8;
if(kvm_oled_state.oled_sleep_param < OLED_SLEEP_DELAY_MIN){
sleep_close_signal = 1;
} else {
// printf("oled_auto_sleep_time_update\n");
oled_auto_sleep_time_update();
}
}
} else {
if(kvm_oled_state.oled_sleep_param != 0){
kvm_oled_state.oled_sleep_param = 0;
sleep_close_signal = 1;
}
}
if(kvm_oled_state.page == 0){
if(kvm_oled_state.oled_sleep_param < OLED_SLEEP_DELAY_MIN){
if(sleep_close_signal == 1){
kvm_sys_state.sub_page = 0;
}
} else {
if((time::time_ms() - kvm_oled_state.oled_sleep_start)/1000 >= kvm_oled_state.oled_sleep_param){
// kvm_oled_state.oled_sleep_state = 1;
kvm_sys_state.sub_page = 1;
} else {
kvm_sys_state.sub_page = 0;
}
}
}
}
void kvm_show_UE(void)
{
if(kvm_hw_ver != 2){
OLED_ShowString(0, 0, "HDMI: UE", 16);
} else {
OLED_Revolve();
OLED_ShowString(0, 0, "HDMI: UE", 16);
// OLED_ShowString_AlignRight(AlignRightEND_P, 3, " FPS", 4);
// kvm_init_pcie_ui();
}
}

View File

@@ -0,0 +1,12 @@
#ifndef OLED_UI_H_
#define OLED_UI_H_
#include "config.h"
#include "oled_ctrl.h"
void kvm_main_ui_disp(uint8_t first_disp, uint8_t subpage_changed);
void kvm_wifi_config_ui_disp(uint8_t first_disp, uint8_t subpage_changed);
void oled_auto_sleep_time_update(void);
void oled_auto_sleep(void);
void kvm_show_UE(void);
#endif // OLED_UI_H_

View File

@@ -0,0 +1,181 @@
#include "system_ctrl.h"
using namespace maix;
using namespace maix::sys;
extern kvm_sys_state_t kvm_sys_state;
extern kvm_oled_state_t kvm_oled_state;
void gen_hostapd_conf(char* ap_ssid)
{
char file_data[300] = {0};
FILE * fp;
sprintf(file_data, "ctrl_interface=/var/run/hostapd\nctrl_interface_group=0\nssid=NanoKVM\nhw_mode=g\nchannel=1\nbeacon_int=100\ndtim_period=2\nmax_num_sta=255\nrts_threshold=-1\nfragm_threshold=-1\nmacaddr_acl=0\nauth_algs=3\nwpa=2\nwpa_passphrase=%s\nieee80211n=1\n", ap_ssid);
fp = fopen("/etc/hostapd.conf", "w");
fwrite(file_data, sizeof(file_data) , 1, fp );
fclose(fp);
}
void gen_udhcpd_conf()
{
char file_data[300] = {0};
FILE * fp;
sprintf(file_data, "start 10.10.10.100\nend 10.10.10.200\ninterface wlan0\npidfile /var/run/udhcpd.wlan0.pid\nlease_file /var/lib/misc/udhcpd.wlan0.leases\noption subnet 255.255.255.0\noption lease 864000\n");
fp = fopen("/etc/udhcpd.wlan0.conf", "w");
fwrite(file_data, sizeof(file_data) , 1, fp );
fclose(fp);
}
void gen_dnsmasq_conf()
{
char file_data[300] = {0};
FILE * fp;
sprintf(file_data, "bind-interfaces\ninterface=wlan0\ndhcp-range=10.10.10.2,10.10.10.254\naddress=/#/10.0.0.1\n");
fp = fopen("/etc/udhcpd.wlan0.conf", "w");
fwrite(file_data, sizeof(file_data) , 1, fp );
fclose(fp);
}
uint8_t sta_connect_ap(void)
{
uint8_t RW_Data[10];
FILE *fp;
fp = popen("hostapd_cli all sta | grep aid", "r");
fgets((char*)RW_Data, 2, fp);
pclose(fp);
if(RW_Data[0] == 'a') return 1;
else return 0;
}
uint8_t ssid_pass_ok(void)
{
if(access("/kvmapp/kvm/wifi_try_connect", F_OK) == 0) return 1;
else return 0;
}
uint8_t wifi_connected(void)
{
uint8_t RW_Data[20];
FILE *fp;
fp = popen("wpa_cli -i wlan0 status | grep \"wpa_state\"", "r");
fgets((char*)RW_Data, 15, fp);
pclose(fp);
if(RW_Data[10] == 'S') return 0;
else if(RW_Data[10] == 'C') return 1;
else return 0;
}
void kvm_start_wifi_config_process(void)
{
if(kvm_sys_state.wifi_config_process == -1){
// printf("[kvmw]开始配置wifi\n");
kvm_sys_state.wifi_config_process = 0;
kvm_sys_state.sub_page = 0;
}
}
void kvm_wifi_web_config_process()
{
if(ssid_pass_ok()){
system("rm /kvmapp/kvm/wifi_try_connect");
system("/etc/init.d/S30wifi restart");
kvm_sys_state.wifi_config_process = 3;
// 尝试连接wifi
if(kvm_sys_state.wifi_config_process == 3){
// time::sleep_ms(WIFI_CONNECTION_DELAY);
if(wifi_connected()){
// 连上了
kvm_sys_state.wifi_config_process = -1;
} else {
// 没连上
kvm_sys_state.wifi_config_process = 0;
}
}
}
}
void kvm_wifi_config_process()
{
int temp;
char ran_num;
static char cmd[70];
switch(kvm_sys_state.wifi_config_process){
case -1:
// printf("[kvms]Not in the process of configuring WiFi\n");
break;
case 0: // 启动wifi
srand((unsigned)time::time_ms());
for(temp = 0; temp < 4; temp++){
do{
ran_num = (char)rand()%10 + '0';
if(temp == 0) break;
} while (ran_num == kvm_sys_state.wifi_ap_pass[(temp-1)*2]);
kvm_sys_state.wifi_ap_pass[temp*2] = ran_num;
kvm_sys_state.wifi_ap_pass[temp*2+1] = ran_num;
}
kvm_sys_state.wifi_ap_pass[8] = '\0';
sprintf(cmd, "echo %s > /kvmapp/kvm/ap.pass", kvm_sys_state.wifi_ap_pass);
system("echo NanoKVM > /kvmapp/kvm/ap.ssid");
system(cmd);
system("/etc/init.d/S30wifi ap");
kvm_sys_state.wifi_config_process = 1;
kvm_sys_state.sub_page = 1;
break;
case 1: // 等待设备连接
if(sta_connect_ap()){
kvm_sys_state.wifi_config_process = 2;
kvm_sys_state.sub_page = 3;
}
break;
case 2: // 等待输入帐号密码
if(ssid_pass_ok()){
system("rm /kvmapp/kvm/wifi_try_connect");
system("/etc/init.d/S30wifi restart");
kvm_sys_state.wifi_config_process = 3;
kvm_sys_state.sub_page = 5;
}
break;
case 3: // 尝试连接wifi
time::sleep_ms(WIFI_CONNECTION_DELAY);
if(wifi_connected()){
// 连上了
kvm_sys_state.wifi_config_process = -1;
kvm_sys_state.page = 0;
kvm_sys_state.sub_page = 0;
} else {
// 没连上
kvm_sys_state.wifi_config_process = 0;
kvm_sys_state.sub_page = 0;
}
break;
}
}
uint8_t kvm_reset_password(void)
{
FILE *fp = popen("bash", "w");
if (fp == NULL) {
perror("popen");
return 0;
}
fputs("passwd root\n", fp);
time::sleep_ms(10);
fputs("root\n", fp);
time::sleep_ms(10);
fputs("root\n", fp);
time::sleep_ms(10);
fputs("rm /etc/kvm/pwd\n", fp);
time::sleep_ms(10);
fputs("sync\n", fp);
time::sleep_ms(10);
fputs("exit\n", fp); // 退出 bash
if (pclose(fp) == -1) {
perror("pclose");
return 1;
}
return 0;
}

View File

@@ -0,0 +1,16 @@
#ifndef SYSTEM_CTRL_H_
#define SYSTEM_CTRL_H_
#include "config.h"
void gen_hostapd_conf(char* ap_ssid);
void gen_udhcpd_conf();
void gen_dnsmasq_conf();
uint8_t sta_connect_ap(void);
uint8_t ssid_pass_ok(void);
uint8_t wifi_connected(void);
void kvm_start_wifi_config_process(void);
void kvm_wifi_web_config_process();
void kvm_wifi_config_process();
uint8_t kvm_reset_password(void);
#endif // SYSTEM_CTRL_H_

View File

@@ -0,0 +1,192 @@
#include "config.h"
#include "system_init.h"
using namespace maix;
using namespace maix::sys;
extern kvm_sys_state_t kvm_sys_state;
extern kvm_oled_state_t kvm_oled_state;
uint8_t get_hdmi_version()
{
FILE *fp;
uint8_t RW_Data[2];
system("/kvmapp/system/init.d/S15kvmhwd get_hdmi_version");
if(access("/etc/kvm/hdmi_version", F_OK) == 0){
fp = fopen("/etc/kvm/hdmi_version", "r");
fread(RW_Data, sizeof(char), 2, fp);
fclose(fp);
if(RW_Data[0] == 'u'){
// 6911uxc
if(RW_Data[1] == 'e'){
return 2;
} else if(RW_Data[1] == 'x') {
return 1;
} else {
return 1;
}
} else {
// 6911c
return 0;
}
} else {
return 0;
}
}
void Production_testing_patch(void)
{
// Product UE version detecte
if(get_hdmi_version() == 2){
printf("ue_patch_state = 1;\n");
kvm_oled_state.ue_patch_state = 1;
} else {
printf("ue_patch_state = 0;\n");
kvm_oled_state.ue_patch_state = 0;
}
// New products default to disabling mDNS functionality
system("rm -f /etc/init.d/S50ssdpd");
system("sync");
}
void new_app_init(void)
{
// Update the necessary scripts
system("cp -f /kvmapp/system/update-nanokvm.py /etc/kvm/");
system("rm -f /etc/init.d/S02udisk");
system("cp -f /kvmapp/system/init.d/S00kmod /etc/init.d/");
system("cp -f /kvmapp/system/init.d/S01fs /etc/init.d/");
system("cp -f /kvmapp/system/init.d/S03usbdev /etc/init.d/");
system("cp -f /kvmapp/system/init.d/S15kvmhwd /etc/init.d/");
system("cp -f /kvmapp/system/init.d/S30eth /etc/init.d/");
system("cp -f /kvmapp/system/init.d/S50sshd /etc/init.d/");
if(kvm_wifi_exist()) {
system("cp -f /kvmapp/system/init.d/S30wifi /etc/init.d/");
} else {
system("rm -f /etc/init.d/S30wifi");
}
// rmmod soph_saradc
system("rmmod soph_saradc");
system("rm -f /mnt/system/ko/soph_saradc.ko");
// PCIe Patch
// system("cp /kvmapp/system/init.d/S95nanokvm /etc/init.d/");
if(access("/kvmapp/jpg_stream/dl_lib/libmaixcam_lib.so", F_OK) != 0){
system("cp -f /kvmapp/system/init.d/S95nanokvm /etc/init.d/");
}
// Remove unnecessary components to speed up boot time
system("rm -f /etc/init.d/S04backlight");
system("rm -f /etc/init.d/S05tp");
system("rm -f /etc/init.d/S40bluetoothd");
system("rm -f /etc/init.d/S50ssdpd");
system("rm -f /etc/init.d/S99*");
// Add necessary configuration files for program execution
system("mkdir /kvmapp/kvm");
system("mkdir /etc/kvm");
system("echo 0 > /kvmapp/kvm/now_fps");
system("echo 30 > /kvmapp/kvm/fps");
system("echo 2000 > /kvmapp/kvm/qlty");
system("echo 720 > /kvmapp/kvm/res");
system("echo h264 > /kvmapp/kvm/type");
system("echo 0 > /kvmapp/kvm/state");
system("touch /etc/kvm/frame_detact");
// rm jpg_stream & kvm_stream
system("rm -rf /kvmapp/jpg_stream");
system("rm -f /kvmapp/kvm_system/kvm_stream"); // Cannot delete temporarily; the old production test script uses this file to determine if the download is complete
system("rm -f /kvmapp/kvm_new_app");
system("sync");
// system("/etc/init.d/S95nanokvm restart");
// update ko
FILE *fp;
uint8_t RW_Data_0[30];
uint8_t RW_Data_1[30];
fp = popen("md5sum /mnt/system/ko/soph_mipi_rx.ko | grep 086ed01749188975afaa40fb569374f8 | awk '{print $2}'", "r");
if ( NULL == fp )
{
pclose(fp);
// return;
}
fgets((char*)RW_Data_0, 10, fp);
pclose(fp);
fp = popen("md5sum /mnt/system/ko/soph_mipi_rx.ko | grep 69be7eeded3777f750480a5dd5a1aa26 | awk '{print $2}'", "r");
if ( NULL == fp )
{
pclose(fp);
// return;
}
fgets((char*)RW_Data_1, 10, fp);
pclose(fp);
int8_t hdmi_ver = -1;
if(access("/etc/kvm/hdmi_version", F_OK) == 0){
uint8_t RW_Data[2];
FILE *fp = fopen("/etc/kvm/hdmi_version", "r");
fread(RW_Data, sizeof(char), 2, fp);
fclose(fp);
if(RW_Data[0] == 'c') hdmi_ver = 1;
else if(RW_Data[0] == 'u') hdmi_ver = 2;
}
// system("/etc/init.d/S03usbdev stop_start");
create_temp_watchdog();
if(hdmi_ver == 2){
if(RW_Data_1[0] != '/'){
system("cp /kvmapp/system/ko/soph_mipi_rx.ko /mnt/system/ko/soph_mipi_rx.ko");
system("sync");
system("reboot");
} else {
system("sync");
system("/etc/init.d/S15kvmhwd start");
system("/etc/init.d/S95nanokvm restart");
}
} else {
if((RW_Data_0[0] != '/') && (RW_Data_1[0] != '/')){
system("cp /kvmapp/system/ko/soph_mipi_rx.ko /mnt/system/ko/soph_mipi_rx.ko");
system("sync");
system("reboot");
} else {
system("sync");
system("/etc/init.d/S15kvmhwd start");
system("/etc/init.d/S95nanokvm restart");
}
}
if(access("/root/old/kvm_new_img", F_OK) == 0){
system("rm -r /root/old");
}
system("sync");
system("killall NanoKVM-Server");
system("rm -r /tmp/server");
system("cp -r /kvmapp/server /tmp/");
system("/tmp/server/NanoKVM-Server &");
}
void build_complete_resolv(void)
{
FILE *fp = NULL;
// fp = fopen("/boot/resolv.conf", "w+");
fp = fopen("/boot/resolv.conf", "w");
// 阿里: 223.5.5.5
// 腾讯: 119.29.29.29
fprintf(fp, "nameserver 192.168.0.1\nnameserver 8.8.4.4\nnameserver 8.8.8.8\nnameserver 114.114.114.114\nnameserver 119.29.29.29\nnameserver 223.5.5.5");
fclose(fp);
system("rm -rf /etc/resolv.conf");
system("cp -vf /etc/resolv.conf /etc/resolv.conf.old");
system("cp -vf /boot/resolv.conf /etc/resolv.conf");
}
void new_img_init(void)
{
build_complete_resolv();
system("rm /kvmapp/kvm_new_img");
}

View File

@@ -0,0 +1,9 @@
#ifndef SYSTEM_INIT_H_
#define SYSTEM_INIT_H_
#include "config.h"
void new_img_init(void);
void new_app_init(void);
void Production_testing_patch(void);
#endif // SYSTEM_INIT_H_

View File

@@ -0,0 +1,522 @@
#include "config.h"
#include "system_state.h"
#include <sys/socket.h>
#include <net/if.h>
#include <sys/ioctl.h>
using namespace maix;
using namespace maix::sys;
extern kvm_sys_state_t kvm_sys_state;
extern kvm_oled_state_t kvm_oled_state;
int get_nic_state(const char* interface_name)
{
int sock;
struct ifreq ifr;
int ret = NIC_STATE_NO_EXIST;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
return ret;
}
strcpy(ifr.ifr_name, interface_name);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
close(sock);
return ret;
}
if (ifr.ifr_flags & IFF_UP) {
if (ifr.ifr_flags & IFF_RUNNING) {
ret = NIC_STATE_RUNNING;
} else {
ret = NIC_STATE_UP;
}
} else {
ret = NIC_STATE_DOWN;
}
close(sock);
return ret;
}
int get_ping_allow_state(void)
{
if(access("/etc/kvm/stop_ping", F_OK) == 0) {
kvm_sys_state.ping_allow = 0;
} else {
kvm_sys_state.ping_allow = 1;
}
return kvm_sys_state.ping_allow;
}
// net_port
int get_ip_addr(ip_addr_t ip_type)
{
switch (ip_type){
case ETH_IP: // eth_addr
if(strcmp(ip_address()["eth0"].c_str(), (char*)kvm_sys_state.eth_addr) != 0){
if(*(ip_address()["eth0"].c_str()) == 0){
printf("can`t get ip addr\r\n");
kvm_sys_state.eth_addr[0] = 0;
return 0;
}
for(int i = 0; i <= 15; i++)
{
kvm_sys_state.eth_addr[i] = *(ip_address()["eth0"].c_str() + i);
printf("%c", kvm_sys_state.eth_addr[i]);
}
printf("\r\n");
}
return 1;
case WiFi_IP: // wifi_addr
if(strcmp(ip_address()["wlan0"].c_str(), (char*)kvm_sys_state.wifi_addr) != 0){
if(*(ip_address()["wlan0"].c_str()) == 0){
printf("can`t get ip addr\r\n");
kvm_sys_state.wifi_addr[0] = 0;
return 0;
}
for(int i = 0; i <= 15; i++)
{
kvm_sys_state.wifi_addr[i] = *(ip_address()["wlan0"].c_str() + i);
printf("%c", kvm_sys_state.wifi_addr[i]);
}
printf("\r\n");
}
return 1;
case Tailscale_IP: // tail_addr
if(*(ip_address()["tailscale0"].c_str()) == 0){
printf("can`t get ip addr\r\n");
kvm_sys_state.tail_addr[0] = 0;
return 0;
}
for(int i = 0; i <= 15; i++)
{
kvm_sys_state.tail_addr[i] = *(ip_address()["tailscale0"].c_str() + i);
printf("%c", kvm_sys_state.tail_addr[i]);
}
printf("\r\n");
return 1;
case RNDIS_IP: // rndis_addr
if(*(ip_address()["usb0"].c_str()) == 0){
printf("can`t get ip addr\r\n");
kvm_sys_state.rndis_addr[0] = 0;
return 0;
}
for(int i = 0; i <= 15; i++)
{
kvm_sys_state.rndis_addr[i] = *(ip_address()["usb0"].c_str() + i);
printf("%c", kvm_sys_state.rndis_addr[i]);
}
printf("\r\n");
return 1;
case ETH_ROUTE: // eth_route
if(access("/etc/kvm/gateway", F_OK) != 0){
// 不存在gateway文件
memset( kvm_sys_state.eth_route, 0, sizeof( kvm_sys_state.eth_route ) );
char Cmd[100]={0};
memset( Cmd, 0, sizeof( Cmd ) );
sprintf( Cmd,"ip route | grep -i '^default' | grep -i 'eth0' | awk '{print $3}'");
FILE* fp = popen( Cmd, "r" );
if ( NULL == fp )
{
pclose(fp);
return 0;
}
memset( kvm_sys_state.eth_route, 0, sizeof( kvm_sys_state.eth_route ) );
while ( NULL != fgets( (char*)kvm_sys_state.eth_route,sizeof( kvm_sys_state.eth_route ),fp ))
{
// printf("ip=%s\n",kvm_sys_state.eth_route);
break;
}
if(kvm_sys_state.eth_route[0] == 0){
// 开机时未插入ETH
pclose(fp);
return 0;
}
for(int i = 0; i < 40; i++){
if(kvm_sys_state.eth_route[i] == 10){
kvm_sys_state.eth_route[i] = ' ';
break;
}
}
pclose(fp);
return 1;
} else {
int file_size;
FILE *fp = fopen("/etc/kvm/gateway", "r");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(kvm_sys_state.eth_route, sizeof(char), file_size, fp);
fclose(fp);
return 1;
}
case WiFi_ROUTE: // wifi_route
memset( kvm_sys_state.wifi_route, 0, sizeof( kvm_sys_state.wifi_route ) );
char Cmd[100]={0};
memset( Cmd, 0, sizeof( Cmd ) );
sprintf( Cmd,"ip route | grep -i '^default' | grep -i 'wlan0' | awk '{print $3}'");
FILE* fp = popen( Cmd, "r" );
if ( NULL == fp )
{
pclose(fp);
return 0;
}
memset( kvm_sys_state.wifi_route, 0, sizeof( kvm_sys_state.wifi_route ) );
while ( NULL != fgets( (char*)kvm_sys_state.wifi_route,sizeof( kvm_sys_state.wifi_route ),fp ))
{
// printf("ip=%s\n",kvm_sys_state.wifi_route);
break;
}
if(kvm_sys_state.wifi_route[0] == 0){
// 开机时未插入ETH
pclose(fp);
return 0;
}
for(int i = 0; i < 40; i++){
if(kvm_sys_state.wifi_route[i] == 10){
kvm_sys_state.wifi_route[i] = ' ';
break;
}
}
pclose(fp);
return 1;
}
return 0;
}
int chack_net_state(ip_addr_t use_ip_type)
{
char Cmd[100]={0};
if (use_ip_type == ETH_ROUTE) sprintf( Cmd,"ping -I eth0 -w 1 %s > /dev/null", kvm_sys_state.eth_route);
else if (use_ip_type == WiFi_ROUTE) sprintf( Cmd,"ping -I wlan0 -w 1 %s > /dev/null", kvm_sys_state.wifi_route);
else return -1; // 不支持的端口
if(system(Cmd) == 0){ // 256不通 = 0
return 1;
}
return 0;
}
void patch_eth_wifi(void)
{
// system("ip link set eth0 down");
// system("ip link set eth0 up");
// system("udhcpc -i eth0 &");
}
int kvm_wifi_exist()
{
if (get_nic_state("wlan0") == NIC_STATE_NO_EXIST) return 0;
else return 1;
}
void kvm_update_usb_state()
{
// usb_state, hid_state, rndis_state, udisk_state
FILE *fp;
int file_size;
uint8_t RW_Data[10];
fp = fopen("/sys/class/udc/4340000.usb/state", "r");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(RW_Data, sizeof(char), file_size, fp);
fclose(fp);
if(RW_Data[0] == 'n') kvm_sys_state.usb_state = 0;
else if(RW_Data[0] == 'c') kvm_sys_state.usb_state = 1;
else kvm_sys_state.usb_state = -1;
// hid_state & udisk_state (rndis_state单独处理)
if(kvm_sys_state.usb_state == 1){
if(access("/sys/kernel/config/usb_gadget/g0/configs/c.1/hid.GS*", F_OK) == 0)
kvm_sys_state.hid_state = 1;
if(access("/sys/kernel/config/usb_gadget/g0/configs/c.1/mass_storage.disk0", F_OK) == 0)
kvm_sys_state.udisk_state = 1;
} else {
kvm_sys_state.hid_state = 0;
kvm_sys_state.udisk_state = 0;
}
}
void kvm_update_hdmi_state()
{
static uint8_t check_times = 4;
FILE *fp;
int file_size;
uint8_t RW_Data[10];
if(++check_times > 5){
check_times = 0;
fp = popen("cat /proc/cvitek/vi_dbg | grep VIFPS | awk '{print $3}'", "r");
if (fp == NULL) {
pclose(fp);
return;
}
fgets((char*)RW_Data, 2, fp);
pclose(fp);
// printf("[kvmd]HDMI exist? %c\n", RW_Data[0]);
if (RW_Data[0] != '0'){
kvm_sys_state.hdmi_state = 1;
} else {
kvm_sys_state.hdmi_state = 0;
}
}
}
void kvm_update_stream_fps(void)
{
FILE *fp;
int file_size;
uint8_t RW_Data[10];
// FPS
fp = fopen("/kvmapp/kvm/now_fps", "r");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(RW_Data, sizeof(char), file_size, fp);
fclose(fp);
RW_Data[file_size] = 0;
kvm_sys_state.now_fps = atoi((char*)RW_Data);
}
void kvm_update_stream_type(void)
{
FILE *fp;
int file_size;
uint8_t RW_Data[10];
// type
fp = fopen("/kvmapp/kvm/type", "r");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(RW_Data, sizeof(char), file_size, fp);
fclose(fp);
if(RW_Data[0] == 'm') kvm_sys_state.type = KVM_TYPE_MJPG;
else if(RW_Data[0] == 'h') kvm_sys_state.type = KVM_TYPE_H264;
else kvm_sys_state.type = KVM_TYPE_none;
}
void kvm_update_stream_qlty(void)
{
FILE *fp;
int file_size;
uint8_t RW_Data[10];
uint16_t tmp16;
// QLTY
fp = fopen("/kvmapp/kvm/qlty", "r");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(RW_Data, sizeof(char), file_size, fp);
fclose(fp);
RW_Data[file_size] = 0;
tmp16 = atoi((char*)RW_Data);
if(kvm_sys_state.type == KVM_TYPE_MJPG){
if(tmp16 < 60) kvm_sys_state.qlty = 1;
else if(tmp16 >= 60 && tmp16 < 75) kvm_sys_state.qlty = 2;
else if(tmp16 >= 75 && tmp16 < 90) kvm_sys_state.qlty = 3;
else if(tmp16 >= 90 && tmp16 <= 100) kvm_sys_state.qlty = 4;
else kvm_sys_state.qlty = 4;
} else {
if(tmp16 < 1500) kvm_sys_state.qlty = 1;
else if(tmp16 >= 1500 && tmp16 < 2500) kvm_sys_state.qlty = 2;
else if(tmp16 >= 2500 && tmp16 < 3500) kvm_sys_state.qlty = 3;
else if(tmp16 >= 3500 && tmp16 <= 5000) kvm_sys_state.qlty = 4;
else kvm_sys_state.qlty = 4;
}
}
void kvm_update_hdmi_res(void)
{
FILE *fp;
int file_size;
uint8_t RW_Data[10];
// HDMI width
fp = fopen("/kvmapp/kvm/width", "r");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(RW_Data, sizeof(char), file_size, fp);
fclose(fp);
RW_Data[file_size] = 0;
kvm_sys_state.hdmi_width = atoi((char*)RW_Data);
// HDMI height
fp = fopen("/kvmapp/kvm/height", "r");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(RW_Data, sizeof(char), file_size, fp);
fclose(fp);
RW_Data[file_size] = 0;
kvm_sys_state.hdmi_height = atoi((char*)RW_Data);
}
void kvm_update_eth_state(void)
{
static uint8_t nic_state = 0;
nic_state = get_nic_state("eth0");
if(nic_state == NIC_STATE_RUNNING){
// Get IP
if(strcmp(ip_address()["eth0"].c_str(), (char*)kvm_sys_state.eth_addr) != 0){
if(get_ip_addr(ETH_IP)){
kvm_sys_state.eth_state = 2;
} else {
kvm_sys_state.eth_state = 1;
return;
}
}
if(kvm_sys_state.ping_allow){
// ping route
if(kvm_sys_state.eth_route[0] == 0){
get_ip_addr(ETH_ROUTE);
} else {
if(chack_net_state(ETH_ROUTE)){
// Ping successful
kvm_sys_state.eth_state = 3;
} else {
kvm_sys_state.eth_state = 2;
}
}
} else {
// Consider the network to be connected
kvm_sys_state.eth_state = 3;
}
} else {
kvm_sys_state.eth_state = 0;
patch_eth_wifi();
}
}
void kvm_update_wifi_state(void)
{
// No WiFi module (check for existence?) -> Module exists & not connected (check if connected) ->
if(kvm_sys_state.wifi_state == -2) return;
switch (kvm_sys_state.wifi_state){
case -1:
// Initial default value.
if (kvm_wifi_exist()) {
kvm_sys_state.wifi_state = 0;
system("touch /etc/kvm/wifi_exist");
}
else {
kvm_sys_state.wifi_state = -2; // WiFi module does not exist, exiting directly.
system("rm /etc/kvm/wifi_exist");
return;
}
// break; // Start checking the connection directly.
case 0:
// WiFi is available but not connected.
system("echo 0 > /kvmapp/kvm/wifi_state");
if (get_ip_addr(WiFi_IP) && get_ip_addr(WiFi_ROUTE)){
// IP+Route has been acquired
if(kvm_sys_state.ping_allow){
if (chack_net_state(WiFi_ROUTE)){
// Ping successful
kvm_sys_state.wifi_state = 1;
}
} else {
// Consider the network to be connected
kvm_sys_state.wifi_state = 1;
}
}
break;
case 1:
// Connected to the network & continuously checking if it can ping successfully.
system("echo 1 > /kvmapp/kvm/wifi_state");
get_ip_addr(WiFi_IP);
if(kvm_sys_state.ping_allow){
if (kvm_sys_state.wifi_route[0] != 0){
if (chack_net_state(WiFi_ROUTE) == 0){
// Ping successful
kvm_sys_state.wifi_state = 0;
}
}
}
// default:
// kvm_sys_state.wifi_state = -1;
}
}
void kvm_update_rndis_state(void)
{
if (get_nic_state("usb0") == NIC_STATE_RUNNING) {
if(kvm_sys_state.rndis_state != 1) {
if (get_ip_addr(RNDIS_IP)) {
kvm_sys_state.rndis_state = 1;
}
}
}
else kvm_sys_state.rndis_state = 0;
}
void kvm_update_tailscale_state(void)
{
if (get_nic_state("tailscale0") == NIC_STATE_RUNNING) {
if(kvm_sys_state.tail_state != 1){
if (get_ip_addr(Tailscale_IP)) {
kvm_sys_state.tail_state = 1;
}
}
}
else kvm_sys_state.tail_state = 0;
}
//============================================================================
uint8_t ion_free_space(void)
{
//cat /sys/kernel/debug/ion/cvi_carveout_heap_dump/summary | grep "usage rate:" | awk '{print $2}'
return 0;
}
int create_temp_watchdog(void)
{
FILE *file;
file = fopen(watchdog_temp_path, "w");
if (file == NULL) {
printf("[kvmv] Temp watchdog create error\n");
return -1;
}
// fprintf(file, "%s", 'v');
fclose(file);
return 1;
}
void rm_temp_watchdog(void)
{
if(access(watchdog_temp_path, F_OK) == 0) {
remove(watchdog_temp_path);
}
}
void auto_remove_temp_watchdog(void)
{
static uint8_t run_times = 0;
static uint8_t temp_watchdog_removed = 0;
if(temp_watchdog_removed) return;
if(run_times++ >= RM_Watchdog_times){
run_times = 0;
temp_watchdog_removed = 1;
rm_temp_watchdog();
}
}
uint8_t watchdog_sf_is_open(void)
{
if(access(watchdog_mode_path, F_OK) == 0) return 1;
if(access(watchdog_temp_path, F_OK) == 0) return 1;
else return 0;
}
int check_watchdog()
{
if(access(watchdog_file, F_OK) == 0) {
if (remove(watchdog_file) == 0) {
return 1;
} else {
return -1;
}
} else return 0;
}

View File

@@ -0,0 +1,44 @@
#ifndef SYSTEM_STATE_H_
#define SYSTEM_STATE_H_
#include "config.h"
enum ip_addr_t
{
ETH_IP=1, WiFi_IP, Tailscale_IP, RNDIS_IP, ETH_ROUTE, WiFi_ROUTE, NULL_IP
};
#define NIC_STATE_UP 1
#define NIC_STATE_DOWN 0
#define NIC_STATE_RUNNING 2
#define NIC_STATE_UNKNOWN -1
#define NIC_STATE_NO_EXIST -2
#define watchdog_mode_path "/etc/kvm/watchdog"
#define watchdog_temp_path "/tmp/watchdog"
#define watchdog_file "/tmp/nanokvm_wd"
// net_port
int get_ip_addr(ip_addr_t ip_type);
int chack_net_state(ip_addr_t use_ip_type);
int get_ping_allow_state(void);
void patch_eth_wifi(void);
int kvm_wifi_exist(void);
void kvm_update_usb_state(void);
void kvm_update_hdmi_state(void);
void kvm_update_stream_fps(void);
void kvm_update_stream_type(void);
void kvm_update_stream_qlty(void);
void kvm_update_hdmi_res(void);
void kvm_update_eth_state(void);
void kvm_update_wifi_state(void);
void kvm_update_rndis_state(void);
void kvm_update_tailscale_state(void);
uint8_t ion_free_space(void);
int get_nic_state(const char* interface_name);
int create_temp_watchdog(void);
void rm_temp_watchdog(void);
void auto_remove_temp_watchdog(void);
uint8_t watchdog_sf_is_open(void);
int check_watchdog();
#endif // SYSTEM_STATE_H_

View File

@@ -0,0 +1,264 @@
#include "config.h"
using namespace maix;
using namespace maix::sys;
using namespace maix::peripheral;
kvm_sys_state_t kvm_sys_state;
kvm_oled_state_t kvm_oled_state;
void build_recovery(void)
{
uint8_t need_recovery = 0;
if (access("/recovery", F_OK) != 0) {
printf("unexist /recovery\n");
mkdir("/recovery", 0777);
need_recovery = 1;
} else {
printf("exist /recovery\n");
}
}
void* thread_oled_handle(void * arg)
{
OLED_Init();
OLED_ColorTurn(0); //0正常显示 1 反色显示
OLED_DisplayTurn(0); //0正常显示 1 屏幕翻转显示
OLED_Clear();
if(kvm_oled_state.ue_patch_state == 1){
kvm_show_UE();
while(kvm_sys_state.oled_thread_running){
time::sleep_ms(100);
}
OLED_Clear();
}
while(kvm_sys_state.oled_thread_running)
{
oled_auto_sleep();
// printf("[kvmd]thread_oled_handle - while\n");
uint8_t page_changed = (kvm_oled_state.page == kvm_sys_state.page)? 0:1;
uint8_t subpage_changed = (kvm_oled_state.sub_page == kvm_sys_state.sub_page)? 0:1;
// printf("subpage_changed = %d", subpage_changed);
// printf("kvm_oled_state.sub_page = %d", kvm_oled_state.sub_page);
// printf("kvm_sys_state.sub_page = %d\n", kvm_sys_state.sub_page);
kvm_oled_state.page = kvm_sys_state.page;
kvm_oled_state.sub_page = kvm_sys_state.sub_page;
switch(kvm_oled_state.page){
case 0 : // main page
kvm_main_ui_disp(page_changed, subpage_changed);
break;
case 1 : // wifi config page
kvm_wifi_config_ui_disp(page_changed, subpage_changed);
break;
default:
OLED_Clear();
}
time::sleep_ms(OLED_DELAY);
}
OLED_Clear();
kvm_sys_state.oled_thread_running = -1;
}
void* thread_key_handle(void * arg)
{
uint64_t __attribute__((unused)) press_time;
uint32_t press_cycle;
int fd = open ("/dev/input/event0", O_RDONLY);
if (fd == -1) {
kvm_sys_state.key_thread_running = 0;
}
struct input_event event;
while(kvm_sys_state.key_thread_running)
{
read (fd, &event, sizeof (event));
if (event.type == EV_KEY) {
if (event.value == 1){
// printf ("[kvmk]按键按下\n");
press_time = time::time_ms();
} else if (event.value == 0){
oled_auto_sleep_time_update();
// printf ("[kvmk]按键抬起\n");
press_cycle = time::time_ms() - press_time;
if(press_cycle >= KEY_LONGLONG_PRESS){
kvm_reset_password();
} else if (press_cycle >= KEY_LONG_PRESS && press_cycle < KEY_LONGLONG_PRESS){
// long
// printf ("[kvmk]按键长按\n");
// printf("[kvmk]wifi_state = %d\n", kvm_sys_state.wifi_state);
if(kvm_sys_state.wifi_state == -2){
kvm_sys_state.page = 0;
kvm_sys_state.sub_page = 0;
continue;
}
switch(kvm_sys_state.page){
case 0: // main page
kvm_sys_state.page = 1;
kvm_sys_state.sub_page = 0;
break;
case 1: // wifi coonfig page
system("/etc/init.d/S30wifi restart");
kvm_sys_state.page = 0;
kvm_sys_state.sub_page = 0;
kvm_sys_state.wifi_config_process = -1;
break;
}
} else {
// short
// printf ("[kvmk]按键短按\n");
// printf ("[kvmk]wifi_config_process = %d\n", kvm_sys_state.wifi_config_process);
// printf ("[kvmk]page = %d\n", kvm_sys_state.page);
// printf ("[kvmk]sub_page = %d\n", kvm_sys_state.sub_page);
switch(kvm_sys_state.page){
case 0: // main page
if(kvm_sys_state.sub_page == 0) kvm_sys_state.sub_page = 1;
else kvm_sys_state.sub_page = 0;
break;
case 1: // wifi coonfig page
switch(kvm_sys_state.wifi_config_process){
case 1: // QR1<->TEXT2
if(kvm_sys_state.sub_page == 1) kvm_sys_state.sub_page = 2;
else kvm_sys_state.sub_page = 1;
// printf("[kvmk]sub_page = %d\n", kvm_sys_state.sub_page);
break;
case 2:
if(kvm_sys_state.sub_page == 1) kvm_sys_state.sub_page = 2;
else if(kvm_sys_state.sub_page == 2) kvm_sys_state.sub_page = 3;
else if(kvm_sys_state.sub_page == 3) kvm_sys_state.sub_page = 4;
else kvm_sys_state.sub_page = 1;
break;
}
break;
}
}
}
}
time::sleep_ms(KEY_DELAY);
}
kvm_sys_state.key_thread_running = 0;
}
void* thread_sys_handle(void * arg)
{
get_ping_allow_state();
while(kvm_sys_state.sys_thread_running)
{
// net
if(kvm_sys_state.page == 0){
kvm_update_eth_state();
kvm_update_wifi_state();
// kvm_update_rndis_state();
// kvm_update_tailscale_state();
// sys_state
kvm_update_usb_state();
kvm_update_hdmi_state();
kvm_update_stream_fps();
kvm_update_hdmi_res();
kvm_update_stream_type();
kvm_update_stream_qlty();
kvm_wifi_web_config_process();
} else if(kvm_sys_state.page == 1){
kvm_wifi_config_process();
}
time::sleep_ms(STATE_DELAY);
auto_remove_temp_watchdog();
}
kvm_sys_state.sys_thread_running = 0;
}
int main(int argc, char* argv[])
{
// Catch SIGINT signal(e.g. Ctrl + C), and set exit flag to true.
signal(SIGINT, [](int sig){
kvm_sys_state.oled_thread_running = 0;
kvm_sys_state.key_thread_running = 0;
kvm_sys_state.sys_thread_running = 0;
app::set_exit_flag(true);
log::info("[kvms]Prepare to exit\n");
});
pthread_t sys_state_thread;
pthread_t display_thread;
pthread_t key_thread;
// Execute only when it's a new image
if(access("/kvmapp/kvm_new_img", F_OK) == 0){
new_img_init();
}
// Execute only when it's a new app
if(access("/kvmapp/kvm_new_app", F_OK) == 0){
new_app_init();
}
// only for production testing
if (access("/tmp/S49kvmtest", F_OK) == 0){
printf("Production testing patch\n");
Production_testing_patch();
}
system("sync");
OLED_state = oled_exist();
if(OLED_state){
printf("oled exist\r\n");
system("touch /etc/kvm/oled_exist");
} else {
printf("oled not exist\r\n");
system("rm /etc/kvm/oled_exist");
}
if(kvm_sys_state.sys_thread_running == 0){
kvm_sys_state.sys_thread_running = 1;
if (0 != pthread_create(&sys_state_thread, NULL, thread_sys_handle, NULL)) {
kvm_sys_state.sys_thread_running = 0;
printf("[kvms]create thread failed!\r\n");
}
}
if(OLED_state == 1 && kvm_sys_state.oled_thread_running == 0){
kvm_sys_state.oled_thread_running = 1;
if (0 != pthread_create(&display_thread, NULL, thread_oled_handle, NULL)) {
kvm_sys_state.oled_thread_running = 0;
printf("[kvms]create thread failed!\r\n");
}
}
if(kvm_sys_state.key_thread_running == 0){
kvm_sys_state.key_thread_running = 1;
if (0 != pthread_create(&key_thread, NULL, thread_key_handle, NULL)) {
kvm_sys_state.key_thread_running = 0;
printf("[kvms]create thread failed!\r\n");
}
}
// while(!app::need_exit()){
uint8_t kvm_wd_count = 0;
int kvm_wd_state = 0;
while(kvm_sys_state.sys_thread_running){
time::sleep_ms(1000);
if(watchdog_sf_is_open()){
kvm_wd_state = check_watchdog();
if(kvm_wd_state == 1) kvm_wd_count = 0;
else if(kvm_wd_state == 0) {
kvm_wd_count++;
printf("Vision service unresponsive : %d\n", kvm_wd_count);
}
if(kvm_wd_count > KVM_WD_COUNT_MAX){
printf("Vision service unresponsive, restart now\n");
system("reboot");
}
} else {
kvm_wd_count = 0;
}
}
kvm_sys_state.sys_thread_running = 0;
kvm_sys_state.oled_thread_running = 0;
kvm_sys_state.key_thread_running = 0;
while(kvm_sys_state.oled_thread_running != -1) time::sleep_ms(100);
}

View File

@@ -0,0 +1,74 @@
############### Add include ###################
list(APPEND ADD_INCLUDE "include"
)
list(APPEND ADD_PRIVATE_INCLUDE "")
###############################################
############ Add source files #################
# list(APPEND ADD_SRCS "src/main.c"
# "src/test.c"
# )
append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS
# list(REMOVE_ITEM COMPONENT_SRCS "src/test2.c")
# FILE(GLOB_RECURSE EXTRA_SRC "src/*.c")
# FILE(GLOB EXTRA_SRC "src/*.c")
# list(APPEND ADD_SRCS ${EXTRA_SRC})
# aux_source_directory(src ADD_SRCS) # collect all source file in src dir, will set var ADD_SRCS
# append_srcs_dir(ADD_SRCS "src") # append source file in src dir to var ADD_SRCS
# list(REMOVE_ITEM COMPONENT_SRCS "src/test.c")
# set(ADD_ASM_SRCS "src/asm.S")
# list(APPEND ADD_SRCS ${ADD_ASM_SRCS})
# SET_PROPERTY(SOURCE ${ADD_ASM_SRCS} PROPERTY LANGUAGE C) # set .S ASM file as C language
# SET_SOURCE_FILES_PROPERTIES(${ADD_ASM_SRCS} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp -D BBBBB")
###############################################
###### Add required/dependent components ######
list(APPEND ADD_REQUIREMENTS basic peripheral kvm)
###############################################
###### Add link search path for requirements/libs ######
# list(APPEND ADD_LINK_SEARCH_PATH "${CONFIG_TOOLCHAIN_PATH}/lib")
# list(APPEND ADD_REQUIREMENTS pthread m) # add system libs, pthread and math lib for example here
# set (OpenCV_DIR opencv/lib/cmake/opencv4)
# find_package(OpenCV REQUIRED)
###############################################
############ Add static libs ##################
# list(APPEND ADD_STATIC_LIB "lib/libtest.a")
###############################################
#### Add compile option for this component ####
#### Just for this component, won't affect other
#### modules, including component that depend
#### on this component
# list(APPEND ADD_DEFINITIONS_PRIVATE -DAAAAA=1)
#### Add compile option for this component
#### and components denpend on this component
# list(APPEND ADD_DEFINITIONS -DAAAAA222=1
# -DAAAAA333=1)
###############################################
############ Add static libs ##################
#### Update parent's variables like CMAKE_C_LINK_FLAGS
# set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group libmaix/libtest.a -ltest2 -Wl,--end-group" PARENT_SCOPE)
###############################################
######### Add files need to download #########
# list(APPEND ADD_FILE_DOWNLOADS "{
# 'url': 'https://*****/abcde.tar.xz',
# 'urls': [], # backup urls, if url failed, will try urls
# 'sites': [], # download site, user can manually download file and put it into dl_path
# 'sha256sum': '',
# 'filename': 'abcde.tar.xz',
# 'path': 'toolchains/xxxxx',
# 'check_files': []
# }"
# )
#
# then extracted file in ${DL_EXTRACTED_PATH}/toolchains/xxxxx,
# you can directly use then, for example use it in add_custom_command
##############################################
# register component, DYNAMIC or SHARED flags will make component compiled to dynamic(shared) lib
register_component()

View File

@@ -0,0 +1,61 @@
#include "kvm_vision.h"
#include "maix_basic.hpp"
using namespace maix;
using namespace maix::sys;
// #define NOT_GET_IMG
int main(int argc, char* argv[])
{
uint64_t __attribute__((unused)) start_time;
// Catch SIGINT signal(e.g. Ctrl + C), and set exit flag to true.
signal(SIGINT, [](int sig){ app::set_exit_flag(true);
log::info("========================\n");
});
kvmv_hdmi_control(0);
kvmv_hdmi_control(1);
kvmv_init(0);
set_h264_gop(30);
uint16_t get_fream_count = 0;
while(!app::need_exit()){
#ifdef NOT_GET_IMG
printf("NOT_GET_IMG ...\n");
time::sleep_ms(1000);
#else
uint8_t* p_kvmv_img_data;
uint32_t kvmv_img_data_size;
int ret;
printf("KVM-Vison Get Fream ...\n");
start_time = time::time_ms();
if(get_fream_count < 1){
get_fream_count ++;
ret = kvmv_read_img(1920, 1080, 1, 3000, &p_kvmv_img_data, &kvmv_img_data_size);
} else if(get_fream_count >= 1 && get_fream_count < 2){
get_fream_count ++;
ret = kvmv_read_img(0, 0, 0, 60, &p_kvmv_img_data, &kvmv_img_data_size);
} else {
get_fream_count = 0;
}
// printf("kvmv_read_img(): %d \r\n", (int)(time::time_ms() - start_time));
// ret = kvmv_read_img(1920, 1080, 1, 3000, &p_kvmv_img_data, &kvmv_img_data_size);
// ret = kvmv_read_img(1920, 1080, 0, 60, &p_kvmv_img_data, &kvmv_img_data_size);
printf("kvmv_read_img ret = %d\n", ret);
// send...
// if(ret >= 0){
free_kvmv_data(&p_kvmv_img_data);
// }
#endif
}
kvmv_deinit();
}