Below is my first attempt at trying to get access to the QS button. My logic on this is that you have to set the pin for input mode, and then sense it for either a ground (0) condition or a power (1) condition(3.3V). I am making an assumption that when you press the button it goes from ground too power (1), and I sense for that. Because the code below is in a loop, technically when the button is held down, the designated LED should stay lit. Of course it is not working, so there must be a problem with my GetPinInp() function, or my assumption as to how 'ina' is supposed too be used, I think?
Ray
REM ==========
REM testQS1.bas
REM ==========
/* Include items */
include "print.bas"
include "propeller.bas"
include "extra.bas"
do
btn = GetPinInp(0)
IF btn = 1 THEN
high(17)
ELSE
low(17)
END IF
loop
END
/* Setup pin for input */
def GetPinInp(pin)
dira = dira | (0 << pin) // Direction to input
ina = ina | (0 << pin) // Sense for input
end def
/* Setup pin for input */
def GetPinInp(pin)
dira = dira | (0 << pin) // Direction to input
ina = ina | (0 << pin) // Sense for input
end def
This function doesn't return any value and also has problems with the masking of both DIRA and INA. You'll need something more like this:
/* Setup pin for input */
def GetPinInp(pin)
dira = dira & ~(1<< pin) // Direction to input
return ina & (1 << pin) // Sense for input
end def
You can then test the return value of GetPinInp for zero or non-zero. If you want GetPinInp to return 0 if the pin is low and 1 if the pin is high then you'll need this:
/* Setup pin for input */
def GetPinInp(pin)
dira = dira & ~(1<< pin) // Direction to input
return (ina & (1 << pin)) <> 0 // Sense for input
end def
Even better would be:
/* Setup pin for input */
def GetPinInp(pin)
dim mask = 1 << pin
dira = dira & ~mask // Direction to input
return (ina & mask) <> 0 // Sense for input
end def
However none of this will work with the touch buttons on the QuickStart because they require more complex code to read them not just a GetPinInp function as I understand it. I've never actually used them though.
This is going to be a little more complicated than expected. Using the new def, in the code below, the LED is turned on, the button pin has power.
do
btn = GetPinInp(0)
IF btn = 1 THEN
high(17)
//ELSE
// low(17)
END IF
loop
Now if I change it to IF btn = 0, the LED does not turn on. I guess that just verifies that the pin is not in a ground state.
do
btn = GetPinInp(0)
IF btn = 0 THEN
high(17)
//ELSE
// low(17)
END IF
loop
So, by actually pressing the button, it seems like the condition is not being changed, or there needs to be some additional condition that should be checked. Now if you would be using a normal button, I guess this code would work because by pressing the button you would be breaking the circuit, and therefore you would check for power or ground, depending how the button circuit was setup. I guess I need some more info as to how the QS button circuit is setup, and how to deal with it, code wise.
Ray
/* Setup pin for input */
def GetPinInp(pin)
dim mask = 1 << pin
dira = dira & ~mask // Direction to input
return (ina & mask) = 0 // Sense for input
end def
/* Setup pin for input */
def GetPinInp(pin)
dim mask = 1 << pin
dira = dira & ~mask // Direction to input
return (ina & mask) = 0 // Sense for input
end def
I edited my message after you read it. This function should be defined like this:
/* Setup pin for input */
def GetPinInp(pin)
dim mask = 1 << pin
dira = dira & ~mask // Direction to input
return (ina & mask) <> 0 // Sense for input
end def
Notice the last line of the function. I should be testing if the value is non-zero not zero as the original code did.
However, I think you're going to need to read up on those touch buttons. You can't just read the state of a pin to determine if the button is pressed. It's more complicated than that I think.
Below is the actual Spin program for the QS button control, it looks very straight forward except for the PASM part. I think the trick would be, is to try too replicate some of PASM code within the xBasic loop to simulate a checking of the button(s). In the PASM code it looks like the pin state outa is being changed wile the dira stays the same. I am not sure as too how to replicate this in def statement. Also, I noticed that there is no use of ina, so what the heck is going on.
Ray
CON
BUTTON_PINS = $FF ' The QuickStart's touch buttons are on the eight LSBs
SAMPLES = 32 ' Require 32 high redings to return true
VAR
long Results
PUB Start(Rate)
Results := Rate
cognew(@Entry, @Results) ' Launch a new cog to read samples
PUB State | Accumulator
Accumulator := Results ' Sample multiple times and return true
repeat constant(SAMPLES - 1) ' if every sample was highw
Accumulator &= Results
return Accumulator
DAT
org
Entry
rdlong WaitTime, par
mov outa, #BUTTON_PINS ' set TestPins high, but keep as inputs
mov Wait, cnt ' preset the counter
add Wait, WaitTime
Loop
or dira, #BUTTON_PINS ' set TestPins as outputs (high)
andn dira, #BUTTON_PINS ' set TestPins as inputs (floating)
mov Reading, #BUTTON_PINS ' create a mask of applicable pins
waitcnt Wait, WaitTime ' wait for the voltage to decay
andn Reading, ina ' clear decayed pins from the mask
wrlong Reading, par ' write the result to RAM
jmp #Loop
Reading res 1
WaitTime res 1
Wait res 1
Below is the actual Spin program for the QS button control, it looks very straight forward except for the PASM part. I think the trick would be, is to try too replicate some of PASM code within the xBasic loop to simulate a checking of the button(s). In the PASM code it looks like the pin state outa is being changed wile the dira stays the same. I am not sure as too how to replicate this in def statement. Also, I noticed that there is no use of ina, so what the heck is going on.
Ray
CON
BUTTON_PINS = $FF ' The QuickStart's touch buttons are on the eight LSBs
SAMPLES = 32 ' Require 32 high redings to return true
VAR
long Results
PUB Start(Rate)
Results := Rate
cognew(@Entry, @Results) ' Launch a new cog to read samples
PUB State | Accumulator
Accumulator := Results ' Sample multiple times and return true
repeat constant(SAMPLES - 1) ' if every sample was highw
Accumulator &= Results
return Accumulator
DAT
org
Entry
rdlong WaitTime, par
mov outa, #BUTTON_PINS ' set TestPins high, but keep as inputs
mov Wait, cnt ' preset the counter
add Wait, WaitTime
Loop
or dira, #BUTTON_PINS ' set TestPins as outputs (high)
andn dira, #BUTTON_PINS ' set TestPins as inputs (floating)
mov Reading, #BUTTON_PINS ' create a mask of applicable pins
waitcnt Wait, WaitTime ' wait for the voltage to decay
andn Reading, ina ' clear decayed pins from the mask
wrlong Reading, par ' write the result to RAM
jmp #Loop
Reading res 1
WaitTime res 1
Wait res 1
I guess that PASM code would have to be compiled into a PASM blob so it could be loaded with cognew. That isn't too difficult and you can see how it is done by look at the TV demo in the xbasic samples directory.
Here are some functions that read quickstart buttons. They are not PASM, but they show how to do it. They will not work with the HID board installed.
include "propeller.bas"
REM ===============================================
REM Get a specific button number.
REM buttons are enumerated from 0 to 7.
REM
def getButton(number)
dim mask = (1 << (number))
dim buttons = getButtons
return buttons & mask
end def
REM ===============================================
REM Get all buttons at once
REM Run this function from HUB if compiled for LMM.
REM
def getButtons
dim n = 8
dim result = -1
dim reading = 0
dim pins = 0xFF
OUTA = OUTA | pins // output high to buttons
do while(n > 0) // sample pins n times
n = n - 1
DIRA = DIRA | pins // output high to buttons
DIRA = DIRA ^ pins // switch to input
reading = pins
waitcnt(CLKFREQ/1000+CNT) // wait for RC time
reading = INA & reading // return button states
result = result & reading
loop
result = ~result & 0xFF
return result
end def
Here are some print utility functions.
dim hexarray(16) = {
'0', '1', '2', '3', '4', '5', '6', '7'
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
}
REM===================================================
REM Print a hexidecimal number
REM @param value - decimal number
REM @param digits - number of digits to print
REM
def printHex(value, digits)
dim n
do while digits > 0
digits = digits - 1
n = (value >> (digits<<2)) & 0xf
uartTx(hexarray(n))
loop
end def
REM===================================================
REM Print a binary number
REM @param value - number
REM @param digits - number of digits to print
REM
def printBin(value, digits)
n = digits-1
do while n > -1
dig = '0' + ( (value & (1<<n)) >> n)
uartTx(dig)
n = n - 1
loop
end def
I've noticed some issues with xbasic and quickstart. The xbasic loader needs to be updated.
I've also noticed that the IDE will hang if you print too fast. Sometimes the IDE won't respond after closing the terminal. Click the + button if it is still "pressed" and "Ok" the terminal until the + button is not pressed.
There are several things about the IDE that do not use improvements that were added to SimpleIDE. They will take time to update especially as I have other things going on. I'll get to them when I can.
Here are some functions that read quickstart buttons. They are not PASM, but they show how to do it. They will not work with the HID board installed.
include "propeller.bas"
REM ===============================================
REM Get a specific button number.
REM buttons are enumerated from 0 to 7.
REM
def getButton(number)
dim mask = (1 << (number))
dim buttons = getButtons
return buttons & mask
end def
REM ===============================================
REM Get all buttons at once
REM Run this function from HUB if compiled for LMM.
REM
def getButtons
dim n = 8
dim result = -1
dim reading = 0
dim pins = 0xFF
OUTA = OUTA | pins // output high to buttons
do while(n > 0) // sample pins n times
n = n - 1
DIRA = DIRA | pins // output high to buttons
DIRA = DIRA ^ pins // switch to input
reading = pins
waitcnt(CLKFREQ/1000+CNT) // wait for RC time
reading = INA & reading // return button states
result = result & reading
loop
result = ~result & 0xFF
return result
end def
Here are some print utility functions.
dim hexarray(16) = {
'0', '1', '2', '3', '4', '5', '6', '7'
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
}
REM===================================================
REM Print a hexidecimal number
REM @param value - decimal number
REM @param digits - number of digits to print
REM
def printHex(value, digits)
dim n
do while digits > 0
digits = digits - 1
n = (value >> (digits<<2)) & 0xf
uartTx(hexarray(n))
loop
end def
REM===================================================
REM Print a binary number
REM @param value - number
REM @param digits - number of digits to print
REM
def printBin(value, digits)
n = digits-1
do while n > -1
dig = '0' + ( (value & (1<<n)) >> n)
uartTx(dig)
n = n - 1
loop
end def
Thanks jazzed, I gave the code a try and it works, as expected. Now I have to figure out what I will be doing with it. Thinking, thinking...
Ray
Since you know C, you can port my Quickstart Whack-a-mole game.
The only real challenge here is making the srand() and rand() functions. Look at these links for descriptions: srand()rand() ... Actual implementation of rand(), a pseudo-random number generator (PRNG), doesn't need to be very complicated. Look at the middle-square method (not a very good PRNG, but better than nothing).
/**
* This is a QuickStart Whack-a-Mole game.
*
* Copyright 2011 by Steve Denson.
* Rights MIT Licensed. See end of file.
*/
/**
* The Blue LED moles are eating up your QuickStart yard!
* You must get rid of them!
*
* Gameplay:
*
* All living moles will run around the QuickStart burrow during
* the game and you'll know they're alive by the dimly lit LEDs.
*
* Sometimes a mole will pop up as brighly lit LED and you must
* wack the mole pad to knock it out.
*
* When the moles are gone, your QuickStart yard will celebrate!
*
*/
#include <stdlib.h> // for rand() and seed()
#include <propeller.h> // for propeller functions.
/* game utilities */
void celebrate(void); // no more moles
int rotateLeft(int mask);
int rotateRight(int mask);
/* simple utilities */
void LEDOUT(int val); // set leds to val
void msleep(int t); // sleep for t ms
int getButton(int n); // used to get button states
int getButtons(); // used to get button states
/*
* Main program entry point
* Start with 8 moles and flick LEDs via rotating mask.
* Choose a random mole to light for fraction of a second.
* If the mole button is pushed while the LED is lit, kill the mole.
* When all moles are dead celebrate - check button press for restart.
*/
int main(void)
{
int molemask = 0xff; // live moles
int ontime = 1; // flicker on time in ms
int offtime = 80; // flicker off time
int whacked = 0; // it's whacked?
int direction = 1; // keep direction of LED mole run
int popcount = 6; // initial popcount
int countmask = 0x1f00; // allow up to 32 mole run steps
int popmask = 0x7; // only 8 LEDs, choose from rand
int popupspot = 0; // show popup position
int popuptime = 500; // popup on time
/* mole run forever loop */
for(;;)
{
/* nothing whacked */
whacked = 0;
/* seed random function with Propeller CNT */
srand(CNT);
/* blank moles */
LEDOUT(0);
/* sleep a little */
msleep(offtime);
/* if all moles gone, celebrate */
while(!molemask) {
/* make LEDs dance */
celebrate();
/* if button press, restart game */
if(getButtons()) {
molemask = 0xff;
}
}
/* get popup spot */
if(popcount-- == 0) {
/* get random number */
popupspot = rand();
/* use upper bits for popup count */
popcount = (popupspot & countmask) >> 8;
/* use lower popmask bits for popup mole LED */
popupspot &= popmask;
/* show popup and check button */
if(molemask & (1<<popupspot)) {
/* set LED to show a mole to whack */
LEDOUT((1<<popupspot) & molemask);
/* single thread limit. sample twice */
msleep(popuptime>>1);
whacked = getButton(popupspot);
msleep(popuptime>>1);
whacked |= getButton(popupspot);
/* set back to mole mask */
LEDOUT(molemask);
}
}
/* mole whacked ? */
if(whacked) {
molemask &= ~(1<<popupspot);
}
/* if a random bit is set switch direction */
if(rand() & 0x20) {
direction ^= 1;
}
/* set new mole run spots */
if(direction) {
molemask = rotateRight(molemask);
}
else {
molemask = rotateLeft(molemask);
}
/* show mole run */
LEDOUT(molemask);
/* sleep a little so we can see the mole run */
msleep(ontime);
}
return 0;
}
/*
* make LEDs dance with a checker board pattern
*/
void celebrate(void)
{
int n = 16;
while(n-- > -1)
{
LEDOUT(0x55);
msleep(50);
LEDOUT(0xAA);
msleep(50);
}
LEDOUT(0);
msleep(400);
}
/*
* rotate mask left
*/
int rotateLeft(int mask)
{
int temp = mask << 1;
mask = (temp & 0x100) ? 1 : 0;
mask |= temp & 0xff;
return mask;
}
/*
* rotate mask right
*/
int rotateRight(int mask)
{
int temp = mask >> 1;
mask &= 0x01;
mask <<= 7;
mask |= temp;
return mask;
}
/*
* Set the LEDs to val
*/
void LEDOUT(int val)
{
DIRA |= 0xff << 16;
OUTA = (OUTA & ~(0xff<<16)) | (val<<16);
}
/*
* msleep makes the cog wait for about t milliseconds.
*/
void msleep(int t)
{
waitcnt((CLKFREQ/1000)*t+CNT);
}
/*
* Get a specific button number.
* buttons are enumerated from 0 to 7.
*/
int getButton(int n)
{
return (getButtons() & (1<<n));
}
/*
* Get all buttons at once
* Run this function from HUB if compiled for LMM.
*/
int getButtons()
{
int n = 16;
int result = -1;
int reading = 0;
int pins = 0xFF;
OUTA |= pins; //output high to buttons
while(n--)
{
DIRA |= pins; //output high to buttons
DIRA ^= pins; //switch to input
reading = pins;
msleep(2); //wait for RC time
reading &= INA; //return button states
result &= reading;
}
result = ~result & 0xFF;
return result;
}
/*
+--------------------------------------------------------------------
| 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.
+--------------------------------------------------------------------
*/
Not sure if it will be useful but this is the code that xlisp uses to generate random numbers:
/* xlosRand - return a random number between 0 and n-1 */
xlEXPORT long xlosRand(long n)
{
long k1;
/* make sure we don't get stuck at zero */
if (rseed == 0L) rseed = 1L;
/* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
k1 = rseed / 127773L;
if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
rseed += 2147483647L;
/* return a random number between 0 and n-1 */
return rseed % n;
}
David posted the rand() function. The srand() function is easy.
Just a little rewrite would look like below. The randomness is pretty good.
int rseed = 1;
/* seed the random number generator */
void Seed(int n)
{
rseed = n;
/* make sure we don't get stuck at zero */
if (rseed == 0) rseed = 1;
}
/* Rand() return a random number between 0 and n-1 */
int Rand(int n)
{
int k1;
/* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
k1 = rseed / 127773;
if ((rseed = 16807 * (rseed - k1 * 127773) - k1 * 2836) < 0)
rseed += 2147483647;
/* return a random number between 0 and n-1 */
return rseed % n;
}
I think it's safer to leave the code like this. It may be that it never reaches zero if you start at 1 but there is no guarantee that it won't for other initial seed values.
int rseed = 1;
/* seed the random number generator */
void Seed(int n)
{
rseed = n;
}
/* Rand() return a random number between 0 and n-1 */
int Rand(int n)
{
int k1;
/* make sure we don't get stuck at zero */
if (rseed == 0) rseed = 1;
/* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
k1 = rseed / 127773;
if ((rseed = 16807 * (rseed - k1 * 127773) - k1 * 2836) < 0)
rseed += 2147483647;
/* return a random number between 0 and n-1 */
return rseed % n;
}
Yes, I think that xBasic should have a standard random number generator which would be included in one of the standard .bas modules that ships with a version of xBasic. Maybe the author of xBasic could keep control of the standard .bas modules, so we always have at least a version of xBasic that is a standard version. With the ability to create your own def functions, this language could get out of hand in a very short time.
It may be that it never reaches zero if you start at 1 but there is no guarantee that it won't for other initial seed values.
Actually there probably is if our maths was up to it. However this is such a sad random number generator you can test it easily.
Starting from an rseed value 42 it gets back to 42 after generating 2147483647 numbers, which happens to be the maximum value of a 32 bit integer. Clearly it goes through all the possibilities in it's cycle without ever hitting zero. Ergo, where ever you start it will run around that same sequence never hitting zero.
At least this PRNG get's back to 42 faster than Deep Thought did.
Can I suggest you use the JKISS32 algorithm. Which generates about 2 to the power 121 numbers before repeating itself and passes the Die Hard tests for randomness.
This is KISS32:
/* Implementation of a 32-bit KISS generator which uses no multiply instructions */
static unsigned int x=123456789, y=234567891, z=345678912, w=456789123, c=0;
unsigned int JKISS32()
{
int t;
y ^= (y<<5); y ^= (y>>7); y ^= (y<<22);
t = z+w+c; z = w; c = t < 0; w = t&2147483647;
x += 1411392427;
return x + y + w;
}
At least this PRNG get's back to 42 faster than Deep Thought did.
Can I suggest you use the JKISS32 algorithm. Which generates about 2 to the power 121 numbers before repeating itself and passes the Die Hard tests for randomness.
This is KISS32:
/* Implementation of a 32-bit KISS generator which uses no multiply instructions */
static unsigned int x=123456789, y=234567891, z=345678912, w=456789123, c=0;
unsigned int JKISS32()
{
int t;
y ^= (y<<5); y ^= (y>>7); y ^= (y<<22);
t = z+w+c; z = w; c = t < 0; w = t&2147483647;
x += 1411392427;
return x + y + w;
}
Actually there probably is if our maths was up to it. However this is such a sad random number generator you can test it easily.
Starting from an rseed value 42 it gets back to 42 after generating 2147483647 numbers, which happens to be the maximum value of a 32 bit integer. Clearly it goes through all the possibilities in it's cycle without ever hitting zero. Ergo, where ever you start it will run around that same sequence never hitting zero.
Even if this algorithm does avoid hitting zero it is still incorrect to check for that case in the function that sets the seed. Someone might tweak the algorithm such that it does sometimes produce zero. Anyway, it isn't obvious that this code is valid so I think it should probably be changed back to the way the original works. I don't see any real advantage to the modified version.
You can seed JKISS32 just by setting x, y, z, and w.
Will setting just one of them and leaving the rest at their defaults work? I'm trying to figure out how to implement the srand() function in C which takes only one argument.
Perhaps you could arrange that when you call the seeding function it shuffles all those state variables, z => w, y => z, z => y. Then sets x to the seed parameter. That way if someone really wanted to seed all the bits they could call it 4 times with different values.
I don't think there are any constraints on the seed values but I seem to remember there is some weird stuff that goes on if you set all the seed bits to zero for example. The sequence you get out looks decidedly non-random, full of two many zeros bits all the time.
This just demonstrates the enormous period of the thing. With a sequence length of 10E36 you should get about 10*25 different permutations of all the numbers you can represent in the 32 bits of the output. Some of those permutations will look decidedly non-random.
You would expect that somewhere in there there are long stretches where there are far to many zeros in the 32 bit output.
When you start with all state bits set to zero you are just in a very strange place.
Perhaps you could arrange that when you call the seeding function it shuffles all those state variables, z => w, y => z, z => y. Then sets x to the seed parameter. That way if someone really wanted to seed all the bits they could call it 4 times with different values.
I don't think there are any constraints on the seed values but I seem to remember there is some weird stuff that goes on if you set all the seed bits to zero for example. The sequence you get out looks decidedly non-random, full of two many zeros bits all the time.
This just demonstrates the enormous period of the thing. With a sequence length of 10E36 you should get about 10*25 different permutations of all the numbers you can represent in the 32 bits of the output. Some of those permutations will look decidedly non-random.
When you start with all state bits set to zero you are just in a very strange place.
you would expect that somewhere in there there are long stretches where there are far to many zeros in the 32 bit output.
This should fix the RevA Quickstart loading issue. There are many IDE enhancements. The terminal behaves much better for example. The IDE will also scan for the first available Propeller and set the com port for use (the port will be blank on startup). Other items: Added current file/path to window title. Fixed SaveAs project setting, Made editor tab with smaller. Added program bytes loaded size. Fixed progress bar.
This should fix the RevA Quickstart loading issue. There are many IDE enhancements. The terminal behaves much better for example. The IDE will also scan for the first available Propeller and set the com port for use (the port will be blank on startup). Other items: Added current file/path to window title. Fixed SaveAs project setting, Made editor tab with smaller. Added program bytes loaded size. Fixed progress bar.
Comments
Ray
This function doesn't return any value and also has problems with the masking of both DIRA and INA. You'll need something more like this:
You can then test the return value of GetPinInp for zero or non-zero. If you want GetPinInp to return 0 if the pin is low and 1 if the pin is high then you'll need this:
Even better would be:
However none of this will work with the touch buttons on the QuickStart because they require more complex code to read them not just a GetPinInp function as I understand it. I've never actually used them though.
Ray
However, I think you're going to need to read up on those touch buttons. You can't just read the state of a pin to determine if the button is pressed. It's more complicated than that I think.
Ray
Here are some print utility functions.
I've noticed some issues with xbasic and quickstart. The xbasic loader needs to be updated.
I've also noticed that the IDE will hang if you print too fast. Sometimes the IDE won't respond after closing the terminal. Click the + button if it is still "pressed" and "Ok" the terminal until the + button is not pressed.
There are several things about the IDE that do not use improvements that were added to SimpleIDE. They will take time to update especially as I have other things going on. I'll get to them when I can.
Ray
The only real challenge here is making the srand() and rand() functions. Look at these links for descriptions: srand() rand() ... Actual implementation of rand(), a pseudo-random number generator (PRNG), doesn't need to be very complicated. Look at the middle-square method (not a very good PRNG, but better than nothing).
Just a little rewrite would look like below. The randomness is pretty good.
I think you broken the algorithm.
In the original rseed is set to 1 if it ever happens to be zero.
In yours if rseed is ever zero it gets stuck producing zeros forever.
Are we sure the algorithm never produces a zero?
Of course if it does not then it's not very random.
Also there is that modulus operator which ensures the output is biased.
It has a cycle length of 2147483646.
Ray
Actually there probably is if our maths was up to it. However this is such a sad random number generator you can test it easily.
Starting from an rseed value 42 it gets back to 42 after generating 2147483647 numbers, which happens to be the maximum value of a 32 bit integer. Clearly it goes through all the possibilities in it's cycle without ever hitting zero. Ergo, where ever you start it will run around that same sequence never hitting zero.
being the answer to life the universe and everything, it is not a representative number...
Massimo
At least this PRNG get's back to 42 faster than Deep Thought did.
Can I suggest you use the JKISS32 algorithm. Which generates about 2 to the power 121 numbers before repeating itself and passes the Die Hard tests for randomness.
This is KISS32:
You can read about it here: http://www0.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf
P.S. 2**121 = 2.6 * 10**36. That should keep Deep Thought busy for a while!
Of course then you are limiting your self to only 4 billion starting positions as opposed to 10*36 or whatever it is when you set all the bits.
I don't think there are any constraints on the seed values but I seem to remember there is some weird stuff that goes on if you set all the seed bits to zero for example. The sequence you get out looks decidedly non-random, full of two many zeros bits all the time.
This just demonstrates the enormous period of the thing. With a sequence length of 10E36 you should get about 10*25 different permutations of all the numbers you can represent in the 32 bits of the output. Some of those permutations will look decidedly non-random.
You would expect that somewhere in there there are long stretches where there are far to many zeros in the 32 bit output.
When you start with all state bits set to zero you are just in a very strange place.
I've posted an xBasicIDE package update here. New revision is 0.2.1.
This should fix the RevA Quickstart loading issue. There are many IDE enhancements. The terminal behaves much better for example. The IDE will also scan for the first available Propeller and set the com port for use (the port will be blank on startup). Other items: Added current file/path to window title. Fixed SaveAs project setting, Made editor tab with smaller. Added program bytes loaded size. Fixed progress bar.
Thanks Steve! Great work!!