NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Microcontroller Programming » I made a new language for programming the Atmega
August 05, 2011 by bretm |
I'm been noticing how tough programming can be for people who are new to it, perhaps forced into it just because they like electronics and just want to use microcontrollers. I see how bad "C" can be for that type of person. So I made up a language. The compiler here is very rough around the edges. It's written for .NET Framework 4 so only works on Windows for now. Mono on Linux maybe someday, but only if people seem interested. Install .NET, download the compiler, put this "sample.oq" file in the same folder and run "oq sample.oq" and it should make "sample.c" out of it. So it's more of a translator-to-C than a full compiler, but I think it still counts. Here's the sample.oq program:
Some features of the language: Syntax borrows heavily from Python. Less hassle reading and writing individual bits of different ports. For example, here's the function in Adc.oq for writing to MUX3:0 in the ADMUX register:
Using custom pins is easier. Here's how to define a pin as an output pin:
Here's how you would set that pin to high:
Or to low:
Or to toggle it:
Or to either high or low depending on whether a button is up or down:
It does units:
Take a look at the sample.oq above, and the Adc.oq, HD44780.oq, and Usart.oq in the ZIP file for examples of other things you can do. |
---|---|
August 05, 2011 by bretm |
LED blinking program in this language:
|
August 06, 2011 by Ralphxyz |
Wow, bretm that is really neat. I am probable a typical target user, I can see that most everything I normally do can be done. Now as soon as I can find some time I'll try it out. Ralph |
August 06, 2011 by mongo |
I just installed the NET4 framework last night and just might take a serious look into this one. If it makes things easier, I am all for it. |
August 06, 2011 by bretm |
Basic syntax is like Python--whitespace is important. It uses indents to indicate the block structure. Tab stops are considered to be every 4 spaces when determining if lines are indented equivalently. Statements that expected an indented block afterword will end with ":". If it doesn't end with ":" it's a one-line statement. The "pins:" block defines friendly names for pins or groups of pins and specifies their direction. If a pin is set to "out" it's an output pin and you won't be able to read its value in an expression. If a pin is set to "in" or "in floating" it's an input pin and you won't be able to set it's value. If it is set to "io" then you can do either, and change its direction at run time. Examples:
Debouncing and denoising are done by checking the pin every 5ms. For debouncing, after a pin change is seen, further changes are ignored for the next 40ms. For denoising, pin changes are ignored until the new pin state has persisted for 40ms. You can also define groups of pins on the same port.
You can respond to pin changes (or a change in any condition) with "when".
|
August 06, 2011 by bretm |
Variables are defined by "sram", "progmem", "eeprom", or "persistent" statements. There is only limited-to-no support for string variables. It's mostly just numbers for now.
Reading and writing EEPROM variables works just like regular variables. Be careful you don't change their value very often because they have a limited lifetime. If you redefine the program to define different EEPROM variables or change the default values, all of the EEPROM variables will be reinitialized. The "persistent" statement is used inside a "def" statement to define the equivalent of static local variables in "C", which are variables local to a function but that keep their values between function calls. They use SRAM. |
August 06, 2011 by bretm |
Some pseudo-multi-tasking:
These commands happen inside a timer interrupt, so they need to be quick. Also, you can't access global variables from inside an interrupt. If you need to share data with the main loop you need to use a queue:
This correctly handles "volatile" issues and ensures that data-sharing operations are done atomically to avoid race conditions. |
August 07, 2011 by Ralphxyz |
bretm, pardon my being dense but:
In the "same folder" as what? The compiler? That might take a bit to find. Or is there a development structure implied like nerdkits/code/initialload? Is there a .zip folder of your trial programs(?)/scripts? I just fired up my Windows box to give it a try! Ralph |
August 07, 2011 by Ralphxyz |
Got it!! Sorry I should have tried doing it before asking. The "folder" is wherever you unzip the oq.zip file to, so use that. I used D:nerdkitsBRETM_scripting. Copied the sample.oq code from above to the folder and ran oq sample.oq from the command line (cd D:nerdkitsBRETM_scripting of course). Now lets see what trouble I can get into. Ralph |
August 07, 2011 by Ralphxyz |
Oh this is cute: When you compile the script the source code is deleted or at least my text editor (Notepad++) thinks it is. It is just a mistake on the editors part sample.oq is still in the folder. If I had closed the editor before running the compiler I would not have seen the message, but I usually do not close the editor so I'll just live with another nagging, useless, stupid application Warning message, after all this is Windows. Ralph |
August 07, 2011 by Robotnik |
Well this is pretty neat! I've always been a fan of c, but this looks like it could save me some time. I am actually tempted to set avr on windows so I can try it out. I tried compiling the generated c with avr-gcc but it didn't work, tons of errors. I was probably doing something wrong though. I need to take the time to learn how to use avr-gcc one of these days instead of just modifying makefiles... |
August 07, 2011 by bretm |
Right now it's easiest if you use the same folder as rhe compiler because I didn't make an installer app to set up the PATH environment variables to support a more traditional compiler set up. I will be doing that eventually. |
August 07, 2011 by bretm |
Let me know what avr-gcc errors you were getting, but I think I know: I forgot to talk about the makefile! The generated C references some include files like "oq.h" that need to be findable by the compiler, and "oq.c" and "oqwait.c" need to be compiled along with your program. My makefile for sample.oq:
And makefiletemplate.inc:
This builds sample.oq all the way to .hex file format. |
August 07, 2011 by Robotnik |
Okay, I successfully compiled the generated c file then uploaded it to the chip, then I realized this was the temp sensor project :/ I'm goin to try again only with a simple blinking led that way I can see it work without rewiring my lcd which is currently in use for something else. |
August 07, 2011 by Robotnik |
... And it works like a charm. :D |
August 07, 2011 by bretm |
Another feature of the language is that it's easy to break a value up into its constituent bits, or to concatenate bits into a larger value.
If you don't care about some of the bits, you can do this:
|
August 08, 2011 by Ralphxyz |
So [quote] x, _ = abyte bits 2:6 # grab top two bits and ignore the rest [/quote] Says to Let x = the top two bits and _ is a throwaway? Is _ always a throughway when used in an assignment? Or can it hold a value? Can _ be referenced? Ralph |
August 08, 2011 by bretm |
It's always thrown away and cannot be referenced. No C assignment code is generated for it. It's also useful when you have a function that returns multiple values and you don't care about some of them:
Multiple variable assignment can also be used directly in an assignment, e.g. to swap two values:
|
Please log in to post a reply.
Did you know that talking to the microcontroller over the USB/Serial link is easy under Windows, Linux, and OS X? Learn more...
|