mirror of
https://github.com/Qortal/Brooklyn.git
synced 2025-02-12 10:15:54 +00:00
388 lines
7.9 KiB
C
388 lines
7.9 KiB
C
#include <stdint.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <chopstx.h>
|
||
|
||
#include "board.h"
|
||
|
||
#define PERIPH_BASE 0x40000000
|
||
#define APB1PERIPH_BASE PERIPH_BASE
|
||
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
|
||
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
|
||
#define AHB2PERIPH_BASE (PERIPH_BASE + 0x08000000)
|
||
|
||
struct GPIO {
|
||
volatile uint32_t MODER;
|
||
volatile uint16_t OTYPER;
|
||
uint16_t dummy0;
|
||
volatile uint32_t OSPEEDR;
|
||
volatile uint32_t PUPDR;
|
||
volatile uint16_t IDR;
|
||
uint16_t dummy1;
|
||
volatile uint16_t ODR;
|
||
uint16_t dummy2;
|
||
volatile uint16_t BSRR;
|
||
uint16_t dummy3;
|
||
volatile uint32_t LCKR;
|
||
volatile uint32_t AFR[2];
|
||
volatile uint16_t BRR;
|
||
uint16_t dummy4;
|
||
};
|
||
#define GPIOA_BASE (AHB2PERIPH_BASE + 0x0000)
|
||
#define GPIOA ((struct GPIO *) GPIOA_BASE)
|
||
#define GPIOF_BASE (AHB2PERIPH_BASE + 0x1400)
|
||
#define GPIOF ((struct GPIO *) GPIOF_BASE)
|
||
|
||
#define GPIO_SPEAKER_PIN 1
|
||
|
||
static struct GPIO *const GPIO_LED = ((struct GPIO *)GPIO_LED_BASE);
|
||
static struct GPIO *const GPIO_OTHER = ((struct GPIO *)GPIO_OTHER_BASE);
|
||
|
||
static chopstx_mutex_t mtx;
|
||
static chopstx_cond_t cnd;
|
||
|
||
static uint8_t
|
||
user_button (void)
|
||
{
|
||
return (GPIO_OTHER->IDR & 1) == 0;
|
||
}
|
||
|
||
static uint8_t l_data[5];
|
||
|
||
static void
|
||
set_led_display (uint32_t data)
|
||
{
|
||
l_data[0] = (data >> 0) & 0x1f;
|
||
l_data[1] = (data >> 5) & 0x1f;
|
||
l_data[2] = (data >> 10) & 0x1f;
|
||
l_data[3] = (data >> 15) & 0x1f;
|
||
l_data[4] = (data >> 20) & 0x1f;
|
||
}
|
||
|
||
|
||
static void
|
||
wait_for (uint32_t usec)
|
||
{
|
||
chopstx_usec_wait (usec);
|
||
}
|
||
|
||
static void
|
||
led_prepare_row (uint8_t col)
|
||
{
|
||
uint16_t data = 0x1f;
|
||
|
||
data |= ((l_data[0] & (1 << col)) ? 1 : 0) << 5;
|
||
data |= ((l_data[1] & (1 << col)) ? 1 : 0) << 6;
|
||
data |= ((l_data[2] & (1 << col)) ? 1 : 0) << 7;
|
||
data |= ((l_data[3] & (1 << col)) ? 1 : 0) << 9;
|
||
data |= ((l_data[4] & (1 << col)) ? 1 : 0) << 10;
|
||
GPIO_LED->ODR = data;
|
||
}
|
||
|
||
static void
|
||
led_enable_column (uint8_t col)
|
||
{
|
||
GPIO_LED->BRR = (1 << col);
|
||
}
|
||
|
||
|
||
#define STACK_MAIN
|
||
#define STACK_PROCESS_1
|
||
#define STACK_PROCESS_2
|
||
#define STACK_PROCESS_3
|
||
#include "stack-def.h"
|
||
|
||
#define PRIO_LED 3
|
||
|
||
#define STACK_ADDR_LED ((uint32_t)process1_base)
|
||
#define STACK_SIZE_LED (sizeof process1_base)
|
||
|
||
static void *
|
||
led (void *arg)
|
||
{
|
||
(void)arg;
|
||
|
||
chopstx_mutex_lock (&mtx);
|
||
chopstx_cond_wait (&cnd, &mtx);
|
||
chopstx_mutex_unlock (&mtx);
|
||
|
||
while (1)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < 5; i++)
|
||
{
|
||
led_prepare_row (i);
|
||
led_enable_column (i);
|
||
wait_for (1000);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
#define PRIO_SPK 4
|
||
|
||
#define STACK_ADDR_SPK ((uint32_t)process2_base)
|
||
#define STACK_SIZE_SPK (sizeof process2_base)
|
||
|
||
static chopstx_mutex_t spk_mtx;
|
||
static chopstx_cond_t spk_cnd;
|
||
static chopstx_cond_t spk_cnd_no_tone;
|
||
|
||
static uint8_t tone;
|
||
#define NO_TONE 255
|
||
|
||
|
||
static uint16_t tone_table[] = {
|
||
568, /* a = 880Hz */
|
||
/* 536, */
|
||
506, /* b */
|
||
478, /* c */
|
||
/* 451, */
|
||
426, /* d */
|
||
/* 402, */
|
||
379, /* e */
|
||
358, /* f*/
|
||
/* 338, */
|
||
319, /* g */
|
||
/* 301, */
|
||
284, /* A = 1760Hz */
|
||
/* 268 */
|
||
253, /* B */
|
||
239, /* C */
|
||
};
|
||
|
||
static void
|
||
change_tone (uint8_t t)
|
||
{
|
||
chopstx_mutex_lock (&spk_mtx);
|
||
tone = t;
|
||
chopstx_cond_signal (&spk_cnd_no_tone);
|
||
chopstx_cond_wait (&spk_cnd, &spk_mtx);
|
||
chopstx_mutex_unlock (&spk_mtx);
|
||
}
|
||
|
||
static void *
|
||
spk (void *arg)
|
||
{
|
||
(void)arg;
|
||
|
||
while (1)
|
||
{
|
||
uint8_t t;
|
||
uint16_t w;
|
||
|
||
chopstx_mutex_lock (&spk_mtx);
|
||
t = tone;
|
||
chopstx_cond_signal (&spk_cnd);
|
||
if (t == NO_TONE)
|
||
{
|
||
chopstx_cond_wait (&spk_cnd_no_tone, &spk_mtx);
|
||
t = tone;
|
||
}
|
||
chopstx_mutex_unlock (&spk_mtx);
|
||
|
||
w = tone_table[t]*5/3;
|
||
GPIO_OTHER->BSRR = (1 << GPIO_SPEAKER_PIN);
|
||
wait_for (w);
|
||
GPIO_OTHER->BRR = (1 << GPIO_SPEAKER_PIN);
|
||
wait_for (w);
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
#define PRIO_MUSIC 2
|
||
|
||
#define STACK_ADDR_MUSIC ((uint32_t)process3_base)
|
||
#define STACK_SIZE_MUSIC (sizeof process3_base)
|
||
|
||
#define C 0
|
||
#define D 1
|
||
#define E 2
|
||
#define F 3
|
||
#define G 4
|
||
#define A 5
|
||
#define B 6
|
||
|
||
#if 0 /* twinkle stars */
|
||
static const char *musical_score =
|
||
"c4c4g4g4A4A4g2f4f4e4e4d4d4c2"
|
||
"g4g4f4f4e4e4d2g4g4f4f4e4e4d2"
|
||
"c4c4g4g4A4A4g2f4f4e4e4d4d4c2";
|
||
#else /* tulip */
|
||
static const char *musical_score =
|
||
"c4d4e2c4d4e2g4e4d4c4d4e4d2"
|
||
"c4d4e2c4d4e2g4e4d4c4d4e4c2"
|
||
"g4g4e4g4A4A4g2e4e4d4d4c2";
|
||
#endif
|
||
|
||
static int get_t_and_l (char *tp, char *lp)
|
||
{
|
||
static unsigned int i = 0;
|
||
char tl, ll;
|
||
|
||
tl = musical_score[i++];
|
||
ll = musical_score[i++];
|
||
|
||
if (tl >= 'a')
|
||
*tp = tl - 'a';
|
||
else
|
||
*tp = tl - 'A' + 7;
|
||
|
||
*lp = ll - '0';
|
||
|
||
if (i >= strlen (musical_score))
|
||
{
|
||
i = 0;
|
||
return 0;
|
||
}
|
||
else
|
||
return 1;
|
||
}
|
||
|
||
#define WAIT_FOR_NO_TONE (1000*20)
|
||
#define WAIT_FOR_TONE (1000000*3/2)
|
||
|
||
static void *
|
||
music (void *arg)
|
||
{
|
||
(void)arg;
|
||
|
||
chopstx_mutex_init (&spk_mtx);
|
||
chopstx_cond_init (&spk_cnd);
|
||
chopstx_cond_init (&spk_cnd_no_tone);
|
||
|
||
chopstx_create (PRIO_SPK, STACK_ADDR_SPK, STACK_SIZE_SPK, spk, NULL);
|
||
|
||
while (1)
|
||
{
|
||
char t, l;
|
||
int r;
|
||
|
||
r = get_t_and_l (&t, &l);
|
||
|
||
change_tone (NO_TONE);
|
||
wait_for (WAIT_FOR_NO_TONE);
|
||
change_tone (t);
|
||
wait_for (WAIT_FOR_TONE / l);
|
||
|
||
if (!r)
|
||
{
|
||
change_tone (NO_TONE);
|
||
wait_for (WAIT_FOR_TONE * 3);
|
||
}
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
|
||
#define DATA55(x0,x1,x2,x3,x4) (x0<<20)|(x1<<15)|(x2<<10)|(x3<< 5)|(x4<< 0)
|
||
#define SIZE55(img) (sizeof (img) / sizeof (uint32_t))
|
||
|
||
static uint32_t image0[] = {
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x01,0x00,0x00,0x00),
|
||
DATA55 (0x01,0x03,0x01,0x01,0x00),
|
||
DATA55 (0x02,0x06,0x02,0x02,0x01),
|
||
DATA55 (0x05,0x0d,0x05,0x05,0x03),
|
||
DATA55 (0x0b,0x1a,0x0a,0x0a,0x06),
|
||
DATA55 (0x16,0x14,0x14,0x14,0x0c),
|
||
DATA55 (0x0d,0x08,0x09,0x08,0x19),
|
||
DATA55 (0x1b,0x11,0x12,0x10,0x13),
|
||
DATA55 (0x17,0x03,0x04,0x00,0x07),
|
||
DATA55 (0x0f,0x06,0x09,0x01,0x0e),
|
||
DATA55 (0x1e,0x0c,0x12,0x02,0x1c),
|
||
DATA55 (0x1d,0x19,0x05,0x05,0x18),
|
||
DATA55 (0x1a,0x12,0x0a,0x0a,0x11),
|
||
DATA55 (0x14,0x04,0x14,0x14,0x03),
|
||
DATA55 (0x08,0x08,0x08,0x09,0x06),
|
||
DATA55 (0x10,0x10,0x10,0x12,0x0c),
|
||
DATA55 (0x00,0x00,0x00,0x04,0x18),
|
||
DATA55 (0x00,0x00,0x00,0x08,0x10),
|
||
DATA55 (0x00,0x00,0x00,0x10,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
};
|
||
|
||
static uint32_t image1[] = {
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x01,0x00,0x00,0x00,0x01),
|
||
DATA55 (0x03,0x00,0x00,0x01,0x03),
|
||
DATA55 (0x07,0x01,0x01,0x03,0x06),
|
||
DATA55 (0x0f,0x02,0x02,0x06,0x0c),
|
||
DATA55 (0x1f,0x05,0x05,0x0c,0x18),
|
||
DATA55 (0x1e,0x0a,0x0a,0x18,0x11),
|
||
DATA55 (0x1d,0x14,0x14,0x10,0x03),
|
||
DATA55 (0x1b,0x08,0x08,0x00,0x07),
|
||
DATA55 (0x17,0x11,0x11,0x01,0x0f),
|
||
DATA55 (0x0e,0x02,0x02,0x02,0x1f),
|
||
DATA55 (0x1c,0x04,0x04,0x04,0x1e),
|
||
DATA55 (0x19,0x08,0x09,0x08,0x1d),
|
||
DATA55 (0x13,0x10,0x13,0x10,0x1b),
|
||
DATA55 (0x07,0x00,0x07,0x00,0x17),
|
||
DATA55 (0x0f,0x00,0x0f,0x00,0x0f),
|
||
DATA55 (0x1e,0x00,0x1e,0x00,0x1e),
|
||
DATA55 (0x1c,0x00,0x1c,0x00,0x1c),
|
||
DATA55 (0x18,0x00,0x18,0x00,0x18),
|
||
DATA55 (0x10,0x00,0x10,0x00,0x10),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
DATA55 (0x00,0x00,0x00,0x00,0x00),
|
||
};
|
||
|
||
int
|
||
main (int argc, const char *argv[])
|
||
{
|
||
uint8_t state = 0;
|
||
|
||
(void)argc;
|
||
(void)argv;
|
||
|
||
chopstx_mutex_init (&mtx);
|
||
chopstx_cond_init (&cnd);
|
||
|
||
chopstx_create (PRIO_LED, STACK_ADDR_LED, STACK_SIZE_LED, led, NULL);
|
||
chopstx_create (PRIO_MUSIC, STACK_ADDR_MUSIC, STACK_SIZE_MUSIC, music, NULL);
|
||
|
||
chopstx_usec_wait (200*1000);
|
||
|
||
chopstx_mutex_lock (&mtx);
|
||
chopstx_cond_signal (&cnd);
|
||
chopstx_mutex_unlock (&mtx);
|
||
|
||
while (1)
|
||
{
|
||
unsigned int i;
|
||
|
||
if (state)
|
||
for (i = 0; i < SIZE55 (image1); i++)
|
||
{
|
||
if (user_button ())
|
||
state = 0;
|
||
set_led_display (image1[i]);
|
||
wait_for (200*1000);
|
||
}
|
||
else
|
||
for (i = 0; i < SIZE55 (image0); i++)
|
||
{
|
||
if (user_button ())
|
||
state = 1;
|
||
set_led_display (image0[i]);
|
||
wait_for (200*1000);
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|