QortalOS Brooklyn for Raspberry Pi 4
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

413 lines
9.3 KiB

#include <stdint.h>
#include <stdlib.h>
#include <chopstx.h>
#include "board.h"
static uint8_t main_finished;
#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)
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 cnd0, cnd1;
#define BUTTON_PUSHED 1
static uint8_t button_state;
static uint8_t
user_button (void)
{
return button_state;
}
static uint8_t l_data[5];
#define LED_FULL ((0x1f << 20)|(0x1f << 15)|(0x1f << 10)|(0x1f << 5)|0x1f)
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
scroll_led_display (uint8_t row)
{
l_data[0] = (l_data[0] << 1) | ((row >> 0) & 1);
l_data[1] = (l_data[1] << 1) | ((row >> 1) & 1);
l_data[2] = (l_data[2] << 1) | ((row >> 2) & 1);
l_data[3] = (l_data[3] << 1) | ((row >> 3) & 1);
l_data[4] = (l_data[4] << 1) | ((row >> 4) & 1);
}
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);
}
static void *
led (void *arg)
{
(void)arg;
chopstx_mutex_lock (&mtx);
chopstx_cond_wait (&cnd0, &mtx);
chopstx_mutex_unlock (&mtx);
while (!main_finished)
{
int i;
for (i = 0; i < 5; i++)
{
led_prepare_row (i);
led_enable_column (i);
wait_for (1000);
}
}
GPIO_LED->ODR = 0x0000; /* Off all LEDs. */
GPIO_LED->OSPEEDR = 0;
GPIO_LED->OTYPER = 0;
GPIO_LED->MODER = 0; /* Input mode. */
GPIO_OTHER->PUPDR = 0x0000; /* No pull-up. */
return NULL;
}
static uint8_t get_button_sw (void) { return (GPIO_OTHER->IDR & 1) == 0; }
static void *
button (void *arg)
{
uint8_t last_button = 0;
(void)arg;
chopstx_mutex_lock (&mtx);
chopstx_cond_wait (&cnd1, &mtx);
chopstx_mutex_unlock (&mtx);
while (!main_finished)
{
uint8_t button = get_button_sw ();
if (last_button == button && button != button_state)
{
wait_for (1000);
button = get_button_sw ();
if (last_button == button)
button_state = button;
}
wait_for (2000);
last_button = button;
}
return NULL;
}
#define PRIO_LED 3
#define PRIO_BUTTON 2
#define STACK_MAIN
#define STACK_PROCESS_1
#define STACK_PROCESS_2
#include "stack-def.h"
#define STACK_ADDR_LED ((uint32_t)process1_base)
#define STACK_SIZE_LED (sizeof process1_base)
#define STACK_ADDR_BUTTON ((uint32_t)process2_base)
#define STACK_SIZE_BUTTON (sizeof process2_base)
#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 l55[] = {
DATA55 (0x08, 0x04, 0x1c, 0x00, 0x00),
DATA55 (0x00, 0x14, 0x0c, 0x08, 0x00),
DATA55 (0x00, 0x04, 0x14, 0x0c, 0x00),
DATA55 (0x00, 0x08, 0x06, 0x0c, 0x00),
DATA55 (0x00, 0x04, 0x02, 0x0e, 0x00),
DATA55 (0x00, 0x00, 0x0a, 0x06, 0x04),
DATA55 (0x00, 0x00, 0x02, 0x0a, 0x06),
DATA55 (0x00, 0x00, 0x04, 0x03, 0x06),
DATA55 (0x00, 0x00, 0x02, 0x01, 0x07),
DATA55 (0x02, 0x00, 0x00, 0x05, 0x03),
DATA55 (0x03, 0x00, 0x00, 0x01, 0x05),
DATA55 (0x03, 0x00, 0x00, 0x02, 0x11),
DATA55 (0x13, 0x00, 0x00, 0x01, 0x10),
DATA55 (0x11, 0x01, 0x00, 0x00, 0x12),
DATA55 (0x12, 0x11, 0x00, 0x00, 0x10),
DATA55 (0x18, 0x11, 0x00, 0x00, 0x01),
DATA55 (0x08, 0x19, 0x00, 0x00, 0x10),
DATA55 (0x09, 0x18, 0x10, 0x00, 0x00),
DATA55 (0x08, 0x09, 0x18, 0x00, 0x00),
DATA55 (0x10, 0x0c, 0x18, 0x00, 0x00),
};
#define DATA55V(x0,x1,x2,x3,x4) (x0<<0)|(x1<<5)|(x2<<10)|(x3<< 15)|(x4<< 20)
#define CHAR_SPC 0
#define CHAR_H 1
#define CHAR_A 2
#define CHAR_P 3
#define CHAR_Y 4
#define CHAR_C 5
#define CHAR_K 6
#define CHAR_I 7
#define CHAR_N 8
#define CHAR_G 9
#define CHAR_EXC 10
#define CHAR_W 11
#define CHAR_h 12
#define CHAR_t 13
#define CHAR_AP 14
#define CHAR_s 15
#define CHAR_U 16
#define CHAR_QT 17
#define CHAR_o 18
#define CHAR_X 19
static uint8_t hh[] = {
CHAR_H, CHAR_A, CHAR_P, CHAR_P, CHAR_Y,
CHAR_SPC,
CHAR_H, CHAR_A, CHAR_C, CHAR_K, CHAR_I, CHAR_N, CHAR_G,
CHAR_EXC,
CHAR_SPC, CHAR_SPC, CHAR_SPC,
};
static uint8_t gnu[] = {
CHAR_W, CHAR_h, CHAR_A, CHAR_t, CHAR_AP, CHAR_s, CHAR_SPC,
CHAR_G, CHAR_N, CHAR_U, CHAR_QT,
CHAR_SPC, CHAR_SPC,
CHAR_G, CHAR_N, CHAR_U, CHAR_AP, CHAR_s, CHAR_SPC,
CHAR_N, CHAR_o, CHAR_t, CHAR_SPC,
CHAR_U, CHAR_N, CHAR_I, CHAR_X,
CHAR_EXC,
CHAR_SPC, CHAR_SPC,
};
struct { uint8_t width; uint32_t data; } chargen[] = {
{ 3, 0 }, /* SPACE */
{ 4, DATA55V (0x1f, 0x04, 0x04, 0x1f, 0x00) }, /* H */
{ 3, DATA55V (0x17, 0x15, 0x0f, 0x00, 0x00) }, /* A */
{ 4, DATA55V (0x1f, 0x14, 0x14, 0x08, 0x00) }, /* P */
{ 4, DATA55V (0x19, 0x05, 0x05, 0x1e, 0x00) }, /* Y */
{ 4, DATA55V (0x0e, 0x11, 0x11, 0x0a, 0x00) }, /* C */
{ 4, DATA55V (0x1f, 0x04, 0x0c, 0x13, 0x00) }, /* K */
{ 3, DATA55V (0x11, 0x1f, 0x11, 0x00, 0x00) }, /* I */
{ 4, DATA55V (0x1f, 0x08, 0x06, 0x1f, 0x00) }, /* N */
{ 4, DATA55V (0x0e, 0x11, 0x15, 0x07, 0x00) }, /* G */
{ 2, DATA55V (0x1d, 0x1c, 0x00, 0x00, 0x00) }, /* ! */
{ 5, DATA55V (0x1e, 0x01, 0x0e, 0x01, 0x1e) }, /* W */
{ 3, DATA55V (0x1f, 0x04, 0x07, 0x00, 0x00) }, /* h */
{ 4, DATA55V (0x08, 0x1e, 0x09, 0x09, 0x00) }, /* t */
{ 3, DATA55V (0x04, 0x18, 0x18, 0x00, 0x00) }, /* ' */
{ 4, DATA55V (0x09, 0x15, 0x15, 0x12, 0x00) }, /* s */
{ 4, DATA55V (0x1e, 0x01, 0x01, 0x1e, 0x00) }, /* U */
{ 4, DATA55V (0x08, 0x10, 0x15, 0x08, 0x00) }, /* ? */
{ 4, DATA55V (0x06, 0x09, 0x09, 0x06, 0x00) }, /* o */
{ 5, DATA55V (0x11, 0x0a, 0x04, 0x0a, 0x11) }, /* X */
{ 4, DATA55V (0x1f, 0x11, 0x11, 0x0e, 0x00) }, /* D */
{ 4, DATA55V (0x0e, 0x15, 0x15, 0x0d, 0x00) }, /* e */
{ 4, DATA55V (0x1f, 0x05, 0x05, 0x06, 0x00) }, /* b */
{ 1, DATA55V (0x17, 0x00, 0x00, 0x00, 0x00) }, /* i */
{ 4, DATA55V (0x02, 0x15, 0x15, 0x0f, 0x00) }, /* a */
{ 4, DATA55V (0x0f, 0x08, 0x08, 0x0f, 0x00) }, /* n */
};
#define REPEAT_COUNT 10
static int
life_display (void)
{
unsigned int i;
uint8_t count = 0;
uint8_t state = 0;
while (count++ < REPEAT_COUNT)
for (i = 0; i < SIZE55 (l55); i++)
{
if (user_button ())
{
set_led_display (LED_FULL);
state = 1;
}
else if (state == 1)
return 0;
else
set_led_display (l55[i]);
wait_for (350*1000);
}
return 1;
}
static int
text_display (uint8_t kind)
{
unsigned int i, j;
uint8_t *text;
uint8_t len;
uint8_t count = 0;
uint8_t state = 0;
if (kind)
{
text = hh;
len = sizeof (hh);
}
else
{
text = gnu;
len = sizeof (gnu);
}
set_led_display (0);
while (count++ < REPEAT_COUNT)
for (i = 0; i < len; i++)
{
for (j = 0; j < chargen[text[i]].width; j++)
{
if (user_button ())
{
set_led_display (LED_FULL);
state = 1;
}
else if (state == 1)
return 0;
else
scroll_led_display ((chargen[text[i]].data >> j * 5) & 0x1f);
wait_for (120*1000);
}
if (user_button ())
{
set_led_display (LED_FULL);
state = 1;
}
else if (state == 1)
return 0;
else
scroll_led_display (0);
wait_for (120*1000);
}
return 1;
}
int
main (int argc, const char *argv[])
{
chopstx_t led_thd;
chopstx_t button_thd;
uint8_t happy = 1;
(void)argc;
(void)argv;
chopstx_conf_idle (1);
chopstx_mutex_init (&mtx);
chopstx_cond_init (&cnd0);
chopstx_cond_init (&cnd1);
led_thd = chopstx_create (PRIO_LED, STACK_ADDR_LED,
STACK_SIZE_LED, led, NULL);
button_thd = chopstx_create (PRIO_BUTTON, STACK_ADDR_BUTTON,
STACK_SIZE_BUTTON, button, NULL);
chopstx_usec_wait (200*1000);
chopstx_mutex_lock (&mtx);
chopstx_cond_signal (&cnd0);
chopstx_cond_signal (&cnd1);
chopstx_mutex_unlock (&mtx);
wait_for (100*1000);
if (user_button ())
{
/* Wait button release. */
while (user_button ())
wait_for (100*1000);
happy = 0;
goto do_text;
}
while (1)
{
if (life_display ())
break;
do_text:
if (text_display (happy))
break;
}
main_finished = 1;
chopstx_join (button_thd, NULL);
chopstx_join (led_thd, NULL);
chopstx_conf_idle (4);
return 0;
}