mirror of
https://gitlab.com/zephray/glider.git
synced 2026-01-11 15:11:13 +00:00
771 lines
23 KiB
C
771 lines
23 KiB
C
//
|
|
// Grimoire
|
|
// Copyright 2025 Wenting Zhang
|
|
//
|
|
// Original copyright information:
|
|
// Copyright (c) 2022 - Analog Devices Inc. All Rights Reserved.
|
|
//
|
|
// This file is licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License. You may
|
|
// obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
// License for the specific language governing permissions and limitations
|
|
// under the License.
|
|
//
|
|
|
|
#include "platform.h"
|
|
#include "board.h"
|
|
#include "shell.h"
|
|
#include "shell_printf.h"
|
|
#include "term.h"
|
|
#include "app_main.h"
|
|
#include "app.h"
|
|
#include "xmodem.h"
|
|
|
|
#ifdef printf
|
|
#undef printf
|
|
#endif
|
|
|
|
#ifdef vprintf
|
|
#undef vprintf
|
|
#endif
|
|
|
|
#define printf(...) shell_printf(ctx, __VA_ARGS__)
|
|
#define vprintf(x,y) shell_vprintf(ctx, x, y)
|
|
|
|
/***********************************************************************
|
|
* Misc helper functions
|
|
**********************************************************************/
|
|
static void dump_bytes(shell_context_t *ctx, unsigned char *rdata, unsigned addr, unsigned rlen) {
|
|
unsigned i;
|
|
for (i = 0; i < rlen; i++) {
|
|
if ((i % 16) == 0) {
|
|
if (i) {
|
|
printf("\n");
|
|
}
|
|
printf("%08x: ", addr + i);
|
|
}
|
|
printf("%02x ", rdata[i]);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
int confirm_danger(shell_context_t *ctx, char *warnStr) {
|
|
char c;
|
|
|
|
printf( "%s\n", warnStr );
|
|
printf( "Are you sure you want to continue? [y/n]" );
|
|
|
|
c = term_getch( &ctx->t, TERM_INPUT_WAIT );
|
|
printf( "%c\n", isprint( c ) ? c : ' ' );
|
|
|
|
if( tolower(c) == 'y' ) {
|
|
return(1);
|
|
}
|
|
|
|
return(0);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CMD: syslog
|
|
**********************************************************************/
|
|
const char shell_help_syslog[] = "\n";
|
|
const char shell_help_summary_syslog[] = "Show the live system log";
|
|
|
|
#define MAX_TS_LINE 32
|
|
#define MAX_LOG_LINE 256
|
|
|
|
void shell_syslog(shell_context_t *ctx, int argc, char **argv) {
|
|
char *line;
|
|
char *lbuf;
|
|
char *ts;
|
|
int c;
|
|
|
|
ts = SHELL_MALLOC(MAX_TS_LINE);
|
|
lbuf = SHELL_MALLOC(MAX_LOG_LINE);
|
|
|
|
c = 0;
|
|
do {
|
|
line = syslog_next(ts, MAX_TS_LINE, lbuf, MAX_LOG_LINE);
|
|
if (line) {
|
|
printf("%s %s\n", ts, line);
|
|
}
|
|
c = term_getch(&ctx->t, TERM_INPUT_DONT_WAIT);
|
|
#ifdef FREE_RTOS
|
|
if ((line == NULL) && (c < 0)) {
|
|
vTaskDelay(pdMS_TO_TICKS(50));
|
|
}
|
|
#endif
|
|
} while (c < 0);
|
|
|
|
if (ts) {
|
|
SHELL_FREE(ts);
|
|
}
|
|
if (lbuf) {
|
|
SHELL_FREE(lbuf);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CMD: stacks
|
|
**********************************************************************/
|
|
const char shell_help_stacks[] = "\n";
|
|
const char shell_help_summary_stacks[] = "Report task stack usage";
|
|
|
|
static void shell_print_task_stack(shell_context_t *ctx, TaskHandle_t task) {
|
|
if (task) {
|
|
printf(" %s: %u\n",
|
|
pcTaskGetName(task), (unsigned)uxTaskGetStackHighWaterMark(task)
|
|
);
|
|
}
|
|
}
|
|
|
|
void shell_stacks(shell_context_t *ctx, int argc, char **argv ) {
|
|
printf("High Water Marks are in 32-bit words (zero is bad).\n");
|
|
printf("Task Stask High Water Marks:\n");
|
|
|
|
shell_print_task_stack(ctx, startup_task_handle);
|
|
shell_print_task_stack(ctx, housekeeping_task_handle);
|
|
shell_print_task_stack(ctx, usb_device_task_handle);
|
|
shell_print_task_stack(ctx, usb_pd_task_handle);
|
|
shell_print_task_stack(ctx, ui_task_handle);
|
|
shell_print_task_stack(ctx, key_scan_task_handle);
|
|
shell_print_task_stack(ctx, power_mon_task_handle);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CMD: test
|
|
**********************************************************************/
|
|
const char shell_help_test[] = "\n";
|
|
const char shell_help_summary_test[] = "Test command";
|
|
|
|
void shell_test(shell_context_t *ctx, int argc, char **argv ) {
|
|
|
|
// uint8_t val = atoi(argv[1]);
|
|
// uint8_t buf[2];
|
|
// buf[0] = 0x19;
|
|
// buf[1] = val | 0x80;
|
|
// pal_i2c_write_payload(ADV7611_I2C, ADV7611_I2C_ADDR, buf, 2);
|
|
|
|
// uint8_t val;
|
|
//
|
|
// val = adv7611_read_reg(ADV7611_I2C_ADDR, 0x6a);
|
|
// if (val & 0x10)
|
|
// printf("TMDS clock detected\n");
|
|
// else
|
|
// printf("No TMDS clock detected\n");
|
|
//
|
|
// uint16_t val16;
|
|
// val = adv7611_read_reg(HDMI_I2C_ADDR, 0x51); // D8-D1
|
|
// val16 = (uint16_t)val << 1;
|
|
// val = adv7611_read_reg(HDMI_I2C_ADDR, 0x52);
|
|
// val16 |= val >> 7;
|
|
//
|
|
// printf("TMDS frequency %d MHz\n", val16);
|
|
//
|
|
// val = adv7611_read_reg(HDMI_I2C_ADDR, 0x04);
|
|
// if (val & 0x2)
|
|
// printf("TMDS PLL locked\n");
|
|
// else
|
|
// printf("TMDS PLL not locked\n");
|
|
//
|
|
// val = adv7611_read_reg(HDMI_I2C_ADDR, 0x05);
|
|
// if (val & 0x80)
|
|
// printf("HDMI mode detected\n");
|
|
// else
|
|
// printf("DVI mode detected\n");
|
|
//
|
|
// val = adv7611_read_reg(HDMI_I2C_ADDR, 0x07);
|
|
// if (val & 0x20)
|
|
// printf("DE regeneration locked\n");
|
|
// else
|
|
// printf("DE regeneration not locked\n");
|
|
//
|
|
// if (val & 0x80)
|
|
// printf("Vertical filter locked\n");
|
|
// else
|
|
// printf("Vertical filter not locked\n");
|
|
//
|
|
// val16 = (uint16_t)adv7611_read_reg(HDMI_I2C_ADDR, 0x1e) << 8;
|
|
// val16 |= adv7611_read_reg(HDMI_I2C_ADDR, 0x1f);
|
|
// printf("Total line width: %d\n", val16);
|
|
//
|
|
// val16 = (uint16_t)(adv7611_read_reg(HDMI_I2C_ADDR, 0x07) & 0x1f) << 8;
|
|
// val16 |= adv7611_read_reg(HDMI_I2C_ADDR, 0x08);
|
|
// printf("Active line width: %d\n", val16);
|
|
//
|
|
// val16 = (uint16_t)(adv7611_read_reg(HDMI_I2C_ADDR, 0x09) & 0x1f) << 8;
|
|
// val16 |= adv7611_read_reg(HDMI_I2C_ADDR, 0x0a);
|
|
// printf("Active field height: %d\n", val16);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CMD: i2c_probe
|
|
**********************************************************************/
|
|
const char shell_help_i2c_probe[] = "<i2c_port>\n"
|
|
" i2c_port - I2C port to probe\n";
|
|
const char shell_help_summary_i2c_probe[] = "Probe an I2C port for active devices";
|
|
|
|
void shell_i2c_probe(shell_context_t *ctx, int argc, char **argv)
|
|
{
|
|
pal_i2c_t *i2c;
|
|
int i;
|
|
|
|
if (argc != 2) {
|
|
printf("Invalid arguments. Type help [<command>] for usage.\n");
|
|
return;
|
|
}
|
|
|
|
int i2c_port = strtol(argv[1], NULL, 0);
|
|
i2c = NULL;
|
|
|
|
if (i2c_port == 1) {
|
|
i2c = &pi2c1;
|
|
}
|
|
else {
|
|
printf("Invalid I2C port!\n");
|
|
return;
|
|
}
|
|
|
|
printf("Probing I2C port %d:\n", i2c_port);
|
|
for (i = 0x08; i < 0x78; i++) {
|
|
bool result = pal_i2c_ping(i2c, i);
|
|
if (result == true) {
|
|
printf(" Found device 0x%02x\n", i);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//const char shell_help_fl[] = "<operation> [brightness]\n"
|
|
// " operation - on | off | set\n"
|
|
// " brightness - 0-255\n";
|
|
//const char shell_help_summary_fl[] = "Control front light";
|
|
//
|
|
//void shell_fl(shell_context_t *ctx, int argc, char **argv)
|
|
//{
|
|
// if ((argc < 2) || (argc > 3)) {
|
|
// printf("Invalid arguments. Type help [<command>] for usage.\n");
|
|
// return;
|
|
// }
|
|
//
|
|
// if (strcmp(argv[1], "on") == 0) {
|
|
// power_on_fl();
|
|
// }
|
|
// else if (strcmp(argv[1], "off") == 0) {
|
|
// power_off_fl();
|
|
// }
|
|
//
|
|
// if (argc == 3) {
|
|
// int brightness = strtol(argv[2], NULL, 0);
|
|
// power_set_fl_brightness(brightness);
|
|
// }
|
|
//}
|
|
|
|
|
|
/***********************************************************************
|
|
* XMODEM helper functions
|
|
**********************************************************************/
|
|
typedef struct {
|
|
shell_context_t *ctx;
|
|
} xmodem_state_t;
|
|
|
|
static void shell_xmodem_putchar(int c, void *usr) {
|
|
xmodem_state_t *x = (xmodem_state_t *)usr;
|
|
shell_context_t *ctx = x->ctx;
|
|
term_state_t *t = &ctx->t;
|
|
|
|
term_putch(t, c);
|
|
}
|
|
|
|
static int shell_xmodem_getchar(int timeout, void *usr) {
|
|
xmodem_state_t *x = (xmodem_state_t *)usr;
|
|
shell_context_t *ctx = x->ctx;
|
|
term_state_t *t = &ctx->t;
|
|
int c;
|
|
|
|
c = term_getch(t, timeout);
|
|
|
|
return(c);
|
|
}
|
|
|
|
typedef struct {
|
|
xmodem_state_t xmodem;
|
|
spiffs_file f;
|
|
void *data;
|
|
int size;
|
|
} file_xfer_state_t;
|
|
|
|
static void file_data_write(void *usr, void *data, int size) {
|
|
file_xfer_state_t *state = (file_xfer_state_t *)usr;
|
|
|
|
/*
|
|
* Need to double-buffer the data in order to strip off the
|
|
* trailing packet bytes at the end of an xmodem transfer.
|
|
*/
|
|
if (state->data == NULL) {
|
|
state->data = SHELL_MALLOC(1024);
|
|
memcpy(state->data, data, size);
|
|
state->size = size;
|
|
} else {
|
|
if (data) {
|
|
SPIFFS_write(&spiffs_fs, state->f, state->data, state->size);
|
|
memcpy(state->data, data, size);
|
|
state->size = size;
|
|
} else {
|
|
uint8_t *buf = (uint8_t *)state->data;
|
|
while (state->size && buf[state->size-1] == '\x1A') {
|
|
state->size--;
|
|
}
|
|
SPIFFS_write(&spiffs_fs, state->f, state->data, state->size);
|
|
if (state->data) {
|
|
SHELL_FREE(state->data);
|
|
state->data = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void file_data_read(void *usr, void *data, int size) {
|
|
file_xfer_state_t *state = (file_xfer_state_t *)usr;
|
|
|
|
if (size > 0) {
|
|
SPIFFS_read(&spiffs_fs, state->f, data, size);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CMD: format
|
|
**********************************************************************/
|
|
const char shell_help_format[] = "";
|
|
const char shell_help_summary_format[] = "Formats an internal flash filesystem";
|
|
|
|
void shell_format(shell_context_t *ctx, int argc, char **argv) {
|
|
printf("Be patient, this may take a while.\n");
|
|
printf("Formatting...\n");
|
|
|
|
TickType_t start = xTaskGetTickCount();
|
|
SPIFFS_unmount(&spiffs_fs);
|
|
if (SPIFFS_format(&spiffs_fs) != SPIFFS_OK) {
|
|
printf("SPIFFS format failed: %d\n", SPIFFS_errno(&spiffs_fs));
|
|
}
|
|
TickType_t end = xTaskGetTickCount();
|
|
printf("Time spent: %d seconds\n", (end - start) / configTICK_RATE_HZ);
|
|
|
|
printf("Done. Please reset the board\n");
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CMD: rm/del
|
|
**********************************************************************/
|
|
const char shell_help_rm[] = "<file1> [<file2> ...]\n";
|
|
const char shell_help_summary_rm[] = "Removes a file";
|
|
|
|
#include <stdio.h>
|
|
|
|
void shell_rm(shell_context_t *ctx, int argc, char **argv) {
|
|
int i;
|
|
|
|
if (argc < 2) {
|
|
printf( "Usage: rm <file1> [<file2> ...]\n" );
|
|
return;
|
|
}
|
|
|
|
for (i = 1; i < argc; i++) {
|
|
if (SPIFFS_remove(&spiffs_fs, argv[i]) != 0) {
|
|
printf("Unable to remove '%s'\n", argv[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
//const char shell_help_dump[] = "[addr] <len>\n"
|
|
// " addr - Starting address to dump\n"
|
|
// " len - Number of bytes to dump (default 1)\n";
|
|
//const char shell_help_summary_dump[] = "Hex dump of flash contents";
|
|
//
|
|
//void shell_dump(shell_context_t *ctx, int argc, char **argv)
|
|
//{
|
|
// uintptr_t addr = 0;
|
|
// unsigned len = 1;
|
|
// uint8_t *buf;
|
|
// int ok;
|
|
//
|
|
// if (argc < 2) {
|
|
// printf("Invalid arguments\n");
|
|
// return;
|
|
// }
|
|
//
|
|
// addr = strtoul(argv[1], NULL, 0);
|
|
// if (argc > 2) {
|
|
// len = strtoul(argv[2], NULL, 0);
|
|
// }
|
|
//
|
|
// buf = SHELL_MALLOC(len);
|
|
// if (buf) {
|
|
// ok = spif_read(addr, len, buf);
|
|
// if (ok == 0) {
|
|
// dump_bytes(ctx, buf, addr, len);
|
|
// }
|
|
// SHELL_FREE(buf);
|
|
// }
|
|
//}
|
|
//
|
|
const char shell_help_fdump[] =
|
|
"[file] <start> <size>\n"
|
|
" file - File to dump\n"
|
|
" start - Start offset in bytes (default: 0)\n"
|
|
" size - Size in bytes (default: full file)\n";
|
|
const char shell_help_summary_fdump[] = "Dumps the contents of a file in hex";
|
|
|
|
#define DUMP_SIZE 512
|
|
|
|
void shell_fdump(shell_context_t *ctx, int argc, char **argv) {
|
|
spiffs_file f;
|
|
size_t start = 0;
|
|
size_t size = SIZE_MAX;
|
|
uint8_t *buf = NULL;
|
|
size_t rlen;
|
|
int c;
|
|
|
|
if( argc < 2 ) {
|
|
printf("No file given\n");
|
|
return;
|
|
}
|
|
|
|
if (argc > 2) {
|
|
start = (size_t)strtoul(argv[2], NULL, 0);
|
|
}
|
|
|
|
if (argc > 3) {
|
|
size = (size_t)strtoul(argv[3], NULL, 0);
|
|
}
|
|
|
|
f = SPIFFS_open(&spiffs_fs, argv[1], SPIFFS_O_RDONLY, 0);
|
|
if (f) {
|
|
buf = SHELL_MALLOC(DUMP_SIZE);
|
|
SPIFFS_lseek(&spiffs_fs, f, start, SPIFFS_SEEK_SET);
|
|
do {
|
|
rlen = (size < DUMP_SIZE) ? size : DUMP_SIZE;
|
|
rlen = SPIFFS_read(&spiffs_fs, f, buf, rlen);
|
|
if (rlen) {
|
|
dump_bytes(ctx, buf, start, rlen);
|
|
size -= rlen;
|
|
start += rlen;
|
|
c = term_getch(&ctx->t, TERM_INPUT_DONT_WAIT);
|
|
}
|
|
} while (size && rlen && (c < 0));
|
|
if (buf) {
|
|
SHELL_FREE(buf);
|
|
}
|
|
SPIFFS_close(&spiffs_fs, f);
|
|
}
|
|
else {
|
|
printf("Unable to open '%s'\n", argv[1]);
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CMD: recv
|
|
**********************************************************************/
|
|
const char shell_help_recv[] = "<file>\n"
|
|
" Transfer and save to file\n";
|
|
const char shell_help_summary_recv[] = "Receive a file via XMODEM";
|
|
|
|
void shell_recv( shell_context_t *ctx, int argc, char **argv )
|
|
{
|
|
file_xfer_state_t file_state = { 0 };
|
|
long size;
|
|
|
|
if( argc != 2 ) {
|
|
printf( "Usage: recv <file>\n" );
|
|
return;
|
|
}
|
|
|
|
file_state.xmodem.ctx = ctx;
|
|
|
|
file_state.f = SPIFFS_open(&spiffs_fs, argv[1], SPIFFS_O_CREAT | SPIFFS_O_TRUNC | SPIFFS_O_WRONLY, 0);
|
|
if( file_state.f == 0) {
|
|
printf( "unable to open file %s\n", argv[ 1 ] );
|
|
return;
|
|
}
|
|
printf( "Prepare your terminal for XMODEM send ... " );
|
|
term_set_mode(&ctx->t, TERM_MODE_COOKED, 0);
|
|
size = XmodemReceiveCrc(file_data_write, &file_state, 4*1024*1024,
|
|
shell_xmodem_getchar, shell_xmodem_putchar);
|
|
term_set_mode(&ctx->t, TERM_MODE_COOKED, 1);
|
|
if (size < 0) {
|
|
printf( "XMODEM Error: %ld\n", size);
|
|
} else {
|
|
printf( "received and saved as %s\n", argv[ 1 ] );
|
|
}
|
|
SPIFFS_close(&spiffs_fs, file_state.f);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* CMD: send
|
|
**********************************************************************/
|
|
const char shell_help_send[] = "<file1> [<file2> ...]\n";
|
|
const char shell_help_summary_send[] = "Send files via YMODEM.";
|
|
|
|
typedef struct {
|
|
file_xfer_state_t state;
|
|
const char *fname;
|
|
size_t fsize;
|
|
} ymodem_state_t;
|
|
|
|
static void ymodem_hdr(void *usr, void *xmodemBuffer, int xmodemSize) {
|
|
ymodem_state_t *y = (ymodem_state_t *)usr;
|
|
snprintf(xmodemBuffer, xmodemSize, "%s%c%u", y->fname, 0, (unsigned)y->fsize);
|
|
}
|
|
|
|
static void ymodem_end(void *xs, void *xmodemBuffer, int xmodemSize) {
|
|
}
|
|
|
|
void shell_send(shell_context_t *ctx, int argc, char **argv)
|
|
{
|
|
size_t size;
|
|
spiffs_file fp = 0;
|
|
int ret = -1;
|
|
int i;
|
|
|
|
ymodem_state_t y = {
|
|
.state.xmodem.ctx = ctx,
|
|
};
|
|
|
|
if (argc < 2) {
|
|
printf("Usage: %s <file1> [<file2> ...]\n", argv[0]);
|
|
return;
|
|
}
|
|
|
|
printf ("Prepare your terminal for YMODEM receive...\n");
|
|
term_set_mode(&ctx->t, TERM_MODE_COOKED, 0);
|
|
for (i = 1; i < argc; i++) {
|
|
fp = SPIFFS_open(&spiffs_fs, argv[i], SPIFFS_O_RDONLY, 0);
|
|
if (fp) {
|
|
spiffs_stat s;
|
|
SPIFFS_fstat(&spiffs_fs, fp, &s);
|
|
size = s.size;
|
|
y.fname = argv[i]; y.fsize = size; y.state.f = fp;
|
|
ret = XmodemTransmit(ymodem_hdr, &y, 128, 0, 1,
|
|
shell_xmodem_getchar, shell_xmodem_putchar);
|
|
if (ret >= 0) {
|
|
ret = XmodemTransmit(file_data_read, &y, y.fsize, 1, 0,
|
|
shell_xmodem_getchar, shell_xmodem_putchar);
|
|
}
|
|
SPIFFS_close(&spiffs_fs, fp);
|
|
if (ret < 0) {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
printf("File not found\n");
|
|
ret = -1;
|
|
}
|
|
}
|
|
if (ret >= 0) {
|
|
ret = XmodemTransmit(ymodem_end, &y, 128, 0, 1,
|
|
shell_xmodem_getchar, shell_xmodem_putchar);
|
|
}
|
|
term_set_mode(&ctx->t, TERM_MODE_COOKED, 1);
|
|
if (ret < 0) {
|
|
printf( "YMODEM Error: %ld\n", ret);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* CMD: df
|
|
**********************************************************************/
|
|
const char shell_help_df[] = "\n";
|
|
const char shell_help_summary_df[] = "Shows internal filesystem disk full status";
|
|
|
|
void shell_df(shell_context_t *ctx, int argc, char **argv) {
|
|
printf("%10s %10s %10s %5s\n", "Size", "Used", "Available", "Use %");
|
|
|
|
int32_t serr; uint32_t ssize; uint32_t sused;
|
|
serr = SPIFFS_info(&spiffs_fs, &ssize, &sused);
|
|
if (serr == SPIFFS_OK) {
|
|
printf("%10u %10u %10u %5u\n",
|
|
(unsigned)ssize, (unsigned)sused, (unsigned)(ssize - sused),
|
|
(unsigned)((100 * sused) / ssize));
|
|
}
|
|
}
|
|
|
|
|
|
const char shell_help_setvolt[] = "<rail> <volt>\n";
|
|
const char shell_help_summary_setvolt[] = "Set voltage";
|
|
|
|
void shell_setvolt(shell_context_t *ctx, int argc, char **argv) {
|
|
if (argc < 3) {
|
|
printf("Usage: <rail> <volt>\n", argv[0]);
|
|
return;
|
|
}
|
|
|
|
float volt = strtof(argv[2], NULL);
|
|
if (strcmp(argv[1], "vcom") == 0) {
|
|
power_set_vcom(volt);
|
|
}
|
|
else if (strcmp(argv[1], "vgh") == 0) {
|
|
power_set_vgh(volt);
|
|
}
|
|
}
|
|
|
|
|
|
const char shell_help_setcfg[] = "<set|get|save> [key] [value]\n";
|
|
const char shell_help_summary_setcfg[] = "Sets configuration. Remember to use save to save it to the flash.";
|
|
|
|
typedef struct {
|
|
const char *name;
|
|
void *pointer;
|
|
enum {UINT8, UINT16, UINT32, FLOAT32} type;
|
|
} cfg_var_t;
|
|
|
|
cfg_var_t vars[] = {
|
|
{"pclk_hz", &(config.pclk_hz), UINT32},
|
|
{"hfp", &(config.hfp), UINT8},
|
|
{"vfp", &(config.vfp), UINT8},
|
|
{"hsync", &(config.hsync), UINT8},
|
|
{"vsync", &(config.vsync), UINT8},
|
|
{"hact", &(config.hact), UINT16},
|
|
{"hblk", &(config.hblk), UINT16},
|
|
{"vact", &(config.vact), UINT16},
|
|
{"vblk", &(config.vblk), UINT16},
|
|
{"size_x_mm", &(config.size_x_mm), UINT16},
|
|
{"size_y_mm", &(config.size_y_mm), UINT16},
|
|
{"mfg_week", &(config.mfg_week), UINT8},
|
|
{"mfg_year", &(config.mfg_year), UINT8},
|
|
{"vcom", &(config.vcom), FLOAT32},
|
|
{"vgh", &(config.vgh), FLOAT32},
|
|
{"tcon_vfp", &(config.tcon_vfp), UINT8},
|
|
{"tcon_vsync", &(config.tcon_vsync), UINT8},
|
|
{"tcon_vbp", &(config.tcon_vbp), UINT8},
|
|
{"tcon_vact", &(config.tcon_vact), UINT16},
|
|
{"tcon_hfp", &(config.tcon_hfp), UINT8},
|
|
{"tcon_hsync", &(config.tcon_hsync), UINT8},
|
|
{"tcon_hbp", &(config.tcon_hbp), UINT8},
|
|
{"tcon_hact", &(config.tcon_hact), UINT16},
|
|
{"mirror", &(config.mirror), UINT8},
|
|
{"input_sel", &(config.input_sel), UINT8}
|
|
};
|
|
int num_vars = sizeof(vars) / sizeof(cfg_var_t);
|
|
|
|
static void setcfg_set_helper(cfg_var_t *var, char *val) {
|
|
if (var->type == UINT8) {
|
|
*(uint8_t *)(var->pointer) = strtol(val, NULL, 10);
|
|
}
|
|
else if (var->type == UINT16) {
|
|
*(uint16_t *)(var->pointer) = strtol(val, NULL, 10);
|
|
}
|
|
else if (var->type == UINT32) {
|
|
*(uint32_t *)(var->pointer) = strtol(val, NULL, 10);
|
|
}
|
|
else if (var->type == FLOAT32) {
|
|
*(float *)(var->pointer) = strtof(val, NULL);
|
|
}
|
|
}
|
|
|
|
static void setcfg_get_helper(shell_context_t *ctx, cfg_var_t *var) {
|
|
if (var->type == UINT8) {
|
|
printf("%d\n", *(uint8_t *)(var->pointer));
|
|
}
|
|
else if (var->type == UINT16) {
|
|
printf("%d\n", *(uint16_t *)(var->pointer));
|
|
}
|
|
else if (var->type == UINT32) {
|
|
printf("%d\n", *(uint32_t *)(var->pointer));
|
|
}
|
|
else if (var->type == FLOAT32) {
|
|
printf("%f\n", *(float *)(var->pointer));
|
|
}
|
|
}
|
|
|
|
void shell_setcfg(shell_context_t *ctx, int argc, char **argv) {
|
|
if (argc < 2) {
|
|
printf("Usage: %s\n", shell_help_setcfg);
|
|
return;
|
|
}
|
|
|
|
cfg_var_t *var = NULL;
|
|
if (argc >= 3) {
|
|
for (int i = 0; i < num_vars; i++) {
|
|
if (strcmp(argv[2], vars[i].name) == 0) {
|
|
var = &vars[i];
|
|
}
|
|
}
|
|
if (var == NULL) {
|
|
printf("Unknown key %s", argv[2]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (strcmp(argv[1], "set") == 0) {
|
|
if (argc < 4) {
|
|
printf("Key and value required for set\n");
|
|
return;
|
|
}
|
|
setcfg_set_helper(var, argv[3]);
|
|
}
|
|
else if (strcmp(argv[1], "get") == 0) {
|
|
if (argc < 4) {
|
|
// Get every var
|
|
for (int i = 0; i < num_vars; i++) {
|
|
printf("%s: ", vars[i].name);
|
|
setcfg_get_helper(ctx, &vars[i]);
|
|
}
|
|
}
|
|
else {
|
|
setcfg_get_helper(ctx, var);
|
|
}
|
|
}
|
|
else if (strcmp(argv[1], "save") == 0) {
|
|
config_save();
|
|
}
|
|
}
|
|
|
|
const char shell_help_sensor[] = "\n";
|
|
const char shell_help_summary_sensor[] = "Get sensor readings";
|
|
|
|
void shell_sensor(shell_context_t *ctx, int argc, char **argv) {
|
|
printf("EPD Supplies:\n");
|
|
printf("VP: %5.2f V\n", power_get_rail_voltage(RAIL_VP));
|
|
printf("VGH: %5.2f V\n", power_get_rail_voltage(RAIL_VGH));
|
|
printf("VN: %5.2f V\n", power_get_rail_voltage(RAIL_VN));
|
|
printf("VGL: %5.2f V\n", power_get_rail_voltage(RAIL_VGL));
|
|
printf("VCOM: %5.2f V\n", power_get_rail_voltage(RAIL_VCOM));
|
|
printf("5VES: %5.2f V %3.0f mA\n", power_get_rail_voltage(RAIL_5VES), power_get_rail_current(RAIL_5VES));
|
|
printf("5VEG: %5.2f V %3.0f mA\n", power_get_rail_voltage(RAIL_5VEG), power_get_rail_current(RAIL_5VEG));
|
|
|
|
printf("System Supplies:\n");
|
|
printf("VBUS: %5.2f V\n", power_get_rail_voltage(RAIL_VBUS));
|
|
printf("3V3: %5.2f V %3.0f mA\n", power_get_rail_voltage(RAIL_3V3), power_get_rail_current(RAIL_3V3));
|
|
printf("1V8VID: %5.2f V %3.0f mA\n", power_get_rail_voltage(RAIL_1V8VID), power_get_rail_current(RAIL_1V8VID));
|
|
printf("3V3VID: %5.2f V %3.0f mA\n", power_get_rail_voltage(RAIL_3V3VID), power_get_rail_current(RAIL_3V3VID));
|
|
printf("5V2FL: %5.2f V %3.0f mA\n", power_get_rail_voltage(RAIL_5V2FL), power_get_rail_current(RAIL_5V2FL));
|
|
printf("1V35: %5.2f V %3.0f mA\n", power_get_rail_voltage(RAIL_1V35), power_get_rail_current(RAIL_1V35));
|
|
printf("1V2: %5.2f V %3.0f mA\n", power_get_rail_voltage(RAIL_1V2), power_get_rail_current(RAIL_1V2));
|
|
|
|
float p_cur, p_avg, p_max;
|
|
float p_cur_sum, p_avg_sum, p_max_sum;
|
|
|
|
printf("Power Consumption (CUR, AVG, MAX):\n");
|
|
power_get_rail_power(RAIL_3V3, &p_cur, &p_avg, &p_max);
|
|
printf("MCU + IO: %5.1f mW %5.1f mW %5.1f mW\n", p_cur, p_avg, p_max);
|
|
power_get_rail_power(RAIL_1V35, &p_cur, &p_avg, &p_max);
|
|
printf("FPGA DDR: %5.1f mW %5.1f mW %5.1f mW\n", p_cur, p_avg, p_max);
|
|
power_get_rail_power(RAIL_1V2, &p_cur, &p_avg, &p_max);
|
|
printf("FPGA CORE: %5.1f mW %5.1f mW %5.1f mW\n", p_cur, p_avg, p_max);
|
|
power_get_rail_power(RAIL_1V8VID, &p_cur_sum, &p_avg_sum, &p_max_sum);
|
|
power_get_rail_power(RAIL_3V3VID, &p_cur, &p_avg, &p_max);
|
|
p_cur_sum += p_cur; p_avg_sum += p_avg; p_max_sum += p_max;
|
|
printf("VIDEO IN: %5.1f mW %5.1f mW %5.1f mW\n", p_cur_sum, p_avg_sum, p_max_sum);
|
|
power_get_rail_power(RAIL_5VES, &p_cur_sum, &p_avg_sum, &p_max_sum);
|
|
power_get_rail_power(RAIL_5VEG, &p_cur, &p_avg, &p_max);
|
|
p_cur_sum += p_cur; p_avg_sum += p_avg; p_max_sum += p_max;
|
|
printf("EPD HV: %5.1f mW %5.1f mW %5.1f mW\n", p_cur_sum, p_avg_sum, p_max_sum);
|
|
}
|