We have gotten a number of Arduino tips in the last couple days, and we thought we would combine them for your convenience. The first tip we received was for some hints provided by [Bill] on some digitalWrite() alternatives. Similar to some previous research we covered, this tip also includes some tips on how to make the direct register writing a little easier by using #define to simplify things. Obviously this wont be as idiot-proof as digitalWrite() is, but we think you can handle it.
Our second tip is for a set of OLED displays from 4dsystems sold as Arduino Shields. They have a couple of different sizes from .96″ to 1.7″, depending on your needs and budget. There is no official display library for them yet, but 4dsystems have been kind enough to provide a few resources to work from. Hopefully we’ll see a few great applications from this, maybe a much bigger pixel Mario? A much smaller Game of Life? Feel free to send us your projects, or leave your ideas in the comments!
“Direct port access is not for the faint of heart”… lmfao
SBI/CBI instructions take 2 cycles, but the OUT instruction only takes 1. So couldn’t you do this:
register unsigned char toggleMask = _BV(bit);
PINB = toggleMask;
PINB = toggleMask;
PINB = toggleMask;
…
I haven’t tested it, but, ignoring the initial setup time (which is only 1 cycle anyway), your pin is now oscillating at 2 cycles per period instead of 4. (assuming you’ve unrolled the hell out of your loop!)
Oh come on. This is old news, and there has long been code posted in the arduino forums and developer mailing lists that allow you do get digitalWrite() down to a single instruction (under appropriate circumstances) USING THE EXISTING SYNTAX. The only reason that it isn’t widely deployed is fear that the faster version would be backwardly incompatible just because of its speed, or because it doesn’t turn off timers that might have been used to produce PWM on the same pin.
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267553811/0
Maybe tomorrow’s Arduino Moment will be about taking the AVR off of the board. Of course, once people realize what the Arduino is after taking out the Atmel chip there won’t be any more Arduino moments.
As for the OLED screens, I have (thorough) completed libraries for interfacing with the 128×128 (in both the serialized 4d board as well as just the screen itself if you want to control it with a uC) so if anyone wants the library to play around with (has a bunch of drawing functions in it as well as text, it is designed for the newer SSD1351 display driver as the older ssd1339 display driver that had built in drawing is no longer made) just say so and I can post a link to it.
@Finger :
Please could you post your SSD1351 library ?
Thanks,
Eric
Thank You HaD!!! I like the combo post :) Please keep it up :)
You can never have enough tips.
“there has long been code”
I wouldn’t call 4-6 months as ‘long been’ but the link has been added to my article, thanks.
What’s all this arduino fuzz about anyway? Is simple bit arithmetic really _so_ hard to learn?
I’m sorry, but I fail to see the advantage in functions like “digitalWrite()” anyway…
@Nakka: ah; you’ve never talked to people who haven’t learned about binary. The abstraction of a microcontroller pin to a, well, “pin”, instead of some random masked bit in some weirdly named register is a good thing, IMO. Sure, you can claim that people who can’t understand how “PORTB &= ~(1<<6)" relates to "BIC PORTB,6" or "turn off the green LED" shouldn't be programming at all. But I'd rather not.
@westfw: i rather would.
Nearly 1 year ago, I wrote an optimized digitalWrite() that compiles to only a single 2-cycle instruction when the inputs are compile-time constants. I’ve been shipping it as part of Teensyduino since November (Teensyduino also has non-const optimizations). The const-case single instruction code has also been sitting in Arduino issue #140, maybe someday to become part of Arduino proper.
56 cycles to write a bit?! Just what in the hell is it doing that whole time?
@r_d: a good question. It maps the pin number to a port using an indexed lookup to a table stored in flash. And to a bitmask. Check for “not a pin.” More mapping to timer information. If the timer register is ‘real’, it then makes sure that any PWM that that timer might have been driving on that pin is turned off (which involves additional logic.) Map the port to the output register for the port. Read the register, AND or OR the value with the bitmask (possibly complimenting the mask first), and write it back (using indexed addressing in both cases, since the register address is a variable. Which requires expanding the register address to 16 bits and saving some extra registers.) Plus normal function call overhead.
It could be optimized a bit more, but it’s designed to keep the same basic structure across several CPUs, and isn’t really designed to be fast. It doesn’t need to be fast. After all, Arduino is designed with the knowledge that if you really need speed, you can drop into plain C code or even inline assembler. It’s not like some environments where the slow function is your only choice…
Awesome, I really like these little Arduino goodies :)
(I’m not so hard core as some seasoned hackers, but I love this site)
Agree with WestfW.
I have a degree in computer science and more than 25 years experience in programming, but no, I can’t handle bit masking error-proof as I can with digitalWrite().
If you are to write a pin, you code should say just that. Any trickery must be delegated to libraries and compilers, IMHO.
You may be interested in an Arduino runtime library replacement I have been developing over the last few months, which addresses this issue, and many others too, such as the ability to send serial data asynchronously.
Full source & tutorials are available at: http://www.makehackvoid.com/group-projects/mhvlib-efficiency-oriented-library-avr-microcontrollers
@John. Thats what she said
The uOLED library I used for the Arduino Watch http://www.instructables.com/id/Arduino-Watch-Build-Instructions/ can be found at http://code.google.com/p/uoled-library/
Some of the libraries listed in the article don’t work with the current versions of the Arduino software while this one does.
@Matthew Garten He has a bit of annoying speech patterns that guy in the video, irks me how he can’t say arduino but says arduinio, why do people put extra letters in a word? it’s like americans saying wimbleton when pronouncing wimbledon, you can’t figure why they do that.
According to avr-libc’s manual:
PORTB |= _BV(0);
and
PORTB &= ~_BV(0);
will compile to
sbi PORTB, 0
cbi PORTB, 0
respectively, if available. These are two cycle instructions. If these instructions are not available, the resulting assembly looks like
; sbi
in r1, PORTB
ori r2, 1
out PORTB, r1
; cbi
in r1, PORTB
andi r1, 0xfe
out PORTB, r1
These are all 1 cycle instructions. In other words, it is faster to sbi/cbi if available, and the compiler automatically takes care of that for you. If you need a faster pulse on a pin, the best you can do is set up PWM.