mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-03-12 05:25:23 -07:00
164 lines
3.4 KiB
C
164 lines
3.4 KiB
C
// SPDX-License-Identifier: LicenseRef-AGPL-3.0-only-OpenSSL
|
|
|
|
#include <setsu.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <signal.h>
|
|
#include <math.h>
|
|
|
|
Setsu *setsu;
|
|
|
|
#define NAME_LEN 8
|
|
const char * const names[] = {
|
|
"accel x ",
|
|
"accel y ",
|
|
"accel z ",
|
|
" gyro x ",
|
|
" gyro y ",
|
|
" gyro z "
|
|
};
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
float accel_x, accel_y, accel_z;
|
|
float gyro_x, gyro_y, gyro_z;
|
|
};
|
|
float v[6];
|
|
} vals;
|
|
uint32_t timestamp;
|
|
bool dirty = false;
|
|
bool log_mode;
|
|
volatile bool should_quit;
|
|
|
|
#define LOG(...) do { if(log_mode) fprintf(stderr, __VA_ARGS__); } while(0)
|
|
|
|
void sigint(int s)
|
|
{
|
|
should_quit = true;
|
|
}
|
|
|
|
#define BAR_LENGTH 100
|
|
#define BAR_MAX 2.0f
|
|
#define BAR_MAX_GYRO M_PI
|
|
|
|
void print_state()
|
|
{
|
|
char buf[6 * (1 + NAME_LEN + BAR_LENGTH) + 1];
|
|
size_t i = 0;
|
|
for(size_t b=0; b<6; b++)
|
|
{
|
|
buf[i++] = '\n';
|
|
memcpy(buf + i, names[b], NAME_LEN);
|
|
i += NAME_LEN;
|
|
buf[i++] = '[';
|
|
size_t max = BAR_LENGTH-2;
|
|
for(size_t bi=0; bi<max; bi++)
|
|
{
|
|
#define BAR_VAL(x) ((b > 2 ? BAR_MAX_GYRO : BAR_MAX) * (2.0f * (float)(x) / (float)max - 1.0f))
|
|
float cur = BAR_VAL(bi);
|
|
float prev = BAR_VAL((int)bi - 1);
|
|
if(prev < 0.0f && cur >= 0.0f)
|
|
{
|
|
buf[i++] = '|';
|
|
continue;
|
|
}
|
|
bool cov = ((vals.v[b] < 0.0f) == (cur < 0.0f)) && fabsf(vals.v[b]) > fabsf(cur);
|
|
float next = BAR_VAL(bi + 1);
|
|
#define MARK_VAL (b > 2 ? 0.5f * M_PI : 1.0f)
|
|
bool mark = cur < -MARK_VAL && next >= -MARK_VAL || prev < MARK_VAL && cur >= MARK_VAL;
|
|
buf[i++] = cov ? (mark ? '#' : '=') : (mark ? '.' : ' ');
|
|
#undef BAR_VAL
|
|
}
|
|
buf[i++] = ']';
|
|
}
|
|
buf[i++] = '\0';
|
|
assert(i == sizeof(buf));
|
|
printf("\033[2J%s", buf);
|
|
fflush(stdout);
|
|
}
|
|
|
|
void event(SetsuEvent *event, void *user)
|
|
{
|
|
dirty = true;
|
|
switch(event->type)
|
|
{
|
|
case SETSU_EVENT_DEVICE_ADDED: {
|
|
if(event->dev_type != SETSU_DEVICE_TYPE_MOTION)
|
|
break;
|
|
SetsuDevice *dev = setsu_connect(setsu, event->path, SETSU_DEVICE_TYPE_MOTION);
|
|
LOG("Device added: %s, connect %s\n", event->path, dev ? "succeeded" : "FAILED!");
|
|
break;
|
|
}
|
|
case SETSU_EVENT_DEVICE_REMOVED:
|
|
if(event->dev_type != SETSU_DEVICE_TYPE_MOTION)
|
|
break;
|
|
LOG("Device removed: %s\n", event->path);
|
|
break;
|
|
case SETSU_EVENT_MOTION:
|
|
LOG("Motion: %f, %f, %f / %f, %f, %f / %u\n",
|
|
event->motion.accel_x, event->motion.accel_y, event->motion.accel_z,
|
|
event->motion.gyro_x, event->motion.gyro_y, event->motion.gyro_z,
|
|
(unsigned int)event->motion.timestamp);
|
|
vals.accel_x = event->motion.accel_x;
|
|
vals.accel_y = event->motion.accel_y;
|
|
vals.accel_z = event->motion.accel_z;
|
|
vals.gyro_x = event->motion.gyro_x;
|
|
vals.gyro_y = event->motion.gyro_y;
|
|
vals.gyro_z = event->motion.gyro_z;
|
|
timestamp = event->motion.timestamp;
|
|
dirty = true;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void usage(const char *prog)
|
|
{
|
|
printf("usage: %s [-l]\n -l log mode\n", prog);
|
|
exit(1);
|
|
}
|
|
|
|
int main(int argc, const char *argv[])
|
|
{
|
|
log_mode = false;
|
|
if(argc == 2)
|
|
{
|
|
if(!strcmp(argv[1], "-l"))
|
|
log_mode = true;
|
|
else
|
|
usage(argv[0]);
|
|
}
|
|
else if(argc != 1)
|
|
usage(argv[0]);
|
|
|
|
setsu = setsu_new();
|
|
if(!setsu)
|
|
{
|
|
printf("Failed to init setsu\n");
|
|
return 1;
|
|
}
|
|
|
|
struct sigaction sa = {0};
|
|
sa.sa_handler = sigint;
|
|
sigemptyset(&sa.sa_mask);
|
|
sigaction(SIGINT, &sa, NULL);
|
|
|
|
dirty = true;
|
|
while(!should_quit)
|
|
{
|
|
if(dirty && !log_mode)
|
|
print_state();
|
|
dirty = false;
|
|
setsu_poll(setsu, event, NULL);
|
|
}
|
|
setsu_free(setsu);
|
|
printf("\nさよなら!\n");
|
|
return 0;
|
|
}
|
|
|