CODE RELEASE v1: SPIN objects to implement Arduino compatible functions
pedward
Posts: 1,642
UPDATE 11/27/2011:
I have written unit tests and debugged all of the routines in this release. Attached is a ZIP file containing all of the implemented functions below and test programs for each SPIN object.
I spent a couple of hours working on the Time functions and just decided to leave them as-is. The problem is that the counters ALWAYS run at _XINFREQ x 16, which means that you can't accumulate slower than 1 in 32 bits, or 80Mhz. If anyone has any great ideas, I'm all ears.
The Arduino has a 4/8 usec main clock, with a 32bit accumulator. This overflows in 70 minutes at 250Khz. Most of the timing functions are intended for performing timing loops, not RTC, so I left this as a caveat to address by other objects like the RTC emulator.
The sin/cos/tan functions take degrees instead of radians. Since the Arduino is C-based and has C floating point, it makes sense they are radians, since the C library doesn't implement degrees and leaves that to the programmer. I took the approach that if radians are needed, the FloatXX objects can be used to do the necessary calculations; most programmers would rather work in degrees anyway.
The trig functions are included in the Math object instead of a separate Trig object, to make things easier. The code was scraped from a forum posting, although for any serious Trig I would recommend looking at Kye's post here: http://forums.parallax.com/showthread.php?123209-Tired-of-no-SIN-COS-TAN-ARCSIN-ARCCOS-ARCTAN-ARCTAN2-support-in-SPIN-Try-the-S
Functions I have implemented:
I have written unit tests and debugged all of the routines in this release. Attached is a ZIP file containing all of the implemented functions below and test programs for each SPIN object.
I spent a couple of hours working on the Time functions and just decided to leave them as-is. The problem is that the counters ALWAYS run at _XINFREQ x 16, which means that you can't accumulate slower than 1 in 32 bits, or 80Mhz. If anyone has any great ideas, I'm all ears.
The Arduino has a 4/8 usec main clock, with a 32bit accumulator. This overflows in 70 minutes at 250Khz. Most of the timing functions are intended for performing timing loops, not RTC, so I left this as a caveat to address by other objects like the RTC emulator.
The sin/cos/tan functions take degrees instead of radians. Since the Arduino is C-based and has C floating point, it makes sense they are radians, since the C library doesn't implement degrees and leaves that to the programmer. I took the approach that if radians are needed, the FloatXX objects can be used to do the necessary calculations; most programmers would rather work in degrees anyway.
The trig functions are included in the Math object instead of a separate Trig object, to make things easier. The code was scraped from a forum posting, although for any serious Trig I would recommend looking at Kye's post here: http://forums.parallax.com/showthread.php?123209-Tired-of-no-SIN-COS-TAN-ARCSIN-ARCCOS-ARCTAN-ARCTAN2-support-in-SPIN-Try-the-S
Functions I have implemented:
- Pins
- pinMode()
- digitalWrite()
- digitalRead()
- Time
- millis()
- micros()
- delay()
- delayMicroseconds()
- Math
- _min()
- _max()
- _abs()
- constrain()
- map()
- pow()
- sqrt()
- sin()
- cos()
- tan()
- Bits -- and bytes
- lowByte()
- highByte()
- bitRead()
- bitWrite()
- bitSet()
- bitClear()
- bit()
- Advanced I/O
- tone()
- noTone()
- shiftIn()
- shiftOut()
- pulseIn()
- Analog I/O
- analogReference()
- analogRead()
- analogWrite() 'PWM DAC
- RandomNumbers
- randomSeed()
- random()
- Serial
- begin()
- end()
- available()
- read()
- peek()
- flush()
- print()
- println()
- write()
- Interrupts 'Maybe doable with waitpeq to emulate
- interrupts()
- noInterrupts()
- attachInterrupt()
- detachInterrupt()
zip
5K
Comments
'Was not able to extract anything.
-Phil
EDIT: I decided to rename them to something like Arduino[XXX].spin. That isn't as elegant as :: and I'm completely open to suggestions to denote some class association hierarchy.
-Phil
That means pow(3,5) is 3*3*3*3*3 right?
In that case the implementation looks very strange to me!
What does exp & 2 mean? The shift you do in that case is only valid if base==2 and it should shift like base << (exp-1).
You need an if in front which is simply if exp==0 return 1
And with the second return I am totally lost ... why (exp ^ 2) ??? That's an bitwise XOR!
CNT is only 32 bits and will wraparound each 50 seconds (when running with 80MHz). My expectation is that in Arduino-world it is a timer without wraparound!
If you really want to port arduino functions to the propeller they should really exactly do what the originals do, otherwise the whole idea of having an arduino library will lead to frustration.
So, for the time you'll definitely need a COG which keeps track of the system time without wraparounds.
bitWrite I don't understand! It should not even compile because |< n is an unary operator. So, b |< n is senseless.
What happens if someone has the idea to call bitWrite( bla, 2, TRUE )? Should be handled properly!
bitClear works ... in 50% of the cases ;o) ^= is a bitwise XOR. This means if the bit is really set in val it works. If the bit was already cleared it will fail. A bitClear function should not have such an constraint!
long[ varptr ] &= ! |< n
i.e
setPinPWM(_pin,_freqhtz)
setPinDutyMode(_pin,_hightime)
stetPinIdle(_pin)
or similar.
James
Yes, you found bugs. I was just blasting through these and haven't tested them. I was following the early and often method that shows progress to get people excited. Obviously before I published these for real I'd have tests for each one to prove they work as intended. Most of the errors are just that SPIN isn't working like my brain expects it to. I'll have it figured out.
val/valptr I foolishly assumed I could write @val in the declaration when I originally wrote the functions, like PHP, however I didn't update the names after syntax checking through the compiler. All the classes compile syntactically, but not semantically
You caught me here. I was trying to cheat, but my algorithm wasn't right. I'll just have to rewrite it to work properly. I was going for code compactness/speed.
There are defined constraints in the Arduino. Your suggestion of a house-keeping cog, although resource intensive, may solve some other issues. It would seem silly to me to have a processor dedicated to housekeeping when the Arduino is a single 8 bit processor. I might get away with using a counter that is much slower so it doesn't overflow. Then the COG the code is running in manages that. If they go multi-COG, they need to know all about CNT and the other mp issues, so I'm not going to try and cover that.
In the first one I was going for (value of b shifted over by n), obviously that doesn't work.
The clear was written assuming someone was clearing a bit that was set, silly me.
Since that post I've implemented pulseIn(), analogWrite(), tone(), and notone().
The lack of a one-shot/retriggerable flag for the counters does present a problem because you have to supervise the counters to disable them after a period of time.
One of my absolute rules I set out for writing these compatibility functions was NOT to require a supervisory COG to make everything work exactly alike the Arduino. However, to have *full* compatibility one must have a supervisor COG to manage the resources.
Another hiccup is that the Arduino can have more than 2 counters in flight, which means you have to go to multi-COG programming to do more than 2 simultaneous outputs. Right now I'm user CTRA of the COG the code is running in. The idea is that the code could be launched in multiple COGs and be transparent. I may add some intelligence or non-standard functions to support A/B counter selection for simultaneous counter output.
The analogWrite is using the DUTY mode of the counter and tone uses NCO mode. These are 2 very different beasts. NCO is variable frequency/fixed duty, DUTY is fixed frequency/variable duty. The Arduino has an 8 bit duty, so I simply multiply the duty cycle by $101_0101 (and I checked the math several times on that).