Author Archives: Allen Huffman

About Allen Huffman

Co-founder of Sub-Etha Software.

10 PRINT big maze in Color BASIC – part 3

See also: part 1, part 2, part 3 and part 4.

When we last left off, it had been so long since I did any BASIC programming that I found myself wondering why these two sections of BASIC did not perform as I expected:

0 'bigmazebench.bas
100 P=0:TIMER=0:A=0
110 P=0
120 P=P+2:IF P>479 THEN PRINT:GOTO 110
120 A=A+1:IF A >1000 THEN 150
140 GOTO 120
150 PRINT TIMER

200 P=0:TIMER=0:A=0
210 PRINT:P=0
220 P=P+2:IF P>479 THEN 210
230 A=A+1:IF A>1000 THEN 250
240 GOTO 220
250 PRINT TIMER

William Astle once again saw the obvious (just not obvious to me at the time)…

If you have both versions in the same program, the “backwards” jumps will be slower the later in the program they are because they have to do a sequential scan of the program from the beginning to find the correct line number. If you have been running them in the same program, try separating them and running them independently.

– William Astle

Well, duh. Of course. When the block of code starting at line 200 runs, the GOTO 220 has to start at the top of the program and seek past every line to find 220. Much slower compared to how few lines the GOTO 120 has to. Normally my benchmark program is inside a FOR/NEXT loop so there is no line seeking and it behaves the same speed regardless of line number location…

So let’s try them one at a time. I loaded the program and deleted the line 0 comment, and lines 200 and up (DEL 0 and DEL 200-):

100 P=0:TIMER=0:A=0
110 P=0
120 P=P+2:IF P>479 THEN PRINT:GOTO 110
120 A=A+1:IF A >1000 THEN 150
140 GOTO 120
150 PRINT TIMER

This gives me 762.

Then, loading it again, and deleting everything up to 200 (“DEL -199”):

200 P=0:TIMER=0:A=0
210 PRINT:P=0
220 P=P+2:IF P>479 THEN 210
230 A=A+1:IF A>1000 THEN 250
240 GOTO 220
250 PRINT TIMER

That gives me 1394!

Yep, William’s suggestion of moving the PRINT to the destination line, instead of using “THEN PRINT:GOTO xxx” almost doubled the speed it takes to run through that code.

Nicely done, William.

Until next time…

10 PRINT big maze in Color BASIC – part 2

See also: part 1, part 2, part 3 and part 4.

Previously, I presented this Color BASIC program:

0 ' BIGMAZE.BAS
10 C=2
20 B$=CHR$(128)
30 L$=CHR$(128+16*C+9)
40 R$=CHR$(128+16*C+6)
50 M$(0,0)=B$+R$:M$(0,1)=R$+B$
60 M$(1,0)=L$+B$:M$(1,1)=B$+L$
70 P=512-32*2
80 M=RND(2)-1
90 PRINT@P,M$(M,0);:PRINT@P+32,M$(M,1);
100 P=P+2:IF P>479 THEN PRINT:GOTO 70
110 GOTO 80

Running it produces this:

4×4 Maze

And I ended with “Make it smaller. Make it faster.”

William Astle commented:

Welp, everything up to line 60 can be mashed into a single line. Since it’s all setup and none of it is performance critical, you can dispense with the variables and just set the M$ array directly. More typing, but it keeps the variable table smaller. Or define P right at the start so it’s the first variable in the table which would give you a speedup all on its own since the lookups to find P will be faster.

I suspect that if you put the PRINT statement from line 100 at, say, the start of line 70 and have “THEN 70” instead of “THEN PRINT:GOTO 70”, you might get a bit of a performance gain there, especially in the false case where that gives a handful fewer bytes to skip over.

There might be some sort of trick involving FOR/NEXT that can be used to improve the main loop but I think the overhead of setting up a FOR loop will be more than the saving in this case, especially if the setup lines are combined into a single program line.

On a side note, and this won’t improve the speed any, you could put a DIM M(1,1) at the start to avoid the implied DIM M(10,10). That saves a bit of memory, though I don’t think that’s even an issue for this program even on a 4K machine. But it is 585 bytes nevertheless.

– William Astle

Let’s start with the “everything up to line 60” part, which gives us this:

10 M$(0,0)=CHR$(128)+CHR$(166):M$(0,1)=CHR$(166)+CHR$(128):M$(1,0)=CHR$(169)+CHR$(128):M$(1,1)=CHR$(128)+CHR$(169)

If I compare that to the original, it’s about a few less characters to type:

10 C=2:B$=CHR$(128):L$=CHR$(128+16*C+9):R$=CHR$(128+16*C+6):M$(0,0)=B$+R$:M$(0,1)=R$+B$:M$(1,0)=L$+B$:M$(1,1)=B$+L$

It loses the ability to change the color of the maze (easily), but it saves three string variables (B$ for blank block, R$ for right block, and L$ for left block) and one numeric variable (C for color). Definitely lower RAM use, and I am sure it is code-space too since you can’t tokenize “128+16*C+6” (10 bytes) which is replaced by “166”.

Combining the rest of the lines, where possible, and moving the PRINT (so line 100 has a bit less to parse through to get to the end of that line when P>479 is not true) results in:

0 ' BIGMAZE2.BAS - William Astle
10 M$(0,0)=CHR$(128)+CHR$(166):M$(0,1)=CHR$(166)+CHR$(128):M$(1,0)=CHR$(169)+CHR$(128):M$(1,1)=CHR$(128)+CHR$(169)
70 PRINT:P=448
80 M=RND(2)-1:PRINT@P,M$(M,0);:PRINT@P+32,M$(M,1);:P=P+2:IFP>479THEN70
110 GOTO80

On my simulated CoCo, removing the REM statements, then loading the original version and doing “? MEM” showed 8256. Doing the same to the second version shows 8307 — saving 51 bytes of program space. I did not measure what the saving in string and variable memory would be, but that would be even more. Great win.

Since the difference was mostly in the setup of the variables, they should run at the same speed — or will they? Let’s quickly test William’s suggestion of moving the PRINT so the IF statement doesn’t have to parse the end of the line:

0 'bigmazebench.bas
100 P=0:TIMER=0:A=0
110 P=0
120 P=P+2:IF P>479 THEN PRINT:GOTO 110
120 A=A+1:IF A >1000 THEN 150
140 GOTO 120
150 PRINT TIMER

200 P=0:TIMER=0:A=0
210 PRINT:P=0
220 P=P+2:IF P>479 THEN 210
230 A=A+1:IF A>1000 THEN 250
240 GOTO 220
250 PRINT TIMER

Not very elegant, but it should do the job. Since I could not easily use a FOR/NEXT loop for the counter, I used A and a check in line 130 or 230 to exit the test.

This prints 771 for the first one, and 1414 for the second one.

This is not what I would have expected. I must be doing something wrong, because I agree with William that…

IF P>479 THEN PRINT:GOTO 210

…should be slower every time P is NOT greater than 479, compared to:

IF P>479 THEN 210

In the first example, each time P is not greater than 479, BASIC should still have to skip everything past then THEN looking for either ELSE or the end of the line. It should be scanning past a PRINT and GOTO token then the number 220.

In the second example, it should only have to skip the number 210.

I think I did something wrong.

What am I missing?

To be continued…

10 PRINT big maze in Color BASIC – part 1

See also: part 1, part 2, part 3 and part 4.

Awhile back, I discussed the famous Commodore 10 PRINT one-line program, inspired by a YouTube video from 8-Bit Show and Tell.

Commodore PET running the 10 PRINT program.

Although most computers could do the same program in BASIC, unless your system had those wonderful diagonal graphics characters, the result could be a bit lacking.

Scrolling maze… Sorta.

On the CoCo, using the 2×2 block graphics characters was not an improvement, either.

But perhaps if you used a 4×4 block it might look more like a maze. This allows 16 maze characters across by 8 down (versus a Commodore VIC-20 with 22×23).

4×4 Maze

Well, it works, but takes up much more than one line. How small can you make it? Here is my version:

0 ' BIGMAZE.BAS
10 C=2
20 B$=CHR$(128)
30 L$=CHR$(128+16*C+9)
40 R$=CHR$(128+16*C+6)
50 M$(0,0)=B$+R$:M$(0,1)=R$+B$
60 M$(1,0)=L$+B$:M$(1,1)=B$+L$
70 P=512-32*2
80 M=RND(2)-1
90 PRINT@P,M$(M,0);:PRINT@P+32,M$(M,1);
100 P=P+2:IF P>479 THEN PRINT:GOTO 70
110 GOTO 80

Make it smaller. Make it faster. Share your work. And someone tell Jim Gerrie since he probably has already done this…

Until next time…

Odd or Even in Color BASIC?

In my 3X+1 post, I needed to check if a value was odd or even. I did so by using “AND 1” which would test the least significant bit. This works, and is fast, but is limited to values 32767 or lower (15 bits).

Comments from William Astle, RogelioP and John offered corrections and updates to my code. I decided to benchmark a few different methods for detecting if a value was odd or even, and here is what I came up with.

0 REM 3x+1 Benchmarking

5 'GOTO 300

100 ' 0-32767 ONLY
110 TIMER=0
120 FOR A=1 TO 1000
130 IF X AND 1 THEN REM
140 NEXT:PRINT TIMER

200 ' ALL RANGES?
210 TIMER=0
220 FOR A=1 TO 1000
230 IF INT(X/2)=X/2 THEN REM
240 NEXT:PRINT TIMER

300 ' ROGELIO P
310 TIMER=0
320 FOR A=1 TO 1000
330 IF INT(X/2)*2=X THEN REM
340 NEXT:PRINT TIMER

400 ' WILLIAM ASTLE
405 T=0:H=0.5
410 TIMER=0
420 FOR A=1 TO 1000
430 T=X*H:IF T=INT(T) THEN REM
440 NEXT:PRINT TIMER

500 ' DIVIDE TEST
505 T=0:H=2
510 TIMER=0
520 FOR A=1 TO 1000
530 T=X/H:IF T=INT(T) THEN REM
540 NEXT:PRINT TIMER

When I run this program in Xroar on my Raspberry Pi 400, I get:

313
508
506
485
485

As expected, AND is the fastest, so use this if you know your values will be 32767 or lower.

Using INT(X/2)=X/2 was a fraction slower as INT(X/2)*2=X, which I guess makes sense since both do an INT and two math functions.

William’s suggestion of multiplying by .5 instead of dividing by two rang a bell. I believe he (or someone) pointed this out to me a few years ago when I was doing similar benchmarks. A big speed up comes just from putting the value in a variable, but I was surprised to see that dividing by a variable of 2 was the same speed as multiplying by a variable of .5.

What ideas do you have? Anything with math (“/2”) can be sped up by using a variable (“/H”), so there are some improvements just from that. Using HEX values (“&H2”) instead of decimal is also faster, as is removing extra spaces.

But are there better approaches we can use?

Thoughts appreciated.

3X+1 in C#

For my day job, I do embedded C programming for PIC24 compilers and some Windows C programming in something called LabWindows. Lately, I’ve been touching some C# stuff, so I decided to revisit last night’s 3X+1 program by converting it to C#.

You can compile and run it online here: https://www.onlinegdb.com/online_csharp_compiler

// 3X+1

using System;
					
public class Program
{
	public static void Main()
	{
		while (true)
		{
			Int32 x = 0;

			Console.WriteLine();
			Console.Write("STARTING NUMBER? ");
			x = Int32.Parse(Console.ReadLine());
			
			while (true)
			{
				Console.Write(x);
				Console.Write(" ");
				
				if (x == 1) break;
				
				if ((x & 1) == 1) // Odd
				{
					x = x * 3 + 1;
				}
				else // Even
				{
					x = x / 2;
				}
			}
		}
	}
}

3X+1 and Color BASIC

For the past three weeks, I have found myself out-of-town for work. This week, I decided to bring my Raspberry Pi 400 along so I could play with it in the hotel room.

Raspberry Pi 400

I soon found myself toying around with the XRoar CoCo emulator, and I knew just what I wanted to program…

Last night, YouTube showed me a video about “the most dangerous problem in mathematics.”

The idea is you start with a number. If it is odd, you multiply it by 3 and add 1. If it is even, you divide it by 2. Repeat until you get to the pattern 4, 2, 1, 4, 2, 1, 4, 2, 1.

Math says that, so far, every number ends up at that pattern. No one has figured out a formula that leads to any number that does not end at 4, 2, 1.

With that in mind, I thought it would be fun to write the 3X+1 problem in CoCo Color BASIC. It looks like this:

0 REM 3X+1
10 PRINT:INPUT "STARTING NUMBER";X
20 PRINT X;
30 IF X=1 THEN 10
40 IF X AND 1 THEN X=X*3+1:GOTO 20
50 X=X/2:GOTO 20 

I tried to avoid using any Extended Color BASIC features such as HEX numbers (&H1) to speed things up. I even skipped ELSE so it could run on a VIC-20 or other system without that command.

I use “X AND 1” to test for a number being odd. Any odd number has the first bit set. 1 (00000001) does, 2 does not (00000010), 3 does (00000011), and so on.

It does have one flaw… if any number is greater than 32767, it will crash with a ?FC ERROR. Apparently Color BASIC’s AND cannot handle any value greater than 7 bits (01111111 = 32767).

Do you know of a different way to test for even or odd values? I can think of two, one of which would be terribly inefficient and the other not as inefficient but much worse than using AND.

Give it a shot and see if you can find the largest sequence of numbers a CoCo can calculatae.

Or better yet, find a better way to do this in Color BASIC.

Enjoy!

Arduino Serial output C macros

Here is a quickie.

In Arduino, instead of being able to use things like printf() and puchar(), console output is done by using the Serial library routines. It provides functions such as:

Serial.print();
Serial.println();
Serial.write();

These do not handle any character formatting like printf() does, but they can print strings, characters or numeric values in different formats. Where you might do something like:

int answer = 42;
printf("The answer is %d\r\n", answer);

…the Arduino version would need to be:

int answer = 42;
Serial.print("This answer is ");
Serial.print(answer);
Serial.println();

To handle printf-style formatting, you can us sprintf() to write the formatted string to a buffer, then use Serial.print() to output that. I found this blog post describing it.

I recently began porting my Arduino Telnet routine over to standard C to use on some PIC24 hardware I have at work. I decided I should revisit my Telnet code and try to make it portable, so the code could be built for Arduino or standard C. This would mean abstracting all console output, since printf() is not used on the Arduino.

I quickly came up with these Arduino-named macros I could use on C:

#include <stdio.h>
#include <stdlib.h>

#define SERIAL_PRINT(s)     printf(s)
#define SERIAL_PRINTLN(s)   printf(s"\r\n")
#define SERIAL_WRITE(c)     putchar(c)

int main()
{
    SERIAL_PRINT("1. This is a line");
    SERIAL_PRINTLN();
    SERIAL_PRINTLN();

    SERIAL_PRINTLN("2. This is a second line.");

    SERIAL_PRINT("3. This is a character:");
    SERIAL_WRITE('x');
    SERIAL_PRINTLN();

    SERIAL_PRINTLN("done.");

    return EXIT_SUCCESS;
}

Ignoring the Serial.begin() setup code that Arduino requires, this would let me replace console output in the program with these macros. For C, it would use the macros as defined above. For Arduino, it would be something like…

#define SERIAL_PRINT(s)     Serial.print(s)
#define SERIAL_PRINTLN(s)   Serial.println(s)
#define SERIAL_WRITE(c)     Serial.write(c)

By using output macros like that, my code would still look familiar to Arduino folks, but build on a standard C environment (for the most part).

This isn’t the most efficient way to do it, since Arduino code like this…

  Serial.print("[");
  Serial.print(val);
  Serial.println("]");

…would be one printf() in C:

printf ("[%d]\n", val);

But, if I wanted to keep code portable, C can certainly do three separate printf()s to do the same output as Arduino, so we code for the lowest level output.

One thing I don’t do, yet, is handle porting things like:

Serial.print(val, HEX);

On Arduino, that outputs the val variable in HEX. I’m not quite sure how I’d make a portable macro for that, unless I did something like:

#define SERIAL_PRINT_HEX(v) Serial.print(v, HEX)

#define SERIAL_PRINT_HEX(v) printf("%x, v)

That would let me do:

SERIAL_PRINT("[");
SERIAL_PRINT_HEX(val);
SERIAL_PRINTLN("]");

I expect to add more macros as-needed when I port code over. This may be less efficient, but it’s easier to make Arduino-style console output code work on C than the other way around.

Cheers…

C: (too) many happy returns…

Here’s another quick C thing…

One of the jobs I had used a pretty complete coding style guide for C. One of the things they insisted on was only one “return” in any function that returns values. For example:

int function(int x)
{
   if SOMETHING
   {
      return 100;
   }
   else SOMETHING ELSE
   {
      return 200;
   }
   else
   {
      return 0;
   }
}

The above function returns values 100, 200 or 0 based on the input (1, 2 or anything else). It has three different places where a value is returned. This saves code, compared to doing it like this:

int function(int x)
{
   int value;

   if SOMETHING
   {
      value = 100;
   }
   else if SOMETHING ELSE
   {
      value = 200;
   }
   else
   {
      value = 0;
   }

   return value;
}

Above, you see we use a variable, and then have three places where it could be set, and then we return that value in one spot at the end of the function. This probably generates larger code and would take longer to run than the top example.

But if you can afford those extra bytes and clock cycles, it is a much better way to do this — at least form a maintenance and debugging standpoint.

I have accepted this, but only today did I run in to a situation where this approach would have saved me some time and frustration. In my case, I was encounter a compiler warning about a function not returning a value where it was defined to return a value. I looked and confirmed the function was indeed returning a value. What was going on?

The problem was that it used multiple returns, and did something like this:

int function(int x)
{
   int value;

   if (!ValueIsValid(x)) return;

   if SOMETHING
   {
      value = 100;
   }
   else if >OMETHING ELSE
   {
      value = 200;
   }
   else
   {
      value = 0;
   }

   return value;
}

Somewhere in the program was a check that just did a “return” and the compiler was seeing that, but my eyes were looking at the lower portion of the program where a value was clearly being returned.

I am guessing the function originally did not return a value, and when a return value was added later, that initial “return;” was not corrected, leaving a compiler warning. This warning may have been in the code for a long time and was simply left alone because someone couldn’t figure it out (my situation) or wasn’t concerned about compiler warnings.

Today, the warning bugged me enough that I did a deep dive through the function, line-by-line, trying to figure out what was going on. And I found it. A simple correction could have been this:

int function(int x)
{
   int value;

   if (!ValueIsValid(x)) return 0; // FIXED: Add missing return value.

   if SOMETHING
   {
      value = 100;
   }
   else if SOMETHING ELSE
   {
      value = 200;
   }
   else
   {
      value = 0;
   }

   return value;
}

That resolved the compiler warning, but still left two spots where a value was returned, so I ended up doing something like this:

int function(int x)
{
   int value;

   if (ValueIsValid(x) == true) // do this if valid
   {
      if SOMETHING
      {
         value = 100;
      }
      else SOMETHING ELSE
      {
         value = 200;
      }
      else
      {
         value = 0;
      }
   }
   else // Not valid
   {
      value = 0;
   }

   return value;
}

Now there is only one place the function returns, and it only processeses things if the initial value appears valid.

I will sleep better at night.

I sleep on a soap box.

GEEKPI’s Getting Started with MicroPython on Raspberry Pi Pico kit

It seems only yesterday I first mentioned the new Raspberry Pi Pico. At this time of its introduction, I wondered two things:

  1. Why did they use the “Raspberry Pi” name for a new piece of hardware that does not run Linux. It was closer to an Arduino than a Pi. I expect this naming will cause confusion, since folks have had years learning what a “Pi” can do (video, audio, keyboard, mouse, etc.) and the Pico does none of that.
  2. Why did they bother with a $4 Pico, if a PiZero can be had for only $1 more.

#2 is answered with “because folks like me dislike the slowness of booting a full OS and all the hassles of dealing with Linux for an embedded project.” However, I already use Arduinos for that purpose. The Pico just seemed more like the larger Arduino models.

Side Note: To me, and many others, “Arduino” will always mean “Arduino Uno“, the tiny and cheap Arduino with 4K of RAM. Because it was the version that started things up, the name Arduino is mostly associated with these smaller limited models. But, Arduino even makes more powerful versions that can run Linux.

#1 I think is “just because it will cause confusion.” I think the same thing about the “new” Atari VCS. (If you didn’t know, there is a new Atari out — and it is called the same thing the original Atari VCS was called back in 1977. No confusion there. ;-)

But I digress…

I recently received a $45 GEEKPI BASIC Pico kit to review. You can find it on Amazon (see that link).

Reading through the specs of this $4 circuit board, I find it is pretty impressive. Speeds up to 133MHz, 264K of RAM, and 2MB of Flash storage. It has enough power, memory and storage to run things like Python, which a 4K Arduino just cannot do.

The included manual had me download a Python IDE, then plug up and connect to the Pico with a USB cable. I could then type and run my first “Hello World” program in Python. You can even copy the “main.py” python script to the Pico so it will power up and run on it’s own. (A few other steps were needed to install MicroPython on the Pico, but they were easy and only took a few minutes.)

Impressive.

The initial downside is that the Pico does not come with the header pins soldered on. I had to turn to a coworker to do this for me so I could plug it into the breadboard and hook up some wires for a blinking LED example.

I expect at some point (if not already) you will be able to buy a model with those pins already soldered on, much like you can do with a Pi Zero.

I do not know when I’ll have time to fully explore the “power of the Pico,” but it looks like it will be a fun time. It appears to be quite capable with I/O and protocols (SPI, I2C, UARTs, etc.).

More to come…