Cosa: An Object-Oriented Platform for Arduino programming

that Cosa is a single source code baseline for a large set of boards, processors (e.g. Uno, Mini Pro, Nano, LilyPad, Might, Mega, Tiny), modules and hardware devices

Any port to M0+, M3, M4 or something like that in planning? :slight_smile:

pito:
Any port to M0+, M3, M4 or something like that in planning? :slight_smile:

Got my hands on a few TI MSP430 LaunchPads but I can't say when I would have time for that. I still have to figure out the tool-chain and the hardware details before porting. There is an Arduino port so some of the work is already done.

For ARM (e.g. Arduino Due) I would like to reduce the amount of tuning for AVR 8-bit (int8_t/uint8_t) and go for more generic and portable (int/unsigned int). Also I would like the toolchain to become more stable.

Still the amount of work is fairly large so I need to dig into the details before doing a plan (to answer your question in classical Dilbert style ;)). Anyway this will not be happening this year as the focus right now is wireless networking protocols including a version of Google Protocol Buffer for data encoding/decoding .

Cheers!

Any port to M0+, M3, M4 or something like that in planning?

I've done quite a lot of work porting the Arduino core stuff to an M0 (LPC1227), I probably won't continue with it partly because other projects like Cosa seem to be 1000% better :slight_smile:

I have half a mind to port Cosa to LPCs but don't really have the time at present.

I guess the actual chip is more important than the ARM core though given that (I would assume) once you get the sysTick worked out almost all the code deals with peripherals.


Rob

I think I need to add a line or two regarding porting to other processors.

Cosa is right now very much adapted/optimized for 8/16-bit MPUs with very limited memory (SRAM). Moving to something with 8 Kbyte SRAM or larger I would redesign the core towards a true micro RTOS with threads, semphore, message queues, the works :). There is no way to scale upwards without that. The device driver layer would be rewritten. And the programming model moved towards active objects (actors).

Cheers!

And a HAL might help as well..

Some news on the latest improvements and addition to Cosa:

  1. Update of Cosa Networking Protocol draft (RETE)
    https://github.com/mikaelpatel/Cosa/blob/master/RETE.txt

  2. Added a template class for bitsets. See interface and example sketch.
    Cosa/BitSet.hh at master · mikaelpatel/Cosa · GitHub
    Cosa/CosaBitSet.ino at master · mikaelpatel/Cosa · GitHub

  3. Support for encoding and decoding Google Protocol Buffers protocol.
    https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/ProtocolBuffer.hh
    https://github.com/mikaelpatel/Cosa/blob/master/examples/Sandbox/CosaProtocolBuffer/CosaProtocolBuffer.ino

Cheers!

I would redesign the core towards a true micro RTOS with threads, semphore, message queues, the works

That would be a lot of fun to do but is all that necessary, could turn into bloatware.

I admit that some simple scheduling would be nice, and once you do that semaphores etc tend to follow. And event queues would be nice especially if usable with an FSM....

Ok maybe it is necessary :slight_smile:


Rob

I think by using ChibiOS / NilRTOS (use same HAL as of v3) as the RTOS, adapting COSA is not to much work.

I already can use parts of COSA using ChibiOS without any problems (for instance the whole digital/analogue pin OO implementation) and it does make my software a lot easier to read and maintain.

In some parts (for instance SPI / TWI stuff), I have to add locks (semaphores) to make sure things won't lock up or crash. Furthermore I don't use the events, as this does not play nice with ChibiOS, but that's about it...

If that synchronization functionality is implemented in COSA by a sync object that either does nothing (default COSA) or calls the underlying RTOS, the user of the COSA objects won't even notice the RTOS.

The only problem I see is that COSA disables interrupts on a lot of places...

sirhax:
After getting this to work fairly reliably, I have run into a situation where the CosaWirelessReceiver appears to stop receiving data after going out of range and then coming back. Simply pushing the reset button on the CosaWirelessReceiver board causes data to start flowing again. Have you run into this?

@sirhax

I have been able to force this behaviour and found what I think was the problem. Pushed a fix for this. See Improving CC1101 device driver robustness; flush receive fifo. · mikaelpatel/Cosa@19b2f9e · GitHub. Basically the receive fifo could contain incomplete messages as the interrupt is only generate for complete messages (correct address, length, crc). I had assumed that this was done automatically and illegal frames discharged.

Need to check if the NRF24L01P also has this behaviour.

Cheers!

MarsWarrior:
The only problem I see is that COSA disables interrupts on a lot of places...

@MarsWarrior

The Cosa synchronized blocks are used to achieve consistent updates and are very short (in the range of 10-50 us). Long interrupt disabled blocks are avoided as Cosa is interrupt and event driven. Very few of these block would or should be replaced by semaphores (or rw_locks). It is consistency on another level of abstraction.

Anyway this is an important issue how to use a RTOS and write code that is still bare-metal and uses very little resources (SRAM). Would like to know more about your experience with this. Great job!

Cheers!

kowalski:

sirhax:
After getting this to work fairly reliably, I have run into a situation where the CosaWirelessReceiver appears to stop receiving data after going out of range and then coming back.

Need to check if the NRF24L01P also has this behaviour.

@sirhax

The Cosa NRF24L01P driver works as expected and does not show this behaviour. Message are retransmitted until the retransmit limit(15) is exceeded and then flushed. Getting back into range starts up the transmission/ack again without any problems.

Cheers!

I have been able to force this behaviour and found what I think was the problem. Pushed a fix for this. See Improving CC1101 device driver robustness; flush receive fifo. · mikaelpatel/Cosa@19b2f9e · GitHub. Basically the receive fifo could contain incomplete messages as the interrupt is only generate for complete messages (correct address, length, crc). I had assumed that this was done automatically and illegal frames discharged.

Thanks Kowalski. I finally got around to testing your latest commits and agree that the CC1101 transceivers appear to be much more reliable now. Nice work!

I don't believe that the CC1101 has hardware message ACK and retransmission like the NRF24. Do you have any plans to implement these features in the CC1101 driver? If not, I may pursue it in my own applications.

Also, the CC1101 has an "Integrated Analog Temperature Sensor" and was wondering if you have any plans to make that component available/accessible in the CC1101 driver?

I'm anxious for some cheap and readily available CC1200 boards to start popping up on ebay.

Thanks again and keep up the great work!

sirhax:
I don't believe that the CC1101 has hardware message ACK and retransmission like the NRF24. Do you have any plans to implement these features in the CC1101 driver?

@sirhax
Thanks! You are right about the CC1101 not having the same ACK support as NRF24L01. The plan is actually to add an implementation of the Wireless interface that adds this for any device driver that lack internal support (a protocol stack). The basic design was previously available in the VWI extended mode. The plan is also to add routing and a higher level protocol (RETE) for wireless sensor handling.

sirhax:
Also, the CC1101 has an "Integrated Analog Temperature Sensor" and was wondering if you have any plans to make that component available/accessible in the CC1101 driver?

To make this available CC1101 pin GD0 must be connected to an analog pin. The GD0 pin needs to be enabled as output and special care taken to enable the sensor during the CC1101 is in IDLE state. Then the difficult part mapping the analog value to temperature reading :). Please note that the value from the device has an accuracy of +- 2 C, 2.47 mV per C at 3V, The analog conversion without scaling approx. 3 mV LSB (3V/1024).

Cheers!

Because of today's turmoil around the RC4 - this modifies the RC4 into the "RC4-dropN".
I set N=1024 (based on some papers I've found).

RC4::restart(const void* key, size_t len)
{
  for (uint16_t i = 0; i < sizeof(m_state); i++)
    m_state[i] = i;
    
  m_x = 0;
  m_y = 0;

  const uint8_t* buf = (const uint8_t*) key;
  uint8_t j = 0;
  for (uint16_t i = 0; i < 256; i++) {
    j = j + m_state[i] + buf[i % len];
    uint8_t tmp = m_state[i];
    m_state[i] = m_state[j];
    m_state[j] = tmp;
    }

  // Pito: drop first 1024 key stream bytes
  for(uint16_t n = 0; n < 1024; n++) {
    m_x += 1;
    uint8_t sx = m_state[m_x];
    m_y += sx;
    uint8_t sy = m_state[m_y];
    m_state[m_x] = sy;
    m_state[m_y] = sx;	
    }
   //
}

Compiled, not crypto tested, no warranty of any kind, use at your own risk :slight_smile:
PS: the vector test in the cosa rc4 example will probably fail as the key stream starts at key_stream_byte_N 1024 now (instead of at 0 as with the original RC4)..

Hey kowalski,
I can't for the life of me get the CC1101 sender working on an AtTiny84. I'm hoping it is something as simple as using the wrong pins. I can successfully use an Uno sender with Mega2560 receiver.
Can you double-check my pinouts:

CC1101      UnoPin# MegaPin# Tiny84#
1:GND       GND     GND      14
2:3.3v      3.3v    3.3v     1
3:CE/GDO0   9       48       10
4:CSN       10      53       11
5:SCK       13      52       9
6:MOSI      11      51       7
7:MISO/GDO1 12      50       8
8:IRQ/GDO2  2/EXT0  2/EXT4   5

I added a D0 output pin to blink an LED in setup() and then at the beginning of loop(). It blinks once in setup() and ONLY once at loop(), so I'm assuming that it croaks in the rf.send() routine. But I don't know how to do any further debugging on a Tiny at this point. Any help is appreciated!

@sirhax

No problem. It looks like you have done something that I do over and over again. The SPI pins are for programming. The DO/DI are the USI pins so you need to reverse that. I dont understand why they made the chip this way. It is a very common mistake and I guess a lot of people just give up.

CC1101      UnoPin# MegaPin# Tiny84#
1:GND       GND     GND      14
2:3.3v      3.3v    3.3v     1
3:CE/GDO0   9       48       10
4:CSN       10      53       11
5:SCK       13      52       9
6:MOSI      11      51       8
7:MISO/GDO1 12      50       7
8:IRQ/GDO2  2/EXT0  2/EXT4   5/EXT0

Cheers!

Kowalksi,
Once again, you save the day. I'm both glad yet extremely annoyed that it was as simple as reversing two pins...
Also, apparently, I'm not the only one: Arduino for Beginners: Getting nRF24L01 working with attiny84

However, I have noticed that the packets can still get out of sync between the sender/receiver. Here is the output from a session where it seems like every other packet was out of sync, and a simple reset of the receiver caused things to start working correctly again:

CosaWirelessReceiver: started
error:timeout(-2)
src=0x10,port=0x1,dest=0x1,len=16,rssi=-71,lqi=45:nr=220,payload=0x21d3: 37 37 37 37 37 37 37 37 37 37 37 37 37 37 
error:timeout(-2)
error:illegal frame size(-1)
error:timeout(-2)
src=0x10,port=0x1,dest=0x1,len=16,rssi=-69,lqi=46:nr=236,payload=0x21d3: 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 3b 
error:timeout(-2)
error:illegal frame size(-1)
error:timeout(-2)
src=0x10,port=0x1,dest=0x1,len=16,rssi=-65,lqi=47:nr=252,payload=0x21d3: 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 
error:timeout(-2)
error:illegal frame size(-1)
error:timeout(-2)
src=0x10,port=0x1,dest=0x1,len=16,rssi=-65,lqi=48:nr=12,payload=0x21d3: 43 43 43 43 43 43 43 43 43 43 43 43 43 43 
CosaWirelessReceiver: started
src=0x10,port=0x1,dest=0x1,len=16,rssi=-66,lqi=46:nr=28,payload=0x21d3: 47 47 47 47 47 47 47 47 47 47 47 47 47 47 
src=0x10,port=0x1,dest=0x0,len=16,rssi=-65,lqi=47:nr=31,payload=0x21d3: 47 47 47 47 47 47 47 47 47 47 47 47 47 47 
src=0x10,port=0x1,dest=0x1,len=16,rssi=-67,lqi=45:nr=32,payload=0x21d3: 48 48 48 48 48 48 48 48 48 48 48 48 48 48 
src=0x10,port=0x1,dest=0x0,len=16,rssi=-67,lqi=43:nr=35,payload=0x21d3: 48 48 48 48 48 48 48 48 48 48 48 48 48 48 
src=0x10,port=0x1,dest=0x1,len=16,rssi=-72,lqi=47:nr=36,payload=0x21d3: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 
src=0x10,port=0x1,dest=0x0,len=16,rssi=-71,lqi=49:nr=39,payload=0x21d3: 49 49 49 49 49 49 49 49 49 49 49 49 49 49 
src=0x10,port=0x1,dest=0x1,len=16,rssi=-66,lqi=45:nr=40,payload=0x21d3: 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 
src=0x10,port=0x1,dest=0x0,len=16,rssi=-66,lqi=45:nr=43,payload=0x21d3: 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a 4a

Have any ideas?
Thanks again!

Here is a short update on the latest development in the Cosa project.

  1. ATtiny861 (ATtinyX61)
    Support for yet another of the ATtiny processors.

  2. Basetta
    Build support for breadboard version (ATmega328, internal clock 8 MHz). Contributed by hasse_bjork. Thanks!

  3. Line and Token scanner
    The Cosa IOStream will now support both Line and Token scanning. The device level function gets() is now fully supported for serial line input. This is based on a new member function, peekchar(c), which allows seaching an input buffer for a specific trigger character such as new-line. The iostream level function scan() may be used to read tokens from an input stream. The tokens are special characters, identifiers or numbers. See the example sketch and documentation for more details https://github.com/mikaelpatel/Cosa/blob/master/examples/Sandbox/CosaUART/CosaUART.ino

1,2,3[Send]
SCAN[Send]
1,2,3[Send]
----------------------------------------------------------------
CosaUART: started (LINE MODE)
7488:502:echo('1,2,3')
12000:811:echo('SCAN')
SCAN MODE
16224:1113:echo('1')
16224:1113:echo(',')
16224:1113:echo('2')
16224:1113:echo(',')
16240:1113:echo('3')
  1. Additional LCD I2C expansion port
    The I2C based LCD expansion port GYIICLCD is now supported by HD44780 device driver and port adapter.

Cheers!

Here is a short update on the latest development in the Cosa project.

  1. Base64
    Great discussion on Base64 inspired to adding this to the Cosa encoders. Could be implemented as a Cosa IOStream::Filter which is basically a decorator pattern for output streams.
    Interface: https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/Cipher/Base64.hh
    Source: https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/Cipher/Base64.cpp
    Example: https://github.com/mikaelpatel/Cosa/blob/master/examples/Cipher/CosaBase64/CosaBase64.ino
    Performance: 4 us/byte

  2. AVR ISP
    Moving towards a Wireless bootloader it is time to add support for device programming. In Cosa style two new support classes have been added; AVR/Programmer with implementation of the AVR serial programming instruction set. AVR/STK500, an implementation of the full protocol for the AVR starterkit. These bring together CosaISP in the Tools library.
    Interfaces: https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/AVR/Programmer.hh
    https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/AVR/STK500.hh
    The example tools sketch CosaISP is simply:

#include "Cosa/Watchdog.hh"
#include "Cosa/IOStream/Driver/UART.hh"
#include "Cosa/AVR/Programmer.hh"
#include "Cosa/AVR/STK500.hh"

Programmer isp;
STK500 stk(&uart, &isp);

void setup()
{
  uart.begin(19200);
  Watchdog::begin();
}

void loop()
{
  stk.run();
}

STK500 handles the parsing of commands issued from avrdude and Programmer the interaction with the device.

  1. New Benchmark
    A new benchmark has been added to measure IOStream, IOBuffer and UART performance. The benchmark gives a baseline for future improvements using some of the great discussions on this forum regarding number to string conversion (fast /10).
    Cosa/CosaBenchmarkUART.ino at master · mikaelpatel/Cosa · GitHub

  2. Template class for BitSet
    Compact and fast implementation of bitsets with operator support.
    Interface: Cosa/BitSet.hh at master · mikaelpatel/Cosa · GitHub
    Example: Cosa/CosaBitSet.ino at master · mikaelpatel/Cosa · GitHub

  3. Device Driver for DS1302 Trickle-Charge Timekeeping Chip.
    Interface: https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/Driver/DS1302.hh
    Example: https://github.com/mikaelpatel/Cosa/blob/master/examples/Drivers/CosaDS1302/CosaDS1302.ino

See the Issues log for further changes; Issues · mikaelpatel/Cosa · GitHub

Cheers!

How about using a TWI LCD adapter for 3X4 keypad decoding? Here is a sketch from the Cosa Sandbox.
https://github.com/mikaelpatel/Cosa/blob/master/examples/Sandbox/CosaTWIKeyPad/CosaTWIKeyPad.ino
Below is an Arduino Mini Pro with a MJKDZ LCD adapter connected to a 4X4 keypad running the demo sketch.

This is a really cheap and easy way to add a keypad to a sketch and if used together with other TWI devices does not require any additional pins. By using the TWI LCD adapter sub-addresses (0..7) it is possible to have several adapters on the same TWI bus and have both keypad and LCD.

Cheers!