Go Down

Topic: Cosa: An Object-Oriented Platform for Arduino programming (Read 104502 times) previous topic - next topic

Graynomad

I already have a lot of Arduino-like code written for the 122x, pinMode, digitalWrite, Serial etc. It's all C but I plan move it to C++ before too long.

One of my next jobs is to separate the 122x-specific stuff into files to help get it running on the other models.

_____
Rob
Rob Gray aka the GRAYnomad www.robgray.com

majenko


I already have a lot of Arduino-like code written for the 122x, pinMode, digitalWrite, Serial etc. It's all C but I plan move it to C++ before too long.

One of my next jobs is to separate the 122x-specific stuff into files to help get it running on the other models.

_____
Rob

Fancy building a core for UECIDE?

Graynomad

Quote
Fancy building a core for UECIDE?

Yeah, when I get back onto that project. Not that I understand the way it works, do you have separate "cores" for each target board/CPU? Maybe answer that back on your thread rather than high jacking this one. Maybe you already described that somewhere I missed or forgot after 13 pages :)

I've been following your UECIDE thread but at 100M per download can't afford to grab every change, I'll have to wait for it to stabilise a bit.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

majenko


Quote
Fancy building a core for UECIDE?

Yeah, when I get back onto that project. Not that I understand the way it works, do you have separate "cores" for each target board/CPU? Maybe answer that back on your thread rather than high jacking this one. Maybe you already described that somewhere I missed or forgot after 13 pages :)

I've been following your UECIDE thread but at 100M per download can't afford to grab every change, I'll have to wait for it to stabilise a bit.

______
Rob

I'm doing some work on the WIki for it - starting with how to write a core ;)

There is a tiny (relatively) upgrade package generated along with the standard installations which just contains the java components and support files.  This can be extracted over the top of an existing installation to upgrade it to the latest version.  This won't upgrade any cores or boards, and doesn't include any of the platform specific executables.

One day this package will form the basis of the auto-update facility ;)

kowalski


Quote
Fancy building a core for UECIDE?

Maybe answer that back on your thread rather than high jacking this one.

Would appreciate that ;-) though I think the work you @majenko are doing on UECIDE and @pito for porting Cosa into this new IDE project is great. Hope to get time to have a closer look soon.

Cheers!

kowalski

#155
Jul 19, 2013, 10:56 pm Last Edit: Jul 20, 2013, 01:55 pm by kowalski Reason: 1
The latest addition to Cosa is a LCD menu system. It ties into the Cosa LCD and Keypad device drivers.

The design is data-driven and uses program memory for all static data, e.g. menu items, lists, strings, etc. This gives a very compact design. The Menu support also allows simple access and change of program state such as enumeration, bitset and integer range variables. A supporting macro set hides all of the details of creating the data structures in program memory. Below are some snippets to give a feel for the declarative programming style.

First, creating a menu item with an action function. As most of the Cosa design this is object-oriented with a support class Menu::Action. The object can hold the state necessary for the implementation of the action.

Code: [Select]

#include "Cosa/LCD/Driver/HD44780.hh"
#include "Cosa/Menu.hh"

// Use the HD44780 LCD driver with 4-bit parallel port and keypad shield
HD44780::Port port;
HD44780 lcd(&port);

// Menu Action ---------------------------------------------------------------
// Menu item with binding to action function and state (object)
// 1. Create an action handler by sub-classing Menu::Action

class FileOpenAction : public Menu::Action {
public:
 virtual void run(Menu::item_P item)
 {
   lcd.display_clear();
   lcd.puts_P(PSTR("opening file..."));
   SLEEP(2);
 }
};

// 2. Create an instance and bind to a menu item.
FileOpenAction do_open;
MENU_ACTION(open_action,"Open",do_open)

// 3. Add to a menu item list.
MENU_BEGIN(file_menu,"File")
MENU_ITEM(open_action)
MENU_END(file_menu)

Selecting "File" from the "Demo" root menu the first item, "Open", in the sub-menu is shown as the title.

Selecting this item will execute the action function.

Second snippet creates enumeration symbols and mapping from a menu item to program state. When the item is selected the up/down buttons will allow change of the associated value. The current value is shown as the enumeration item string. These configuration/control variables are collected in an "Options" sub-menu in "Edit". Please note that the menu system data structures handle the mapping between the binary and textual representation of the value.

Code: [Select]

// Menu Enumeration Variable -------------------------------------------------
// Menu item with enumeration to change program state
// 1. Define the symbols needed for the enumeration type
MENU_SYMB(on_symb,"On")
MENU_SYMB(off_symb,"Off")

// 2. Define the enumeration type
MENU_ENUM_BEGIN(onoff_enum_t)
 MENU_ENUM_ITEM(off_symb)
 MENU_ENUM_ITEM(on_symb)
MENU_ENUM_END(onoff_enum_t);

// 3. Create a menu item with reference to program state to control
uint16_t tracing = 1;
MENU_ENUM(onoff_enum_t,tracing_enum,"Tracing",tracing)

Selecting the "Edit" and "Options" will take us to the above settings.

Selecting the "Tracing" item will allow us to change the tracing state. In modify mode the menu item title is prefixed with an asterisks.

Third snippet shows mapping from a menu item to an integer range variable. When selected the up/down keys will allow the variable to be changed within the given range.
Code: [Select]

// Menu Integer Range Variable -----------------------------------------------
// Menu item with integer range(low..high) to change program state change
// 1. Create menu item with integer range and reference to variable
int16_t limit = 42;
MENU_RANGE(limit_range,"Limit",-10,100,limit)

// 2. Add menu item to menu item list
MENU_BEGIN(options_menu,"Options")
 MENU_ITEM(tracing_enum)
 MENU_ITEM(state_enum)
 MENU_ITEM(limit_range)
MENU_END(options_menu)

The integer range menu item will show the lower and upper value in modification mode. The up/down keys will handle decrement/increment of the variable.

The enumeration symbol lists may also be used for bitset, i.e. to create configuration variables with one-or-many selection.

Below is a snippet that allows setting of a number of debug attributes. Selecting the menu item will allow adding/removing attributes for the set.
Code: [Select]

// Menu Bitset Variable ------------------------------------------------------
// Menu item with bitset to change program state
// 1. Define the symbols needed for the enumeration type
MENU_SYMB(break_symb,"Break")
MENU_SYMB(mockup_symb,"Mockup")
MENU_SYMB(profile_symb,"Profile")
MENU_SYMB(trace_symb,"Trace")

// 2. Define the enumeration type. Symbol order is the value set (0.3).
MENU_ENUM_BEGIN(debug_enum_t)
 MENU_ENUM_ITEM(break_symb)
 MENU_ENUM_ITEM(mockup_symb)
 MENU_ENUM_ITEM(profile_symb)
 MENU_ENUM_ITEM(trace_symb)
MENU_ENUM_END(debug_enum_t);

// 3. Create a menu item with reference to program state to control
// The enumeration type values are bit positions. The initial value is
// Break | Mockup.
uint16_t debug = 3;
MENU_BITSET(debug_enum_t,debug_enum,"Debug",debug)

// The Edit sub-menu with Options and Debug settings
MENU_BEGIN(edit_menu,"Edit")
 MENU_ITEM(options_menu)
 MENU_ITEM(debug_enum)
MENU_END(edit_menu)

Selecting an item in the bitset with toggle the corresponding bit in the control variable.

A Menu::Walker class handles all of the details of stepping through the menu tree and decoding the key events. The walker keeps track of the path through the menu tree and handles the select/up/down/left/right keypad button events. Below is the setup/loop snippet. It is pure event driven.
Code: [Select]

// The walker will receive key events from the keypad
Menu::Walker walker(&lcd, &root_menu);

void setup()
{
  Watchdog::begin(16, SLEEP_MODE_IDLE, Watchdog::push_timeout_events);
  lcd.begin();
  lcd.puts_P(PSTR("CosaLCDmenu: started"));
  SLEEP(2);
  walker.begin();
}

void loop()
{
 Event event;
 Event::queue.await(&event);
 event.dispatch();
}

See the full example sketch on github (or in the Cosa/examples directory):
https://github.com/mikaelpatel/Cosa/blob/master/examples/Sandbox/CosaLCDmenu/CosaLCDmenu.ino

The LCD menu class documentation: http://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/dc/db6/Menu_8hh.html

Cheers!

pito

#156
Jul 20, 2013, 12:31 pm Last Edit: Jul 20, 2013, 02:39 pm by pito Reason: 1
To try the above Cosa menu example (CosaLCDmenu.ino) with the new UECIDE you may:

1. Place Cosa's library ("Cosa") and Cosa's examples ("Examples") folders into your Sketchbook directory - into "libraries\Cosa" folder, for example:

Code: [Select]
C:\MyCode\Arduino\libraries\Cosa\Cosa
C:\MyCode\Arduino\libraries\Cosa\Examples


2. Place this #pragma at the beginning of the CosaLCDmenu.ino sketch, for example:

Code: [Select]
..
* Baseline(Watchdog, LCD) 4006 bytes, +Menu::Walker 6430 bytes
* and +Demo menu code 6678 bytes.
*
* This file is part of the Arduino Che Cosa project.
*/

#pragma parameter extension=C:\MyCode\Arduino\libraries\Cosa

#include "Cosa/Watchdog.hh"
#include "Cosa/LCD/Driver/HD44780.hh"
#include "Cosa/Menu.hh"
..


3. As the result of the build process you may get (built for Mighty1284p)

Code: [Select]
Program Size:
 Flash: 6608 bytes
 RAM:   400 bytes




kowalski

@pito
Nice job! Looking good ;-)

If it is possible to add an "-I." (allow include path expansion from current directory) to the IDE compiler option it should be possible to remove the need for the pragma and the modification of the example sketch code.

Thanks for your effort of getting Cosa up and running in this new IDE.

Cheers!

majenko


@pito
Nice job! Looking good ;-)

If it is possible to add an "-I." (allow include path expansion from current directory) to the IDE compiler option it should be possible to remove the need for the pragma and the modification of the example sketch code.

Thanks for your effort of getting Cosa up and running in this new IDE.

Cheers!

Adding the -I for include files is simple enough, but that won't include the source (.cpp) files.  The #pragma tells the compiler to include those files into the compilation of the core.a library file.

kowalski

#159
Jul 21, 2013, 12:53 am Last Edit: Jul 21, 2013, 01:04 am by kowalski Reason: 1

Adding the -I for include files is simple enough, but that won't include the source (.cpp) files.  The #pragma tells the compiler to include those files into the compilation of the core.a library file.

@majenko

Great work with the UECIDE! I have followed some of its progress. And the work by @pito with getting Cosa to build.

I am aware of the problem with compiling the source. The focus with the include was the sub-directory structuring of header files in Cosa. I see the pragma solution as only temporary and do not see that as a long term solution for the Cosa source code.

I was hoping to delay the transition to a core for Cosa but it seems like this would be the natural next step to make build of the library easier. I wanted to allow Cosa and the Arduino core to coexist so that porting of code to Cosa could be done in increments. Going to a core would allow me to remove all of the Arduino core code and create my own main() and init(). This would remove some ISR conflicts and reduce the footprint with a few hundred bytes.

What would be the optimum structuring of Cosa for the UECIDE build process? Would it be possible to install Cosa as a library and header files? This is what I would like to do later on in the project to achieve more traditional software delivery/install.

BW if would be great if UECIDE link/upload to include the EEMEM section. The Arduino IDE just skips this part and EEMEM variables are not initiated correctly (i.e. the eeprom section is not generated and uploaded).

Cheers!

majenko

The core format (what little there is of it) is detailed at http://uecide.org/wiki/index.php/Writing_Cores.  The actual format is pretty flexible and you can put what you like where you like, within reason.  Any file locations are pointed to by entries in the core.txt file.  There's only really 2 or 3 bits to worry about - the "core" or "api" folder, which is where the main Cosa software would be, the "libraries" folder, which would be any importable libraries in the format that the Arduino uses (libname/libname.cpp & libname/libname.h + extra files), and the examples folder (which is actually a hard-coded name at the moment) where your example sketches can go.  You can also add a "plugins" directory (again hard coded at this moment in time) where you can put java plugins to be included with the core.  The compiler and any tools you need for uploading, like avrdude, can go in a folder in the core too - I usually use a "compiler" and a "tools" folder.  These don't have to be included with the core if the user is able to use a compiler or tools installed in the OS somewhere, or you could reference the compiler and tools located in another core (say the avr105 core), as long as that core is installed.

During compilation the .eeprom section of the compiled elf file is stripped out into a separate file (named "${build.folder}/${filename}.eep"), which you can do what you want with.  You can craft the upload command to use that .eep file should you wish.

kowalski

@majenko

Thanks for the link and info. I was considering starting off with a Arduino core and then adapt to UECIDE. Guess the formats/structure are more or less the same.

What I really would like is support for frameworks and binary libraries with header files as a delivery. If I understand the intension of the cores, they came about to allow new custom boards to use Arduino software without updating the "core".

The eeprom stuff I am doing when I need to but it would have been great if the IDE had done this from the start.

Thanks again for your help!

majenko


What I really would like is support for frameworks and binary libraries with header files as a delivery.

I have been thinking about this too, but from the PoV of caching core and library pre-compiled code to speed up compilations.  The first time you compile a sketch for a board and it compiles the libraries and the core it could put the libraries into .a files (say ~/.uecide/cache/uno/libSPI.a) and store them, along with the core.a file, somewhere it can get at later.  Then it just links against the libraries it needs to (-L~/.uecide/cache/uno -lSPI).

I guess it could look for .a files inside the library too if the code is generic enough to do it as one library for all boards - MyLib/libMyLib.a and MyLib/libMyLib.h - if it finds the .a then it links against it instead of compiling .cpp files.

kowalski

#163
Jul 22, 2013, 04:32 pm Last Edit: Jul 23, 2013, 08:36 am by kowalski Reason: 1
The latest update to Cosa includes a new installation procedure. Cosa is now packaged as an Arduino core and supports Standard Arduino (ATmega328), Mighty (ATmega1248), Mega (ATmega2560) and Tiny (ATtinyX4/X5) out-of-the-box.

To install Cosa download from github and unzip in the Arduino Sketchbook hardware directory.

https://github.com/mikaelpatel/Cosa/archive/master.zip

Restart the Arduino IDE and the Cosa example sketches and board support will be available in the File>Sketchbook> and Tools>Boards> menus.

Advanced users should git clone to allow faster update.

Use the issue handling at github for trouble reports and improvement suggestions. Do not forget "Watch/Star" the repo in github.

https://github.com/mikaelpatel/Cosa
http://cosa-arduino.blogspot.se/
http://dl.dropboxusercontent.com/u/993383/Cosa/doc/html/index.html

Cheers!

kowalski

#164
Jul 23, 2013, 09:23 am Last Edit: Jul 23, 2013, 11:05 am by kowalski Reason: 1
Here are some details on the new Cosa installation package and core. The Cosa Arduino core contains its own main.cpp and Arduino.h file. The main() function looks like this:
Code: [Select]

extern void setup(void);
int main(void) __attribute__((weak));
int main(void)
{
 init();
 setup();
 while (1) loop();
 return (0);
}

The function attribute "weak" allows sketches to replace the main() function. The setup() and loop() are the Arduino major sketch functions. For Cosa there is a default loop() function. This is possible as Cosa is an object-oriented event driven framework.
Code: [Select]

void loop() __attribute__((weak));
void loop()
{
 Event event;
 Event::queue.await(&event);
 event.dispatch();
}

The Arduino.h file is required for the Arduino build pre-processing. The Cosa version of this file is more or less empty as all Cosa symbols are handled by the Cosa/Types.h, Cosa/Board.hh and other header files.

https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/Types.h
https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/Board.hh

The Cosa/Board.hh and sub-directory Board with implementations of the class Board is how variants are handled in Cosa. It replaces the core variants directory with the pins_arduino.h file.

The Board class contains the low-level special function register access functions and pin symbols. This method of implementation allows compiler error detection when building a sketch and high performance. The Cosa object-oriented pin functions are 2-10X faster than Arduino/Wiring. And as the pins are symbols defined in enum's in the Board class the compiler can help detect illegal usage of pins.  

The Cosa Arduino core is truly stand-alone. It is easy to include the Arduino core baseline functions if needed. In that case copy them from the Arduino core.

Cheers!

Go Up