Saturday, June 9, 2018

Tutorial: Hello, World!

Welcome back! In my last post, I promised a minor modification to the codebase. The modification is to add the simplest-possible app, a "Hello, World" program for Ornament and Crime. The project does two things:
  1. It adds "Hello, World" to the bottom of the app menu (the one you get when you hold down the right encoder button for two seconds and release)
  2. It adds an Arduino sketch file for the Hello World app, the purpose of which is simply to say "Hello, World!"
Clone my Tutorial fork into your project directory, so you can follow along:
There are three files that have been modified. I'll explain those modifications here (all these files are in the O_C_Tutorial1/software/o_c_REV directory).

Modified OC_version.h


This is a super-simple one. This is just a string that contains the version at the bottom of the O_C's boot screen. A comment warns that this is a generated file, but it's not going to be overwritten as part of any process that we're undertaking. And it seems to me that if this were a real danger, this file wouldn't be under version control in the first place. So I modified it just to remind you of what your O_C is running.

Modified OC_apps.ino

 

I've been working with the O_C firmware for one day now, and here's something that's awesome about it: Apps are fairly self-contained. That is, you just need to tell OC_apps.ino about a new app, and then create a sketch file for it. Compare this to Peaks's firmware, in which references to new modes need to be scattered all over the place. The comments in the code are self-effacing ("This is a very poor-man's application 'switching' framework"), but this is really quite considerate.

To let O_C know what your new app is, you simply add two lines to OC_apps.ino. Both lines are variations of the same information; one is specifying a "boring" but useful name, and one is specifying an absurd pun that provides little information. Absurd pun is the default.

The lines to be added are near the top, as DECLARE_APP function-like macro calls, like this:

DECLARE_APP('H','W', "Hello, World", HELLO, HELLO_isr)

It would be instructive to take a look at the macro definition starting on line 27. The first two values, as far as I can tell, don't matter much. chars are passed, and the first one becomes a most-significant byte, and the second one becomes a least-significant byte of a 16-bit integer value. At this time, I'm not clear about the point of this value.

The next value is the natural language name of the item, as it will appear in the menu. You're expected to provide two DECLARE_APP() calls, one for if a BORING_APP_NAMES preprocessor option is selected, and one if not.

The next value is the prefix of the function names. For example, the "Hello, World" code will require method called HELLO_init(), HELLO_menu(), etc. This value is also used for the filename of the .ino file. In our present example, the app file will be called APP_HELLO.ino.

The final value is the name of the interrupt service routine (ISR) function for the app. I don't know why the macro doesn't just use prefix ## _isr, like it does for the other funcitons. I suspect it has something to do with allowing apps to share the same ISR function, if necessary. But if that was the case, then APP2_isr() could just call APP2_isr(). Anyway, I'm sure there's a good reason for it.

Once you've got the two DECLARE_APP() calls in, then you're pretty much done modifying the "framework" code. From now on, you're just creating your own stuff.

Created APP_HELLO.ino

 

The APP_SOMETHING.ino file is where the main functionality of your app is defined. If you open up APP_HELLO.ino now to examine it, you'll see that I left most of the functions blank (or returning zero, where a return value is needed). This app does only one thing, and that's to print "Hello, World!" in a title bar at the top of the screen. This is done with the graphics object, which is instantiated as an extern Graphics instance in src/drivers/display.h.

void HELLO_menu() {
    menu::DefaultTitleBar::Draw();
    graphics.setPrintPos(1,1);
    graphics.print("Hello, World!") ;
}


Incidentally, the interface for the Graphics class is in src/drivers/weegfx.h, and the implementations are in weegfx.cpp. This looks like a no-nonsense but capable display system, and I look forward to playing around with it.

Note that all eleven of the functions specified in the DECLARE_APP macro (that's including the ISR function) must be implemented, even if they're just empty stubs. Otherwise, you get a compile-time error.

Take a look at these three file changes, then upload the code to your O_C. Look for the new version at the bottom of the boot screen. Then, hold the right encoder for two seconds, and scroll down to look for the Hello, World app. Select the app and make sure that "Hello, World!" appears. You can get out of "Hello, World" by holding the right encoder down again.

Next, we'll be starting on an app that actually does something. In the near future, we'll go over
  • Dealing with app settings and fleshing out the menu
  • Reading from one trigger input and one CV input
  • Writing to one DAC

No comments:

Post a Comment

Pitch Calculation and Output

"If pitches were horses, we'd all be eatin' steak." --Jayne Cobb And where have I been for almost two months? I was busy...