Clean slate with Demoboard
I am putting the past experience with the C3, and GG boards behind me. Maybe someday, down the road, I will find interest in those boards again.
The keyboard demo program worked just fine, on my Demoboard, when I ran it in COG mode. I also ran it in LMM mode, I noticed a delayed reaction when I was pressing the keyboard. I think I pressed about seven keys, and then the keypresses started to appear on the screen. What should be changed in order to get the keyboard program to run correctly in LMM mode?
Is there a small VGA program that I can run to test the VGA component of the Demoboard? I am still considering a test program of keyboard, and VGA output. I am thinking, maybe there should be a test program that tests all of the components of the Demoboard, written in C of course.
Ray
The keyboard demo program worked just fine, on my Demoboard, when I ran it in COG mode. I also ran it in LMM mode, I noticed a delayed reaction when I was pressing the keyboard. I think I pressed about seven keys, and then the keypresses started to appear on the screen. What should be changed in order to get the keyboard program to run correctly in LMM mode?
Is there a small VGA program that I can run to test the VGA component of the Demoboard? I am still considering a test program of keyboard, and VGA output. I am thinking, maybe there should be a test program that tests all of the components of the Demoboard, written in C of course.
Ray
Comments
I was playing with the VgaText demo in the demos folder yesterday on my Demoboard. a couple gotcha's
The SimpleIDE won't read UTF-16 files, so I needed to copy/paste the VGA.SPIN text into a new IDE file and then add that to my project (see your keyboard thread, posts 15,16, & 17). For now, cut/paste is your friend when adding existing .spin files to a SIDE project.
The demo is also written with pins for the C3 (pin #16) if you define C3 or the PropBOE (pin #8), so you need to change the PropBOE pin definition to match the Demoboard (pin #16) and then it works just fine. I'm working on connecting the keyboard to the various outputs (serial, VGA, TV) but I'm only a weekend Propeller warrior....my day job REALLY cuts into play time!! Tshi said, it may be a while until I make any progress....unless I get stuck on a few boring conference calls this week.
There are 2 problems with delay reaction now:
1) the serial port handler in SimpleIDE needs a fix - the loader works fine.
I'm busting but trying to find a workable solution.
2) the stdout needs to be set to unbuffered. Put this in your main function startup:
/* set stdout port to non-buffered */
setvbuf(stdout, NULL, _IONBF, 0);
I'm not having any luck with PST either.
Thanks,
--Steve
Ray
/* * test1.c * * Test the LEDs on the Demoboard. */ #include <stdio.h> #include <propeller.h> #include "misc.h" int main() { int x = 16; while(1) { high(x); waitMS(1000); low(x); waitMS(1000); x = x + 1; if (x > 16) { x = 16; } } return 0; }
How about starting x at 16 and then checking if it's > 23 before you reset it to 16?
if (x > 23) {
x = 16;
}
The Demoboard has an earphone plug, is there a driver for this? I am thinking every time it makes a pass, it could make some kind noise?
Ray
/* * test1.c * * Test the LEDs on the Demoboard. * */ #include <stdio.h> #include <propeller.h> #include "misc.h" int main() { int x = 16; int y = 0; while(1) { high(x); waitMS(1000); low(x); waitMS(1000); x = x + 1; if (x >= 23) { x = 16; y++; if (y > 5) { break; } } } return 0; }
If you're looking to blink the 8 LEDs, you need to check >=23 at the end of the loop:
if (x > 23) {
x = 16;
}
Otherwise you end up toggling P24, which is connected to the mouse data line.
Ray
<edit> I just verified that 23 does work.<edit>
Ray
I'll go back to my original code. Assuming the pins start numbering from 0 and your high/low routines affect the pin number specified,when you got through your loop with x=23, it will blink pin 23 and then x is incremented to 24. The (x>23) condition will be true and x will be reset to 16. Back you go to the top of the loop with x=16 and the blinking starts again. 16 through 23 will blink, 24 won't.
Sorry for contributing to any confusion.
However, this gets into why one avoids this style of code. It's so much clearer to use something like this:
int main() { for (y = 1; y <= 5; y++) { for (x = 16; x <= 23; x++) { high(x); waitMS(1000); low(x); waitMS(1000); } } return 0; }
Shorter, simpler, and less difficult to spot off-by-one errors.
This should work just fine on your Demoboard. It gets all 8 cogs running, all 8 LEDs (16-23) lit up and all 16 timers timing. It's a port of one of the Quickstart demo programs ported to propgcc. It shows one of the ways to start code in COGs in propgcc. It needs to be better commented but I thoguht you might like to play more.
/** * @file twinkle.c * This program is loosely ported from the Quickstart 5: Multicogtwinkledemo.spin * from the Parallax Semiconductor site. * * This program is targeted toward the QUICKSTART pin numebrs * and COG counts (up to 8)but can be adjusted as required. * * It starts multiple COGs running the twinkle function in each COG * demonstrating multi-cog support for LMM c routines * * Progress of COG initialization will be logged on stdout * * The counters in each COG are set up to control the LED brightness * * Original SPIN program Copyright (c) 2011 Parallax, Inc. * This port Copyright (c) 2012 Rick Post * MIT Licensed (see at end of file for exact terms) */ #include <stdio.h> #include <propeller.h> #include <sys/thread.h> #define STACK_SIZE 16 #define COGS_TO_START 8 /* you do NOT need stack space for COG0 /* but we'll set aside space just to make the indexing easier /* stack for cogs */ /* - pass (COG# * STACK_SIZE) + STACK_SIZE to _start_cog_thread */ static int cog_stack[STACK_SIZE * COGS_TO_START]; /* per-thread library variables ("Thread Local Storage") */ static _thread_state_t thread_data[COGS_TO_START]; /* variables that we share between cogs */ volatile unsigned int rate[COGS_TO_START]; volatile unsigned int pin[COGS_TO_START]; /* * here's the toggle code that runs in another cog */ void do_twinkle(void *arg __attribute__((unused)) ) { unsigned int wait_time, counter, cognum, mask; cognum = cogid(); mask = 1 << pin[cognum] ; DIRA = mask; OUTA = 0; CTRA = 0 + (0b0100 << 26) + pin[cognum]; CTRB = 0 + (0b0110 << 26) + pin[cognum]; INA = 0; FRQA = 0; PHSA = 0; FRQB = 0; PHSB = 0; while (1) { for (counter = 0; counter < 101; counter++) { FRQB = counter * (0x7fffffff / 50); waitcnt(rate[cognum] + CNT); } for (counter = 0; counter < 101; counter++) { FRQB = (100 - counter)* (0x7fffffff / 50); waitcnt(rate[cognum] + CNT); } } } /* * main code * This is the code running in the LMM cog (cog 0). * It launches another cog to actually run the * toggling code */ void main (int argc, char* argv[]) { int i, n; printf("Twinkle Time!\n"); pin[0] = 16; rate[0] = CLKFREQ / 25; rate[1] = CLKFREQ / 150; rate[2] = CLKFREQ / 225; rate[3] = CLKFREQ / 50; rate[4] = CLKFREQ / 200; rate[5] = CLKFREQ / 100; rate[6] = CLKFREQ / 10; rate[7] = CLKFREQ / 75; /* start the new cog */ for (i=1;i<COGS_TO_START;i++) { pin[i] = 16 + i; n = _start_cog_thread(cog_stack[i * COGS_TO_START]+ STACK_SIZE, do_twinkle, NULL, &thread_data[i]); printf("toggle cog %d has started\n", n); } do_twinkle(1); } /* +-------------------------------------------------------------------- * ¦ TERMS OF USE: MIT License * +-------------------------------------------------------------------- * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files * (the "Software"), to deal in the Software without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +-------------------------------------------------------------------- */
You should just be able to build a SIDE project around this code.
Ray
* test2.c * * Test the LEDs on the Demoboard version 2. * Cleaner code logic, and more appropriate for this job? * */ #include <stdio.h> #include <propeller.h> #include "misc.h" int main() { int x, y; for (y = 1; y <= 5; y++) { for (x = 16; x <= 23; x++) { high(x); waitMS(1000); low(x); waitMS(1000); } } return 0; }
Here's a link to a C and C++ online Tutorial
There was another thread around here with lots of online information about learning C...of course, I can't find it now.
The K&R Leon refers to is the classic The C Programming Language, by Kernighan and Ritchie - well worth the money. Get the 2nd edition as it is the latest and greatest! See if you can pick up a used copy someplace, it is a bit expensive but worth it!
I have the K&R book, that is what I used to figure out what the 'For...Next' really does.
I had mentioned a driver for the speaker/headphones, on the Demoboard, anybody find one yet? I think adding a little noise to the finale() function might be interesting. After I get a good understanding of the stuff I just programmed, VGA will be next. Flashing LEDs, noise, and some graphics on the VGA monitor, would make a good Demoboard test example.
Ray
/* * test4.c * * Test the LEDs on the Demoboard version 3. * Made it little bit fancier. * * I am not putting in any comments. While it is still * simple concepts, you can try to figure it out. * */ #include <stdio.h> #include <propeller.h> #include "misc.h" void finale() { int y, x = 0; while(x < 10) { for (y = 16; y <= 23; y++) { high(y); waitMS(10); low(y); waitMS(10); } for (y = 23; y >= 16; y--) { high(y); waitMS(10); low(y); waitMS(10); } x++; } } int main() { int x, y; for (y = 1; y <= 2; y++) { for (x = 16; x <= 23; x++) { high(x); waitMS(250); low(x); waitMS(250); } } finale(); return 0; }
I haven't seen any sound demos/code that's been ported from SPIN/PASM to C. There are a number of candidate objects in the OBEX that have a PASM driver that could have a wrapper written for it. That might be something to try if you use jazzed's keyboard wrappers or the VGA wrappers in the propgcc demo folder.
At page 147 of the Propeller Education Kit (PEK) document (comes with the Propeller Tool), they start talking about making noise with a piezospeaker and the counters. This can certainly and easily be done from C. My twinkle program above uses the timers to vary the brightness of the LEDs. Same idea to vary the frequency to the speaker (or headphone jack in the Demoboards case). The PEK document is a great way to get started with the Propeller and exercise its features. At some point, there should be a C version of the PEK - maybe when the PropBOE comes out??
I am considering purchasing a uSD reader from Parallax, hopefully this been through a lot of production runs, and the product is stable. The only concern that I have is, how beneficial would this be, considering the Demoboard has no no access to XMM or XMMC? Using the Dave Hine example uSD program, in LMM mode you do not have a lot of memory left over to do any thing substantial.
Ray
I'm sure there will be a document/tutorial on writing this. I'm trying to figure this process out currently...there's lots of debate as to the correct way to do it, the standards a .spin should expose and use so it's easily wrappable. I just want to do a couple easy objects to make sure I understand it.
It's like the thread/multi-cog document, lots of different ways to accomplish the same thing depending on where you are and where you need to get to.
EDIT: You can run XMMC code directly from an SD card. I know it works on the C3 card. I don't know if it's been implemented for other cards that support SD. You would need to create a loader board description to add SD XMMC support to a board that doesn't come with an SD card connector.
EDIT2: I stubbed out the file code in the c3files demo, and the SD support does use a significant amout of space. It looks like it uses about 15K. A minimal program with the SD file driver is around 22K in size, so that only leaves about 8K for user code. It might make sense to create a minimal file driver that doesn't support subdirectories and maybe only handles FAT16. We could try stubbing out code in FileDriver.c and dosfs.c to see how much memory we could save.
I have this exact problem in a data logging project designing using PropGCC - the SD card code and GCC were (and in some cases still are) just taking too much space. I'm just getting ready to get the fsrw spin object to work in a separate Spin Cog, callable from C via a mailbox. The fsrw spin code takes half the space of the PropGCC SD card support code. It's interesting to note that the fsrw.c code, when compiled with PropGCC, takes just about the same amount of memory as PropGCC's SD card code.
Ray
/* * fds1.c */ #include <stdio.h> #include <propeller.h> #include "misc.h" int main() { char *serdevice = "SSER:9600,1,0"; FILE *port = fopen(serdevice, "+r"); waitMS(5000); fprintf(port,"This is some text.\n"); while(1) { int byte = fgetc(stdin); fprintf(port,"%c",byte); } fclose(port); return 0; }
To change the baud rate, this code will work on the demo board:
#include <stdio.h> int main() { freopen("SSER:9600", "w", stdout); while (1) printf("Hello World\n"); }
To change the pin numbers, use:
freopen("SSER:9600,31,30", "w", stdout);
To load to propeller for my tests I used: propeller-load -b demoboard -r -t9600 main.elf
Ray
/* * fds1.c */ #include <stdio.h> #include <propeller.h> #include "misc.h" int main() { /* Rx Tx */ char *serdevice = "SSER:9600,27,26"; FILE *port = fopen(serdevice, "+r"); waitMS(1000); freopen(serdevice, "w",port); waitMS(5000); fprintf(port,"This is some text.\n"); while(1) { int byte = fgetc(stdin); /* int byte = fgetc(port); */ fprintf(port,"%c",byte); } fclose(port); return 0; }
You don't need the fopen, just the freopen.
Also, if you want to use stdin with a non-standard baud, you have to reopen it too. This works for me:
#include <stdio.h> int main() { freopen("SSER:9600,31,30", "w", stdout); freopen("SSER:9600,31,30", "r", stdin); printf("This is some text.\n"); while(1) { int byte = fgetc(stdin); printf("Your byte: %c\n", byte); } return 0; }
- Ted
Ray
/* * keybterm.c */ #include <stdio.h> #include <propeller.h> #include "Keyboard.h" #include "misc.h" int main() { char *serdevice = "SSER:9600,1,0"; FILE *port = fopen(serdevice, "+r"); waitMS(1000); freopen(serdevice, "w", port); keybd_start(26,27); waitMS(3000); fprintf(port,"Keyboard Demo\n"); while(1) { /* putchar(keybd_getkey()); */ fprintf(port, "%c",keybd_getkey()); waitMS(10); fflush(port); } return 0; }
The only time you really need to use freopen AFAIK is when you change a parameter on stdin or stdout (pin 30,31).
Also, it seems the pin sequence has changed from an earlier version. It used to be "SSER:baud,tx,rx" now it's "SSER:baud,rx,tx".
FILE *port = fopen(serdevice, "+r");
This line compiled without any errors or warnings. As soon as I changed the "+r" to "r+" then everything started to work as expected. I would of thought that the compiler would of picked up on that. This would of been a horrible thing to try to find if it was in a two or three hundred line program, and the program compiled without any complaints.
Ray
Said parameters being either the pin numbers or baud rate. In Ray's case, he's trying to change the baud rate. Isn't freopen more appropriate than fopen in this case?