2023-03-07 19:05:21 +00:00
|
|
|
// This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
|
|
|
|
// License: BSD
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
#include <generated/csr.h>
|
2023-03-07 19:05:21 +00:00
|
|
|
#include <irq.h>
|
|
|
|
#include <libbase/console.h>
|
2023-03-07 20:09:56 +00:00
|
|
|
#include <libbase/uart.h>
|
2023-03-07 19:05:21 +00:00
|
|
|
|
2023-06-04 11:58:14 +00:00
|
|
|
#include "can"
|
2023-05-16 21:09:35 +00:00
|
|
|
#include "note"
|
|
|
|
|
2023-03-07 19:05:21 +00:00
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/* Uart */
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
static char *readstr(void) {
|
2023-03-07 19:05:21 +00:00
|
|
|
char c[2];
|
|
|
|
static char s[64];
|
2023-05-12 18:53:27 +00:00
|
|
|
static unsigned int ptr = 0;
|
2023-03-07 19:05:21 +00:00
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
if (readchar_nonblock()) {
|
2023-03-07 19:05:21 +00:00
|
|
|
c[0] = getchar();
|
|
|
|
c[1] = 0;
|
2023-03-07 20:09:56 +00:00
|
|
|
switch (c[0]) {
|
2023-03-07 19:05:21 +00:00
|
|
|
case 0x7f:
|
|
|
|
case 0x08:
|
2023-03-07 20:09:56 +00:00
|
|
|
if (ptr > 0) {
|
2023-03-07 19:05:21 +00:00
|
|
|
ptr--;
|
|
|
|
fputs("\x08 \x08", stdout);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 0x07:
|
|
|
|
break;
|
|
|
|
case '\r':
|
|
|
|
case '\n':
|
|
|
|
s[ptr] = 0x00;
|
|
|
|
fputs("\n", stdout);
|
|
|
|
ptr = 0;
|
|
|
|
return s;
|
|
|
|
default:
|
2023-03-07 20:09:56 +00:00
|
|
|
if (ptr >= (sizeof(s) - 1))
|
2023-03-07 19:05:21 +00:00
|
|
|
break;
|
|
|
|
fputs(c, stdout);
|
|
|
|
s[ptr] = c[0];
|
|
|
|
ptr++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
static char *get_token(char **str) {
|
2023-03-07 19:05:21 +00:00
|
|
|
char *c, *d;
|
|
|
|
|
|
|
|
c = (char *)strchr(*str, ' ');
|
2023-03-07 20:09:56 +00:00
|
|
|
if (c == NULL) {
|
2023-03-07 19:05:21 +00:00
|
|
|
d = *str;
|
2023-03-07 20:09:56 +00:00
|
|
|
*str = *str + strlen(*str);
|
2023-03-07 19:05:21 +00:00
|
|
|
return d;
|
|
|
|
}
|
|
|
|
*c = 0;
|
|
|
|
d = *str;
|
2023-03-07 20:09:56 +00:00
|
|
|
*str = c + 1;
|
2023-03-07 19:05:21 +00:00
|
|
|
return d;
|
|
|
|
}
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
static void prompt(void) {
|
|
|
|
printf("\e[92;1mStackSynth\e[0m> ");
|
2023-03-07 19:05:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/* Help */
|
|
|
|
/*-----------------------------------------------------------------------*/
|
2023-05-12 19:07:39 +00:00
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
static void help(void) {
|
2023-05-12 16:44:43 +00:00
|
|
|
puts("\nLiteX custom demo app built " __DATE__
|
|
|
|
" " __TIME__
|
2023-03-07 20:09:56 +00:00
|
|
|
"\n");
|
2023-03-07 19:05:21 +00:00
|
|
|
puts("Available commands:");
|
|
|
|
puts("help - Show this command");
|
|
|
|
puts("reboot - Reboot CPU");
|
|
|
|
puts("donut - Spinning Donut demo");
|
2023-03-07 20:09:56 +00:00
|
|
|
#ifdef CSR_LEDS_BASE
|
2023-05-24 11:42:34 +00:00
|
|
|
puts("led - Led demo");
|
2023-03-07 20:09:56 +00:00
|
|
|
puts("leds - Led set demo");
|
|
|
|
#endif
|
2023-03-11 18:06:19 +00:00
|
|
|
#ifdef CSR_AUDIO_BASE
|
2023-05-18 11:52:17 +00:00
|
|
|
puts("saw - Sawtooth Wave demo");
|
|
|
|
puts("square - Square Wave demo");
|
|
|
|
puts("triangle - Triangle Wave demo");
|
|
|
|
puts("sine - Sine Wave demo");
|
2023-05-16 21:09:35 +00:00
|
|
|
puts("imperial - Imperial March demo");
|
|
|
|
puts("roll - Music demo");
|
2023-03-11 18:06:19 +00:00
|
|
|
#endif
|
2023-05-21 00:23:08 +00:00
|
|
|
#ifdef CSR_DAC_VOL_BASE
|
|
|
|
puts("volume - Get / Set DAC Volume");
|
|
|
|
#endif
|
2023-06-04 11:58:14 +00:00
|
|
|
#ifdef CSR_CAN_BASE
|
|
|
|
puts("can_id - Get / Set CAN ID");
|
|
|
|
puts("can_mask - Get / Set CAN Mask");
|
|
|
|
puts("can_read - Receive CAN Frames and print (delay in s)");
|
|
|
|
puts("can_watch - Watch CAN Frames at 2Hz");
|
|
|
|
#endif
|
2023-03-07 19:05:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/* Commands */
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
static void reboot_cmd(void) {
|
2023-03-07 19:05:21 +00:00
|
|
|
ctrl_reset_write(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CSR_LEDS_BASE
|
2023-05-12 19:07:39 +00:00
|
|
|
void led(void);
|
2023-03-07 21:00:30 +00:00
|
|
|
|
2023-05-12 19:07:39 +00:00
|
|
|
static void led_cmd(void) {
|
|
|
|
led();
|
2023-03-07 19:05:21 +00:00
|
|
|
}
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
static void leds_cmd(char **val) {
|
|
|
|
int value = (int)strtol(get_token(val), NULL, 0);
|
|
|
|
printf("Setting LED to %6x\n", value);
|
2023-05-12 19:07:39 +00:00
|
|
|
leds_out_write(value);
|
2023-03-07 20:09:56 +00:00
|
|
|
}
|
|
|
|
#endif
|
2023-03-11 18:06:19 +00:00
|
|
|
#ifdef CSR_AUDIO_BASE
|
2023-05-12 19:07:39 +00:00
|
|
|
static void saw_cmd(char **val) {
|
2023-03-11 18:06:19 +00:00
|
|
|
int value = (int)strtol(get_token(val), NULL, 0);
|
2023-05-18 11:52:17 +00:00
|
|
|
printf("Setting Oscillator 0 to Sawtooth: %dHz\n", value);
|
|
|
|
wave(WAVE_SAW);
|
|
|
|
audio_targ0_write(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void square_cmd(char **val) {
|
|
|
|
int value = (int)strtol(get_token(val), NULL, 0);
|
|
|
|
printf("Setting Oscillator 0 to Square: %dHz\n", value);
|
|
|
|
wave(WAVE_SQUARE);
|
|
|
|
audio_targ0_write(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void triangle_cmd(char **val) {
|
|
|
|
int value = (int)strtol(get_token(val), NULL, 0);
|
|
|
|
printf("Setting Oscillator 0 to Triangle: %dHz\n", value);
|
|
|
|
wave(WAVE_TRIANGLE);
|
|
|
|
audio_targ0_write(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sine_cmd(char **val) {
|
|
|
|
int value = (int)strtol(get_token(val), NULL, 0);
|
|
|
|
printf("Setting Oscillator 0 to Sine: %dHz\n", value);
|
|
|
|
wave(WAVE_SINE);
|
2023-05-18 10:38:39 +00:00
|
|
|
audio_targ0_write(value);
|
2023-03-11 18:06:19 +00:00
|
|
|
}
|
2023-05-16 21:09:35 +00:00
|
|
|
|
|
|
|
static void imperial_cmd() {
|
|
|
|
note(NOTE_G4, 400);
|
|
|
|
note(NOTE_NONE, 400);
|
|
|
|
note(NOTE_G4, 400);
|
|
|
|
note(NOTE_NONE, 400);
|
|
|
|
note(NOTE_G4, 600);
|
|
|
|
note(NOTE_NONE, 600);
|
|
|
|
note(NOTE_D4S, 200);
|
|
|
|
note(NOTE_A4S, 200);
|
|
|
|
note(NOTE_G4, 600);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_D4S, 400);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_A4S, 200);
|
|
|
|
note(NOTE_G4, 1000);
|
|
|
|
note(NOTE_D4S, 600);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_D5, 600);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_D5, 600);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_D5, 600);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_D5S, 400);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_A4S, 200);
|
|
|
|
note(NOTE_F4S, 600);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_D4S, 400);
|
|
|
|
note(NOTE_NONE, 200);
|
|
|
|
note(NOTE_A4S, 200);
|
|
|
|
note(NOTE_G4, 800);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void roll_cmd() {
|
|
|
|
note(NOTE_C4S, 450);
|
|
|
|
note(NOTE_D4S, 600);
|
|
|
|
note(NOTE_G3S, 150);
|
|
|
|
note(NOTE_D4S, 450);
|
|
|
|
note(NOTE_F4, 450);
|
|
|
|
note(NOTE_G4S, 90);
|
|
|
|
note(NOTE_F4S, 90);
|
|
|
|
note(NOTE_F4, 90);
|
|
|
|
note(NOTE_C4S, 510);
|
|
|
|
note(NOTE_D4S, 600);
|
|
|
|
note(NOTE_G3S, 1500);
|
|
|
|
note(NOTE_C4S, 450);
|
|
|
|
note(NOTE_D4S, 600);
|
|
|
|
note(NOTE_G3S, 150);
|
|
|
|
note(NOTE_D4S, 450);
|
|
|
|
note(NOTE_F4, 450);
|
|
|
|
note(NOTE_G4S, 90);
|
|
|
|
note(NOTE_F4S, 90);
|
|
|
|
note(NOTE_F4, 90);
|
|
|
|
note(NOTE_C4S, 510);
|
|
|
|
note(NOTE_D4S, 600);
|
|
|
|
note(NOTE_G3S, 1500);
|
|
|
|
}
|
2023-03-11 18:06:19 +00:00
|
|
|
#endif
|
2023-05-21 00:23:08 +00:00
|
|
|
#ifdef CSR_DAC_VOL_BASE
|
|
|
|
static void dac_vol_cmd(char **val) {
|
|
|
|
char *token = get_token(val);
|
|
|
|
if (token == *val) {
|
|
|
|
printf("DAC volume is %d (of 128)\n", dac_vol_volume_read());
|
|
|
|
} else {
|
|
|
|
int value = (int)strtol(token, NULL, 0);
|
|
|
|
printf("Setting DAC volume to %d (of 128)\n", value);
|
|
|
|
dac_vol_volume_write(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2023-03-07 20:09:56 +00:00
|
|
|
|
2023-06-04 11:58:14 +00:00
|
|
|
#ifdef CSR_CAN_BASE
|
|
|
|
static void can_id_cmd(char **val) {
|
|
|
|
char *token = get_token(val);
|
|
|
|
if (token == *val) {
|
|
|
|
printf("Current CAN ID (filter) is 0x%03X (max 0x7FF)\n", can_id_read());
|
|
|
|
} else {
|
|
|
|
int value = (int)strtol(token, NULL, 0);
|
|
|
|
printf("Setting CAN ID (filter) to 0x%03X (max 0x7FF)\n", value);
|
|
|
|
can_id_write(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void can_mask_cmd(char **val) {
|
|
|
|
char *token = get_token(val);
|
|
|
|
if (token == *val) {
|
|
|
|
printf("Current CAN mask is 0x%03X (max 0x7FF)\n", can_mask_read());
|
|
|
|
} else {
|
|
|
|
int value = (int)strtol(token, NULL, 0);
|
|
|
|
printf("Setting CAN mask to 0x%03X (max 0x7FF)\n", value);
|
|
|
|
can_mask_write(value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void can_read_cmd(char **val) {
|
|
|
|
char *token = get_token(val);
|
|
|
|
int loop_delay;
|
|
|
|
if (token == *val) {
|
|
|
|
loop_delay = 10;
|
|
|
|
} else {
|
|
|
|
loop_delay = (int)strtol(token, NULL, 0) * 10;
|
|
|
|
}
|
|
|
|
while (true) {
|
|
|
|
can_frame frame = can_read();
|
|
|
|
printf("CAN ID: 0x%03X, data:", frame.id);
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
printf(" 0x%02X", frame.data[i]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
for (int i = 0; i < loop_delay; i++) {
|
|
|
|
if (readchar_nonblock()) {
|
|
|
|
getchar();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
busy_wait(100);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void can_watch_cmd() {
|
|
|
|
while (true) {
|
|
|
|
can_frame frame = can_read();
|
|
|
|
printf("CAN ID: 0x%03X, data:", frame.id);
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
printf(" 0x%02X", frame.data[i]);
|
|
|
|
}
|
|
|
|
printf("\r");
|
|
|
|
if (readchar_nonblock()) {
|
|
|
|
getchar();
|
|
|
|
printf("\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
busy_wait(200);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-05-12 18:53:27 +00:00
|
|
|
void donut(void);
|
2023-03-07 19:05:21 +00:00
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
static void donut_cmd(void) {
|
2023-03-07 19:05:21 +00:00
|
|
|
printf("Donut demo...\n");
|
|
|
|
donut();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
/* Console service / Main */
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
static void console_service(void) {
|
2023-03-07 19:05:21 +00:00
|
|
|
char *str;
|
|
|
|
char *token;
|
|
|
|
|
|
|
|
str = readstr();
|
2023-03-07 20:09:56 +00:00
|
|
|
if (str == NULL)
|
|
|
|
return;
|
2023-03-07 19:05:21 +00:00
|
|
|
token = get_token(&str);
|
2023-03-07 20:09:56 +00:00
|
|
|
if (strcmp(token, "help") == 0)
|
2023-03-07 19:05:21 +00:00
|
|
|
help();
|
2023-03-07 20:09:56 +00:00
|
|
|
else if (strcmp(token, "reboot") == 0)
|
2023-03-07 19:05:21 +00:00
|
|
|
reboot_cmd();
|
2023-03-07 20:09:56 +00:00
|
|
|
else if (strcmp(token, "donut") == 0)
|
2023-03-07 19:05:21 +00:00
|
|
|
donut_cmd();
|
2023-03-11 18:06:19 +00:00
|
|
|
#ifdef CSR_LEDS_BASE
|
2023-05-24 11:42:34 +00:00
|
|
|
else if (strcmp(token, "led") == 0)
|
|
|
|
led_cmd();
|
2023-03-07 20:09:56 +00:00
|
|
|
else if (strcmp(token, "leds") == 0)
|
|
|
|
leds_cmd(&str);
|
|
|
|
#endif
|
2023-03-11 18:06:19 +00:00
|
|
|
#ifdef CSR_AUDIO_BASE
|
2023-05-12 19:07:39 +00:00
|
|
|
else if (strcmp(token, "saw") == 0)
|
|
|
|
saw_cmd(&str);
|
2023-05-18 11:52:17 +00:00
|
|
|
else if (strcmp(token, "square") == 0)
|
|
|
|
square_cmd(&str);
|
|
|
|
else if (strcmp(token, "triangle") == 0)
|
|
|
|
triangle_cmd(&str);
|
|
|
|
else if (strcmp(token, "sine") == 0)
|
|
|
|
sine_cmd(&str);
|
2023-05-16 21:09:35 +00:00
|
|
|
else if (strcmp(token, "imperial") == 0)
|
|
|
|
imperial_cmd();
|
|
|
|
else if (strcmp(token, "roll") == 0)
|
|
|
|
roll_cmd();
|
2023-05-21 00:23:08 +00:00
|
|
|
#endif
|
|
|
|
#ifdef CSR_DAC_VOL_BASE
|
|
|
|
else if (strcmp(token, "volume") == 0)
|
|
|
|
dac_vol_cmd(&str);
|
2023-06-04 11:58:14 +00:00
|
|
|
#endif
|
|
|
|
#ifdef CSR_CAN_BASE
|
|
|
|
else if (strcmp(token, "can_id") == 0)
|
|
|
|
can_id_cmd(&str);
|
|
|
|
else if (strcmp(token, "can_mask") == 0)
|
|
|
|
can_mask_cmd(&str);
|
|
|
|
else if (strcmp(token, "can_read") == 0)
|
|
|
|
can_read_cmd(&str);
|
|
|
|
else if (strcmp(token, "can_watch") == 0)
|
|
|
|
can_watch_cmd();
|
2023-03-07 19:05:21 +00:00
|
|
|
#endif
|
|
|
|
prompt();
|
|
|
|
}
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
int main(void) {
|
2023-03-07 19:05:21 +00:00
|
|
|
#ifdef CONFIG_CPU_HAS_INTERRUPT
|
|
|
|
irq_setmask(0);
|
|
|
|
irq_setie(1);
|
|
|
|
#endif
|
|
|
|
uart_init();
|
|
|
|
|
|
|
|
help();
|
|
|
|
prompt();
|
|
|
|
|
2023-03-07 20:09:56 +00:00
|
|
|
while (1) {
|
2023-03-07 19:05:21 +00:00
|
|
|
console_service();
|
|
|
|
}
|
|
|
|
}
|