Can I mix assembly code and C in the Arduino IDE?

Hello, after many hours of researching and finally giving up I decided to ask directly how to use assembly code alongside the Arduino code (like the analogWrite function, for example).

The reason for this is I need to enable timer interrupts while keeping the functions delay() and delayMicroseconds() available, mainly because one part of the code has to run as fast as possible while other parts need a 2 second delay between each line of code.

Aditionally, using millis() and/or micros() makes my code too slow.

So, if anyone would be a as kind as to answer the following questions I'd be really thankfull:

1.-how do I declare I'm using ASM code? 2.-what's the ASM code to enable timer interrupts on an ATMEGA328P? (I'm using an Arduino Uno) 3.-how do I declare the function which contains the code to be executed during the interrupt?

Hope someone can help me out, thanks for reading.

  1. The term you are searching for is "inline assembly". http://arduino.cc/playground/Main/AVR
  2. Probably want to start looking at the ATmega328 datasheet. You'll need to determine which registers you want.
  3. Don't know. I'm not sure I understand the point of using assembly to enable interrupts which can just as easily be enabled with C.

thanks for the answers

I asked how to do it in assembler because in the reference page all I could find regarding interrupts was attachInterrupt() wich only works with external interrupts

if you know of a similar instruction to enable timer interrupts please let me know

You probably won't find an Arduino function. Arduino just calls avr-gcc so don't look for an Arduino-specific example, you might look for an "avr" example.

You could also look at the Arduino core files to see how millis() is implemented as an example of enabling timer interrupts.

Calaveron: I asked how to do it in assembler because in the reference page all I could find regarding interrupts was attachInterrupt() wich only works with external interrupts

There is absolutely no need to use assembler to do this. Read this:

http://gammon.com.au/forum/?id=11504

All the processor registers can be accessed from C / C++.

The reason for this is I need to enable timer interrupts while keeping the functions delay() and delayMicroseconds() available, mainly because one part of the code has to run as fast as possible while other parts need a 2 second delay between each line of code.

This makes no sense. A line of code does not necessarily correspond to 1 machine instructions.

Maybe you ought to start with explaining what you are trying to do rather than how you think you should do it.

[quote author=Nick Gammon link=topic=92389.msg694077#msg694077 date=1329462230] There is absolutely no need to use assembler to do this. Read this:

http://gammon.com.au/forum/?id=11504

All the processor registers can be accessed from C / C++. [/quote]

thanks, that was really useful :)

PaulS:

The reason for this is I need to enable timer interrupts while keeping the functions delay() and delayMicroseconds() available, mainly because one part of the code has to run as fast as possible while other parts need a 2 second delay between each line of code.

This makes no sense. A line of code does not necessarily correspond to 1 machine instructions.

I didn't mean it like that, it was more along the lines of "turn one led on, wait two seconds, turn another led on, wait two seconds, turn the first led off"

PaulS: Maybe you ought to start with explaining what you are trying to do rather than how you think you should do it.

I'm trying to drive a custom built 5x3 LED matrix with variable brightness for each LED

Calaveron: thanks for the answers

I asked how to do it in assembler because in the reference page all I could find regarding interrupts was attachInterrupt() wich only works with external interrupts

if you know of a similar instruction to enable timer interrupts please let me know

There are several libraries available that you can use to setup time interrupts. Look in the Arduino playground under Timing. The one I have ben using is Timer1.

Calaveron: I'm trying to drive a custom built 5x3 LED matrix with variable brightness for each LED

You don't need machine code to do that.

But for your curiosity, from the site that AVR GCC comes from: http://www.nongnu.org/avr-libc/user-manual/inline_asm.html

You don't need machine code to do that.

the devil is in the details

variable brightness for each LED

what does that mean,2,4,16,64,16384, more?

it could get complicated depending on the shades * quantity (which we know) * display refresh * method (direct parallel vs SPI or whatever) ...

more info is needed, but I would not dismiss it as "you don't need it" without the full story

Calaveron: The reason for this is I need to enable timer interrupts while keeping the functions delay() and delayMicroseconds() available ...

Osgeld:

You don't need machine code to do that.

the devil is in the details

No doubt, but you don't need assembly code to enable timer interrupts, as my link showed.

I am not arguing that, but lets say there’s 16 bit gray scale involved while timers are free to do whatever while dealing with interrupts, your not going to do all of that without a hint of flicker with out some magic unicorn farts

for all we know the op needs 2 bit monochrome, or 16bit RGB while doing a pile of unknown stuff between input from a ADB keyboard with no clock, we don’t know

the devil is in the details, and to say “you dont need asm to do that” is kind of like saying “this 150 year old gun wont blow up in your face”

There's led driver chips easily capable of what's been presented.

But more simply with soft pwm yes it can be done without resorting to assembly. 16 shades... LOL!

Osgeld: for all we know the op needs 2 bit monochrome, or 16bit RGB while doing a pile of unknown stuff between input from a ADB keyboard with no clock, we don't know

that's right, I need 16 bit RGB for each led, I need to drive five 5W RGB LEDs (hence the need to arrange them in a matrix to save up on transistors)

As each RGB LED is made up of three different LEDs, this translates as a 5x3 matrix display, here's my setup: [ ] LED off [-] LED on

[ ][ ][ ]-----data line 1 [ ][ ][ ]-----data line 2 [ ][ ][ ]-----data line 3 [ ][ ][ ]-----data line 4 [ ][ ][ ]-----data line 5 | | | R G B multiplexing control lines

here's what I need it to do, with color fading between each transition (not the actual sequence, just an example)

[ ][ ][ ]    [-][ ][ ]    [-][-][ ]    [ ][-][ ]    [ ][-][-]
[ ][ ][ ]    [ ][ ][ ]    [-][ ][ ]    [-][-][ ]    [ ][-][ ]
[ ][ ][ ]--->[ ][ ][ ]--->[ ][ ][ ]--->[-][ ][ ]--->[-][-][ ]
[ ][ ][ ]    [ ][ ][ ]    [ ][ ][ ]    [ ][ ][ ]    [-][ ][ ]
[ ][ ][ ]    [ ][ ][ ]    [ ][ ][ ]    [ ][ ][ ]    [ ][ ][ ]

[ ][ ][-]    [-][ ][-]    [-][-][-]    [ ][ ][ ]    [ ][ ][ ]
[ ][-][-]    [ ][ ][-]    [-][ ][-]    [-][-][-]    [ ][ ][ ]
[ ][-][ ]--->[ ][-][-]--->[ ][ ][-]--->[-][ ][-]--->[-][-][-]
[-][-][ ]    [ ][-][ ]    [ ][-][-]    [ ][ ][-]    [-][ ][-]
[-][ ][ ]    [-][-][ ]    [ ][-][ ]    [ ][-][-]    [ ][ ][-]

[ ][ ][ ]    [ ][ ][ ]
[ ][ ][ ]    [ ][ ][ ]
[ ][ ][ ]--->[ ][ ][ ]
[-][-][-]    [ ][ ][ ]
[-][ ][-]    [-][-][-]

Right. Edit your post, select all that stuff, and hit the "#" button to put it into code tags.

So it turned out I didn't need to use ASM code (altough I did need to use port manipulation) thanks to Nick Gammon for showing me how to set up the timer interrupt.

Also, I had to write my own 8-bit 5-channel PWM function to make sure a full PWM cycle was completed before switching columns.

A problem still remains, though, the interrupt activates so often the rest of the code slows down a lot, a delayMicroseconds(100); in the main program roughly translates to 5 seconds in real time, maybe fiddling with the prescaler can solve this issue.

Thankyou all for your comments