// SPDX-License-Identifier: LicenseRef-AGPL-3.0-only-OpenSSL #include #include #include #include #include #include #include #include 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 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; }