Browse Source

update

master
zhaohe 2 years ago
commit
92270c796d
  1. 9
      .clang-format
  2. 1
      .gitignore
  3. 2
      README.md
  4. 1
      build.sh
  5. 1
      install.sh
  6. 199
      spisound.c
  7. 65
      spisound.h

9
.clang-format

@ -0,0 +1,9 @@
# Defines the Chromium style for automatic reformatting.
# http://clang.llvm.org/docs/ClangFormatStyleOptions.html
Language: Cpp
BasedOnStyle: Google
ColumnLimit: 160
AlignConsecutiveMacros: true
AlignConsecutiveDeclarations: true
AlignConsecutiveAssignments: true
AlignOperands: true

1
.gitignore

@ -0,0 +1 @@
libspisound.so

2
README.md

@ -0,0 +1,2 @@
# linux_demo_project

1
build.sh

@ -0,0 +1 @@
gcc -shared -fPIC spisound.c -o libspisound.so

1
install.sh

@ -0,0 +1 @@
sudo cp libspisound.so /usr/lib/

199
spisound.c

@ -0,0 +1,199 @@
#include "spisound.h"
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/spi/spidev.h>
#include <linux/types.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> //for strerror()
#include <sys/ioctl.h>
#include <unistd.h>
#define MAX_ONE_FRAME_VOICE_SIZE 2000
#define IOCTL(vfd, vkey, vvalue, errorcode) \
{ \
int ret = ioctl(vfd, vkey, &vvalue); \
if (ret != 0) { \
close(vfd); \
vfd = -1; \
m_sys_error = errno; \
m_last_error = errorcode; \
return errorcode; \
} \
}
// static const char *m_deviceName = NULL;
static spisound_cb_t m_callback = NULL;
static int m_fd = 0;
static int m_sys_error = 0;
static error_code_t m_last_error = ksp_success;
static int m_cs_gpio_id = 0;
static int m_gpiofd = 0;
static pthread_t sound_read_thread;
static bool inited = false;
static bool started = false;
static void *sound_read_thread_func(void *v);
static void gpio_set_value(int value) { write(m_gpiofd, value ? "1\n" : "0\n", 2); }
static void readvoice();
static int32_t *multiplierX2(int32_t *voice, int32_t size, int32_t *outsize) {
static int32_t voicebuf[MAX_ONE_FRAME_VOICE_SIZE * 2]; // 50ms
if (size > MAX_ONE_FRAME_VOICE_SIZE) {
size = MAX_ONE_FRAME_VOICE_SIZE;
}
for (size_t i = 0; i < size; i++) {
voicebuf[i * 2] = voice[i];
if (i + 1 < size) {
voicebuf[i * 2 + 1] = (voice[i] + voice[i + 1]) / 2;
}
}
*outsize = size * 2;
return voicebuf;
}
static void filterVoice(int32_t *voice, int32_t size) {
/**
* @brief 1.5
*/
static int32_t lastvoice = 0;
lastvoice = voice[size - 1];
{ //
int32_t avg = (lastvoice + voice[1]) / 2;
if (abs(voice[0]) > abs(avg * 1.5)) {
voice[0] = avg;
}
}
for (size_t i = 1; i < size - 1; i++) {
int32_t avg = (voice[i - 1] + voice[i + 1]) / 2;
if (abs(voice[i]) > abs(avg * 1.5)) {
voice[i] = avg;
}
}
{
int32_t expectendvoice = voice[size - 2] + (voice[size - 2] - voice[size - 3]);
if (abs(voice[size - 1]) > abs(expectendvoice * 1.5)) {
voice[size - 1] = expectendvoice;
}
}
}
error_code_t spisound_init(const char *deviceName, int csgpionameId, spisound_cb_t callback) {
m_callback = callback;
m_cs_gpio_id = csgpionameId;
//
m_fd = open(deviceName, O_RDWR);
if (m_fd < 0) {
m_sys_error = errno;
m_last_error = ksp_init_spi_error_open_fail;
return ksp_init_spi_error_open_fail;
}
//
int mode = SPI_MODE_3;
int bits = 8;
int speed = 3000000;
// SPI初始化
IOCTL(m_fd, SPI_IOC_WR_MODE, mode, ksp_init_spi_error_set_mode_fail);
IOCTL(m_fd, SPI_IOC_WR_BITS_PER_WORD, bits, ksp_init_spi_error_set_mode_fail);
IOCTL(m_fd, SPI_IOC_WR_MAX_SPEED_HZ, speed, ksp_init_spi_error_set_mode_fail);
char cmd[256] = {0};
sprintf(cmd, "echo %d 1> /sys/class/gpio/export 2>/dev/null", m_cs_gpio_id);
system(cmd);
sprintf(cmd, "echo out > /sys/class/gpio/gpio%d/direction", m_cs_gpio_id);
system(cmd);
sprintf(cmd, "/sys/class/gpio/gpio%d/value", m_cs_gpio_id);
m_gpiofd = open(cmd, O_RDWR);
if (m_gpiofd < 0) {
m_sys_error = errno;
m_last_error = ksp_init_spi_cs_pin_open_fail;
return ksp_init_spi_cs_pin_open_fail;
}
inited = true;
return ksp_success;
}
static void *sound_read_thread_func(void *v) {
while (true) {
// 500us
readvoice();
usleep(10000);
}
return NULL;
}
error_code_t spisound_start_capture(void) {
//
if (!inited) {
return ksp_module_not_inited;
}
if (started) {
return ksp_module_has_started;
}
int ret = pthread_create(&sound_read_thread, NULL, sound_read_thread_func, NULL);
if (ret != 0) {
m_sys_error = errno;
return ksp_create_thread_fail;
}
started = true;
return ksp_success;
}
static void readvoice() {
static int32_t voicebuf[MAX_ONE_FRAME_VOICE_SIZE]; // 50ms
static int32_t rxdatabytesize; //
rxdatabytesize = 0;
memset(voicebuf, 0, sizeof(voicebuf));
gpio_set_value(0);
// usleep(1500); // CS信号触发后
int ret = read(m_fd, &rxdatabytesize, 4);
// printf("read rxdatabytesize:%d\n", rxdatabytesize);
if (rxdatabytesize <= 0) {
gpio_set_value(1);
return;
}
if (rxdatabytesize > MAX_ONE_FRAME_VOICE_SIZE * 4) {
printf("WARNING: rxdatabytesize(%d) > voiceBufSize \n", rxdatabytesize);
gpio_set_value(1);
return;
}
ret = read(m_fd, voicebuf, rxdatabytesize);
gpio_set_value(1);
{
int32_t voiceframesize = 0;
filterVoice(voicebuf, rxdatabytesize / 4);
int32_t *voicereport = multiplierX2(voicebuf, rxdatabytesize / 4, &voiceframesize);
if (m_callback) m_callback(voicereport, voiceframesize);
}
return;
}
void spisound_dump_last_error() {
printf("----------------spisound_dump_last_error-----------------\n");
printf("- module error: %s(%d)\n", error_code_to_string(m_last_error), m_last_error);
printf("- sys_ error : %s(%d)\n", strerror(m_sys_error), m_sys_error);
printf("-\n");
}

65
spisound.h

@ -0,0 +1,65 @@
#pragma once
#include <stdint.h>
#ifdef cplusplus
extern "C" {
#endif
/**
* @brief 48k音频数据32位音频数据
*
* @param data
* @param len
*
*/
typedef void (*spisound_cb_t)(int32_t *data, uint32_t len);
typedef enum {
ksp_success,
ksp_module_not_inited,
ksp_module_has_started,
ksp_create_thread_fail,
ksp_init_spi_cs_pin_open_fail,
ksp_init_spi_error_open_fail,
ksp_init_spi_error_set_speed_fail,
ksp_init_spi_error_set_nbits_fail,
ksp_init_spi_error_set_mode_fail,
} error_code_t;
static inline const char *error_code_to_string(error_code_t code) {
switch (code) {
case ksp_success:
return "success";
case ksp_module_not_inited:
return "module not inited";
case ksp_module_has_started:
return "module has started";
case ksp_create_thread_fail:
return "create thread fail";
case ksp_init_spi_cs_pin_open_fail:
return "init spi cs pin open fail";
case ksp_init_spi_error_open_fail:
return "init spi error open fail";
case ksp_init_spi_error_set_speed_fail:
return "init spi error set speed fail";
case ksp_init_spi_error_set_nbits_fail:
return "init spi error set nbits fail";
case ksp_init_spi_error_set_mode_fail:
return "init spi error set mode fail";
default:
return "unknown error";
}
}
/**
* @brief
*
* @param deviceName
* @param callback
*/
error_code_t spisound_init(const char *deviceName, int csgpionId, spisound_cb_t callback);
error_code_t spisound_start_capture(void);
void spisound_dump_last_error();
#ifdef cplusplus
}
#endif
Loading…
Cancel
Save