17. Norns
Norns hookup into the monolith struct. Only works with
MONOLITH_NORNS
macro defined.
17.1. Top Level Constructs
Functions, forward declarations, and struct contents are all
conditinally included with the macro MONOLITH_NORNS
. To
make this easier, special named blocks have been made
around these elements.
#ifdef MONOLITH_NORNS
<<norns_functions>>
#endif
The < Monolith has a single instance of drawing thread stored
inside of the monolith data.
A flag is used to store whether or not the drawing thread
has been allocated + started. When monolith first
initializes, it is set to be false (0).
Note that this is only included if The drawing thread data is set to be This opens + allocates the framebuffer data, without
starting the drawing thread. This also includes allocating
data needed for the drawing thread as well.
This will actually start the thread and allocate data
for it, if it has not been done already.
The thread stop callback is called at cleanup, whether or
not the thread has actually been started.
CLOSED: [2019-11-22 Fri 20:07]
This is used to get the internal video + frame buffers.
This is useful for situations where interacting with the
framebuffer directly is better than trying to use the
drawing thread.
Getting the video buffer allows for certain norns drawing
operations to be used directly, instead of having to write
a bunch of wrapper functions around it.
Any time a change is made in the video buffer, it must
be updated to the frame buffer. This function will send a
message to update it in the drawing thread.
The function The function Note that It is called in the top-level monolith cleanup function,
even if the norns listener has not been started.
Any time a knob or key event happens, a user-supplied
callback can happen. These functions are inteded to
be used by any monolith pages wishing to extend their
functionality onto the norns. These callbacks should
be assigned when a page is opened.
Since norns callbacks are not part of the main page
interface, this means that they can persist between page
selections if the new page does not utilize them. This
is a delibrate design decision.
In practice, it is highly recommend to leave key 1 (top
left) alone. This should be reserved for a "return to main
menu" button.
Norns gets polled inside the main event loop thread with
Only if A quick and simple event loop, to get some simple standalone
monolith programs working.
This will start a blocking loop that polls for the top left
norns button. When pressed, the device will power off.
#ifdef MONOLITH_NORNS
<<norns_function_declarations>>
#endif
#ifdef MONOLITH_NORNS
<<norns_struct_contents>>
#endif
#ifdef MONOLITH_NORNS
<<norns_init>>
#endif
#ifdef MONOLITH_NORNS
<<norns_cleanup>>
#endif
#ifdef MONOLITH_NORNS
<<norns_janet_entries>>
#endif
#ifdef MONOLITH_NORNS
<<norns_janet_functions>>
#endif
17.2. TODO Monolith Drawing Thread
17.2.1. TODO Running flag
17.2.2. TODO Drawing Thread Data in Struct
MONOLITH_NORNS
is
enabled.
NULL
by default, to
indicate that nothing has been allocated + initialized.
norns_drawthread *ndt;
m->ndt = NULL;
17.2.3. TODO Opening + Allocating the framebuffer
17.2.3.1. In C (via monolith_norns_gfx_init)
void monolith_norns_gfx_init(monolith_d *m);
void monolith_norns_gfx_init(monolith_d *m)
{
if (m->ndt != NULL) return;
norns_drawthread_new(&m->ndt);
norns_drawthread_init(m->ndt);
}
17.2.3.2. In Janet (via monolith/norns-gfx-init)
#ifdef MONOLITH_NORNS
{
"monolith/norns-gfx-init",
j_norns_gfx_init,
"Initialize/open, but do not start, norns graphics thread."
},
#endif
#ifdef MONOLITH_NORNS
static Janet j_norns_gfx_init(int32_t argc, Janet *argv)
{
monolith_d *m;
janet_fixarity(argc, 0);
m = monolith_data_get();
monolith_norns_gfx_init(m);
return janet_wrap_nil();
}
#endif
17.2.4. TODO Starting the thread (user-level)
17.2.4.1. TODO From Scheme
17.2.4.2. TODO From Janet
17.2.5. TODO Drawing Thread at Cleanup
void monolith_norns_gfx_clean(monolith_d *m);
void monolith_norns_gfx_clean(monolith_d *m)
{
norns_drawthread *ndt;
if (m->ndt == NULL) return;
ndt = m->ndt;
m->ndt = NULL;
norns_drawthread_clean(ndt);
norns_drawthread_del(&ndt);
}
17.2.6. DONE Getting the buffers
norns_framebuffer * monolith_norns_framebuffer(monolith_d *m);
norns_videobuf * monolith_norns_videobuf(monolith_d *m);
norns_framebuffer * monolith_norns_framebuffer(monolith_d *m)
{
if (m->ndt == NULL) return NULL;
return norns_drawthread_framebuffer(m->ndt);
}
norns_videobuf * monolith_norns_videobuf(monolith_d *m)
{
if (m->ndt == NULL) return NULL;
return norns_drawthread_videobuf(m->ndt);
}
17.2.7. TODO Updating the display (via the drawing thread)
void monolith_norns_draw(monolith_d *m);
void monolith_norns_draw(monolith_d *m)
{
norns_framebuffer *fb;
norns_videobuf *vb;
if (m->ndt == NULL) return;
fb = norns_drawthread_framebuffer(m->ndt);
vb = norns_drawthread_videobuf(m->ndt);
norns_videobuf_copy(vb, fb);
}
17.3. Monolith Norns Event Polling
17.3.1. Event polling struct declaration
norns_poll_d *norns_poll;
m->norns_poll = NULL;
17.3.2. Setup + Start the norns listener
17.3.2.1. norns listener setup in C
monolith_norns_setup
is used to setup and
start polling.
void monolith_norns_setup(monolith_d *m);
void monolith_norns_setup(monolith_d *m)
{
norns_poll_d *poll;
if (m->norns_poll != NULL) return;
norns_poll_new(&poll);
norns_poll_init(poll);
m->norns_poll = poll;
}
17.3.2.2. norns listener setup in Janet
#ifdef MONOLITH_NORNS
{
"monolith/norns-setup",
j_norns_setup,
"Starts norns listener."
},
#endif
#ifdef MONOLITH_NORNS
static Janet j_norns_setup(int32_t argc, Janet *argv)
{
monolith_d *m;
janet_fixarity(argc, 0);
m = monolith_data_get();
monolith_norns_setup(m);
return janet_wrap_nil();
}
#endif
17.3.3. Stop + Clean the norns listener
monolith_norns_clean
will stop and clean up
the listener.
void monolith_norns_clean(monolith_d *m);
norns_poll
is set to be NULL before it is freed,
in case the event loop is still running.
void monolith_norns_clean(monolith_d *m)
{
norns_poll_d *poll;
if (m->norns_poll != NULL) {
poll = m->norns_poll;
m->norns_poll = NULL;
norns_poll_del(&poll);
}
}
monolith_norns_clean(m);
17.3.4. Setting peripheral callbacks
17.3.4.1. Setting Buttons
void monolith_norns_key(monolith_d *m,
int key,
void (*fun)(void *, int),
void *ud);
void monolith_norns_key(monolith_d *m,
int key,
void (*fun)(void *, int),
void *ud)
{
if (m->norns_poll == NULL) return;
norns_poll_cb_key(m->norns_poll, key, fun, ud);
}
17.3.4.2. Setting Knobs
void monolith_norns_knob(monolith_d *m,
int knob,
void (*fun)(void *, int),
void *ud);
void monolith_norns_knob(monolith_d *m,
int key,
void (*fun)(void *, int),
void *ud)
{
if (m->norns_poll == NULL) return;
norns_poll_cb_knob(m->norns_poll, key, fun, ud);
}
17.3.5. Norns polling in the main event loop
MONOLITH_NORNS
is enabled.
#ifdef MONOLITH_NORNS
if (m->norns_poll != NULL) {
norns_poll(m->norns_poll);
}
#endif
17.3.6. Getting the poll data
norns_poll_d * monolith_norns_poll(monolith_d *m);
norns_poll_d * monolith_norns_poll(monolith_d *m)
{
return m->norns_poll;
}
17.4. Simple Loop
17.4.1. C Function (monolith_norns_simpleloop)
void monolith_norns_simpleloop(monolith_d *m);
void monolith_norns_simpleloop(monolith_d *m)
{
int fid;
int rc;
struct input_event evt[8];
int nevts;
int e;
int running;
int poweroff;
norns_framebuffer *fb;
norns_videobuf *vb;
running = 1;
poweroff = 0;
fid = norns_open_keys();
norns_framebuffer_new(&fb);
norns_framebuffer_open(fb);
norns_videobuf_new(&vb);
norns_videobuf_init(vb);
norns_draw_string(vb, 63 - (4*8), 28, 0xff, 0x00, "monolith");
norns_videobuf_copy(vb, fb);
while(running) {
rc = read(fid, evt, sizeof(struct input_event) * 8);
if(rc != -1) {
nevts = rc / sizeof(struct input_event);
for(e = 0; e < nevts; e++) {
if(evt[e].type) {
if (evt[e].code == 1 && evt[e].value == 1) {
running = 0;
poweroff = 1;
} else if (evt[e].code == 2 && evt[e].value == 1) {
running = 0;
}
fflush(stdout);
}
}
}
usleep(10);
}
norns_videobuf_clear(vb);
if (poweroff) {
norns_draw_string(vb, 63 - (8*2), 28, 0x20, 0x00, "bye.");
} else {
norns_draw_string(vb, 63 - (4*5), 28, 0x20, 0x00, "quit.");
}
norns_videobuf_copy(vb, fb);
close(fid);
norns_framebuffer_close(fb);
norns_framebuffer_del(&fb);
norns_videobuf_del(&vb);
if (poweroff) {
system("poweroff");
}
}
17.4.2. Janet Function (monolith/norns-simpleloop)
{
"monolith/norns-simpleloop",
norns_simpleloop,
"A simple event loop for the norns"
},
static Janet norns_simpleloop(int32_t argc, Janet *argv)
{
janet_fixarity(argc, 0);
monolith_norns_simpleloop(monolith_data_get());
return janet_wrap_nil();
}
17.5. Norns Wait + Quit
int norns_running;
m->norns_running = 1;
void monolith_norns_wait(monolith_d *m);
void monolith_norns_wait(monolith_d *m)
{
while (m->norns_running) {
sleep(1);
}
}
void monolith_norns_quit(monolith_d *m);
void monolith_norns_quit(monolith_d *m)
{
m->norns_running = 0;
}
{
"monolith/norns-wait",
norns_wait,
"Wait to quit or poweroff."
},
static Janet norns_wait(int32_t argc, Janet *argv)
{
janet_fixarity(argc, 0);
monolith_norns_wait(monolith_data_get());
return janet_wrap_nil();
}
prev | home | next