![]() |
Forum Index : Microcontroller and PC projects : Bypic PIC32 Basic
Author | Message | ||||
memberx Newbie ![]() Joined: 20/04/2012 Location: AustraliaPosts: 24 |
Has anyone used Bypic BV500(MX1) and compared to micromite, same PIC32 chip? Looks like it has more functions, and even user functions are compiled before used in Basic interpreter. Compiled Basic user functions could make it very fast and powerful? Has Integer and Double float data types. Micromite has single floats, and has caused a number of conversion and accuracy issues. http://www.bypic.co.uk/index.php/What_Is_It http://www.bypic.co.uk/index.php/Key_Words http://www.bypic.co.uk/index.php/Language_Guide http://www.bypic.byvac.com/index.php/Products http://www.bypic.byvac.com/index.php/BV500 |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 3998 |
I've a couple of their boards but bought them as cheap boards to use with C - partly because their Basic isn't open source in any sense. (I'm unlikely to use MMBasic for the same reason.) It looks a reasonable "just another" non-open BASIC, to me. The boards I have are like a typical 44-pin umite one (and run the 44-pin umite firmware apparently fine). I did try a "flash LED quickly" loop out of curiosity and came up with this constant ANSELBCLR 0xBF886104
constant TRISBCLR 0xBF886114 constant LATBINV 0xBF88613C @ANSELBCLR = 1 @TRISBCLR = 1 function led() while 1 @LATBINV = 1 wend endf maybe gives you a flavour of what can be done. 16M loops (measured using a couple of 12-bit counters) took about 70 secs. John |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
@memberx I've just received one of their MX150s loaded with ByPic, and first impressions are that the entry effort is much greater than uMite, but because it's more "raw"/close to the bare metal, one could probably get more done with it, and it does seem quick. ByPic also has more in common with C than Basic IMHO, eg pointers, and it is case sensitive. The MX150 loaded with ByPic comes in at about GBP 5.00 here in the UK, so not a lot of money to get one or two and have a play with. The C plugin facility is very interesting but limited, eg the C function cannot call another function, so everything U need to do has to be in the one function, but still useful I would have thought. The MX150 ByPic doesn't have a proper interactive environment because of memory limitations, eg type list, and nothing shows up (apparently list works on the larger PIC32 chips). And, there is no IDE like MMEdit - PSPad is very good as an editor, but it is just an editor, whereas MMEdit is much more like an IDE. So in summary, ByPic is a lot more rougher around the edges, more raw, needs more effort to use than uMite mmBasic, but can probably go faster. (Custom car vs Production car analogies) Whilst playing with ByPic, I got the distinct sense/flavour that FORTH was somehow involved - nothing wrong with that. Don't know why, but it just had that whiff of FORTH. Perhaps I was imagining things or wishful thinking of late 70s/early 80s ! Peter The only Konstant is Change |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
@memberx see this MX1 ByPic Data Types I tried print 10+2.5 as a double check, and it error'ed out. The 'MX150 version of ByPic definitely doesn't have any floating point capability at all :( Peter The only Konstant is Change |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
I posted this into the wrong topic previously so I'm reposting it here because this post is about ByPic. I've just completed benchmarking some code on the ByPic 'MX150 which runs at 40MHz, specifically 18 decimal digit ADD and SUBTRACT, and the ByPic performs an 18 digit Add/subtract in around 800uS compared to about 2.5 mS for the uMite, ie about 3 x faster. Here's the ByPic code. I've previously posted 24 digit BCD library in mmBasic on TBS, and the equivalent 18 digit Add/Subtract routines may be found in the AD9850Controller.bas mmBasic code I have previously posted on TBS. The simplicity of the Add and Subtract functions makes them ideal candidates to try and code them in MIPS assembler/C and use the plugin feature of ByPic. Peter constant Billion 1000000000 constant Million 1000000 constant Thousand 1000 constant HalfMillion 500000 constant SizeOfInt 4 constant MillionX10 10000000 // // Add 2 x 18 digit integers, return result in p // m, n, p are the base addresses of integer arrays // p()=m()+n() // function AddMN2P(m,n,p) dim i,Cy i=peek(m) + peek(n) Cy=i / Billion i=i % Billion poke(p+0,i) i=peek(m+SizeOfInt) + peek(n+SizeOfInt) + Cy i=i % Billion poke(p+SizeOfInt,i) endf // // Add 2 x 18 digit integers, return result in m // m, n are the base addresses of integer arrays // m()=m()+n() // function AddMN2M(m,n) dim i,Cy i=peek(m) + peek(n) Cy=i / Billion i=i % Billion poke(m,i) i=peek(m+SizeOfInt) + peek(n+SizeOfInt) + Cy i=i % Billion poke(m+SizeOfInt,i) endf // // Sub 2 x 18 digit integers, return result in p // m, n, p are the base addresses of integer arrays // p()=m()-n() // function SubMN2P(m,n,p) dim i,Cy i=peek(m) - peek(n) + Billion Cy=1 - i / Billion i=i % Billion poke(p+0,i) i=peek(m+SizeOfInt) - peek(n+SizeOfInt) - Cy +Billion i=i % Billion poke(p+SizeOfInt,i) endf // // Sub 2 x 18 digit integers, return result in m // m, n are the base addresses of integer arrays // m()=m()-n() // function SubMN2M(m,n) dim i,Cy i=peek(m) - peek(n) + Billion Cy=1 - i / Billion i=i % Billion poke(m,i) i=peek(m+SizeOfInt) - peek(n+SizeOfInt) - Cy + Billion i=i % Billion poke(m+SizeOfInt,i) endf // // m, p are the addresses of the first element of the arrays // p()=m() / 1,000,000 // function Div1e6M2P(m,p) dim i,j,Cy,n dim r$[32] //m(0) i=peek(m) //m(1) j=peek(m+SizeOfInt) //Add 500000 to make sure we round correctly i=i+HalfMillion //Any Carry Cy=i/Billion if Cy i=i % Billion j=j+Cy endif //Now throw away the bottom six digits i=i / Million Cy=j % Million j=j / Million //9 Digits per integer var so we divided by 1E6 so the remainder //has to be multiplied by 1E3 i=i+(Cy*Thousand) //Return the results poke(p+0,i) poke(p+SizeOfInt,j) endf // // Return String representation of 18 digit BCD variable // function BCD2Asc$(m) return format$( "%9u", peek(m+SizeOfInt) ) + format$( "%9u", peek(m) ) endf // // This is a test harness is for testing ByPic's capabilities to calculate // the 32 bit tuning word for an AD9850 DDS chip. The assumptions are that // the AD9850 is clocked at 125,000,000 Hz, ie as commonky found on eBay // for the cheap modules. // function start() dim I(2),J(2),K(2),L(2),R$[24] dim n,i //10MHz Tuning Word for an AD9850 with CLK=125MHz scaled by 1e6 I(0)=383680000 I(1)=343597 print "Starting I()=";print BCD2Asc$(?I(0));print "\n" //Increment to add/subtract to the tuning word for a 10,000Hz shift in frequency J(0)=597383680 J(1)=343 print "Starting J()=";print BCD2Asc$(?J(0));print "\n" //Move frequency up 10 KHz //Result should be 343940981063680 tmr_set(?TIMER23, MillionX10) for i=1 to 100 //AddMN2P(?I(0),?J(0),?I(0)) AddMN2M(?I(0),?J(0)) next i n=tmr_get(?TIMER23);tmr_set(?TIMER23, 0) print n/100 ;print " uS AddMN2M";print "" print BCD2Asc$(?I(0));print "\n" //Move frequency down 10 KHz //Result should be 343253786296320 tmr_set(?TIMER23, MillionX10) for i=1 to 100 //SubMN2P(?I(0),?J(0),?I(0)) SubMN2M(?I(0),?J(0)) next i n=tmr_get(?TIMER23);tmr_set(?TIMER23, 0) print n/100 ;print " uS SubMN2M";print "" print BCD2Asc$(?I(0));print "\n" //Divide RawTuning Word by 1E6 to get actual tuning word we will send //to the DDS chip //Result should be 347033358 tmr_set(?TIMER23, MillionX10) for i=1 to 100 Div1e6M2P(?I(0),?L(0)) next i n=tmr_get(?TIMER23);tmr_set(?TIMER23, 0) print n/100 ;print " uS Div1E6";print "" print BCD2Asc$(?L(0));print "\n" print "Tuning Word is ";print toupper$(hex$(L(0)));print "\n" endf The only Konstant is Change |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
Hi I've implemented the 18 digit BCD Add as a ByPic C plugin, and the benchmark result for the 18 digit Add is 107 uS which is a phenomenal improvement. The C code is shown below. I am using MPLab v8.84 with PIC32-gcc v2.02. Now when Geof implements 32 bit integers in MMBasic, and the ability to pass arrays to/from MMBasic functions, we should see some huge performance improvements in this extended precision area. I'm beginning to be really torn between the ease of use, development time, and support from Geoff and everybody on TBS of MMBasic+MMEdit, against the raw power of ByPic. I don't think I'll be able to decide what to do until I've implemented something really serious in ByPic, so I guess that means porting my MMBasic AD9850Controller.bas over to ByPic and seeing what problems I hit along on the way, that stuff uses Rotary Encoder, Push-Button, I2C LCD, I2C Keypad, and drives the AD9850 eBay module, so something fairly meaty and diverse. I hope this helps other people. Peter // This simple plugin will take 2 x 18 digit BCD digits and add them // The digits are stored in consecutive quad byte words // ie +0 is lo 9 digits of first number, ie a // +1 is hi 9 digits of first number // +2 is lo 9 digits of second number, ie b // +3 is hi 9 digits of second number // // Result is returned in +0, +1, ie a // a = a + b int addab2aR(char *c) { unsigned long *ip; register unsigned long a; register unsigned long b; register unsigned long cy; ip = (unsigned long*)c; // pointer to long (32 bit unsigned integer) //Add lo parts of a & b a = *(ip); // contents of memory as integer b = *(ip+2); // contents of memory as integer a += b; cy = a / 1000000000; a %= 1000000000; *ip++=a; //save lo result and point at high parts //get high parts a = *(ip); // contents of memory as integer b = *(ip+2); // contents of memory as integer //Add high parts together with Carry from lo parts a += b; a += cy; a %= 1000000000; *(ip)=a; return (0); } and here's the disassembly of the Compilers's output - the opcodes are what is stored in ByPic as a constant array, and call'ed. (it looks like the compiler has ignored my 'register' hint and used the stack anyway !) 9d00012c <addab2aR>: 9d00012c: 27bdffe8 addiu sp,sp,-24 9d000130: afbe0014 sw s8,20(sp) 9d000134: afb20010 sw s2,16(sp) 9d000138: afb1000c sw s1,12(sp) 9d00013c: afb00008 sw s0,8(sp) 9d000140: 03a0f021 move s8,sp 9d000144: afc40018 sw a0,24(s8) 9d000148: 8fc20018 lw v0,24(s8) 9d00014c: afc20000 sw v0,0(s8) 9d000150: 8fc20000 lw v0,0(s8) 9d000154: 8c500000 lw s0,0(v0) 9d000158: 8fc20000 lw v0,0(s8) 9d00015c: 24420008 addiu v0,v0,8 9d000160: 8c510000 lw s1,0(v0) 9d000164: 02118021 addu s0,s0,s1 9d000168: 00101a42 srl v1,s0,0x9 9d00016c: 3c020004 lui v0,0x4 9d000170: 34424b83 ori v0,v0,0x4b83 9d000174: 00620019 multu v1,v0 9d000178: 00001010 mfhi v0 9d00017c: 000291c2 srl s2,v0,0x7 9d000180: 00101a42 srl v1,s0,0x9 9d000184: 3c020004 lui v0,0x4 9d000188: 34424b83 ori v0,v0,0x4b83 9d00018c: 00620019 multu v1,v0 9d000190: 00001010 mfhi v0 9d000194: 000219c2 srl v1,v0,0x7 9d000198: 3c023b9a lui v0,0x3b9a 9d00019c: 3442ca00 ori v0,v0,0xca00 9d0001a0: 70621002 mul v0,v1,v0 9d0001a4: 02021023 subu v0,s0,v0 9d0001a8: 00408021 move s0,v0 9d0001ac: 8fc20000 lw v0,0(s8) 9d0001b0: ac500000 sw s0,0(v0) 9d0001b4: 8fc20000 lw v0,0(s8) 9d0001b8: 24420004 addiu v0,v0,4 9d0001bc: afc20000 sw v0,0(s8) 9d0001c0: 8fc20000 lw v0,0(s8) 9d0001c4: 8c500000 lw s0,0(v0) 9d0001c8: 8fc20000 lw v0,0(s8) 9d0001cc: 24420008 addiu v0,v0,8 9d0001d0: 8c510000 lw s1,0(v0) 9d0001d4: 02118021 addu s0,s0,s1 9d0001d8: 02128021 addu s0,s0,s2 9d0001dc: 00101a42 srl v1,s0,0x9 9d0001e0: 3c020004 lui v0,0x4 9d0001e4: 34424b83 ori v0,v0,0x4b83 9d0001e8: 00620019 multu v1,v0 9d0001ec: 00001010 mfhi v0 9d0001f0: 000219c2 srl v1,v0,0x7 9d0001f4: 3c023b9a lui v0,0x3b9a 9d0001f8: 3442ca00 ori v0,v0,0xca00 9d0001fc: 70621002 mul v0,v1,v0 9d000200: 02021023 subu v0,s0,v0 9d000204: 00408021 move s0,v0 9d000208: 8fc20000 lw v0,0(s8) 9d00020c: ac500000 sw s0,0(v0) 9d000210: 00001021 move v0,zero 9d000214: 03c0e821 move sp,s8 9d000218: 8fbe0014 lw s8,20(sp) 9d00021c: 8fb20010 lw s2,16(sp) 9d000220: 8fb1000c lw s1,12(sp) 9d000224: 8fb00008 lw s0,8(sp) 9d000228: 27bd0018 addiu sp,sp,24 9d00022c: 03e00008 jr ra 9d000230: 00000000 nop Here's the no register version using pointers only - it's 4 uS slower // This simple plugin will take 2 x 18 digit BCD digits and add them // The digits are stored in consecutive quad byte words // ie +0 is lo 9 digits of first number, ie a // +1 is hi 9 digits of first number // +2 is lo 9 digits of second number, ie b // +3 is hi 9 digits of second number // // Result is returned in +0, +1, ie a // a = a + b int addab2a(char *c) { unsigned long *ip, cy; ip = (unsigned long*)c; // pointer to long (unsigned int) //Add lo parts of a & b, a(lo)=a(lo)+b(lo) *(ip) += *(ip+2); cy = *(ip) / 1000000000; *(ip)++ %= 1000000000; //Add high parts of a & b, a(hi)=a(hi)+b(hi)+Carry *(ip) += *(ip+2); *(ip) += cy; *(ip) %= 1000000000; return (0); } The only Konstant is Change |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 3998 |
When I wrote a C plugin I tweaked the gcc flags beyond those they document. If you want that code smaller/faster let me know the flags you used and I'll dig out what I did. John |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
Hi John, thanks for the kind offer. This is what I used -mlong-calls -fPIC -mno-gpopt -mshared -mno-abicalls These were as given by Jim from ByVac. I have to admit that I have very little idea what these flags mean. Thank you Peter The only Konstant is Change |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 3998 |
try adding -O3 or -Os You could also use const for some of the things so gcc knows it can safely optimise more. Though it's already plenty fast enough for most things! John |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
Hi Jonh Thanks, will try that out right now. Just done -Os, WOW, where did that come from ! 117uS down to 107uS, 9.4% performance improvement just by specifying an option ! This ByPIC stuff is really interesting, especially the C plugin capability. The main problem I have with ByPIC is that if I commit to developing a product using ByPIC, what happens if ByVac/Jim Spence goes belly up ? I'd be stuffed. At least with MMBasic, the source/runtime is out in the public domain so I could continue to ship my product even in Geoff's absence, (which hopefully will outlive my lifetime) but with ByPIC, only ByVac/Jim can supply the chips with ByPIC installed. I'll have to ask Jim what escrow arrangements he has in place, and what code release arrangements he has in place in the unfortunate event of his/ByVac's demise - seems morbid, but ... Hope all is well with you. Thank you. Peter The only Konstant is Change |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
Hi John I tend to use #define rather than const, I guess the PP makes #define transparent to gcc, whereas const tells the gcc what's going on. Is my thinking correct ? Therefore I should use const more frequently ? Peter The only Konstant is Change |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 3998 |
const & #define are in many cases probably no different to a decent optimising compiler but there are extra ways you can use const, such as: const int * ptr; or const * const int ptr; Sometimes an optimiser can figure out the way you use a pointer and then effectively add the const but it's tough for an optimiser to be sure (e.g. it has to be sure you're not using aliased or overlapping pointers). Do bear in mind that over-optimised over-sped-up code tends to get unreadable at some point, though! John |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
Thanks once again Peter The only Konstant is Change |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |