See more at the announce forum.
The interview Mike did with Walter is a kinda fun listen.
The submission deadline for it just passed. I didn't formally submit but hinted I might improvise something anyway if they want. So we'll see what happens.
I adjusted adrdox to not break local links to dub packages that call themselves std.experimental. I'm also writing more little docs in the arsd repo. I wanna do more of that in between work and stuff.
And now, our feature presentation:
I have an Arduino Uno here in the house that I have barely used, but was reminded of it when a person on the D newsgroup asked about D on Arduino and someone on Stack Overflow asked what the -gcc switch does.
The ng thread: https://forum.dlang.org/post/hhvarlzfqaowgjjprxfr@forum.dlang.org
My SO answer: https://stackoverflow.com/a/73762836/1457000
There's a wiki page about it written by WebFreak, and there's a link there to a project with some basic code ported to D. It is a bit out of date - you don't have to build LDC anymore (I just edited this out of the page, but you can still see it in history if you are curious) and doesn't go into detail of how to port. So let me put an example here to discuss it a bit more.
The wiki page: https://wiki.dlang.org/D_on_AVR
You can use a standard ldc2 install, just grab a binary build from the ldc website. You don't have to compile it yourself; avr support has been included in the normal download for a while now.
After getting ldc, first thing you'll want to do is install the arduino tools. I'm sure there's other ways to do it, but what I did on my computer is simply install the Arduino Studio. I put its files in /opt/arduino/arduino-1.8.10/. You'll want to adjust that path for your computer's setup. In there, you'll see the arduino command, a hardware folder, among others.
me@arsd:/opt/arduino/arduino-1.8.10$ ls arduino arduino-linux-setup.sh hardware java libraries revisions.txt tools-builder arduino-builder examples install.sh lib reference tools uninstall.sh
Now, let's make a test program:
1 import ldc.llvmasm; 2 3 // Ports from the delay_basic.h in the thing 4 void _delay_loop_1(ubyte __count) { 5 // this template param is required to avoid 6 // assertion `!Call.getType()->isVoidTy() && "Bad inline asm!"' failed. 7 8 __asm!ubyte ( 9 "1: dec $0\n\tbrne 1b", 10 "=r,0", (__count) 11 ); 12 } 13 void _delay_loop_2(ushort __count) { 14 __asm!ushort (` 15 1: sbiw $0,1 16 brne 1b 17 `, 18 `=w,0`, 19 __count); 20 } 21 22 // port from delay.h in arduino thing 23 enum F_CPU = 1000000UL; 24 25 // this was _delay_ms but i did something wrong and changed double to int and i still don't love it 26 void _delay(int __ms) { 27 ushort __ticks; 28 ulong __tmp = (F_CPU * __ms) / 4000; 29 if(__tmp < 1) 30 __ticks = 1; 31 else if(__tmp > 65535) { 32 __ticks = cast(ushort) (__ms * 10.0); 33 while(__ticks) { 34 _delay_loop_2(cast(ushort) (((F_CPU) / 4e3) / 10)); 35 __ticks--; 36 } 37 return; 38 } else 39 __ticks = cast(ushort) __tmp; 40 _delay_loop_2(__ticks); 41 } 42 43 44 // and this is from WebFreak's sample code on the D wiki 45 46 enum AVR_ARCH = 5; // AVR architecture of your MCU 47 48 static if (AVR_ARCH >= 100) { 49 enum SFR_OFFSET = 0x00; 50 } else { 51 enum SFR_OFFSET = 0x20; 52 } 53 54 enum ubyte* MMIO_BYTE(ubyte memAddr) = cast(ubyte*) memAddr; 55 enum ubyte* SFR_IO8(ubyte ioAddr) = MMIO_BYTE!(ioAddr + SFR_OFFSET); 56 57 enum ubyte* PINB = SFR_IO8!(0x03); 58 enum ubyte* DDRB = SFR_IO8!(0x04); 59 enum ubyte* PORTB = SFR_IO8!(0x05); 60 61 extern(C) void main() { 62 import core.volatile; 63 64 volatileStore(DDRB, 0xFF); // Set all PORT B to output 65 66 // and I added the delays 67 68 while (true) { 69 volatileStore(PORTB, 0xFF); // Set all PORT B to high 70 foreach(i; 0 .. 10) 71 _delay(1000); 72 volatileStore(PORTB, 0x00); // Set all PORT B to low 73 foreach(i; 0 .. 20) 74 _delay(1000); 75 } 76 }
OK, there's a few parts there that I'll come back to, but first, the make process:
# Makefile $ cat Makefile all: ldc2 delay.d -betterC -Oz -mtriple=avr -mcpu=atmega328p -Xcc=-mmcu=atmega328p -gcc=avr-gcc avr-objcopy -O ihex -R .eeprom delay delay.hex avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:delay.hex -C /opt/arduino/arduino-1.8.10/hardware/tools/avr/etc/avrdude.conf
Please note the path to my arduino install there on the last line again.
To run that, set the PATH to your arduino install and run make, like this:
PATH=/opt/arduino/arduino-1.8.10/hardware/tools/avr/bin:$PATH make
This will compile the D code, then copy it over to your arduino hardware and start running it. The light (and anything else you have attached to the pins) will blink on and off.
If you looked at the wiki page linked above, most of this will look familiar. I copy/pasted liberally.
A few important things to notice:
void _delay_loop_1(uint8_t __count) { __asm__ volatile ( "1: dec %0" "\n\t" "brne 1b" : "=r" (__count) : "0" (__count) ); }
And here's my D:
import ldc.llvmasm; // Ports from the delay_basic.h in the thing void _delay_loop_1(ubyte __count) { // this template param is required to avoid // assertion `!Call.getType()->isVoidTy() && "Bad inline asm!"' failed. __asm!ubyte ( "1: dec $0\n\tbrne 1b", "=r,0", (__count) ); }
The asm is different. In gcc, it used __asm__. In ldc, it used ldc.llvmasm.__asm. They're similar but not the same:
I know this is a surface-level addition to info already out there, but my hope is this little thing can get someone going and we can expand this a bit more. If you do, please email me (destructionator@gmail.com) so I can write about it and help update the wiki too.
edit: Maxter on the discord chat suggested we read this for info on the constraints: https://www.nongnu.org/avr-libc/user-manual/inline_asm.html
In theory, importC can mean we can include the C inline functions directly, but in practice it doesn't work at this time, and there doesn't seem to be a way forward on that right now. I can imagine a gdc cross-compiler build could make that work very well though, just reading those .h files directly and using the gcc inline asm without modification.
I used ldc here because it works out of the box on the download, no need to build it yourself. A gdc cross compiler could perhaps be offered for download once it gets working too, and I think that'd be a nice demo of importc helping get these things right.
But for now, I think you're best off writing it yourself, hence why I wanted to show that above. The inline asm is somewhat important for timing on these controllers so being able to do that is cool. (though I don't actually know what all those constraint strings mean. alas.)
I write some explanation and brief update to the D Wiki AVR article.