Initiate version

This commit is contained in:
CSSC-WORK\murmur 2024-11-30 10:15:30 +08:00
parent 89d39daeb4
commit 6c5fc45750
5 changed files with 477 additions and 0 deletions

197
decode.c Normal file
View File

@ -0,0 +1,197 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <windows.h>
// 定义缓冲区大小(可以根据实际需求调整)
#define BUFFER_SIZE 1024 // 每次读取1024条记录
// MPU传感器数据结构
typedef struct {
int16_t ax; // 加速度计 X轴
int16_t ay; // 加速度计 Y轴
int16_t az; // 加速度计 Z轴
int16_t gx; // 陀螺仪 X轴
int16_t gy; // 陀螺仪 Y轴
int16_t gz; // 陀螺仪 Z轴
} sensor_data_t;
// 完整的数据记录结构
#pragma pack(1)
typedef struct {
uint8_t y; // 年相对值需要加上2000
uint8_t month; // 月
uint8_t d; // 日
uint8_t h; // 时
uint8_t m; // 分
uint8_t s; // 秒
uint16_t ms; // 毫秒
int16_t deepth; // 深度
sensor_data_t data; // MPU传感器数据
} info_t;
#pragma pack()
void print_usage() {
printf("用法:\n");
printf("decode.exe -f <文件名> [-o <输出文件名>]\n");
printf("选项:\n");
printf(" -f <文件名> 指定输入文件\n");
printf(" -o <文件名> 指定输出文件(可选,默认输出到与输入同名的.csv文件\n");
printf(" -h 显示帮助信息\n");
printf("\n示例:\n");
printf("decode.exe -f 20241112.BIN\n");
printf("decode.exe -f 20241112.BIN -o output.csv\n");
}
// 原有的decode函数保持不变
void decode(char *filename) {
FILE *file = fopen(filename, "rb");
if (!file) {
fprintf(stderr, "无法打开文件\n");
return;
}
// 获取文件大小
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
fseek(file, 0, SEEK_SET);
// 计算记录数量
int recordCount = fileSize / sizeof(info_t);
// 打印CSV格式的表头
printf("年,月,日,时,分,秒,毫秒,深度,ax,ay,az,gx,gy,gz\n");
// 使用缓冲区读取以提高效率
info_t buffer[BUFFER_SIZE];
size_t records_read;
while ((records_read = fread(buffer, sizeof(info_t), BUFFER_SIZE, file)) > 0) {
for (size_t i = 0; i < records_read; i++) {
// 直接使用小端序数据,无需转换
// 单字节数据y, month, d, h, m, s
// 双字节数据ms, deepth, ax, ay, az, gx, gy, gz 已经是正确的小端序
printf("%04d,%02d,%02d,%02d,%02d,%02d,%03d,%04d,%d,%d,%d,%d,%d,%d\n",
buffer[i].y + 2000, // 年份偏移2000
buffer[i].month, // 月
buffer[i].d, // 日
buffer[i].h, // 时
buffer[i].m, // 分
buffer[i].s, // 秒
buffer[i].ms, // 毫秒uint16_t
buffer[i].deepth, // 深度uint16_t
buffer[i].data.ax, // 加速度计xint16_t
buffer[i].data.ay, // 加速度计yint16_t
buffer[i].data.az, // 加速度计zint16_t
buffer[i].data.gx, // 陀螺仪xint16_t
buffer[i].data.gy, // 陀螺仪yint16_t
buffer[i].data.gz // 陀螺仪zint16_t
);
}
}
fclose(file);
fprintf(stderr, "共解析 %d 条记录\n", recordCount);
}
// 生成输出文件名
char* generate_output_filename(const char* input_file) {
size_t len = strlen(input_file);
char* output = (char*)malloc(len + 5); // +5 为了容纳 .csv 和结束符
// 复制输入文件名
strcpy(output, input_file);
// 找到最后一个点的位置
char* dot = strrchr(output, '.');
if (dot != NULL) {
// 如果找到点,在点的位置替换后缀
strcpy(dot, ".csv");
} else {
// 如果没有找到点,直接在末尾添加.csv
strcat(output, ".csv");
}
return output;
}
int main(int argc, char *argv[]) {
// 设置控制台输出代码页为 UTF-8
SetConsoleOutputCP(65001);
char *input_file = NULL;
char *output_file = NULL;
// 解析命令行参数
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0) {
print_usage();
return 0;
}
else if (strcmp(argv[i], "-f") == 0) {
if (i + 1 < argc) {
input_file = argv[i + 1];
i++;
} else {
printf("错误:-f 参数后需要指定文件名\n");
print_usage();
return 1;
}
}
else if (strcmp(argv[i], "-o") == 0) {
if (i + 1 < argc) {
output_file = argv[i + 1];
i++;
} else {
printf("错误:-o 参数后需要指定文件名\n");
print_usage();
return 1;
}
}
else {
fprintf(stderr, "错误:未知参数 %s\n", argv[i]);
print_usage();
return 1;
}
}
// 检查必需参数
if (input_file == NULL) {
fprintf(stderr, "错误:未指定输入文件\n");
print_usage();
return 1;
}
// 检查输入文件是否存在
FILE *file = fopen(input_file, "rb");
if (!file) {
printf("错误:无法打开输入文件 %s\n", input_file);
return 1;
}
fclose(file);
// 如果没有指定输出文件,生成默认的输出文件名
char *auto_output_file = NULL;
if (output_file == NULL) {
auto_output_file = generate_output_filename(input_file);
output_file = auto_output_file;
}
// 重定向标准输出到文件
if (freopen(output_file, "w", stdout) == NULL) {
printf("错误:无法创建输出文件 %s\n", output_file);
if (auto_output_file) free(auto_output_file);
return 1;
}
// 解析文件
decode(input_file);
// 清理
if (auto_output_file) {
free(auto_output_file);
}
return 0;
}

93
deepth.c Normal file
View File

@ -0,0 +1,93 @@
#include <stdio.h>
#include <stdlib.h> // 包含 strtof()
#include <string.h>
#include <stdint.h>
#define START_CMD 'start()'
#define STOP_CMD 'stop()'
/**
: $P=XXX.XXX空格;<><>
dbar
-+
$P=005.000 ;
$P=-01.000 ;
1000dbar 3 3 1000dabr 4
3
$P=999.999
$P=1000.000
**/
/**
* @brief dbar
* 1dbar=1.02m
* @param str "$P=6999.454 ;"
* @return dbar数值对应的深度值m
* INT16_MIN
*/
int16_t dbar2Deepth(char *str)
{
//char str[] = "$P=6999.454 ;";
char *start, *end;
float num;
int8_t err;
// 查找等号后的字符位置
start = strchr(str, '='); // 找到 '=' 的位置
if (start != NULL)
{
start++; // 跳过 '='
// 使用 strtof() 函数从字符串中提取浮点数
num = strtof(start, &end);
// 检查转换是否成功,并且确保后面是分号 ' '
if (*end == ' ')
{
printf("提取的dbar数值: %f\n", num);
err = 0;
}
else
{
err = 1;
printf("转换失败,剩余未转换的字符: %s\n", end);
}
}
else
{
err = -1;
printf("没有找到等号。\n");
}
if (err == 0 || err == 1)
{
//1dbar=1.02m
return (int16_t)(num * 1.02);
}
if (err == -1)
{
return INT16_MIN;
}
}
/**
* @brief
* dbar2Deepth() "$P=6999.454 ;" 转换为
* m
* @return m
*/
int16_t getDeepth() {
char str[] = "$P= 6999.454 ;";
return dbar2Deepth(str);
}
int main() {
// char str[] = "$P=-1999.454 ;";
printf("当前深度:%d\n", getDeepth());
}

109
demo/hamming.c Normal file
View File

@ -0,0 +1,109 @@
#include "hamming.h"
/**
* @brief 1
* @param byte
* @return 1
*/
static inline int countOnes(unsigned char byte) {
static const unsigned char ones[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
return ones[byte & 0x0F] + ones[byte >> 4];
}
/**
* @brief
* @param data
* @param size
* @param parity 3
* @note
* -
* -
*/
void calculateParity(const unsigned char *data, int size, unsigned char *parity) {
// 初始化校验位数组
memset(parity, 0, PARITY_BYTES);
int totalOnes = 0;
// 对每个数据字节
for(int i = 0; i < size; i++) {
unsigned char byte = data[i];
totalOnes += countOnes(byte);
// 对字节中的每一位
for(int j = 0; j < 8; j++) {
if(byte & (1 << j)) {
// 计算该位在整个数据中的位置
int bitPos = i * 8 + j;
// 更新相应的校验位
for(int k = 0; k < 20; k++) {
if(bitPos & (1 << k)) {
if(k < 8)
parity[0] ^= (1 << k);
else if(k < 16)
parity[1] ^= (1 << (k - 8));
else
parity[2] ^= (1 << (k - 16));
}
}
}
}
}
// 添加总体奇偶校验
if(totalOnes % 2) {
parity[2] |= 0x08; // 设置最高位
}
}
/**
* @brief
* @param data
* @param size
* @param parity
* @return
* 0 -
* 1 -
* -1 -
* -2 -
*/
int detectAndCorrect(unsigned char *data, int size, const unsigned char *parity) {
unsigned char currentParity[PARITY_BYTES];
calculateParity(data, size, currentParity);
// printf("parity: %02X %02X %02X\n", parity[2], parity[1], parity[0]);
// printf("currentParity: %02X %02X %02X\n", currentParity[2], currentParity[1], currentParity[0]);
// 计算syndrome
unsigned int syndrome = 0;
syndrome |= (currentParity[0] ^ parity[0]);
syndrome |= (currentParity[1] ^ parity[1]) << 8;
syndrome |= ((currentParity[2] ^ parity[2]) & 0x07) << 16;
// 检查总体奇偶校验
int parityError = ((currentParity[2] ^ parity[2]) & 0x08) ? 1 : 0;
if(syndrome == 0) {
if(parityError) {
return -2; // 检测到多位错误
}
return 0; // 无错误
}
if(!parityError) {
return -1; // 校验位错误syndrome不为0但奇偶校验正确
}
// 单比特错误
int bitPos = syndrome;
int bytePos = bitPos / 8;
int bitInByte = bitPos % 8;
if(bytePos < size) {
data[bytePos] ^= (1 << bitInByte);
// printf("纠正位置:字节 %d位 %d\n", bytePos, bitInByte);
return 1;
}
return -2; // 检测到多位错误
}

14
demo/hamming.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef HAMMING_H
#define HAMMING_H
#include <stdio.h>
#include <string.h>
#define PARITY_BYTES 3 // 3字节校验位
// 函数声明
void calculateParity(const unsigned char *data, int size, unsigned char *parity);
int detectAndCorrect(unsigned char *data, int size, const unsigned char *parity);
#endif // HAMMING_H

64
demo/main.c Normal file
View File

@ -0,0 +1,64 @@
#include "hamming.h"
#define DATA_SIZE 10231
int mainn() {
unsigned char data[DATA_SIZE], newData[DATA_SIZE];
unsigned char parity[3] = {0};
// 初始化测试数据
for(int i = 0; i < DATA_SIZE; i++) {
data[i] = i & 0xff;
newData[i] = data[i];
}
// 计算校验位
calculateParity(data, DATA_SIZE, parity);
size_t k = 0;
for (size_t i = 0; i < DATA_SIZE; i++)
{
// 注入错误
newData[i] ^= (1 << 7);
// 检测并纠正错误
int result = detectAndCorrect(newData, DATA_SIZE, parity);
// 输出结果
// printf("错误检测结果: ");
switch(result) {
case 0:
printf("无错误\n");
break;
case 1:
// printf("错误已纠正\n");
k++;
break;
case -1:
// printf("校验位错误\n");
k=-1;
break;
case -2:
printf("检测到多位错误\n");
k=-1;
break;
}
if (k == -1)
{
printf("数据恢复失败\n");
break;
}
if (memcmp(newData, data, DATA_SIZE) == 0) {
// printf("恢复后数据与原始数据一致\n");
} else {
printf("恢复后数据与原始数据不一致\n");
}
if ( i == DATA_SIZE - 1)
{
printf("数据恢复完毕,k=%d\n",k);
}
}
return 0;
}