program-structure macros for PIC16 & 6502

Post here to teach people how to do something.

Moderators: Chuckt, Garth, bitfogav

Post Reply
Garth
I practically live here!
I practically live here!
Posts: 220
Joined: Wed Jan 16, 2013 1:17 pm
Contact:

program-structure macros for PIC16 & 6502

Post by Garth » Mon Feb 04, 2013 6:06 pm

I have an article on using macros to give program structures in 6502 assembly, with links to the assembly-language source code, and had been planning to do it with the PIC also. I finally have that done, with the MPASM source code here. It has enough in common with the 6502 stuff that I probably won't write a separate article for it though. As we were discussing it here, BitWise recommended using MPASM's #v(x) feature to make it easier to synthesize the needed stack in the assembler. I might still convert to that, but I had already started with my other method that I had used for the 6502 on the C32 assembler, and since my plate is awfully full and what I have does work, I might just leave it as is.

The goal of these macros of course is to get better control of code by making it much more clear what you're doing, and getting rid of the mass of labels and jumps that commonly constitute assembly code. The macros let you keep full control of every speck of code laid down by the assembler, but you don't have to keep looking at the internal details. In most cases there is absolutely zero penalty in program memory taken or in execution speed. You get the performance of assembly with a lot of the benefits of higher-level languages. Code becomes quicker to develop, more bug-free, and easier to maintain, meaning that it's easier to come back later and figure out what you did when you decide to add a feature or change something.

For an example, take this short piece of code from my I²C sample code, actual code I used on a PIC12CE673 which had no SSP (even though the I²C serial EEPROM was onboard, with CLK and SDA on bits 6 & 7 of the GPIO) so the I²C had to be bit-banged:

Code: Select all

RCV_I2C_BYTE:
        I2C_DATA_UP
        CLRF      EEPROM_DATA           ; Init EEPROM_DATA as 0.
        MOVLW     8
        MOVWF     LOOP_COUNT1
rib1:   I2C_DATA_UP
        I2C_CLK_UP
        CALL      RD_I2C_BIT
        I2C_CLK_DN
        DECFSZ    LOOP_COUNT1,F
        GOTO      rib1
        RETURN                          ; The ACK or NAK bit must be sent separately.
 ;----------------------------
[/size]
(Even there, you can see the use of macros, as for example I2C_DATA_UP is more clear than BSF GPIO,6 but assembles exactly the same thing.) The loop is to gather the 8 bits of data to read for one byte. If we do a FOR...NEXT loop with the macros, we get:

Code: Select all

RCV_I2C_BYTE:
        I2C_DATA_UP
        CLRF      EEPROM_DATA              ; Init EEPROM_DATA as 0.
        FOR LOOP_COUNT1, 8, DOWN_TO, 0
            I2C_DATA_UP
            I2C_CLK_UP
            CALL  RD_I2C_BIT
            I2C_CLK_DN
        NEXT      LOOP_COUNT1
        RETURN                             ; The ACK or NAK bit must be sent separately.
 ;----------------------------
[/size]
Looking at the .hex file output, you would have no way of telling which source code it came from, because the assembled code is exactly the same for the two versions. In BASIC you would probably have the FOR...NEXT count up instead of down, but here it's more efficient to count down and end at zero since it allows branching on the Z flag without doing another comparison first. This way it just assembles the DECFSZ LOOP_COUNT1,F and then the GOTO like the more-manual version above.

Here's an example of using an "IF...END_IF" (and as you can see, it's also in part of a larger CASE statement). This is part of a project I'm working on.

Code: Select all

           CASE_OF  4                         ; We were waiting for the low address byte to be shifted out to the flash memory.
               RAM_BANK  1                    ; Is that finished yet?  (Check buffer-full bit in SSP-status register.)
               IF_BIT  SSPSTAT, BF, IS_SET    ; If so,
                   RAM_BANK  0
                   CLRF  SSPBUF               ; send out a dummy byte in order to get the first data byte to read,
                   INCF  FLASH_RD_STATE,F     ; then increment the state.
               END_IF
           END_OF
[/size]
In this case, the serial-port shifting for the given hardware takes time, and there's too much to do to twiddle our thumbs, so I have kind of a multitasking system where every time a task is called up, it looks to see if there's anything it can or should do at the moment, and if not, lets the computer move on to do other necessary things while it's waiting. (Don't worry about it being left in RAM bank 1 if the buffer-full bit is not set. There's a RAM_BANK 0 instruction right after the END_CASE.)

As you get a lot of decision-making, branching, looping, and exceptions to unevetful straight-line code, the macros become more and more valuable. It's nice going a hundred lines or more without a single label, and being able to more easily see the structure and the conditions under which the program carries out various operations. See the article for more info.

Brad, I don't know if I'm posting this in the best place. If there's a more appropriate place, go ahead and move it.
Last edited by Garth on Tue May 06, 2014 7:28 am, edited 1 time in total.
http://WilsonMinesCo.com/ lots of 6502 resources

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Re: program-structure macros for PIC16 & 6502

Post by brad » Mon Feb 04, 2013 8:54 pm

Excellent write up - thanks for that Garth. This forum is probably the best fit for the content so I am happy to leave it here :)

Garth
I practically live here!
I practically live here!
Posts: 220
Joined: Wed Jan 16, 2013 1:17 pm
Contact:

Re: program-structure macros for PIC16 & 6502

Post by Garth » Thu May 16, 2013 10:35 am

I added more structure macros, plus some related accessory macros, on Sat, May 11, 2013.

Edit, 5/5/14: I added alternate versions of CASE_OF and END_OF to the PIC code. They save an instruction every time they can be used (although PIC16's new CASE_OF is still not as efficient as the 6502's old one.) See the notes at their source code for the frequent conditions under which they can be used in place of the original version.
Last edited by Garth on Tue May 06, 2014 7:39 am, edited 1 time in total.
http://WilsonMinesCo.com/ lots of 6502 resources

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Re: program-structure macros for PIC16 & 6502

Post by brad » Wed May 22, 2013 10:07 pm

Thanks for the update Garth, I had another good read through of your post :)

Garth
I practically live here!
I practically live here!
Posts: 220
Joined: Wed Jan 16, 2013 1:17 pm
Contact:

Re: program-structure macros for PIC16 & 6502

Post by Garth » Thu May 23, 2013 5:29 pm

Related: A request for requests

Implementing a stack in the assembler itself (which might run on a computer that's entirely separate from the one that the finished, assembled code will run on) is part of how to get there. This is shown in the article and accompanying .asm files, but it is assumed that the reader is already familiar with stacks and can, without much hand-holding, get the idea of how to use one in the assembler in order to modify my structure macros if necessary for their own assembler, or for making new structures.

However, 6502.org forum posts have indicated that a good primer on stacks is in order, so I plan to be working on that, albeit slowly (unless I reach another lull in my job). Note that it's "stacks" (plural), not just the page-1 hardware stack, but virtual stacks too. Actually "primer" might not be the best name, because although it will start with the definition and the very basics, it will work its way up gradually into more advanced stuff, including a more complete explanation of how stacks are used to assemble or compile nestable program structures, as you see near the bottom of the list below. (This particular info is in the program-structures pages too, but not explained as thoroughly as a separate treatise on stacks might explain it.) I have not found any such stacks primer on the web.

Here's what I tentatively have lined up to discuss:
  1. definition and very basics
  2. subroutine return addresses and nesting
  3. interrupts (plus link to the interrupts primer)
  4. virtual stacks and various ways to implement them
  5. stack addressing, both hardware and virtual
  6. passing parameters, and comparison of methods
  7. having a subroutine find inlined data, using the return address
  8. doing math and other operations by stacks in RPN
  9. RPN efficiency
  10. 65c02's added instructions that are useful in stack operations
  11. using RTS to synthesize other instructions
  12. where-am-I routines
  13. local variables
  14. saving environments
  15. recursion
  16. safety from running out of stack space
  17. a peek at the 65816's new instructions and capabilities that are relevant to stacks, and 65c02 code which partially synthesizes some of them
  18. compiling or assembling program structures
  19. measuring current stack depth, necessary for certain operations even if you know you won't run out of stack space
I don't plan to go any further than that except possibly to give an idea of how you can split up the stack space for multitasking or multithreading, with no real details, only enough to stir the imagination of someone who can envision how they might go further.

I'm open to anyone's ideas of what they would like to see covered. Do you have any pet peeves about how stacks are often defined, described, discussed, etc.? Is there something that is consistently poorly explained or misleading or misunderstood? Can you think of any good ideas that keep getting ignored? Anything special you would like to see in the primer? Any questions you're too embarrassed to ask publically? Email me at wilsonmineszdslextremezcom (replacing the z's with @ and .)

There are plenty of things that are simple to understand but might not have occurred to the beginning or mid-level 6502 programmer. It will be mostly 6502-oriented, but I will definitely give some reasons to be interested in the 65816. I have found however that going heavy on the '816 with someone who's not thoroughly familiar with the 6502 yet just gets the blank-stare reaction, followed by their running away.

My favorite thing is probably that the reader catches a concept quickly because it is clearly presented and it wasn't something that required a lot of study, but pointed out what simply didn't occur to them naturally. I had been programming in 6502 assembly for a long time before someone mentioned TSX LDA 103,X etc., and I understood it immediately but was amazed that there was something so useful and simple that I hadn't thought of yet. It would be great to be able to fill the primer with things like that.

[Edit, 10/2/15: It's up, at http://wilsonminesco.com/stacks/ ]
Last edited by Garth on Sat Oct 03, 2015 3:33 pm, edited 1 time in total.
http://WilsonMinesCo.com/ lots of 6502 resources

Chuckt
I practically live here!
I practically live here!
Posts: 1127
Joined: Sun Mar 28, 2010 1:36 pm

Re: program-structure macros for PIC16 & 6502

Post by Chuckt » Sat May 25, 2013 2:19 am

Garth wrote:For an example, take this short piece of code from my I²C sample code, actual code I used on a PIC12CE673 which had no SSP (even though the I²C serial EEPROM was onboard, with CLK and SDA on bits 6 & 7 of the GPIO) so the I²C had to be bit-banged:
I looked up the datasheet on the PIC12CE673 and then I started to understand how it could be used with what you are doing because I would want it on a PIC32 but then I understand that the PIC32 is 32 bit and the 6502 is 8 bit. I would have to research whether the PIC 32 has the same advantage of converting numbers as ARM chips have.

You might want to keep in mind that ARM might be a chip in the future that your project could be translated for:
"A 32-bit data location would store 4 bytes and that is twice as many as most numbers that are used in control applications. To overcome some of the code size issues, the Thumb instruction set was designed."

"This was a subset of the full instruction set and resulted in less code and data usage in application where the 32-bit number crunching was not needed. This opened engineers’ eyes to ARM and how the core could serve 8/16-bits applications as well as full 32-bit applications."
http://www.electronicsweekly.com/news/b ... m-2013-05/

I would have to look into the capability of the PIC 32 and other chips.

Your project is very interesting.

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Re: program-structure macros for PIC16 & 6502

Post by brad » Sat May 25, 2013 2:43 pm

Your write up's are certainly very high quality Garth and your level of programming knowledge is amazing. I have to admit, I would like to be at a higher level of knowledge with my programming than where I currently am. But I still have plenty of time to learn I guess :)

Garth
I practically live here!
I practically live here!
Posts: 220
Joined: Wed Jan 16, 2013 1:17 pm
Contact:

Re: program-structure macros for PIC16 & 6502

Post by Garth » Sat May 25, 2013 4:08 pm

I looked up the datasheet on the PIC12CE673 and then I started to understand how it could be used with what you are doing because I would want it on a PIC32 but then I understand that the PIC32 is 32 bit and the 6502 is 8 bit. I would have to research whether the PIC 32 has the same advantage of converting numbers as ARM chips have.

You might want to keep in mind that ARM might be a chip in the future that your project could be translated for:
The PIC12CE673 was used for the project years ago because it was a low-cost microcontroller in an 8-pin DIP that fit the need at the time. Today we would definitely not use an EPROM-based microcontroller (which the "C" in the part number means), but rather flash-based ones (which have an "F" in the number). Also, the last PIC project I did for a product (with a PIC16F72) had the synchronous serial port (SSP) in hardware, so bit-banging was not necessary. I suppose the designers figured it was not worth the silicon real estate to put the I²C in hardware for the PIC12CE673's user EEPROM that had only 16 bytes for storing custom defaults, or, in this case, how many times the product shut itself down due to a power fault), so it was bit-banged. No problem. We didn't need any speed anyway.

The microcontroller projects that I personally have done for commercial products would gain virtually no benefit by going to 16- or 32-bit-- not that those don't have their place (obviously they do), but there are some applications where you seldom need to handle more than 8 bits at a time. Interestingly, the 6502 regularly ran circles around the 32016 32-bit processor from National, and the 65816 with 16-bit registers and 8-bit data bus runs the Sieve of Isosthenes benchmark faster than the 68000, even though the 68000 has more and wider registers-- so more bits does not by itself automatically translate to more computing power. Obviously the ARM is infinitely favored over the 32016 or 68000 today though, and for good reason.

Dave Jones of EEV Blog went awfully hard on people still using assembly language in microcontrollers. I would have two arguments against his position, one being that he apparently is not familiar with the program-structure macros I'm promoting (program structures being largely why he advocates using C instead), and the other being that regardless of the performance of the microcontroller, sometimes you just need to know the exact amount of time it takes to get through certain instructions, and unless you really, really know the insides of your C compiler, you won't know what that timing is in C. I think C is an awfully ugly language anyway, for several reasons I could list, but that's a personal opinion so I probably can't legitimately argue about that any more than I can about favorite colors.

I use Forth for the workbench computer because the development time plummets and makes the software portion of a project almost trivial. I can of course go into assembly at any point, but I only do it for short pieces that need the greatest performance. My 65816 Forth is two to three times as fast as my 6502 Forth at a given clock speed, as the '816 can handle 16-bit quantities so much more efficiently. If I were really hurting for more computing power, I probably would look into ARM. When I started into the PIC16 (mid-1990's?), Microchip's high end was the PIC17 (no PIC18, 24, or 32 yet), and they were bragging about the PIC16's RISC performance; but as I began getting familiar with it, and translating their own programs from the seminar, I began to see that the 6502 could usually do the job in half as many instructions and half as many clocks as the PIC took to do the same thing with their Harvard architecture. I give some examples at http://forum.6502.org/viewtopic.php?f=1&t=784&start=5 . Take the "&start=5" off the end if you want to see the beginning of the topic. Admittedly it appears that Microchip has added some new instructions to some new PIC16's, and they don't have the PIC17 line anymore. Perhaps the old 17's are now called 16's and still have the added instructions of the old 17's.

In any case, the program-structure macro idea could be carried out for any processor one could wish for, as long as the assembler has the macro capability.

So no requests for things to clarify in a primer on stacks?
http://WilsonMinesCo.com/ lots of 6502 resources

Garth
I practically live here!
I practically live here!
Posts: 220
Joined: Wed Jan 16, 2013 1:17 pm
Contact:

Re: program-structure macros for PIC16 & 6502

Post by Garth » Wed Jan 20, 2016 6:44 pm

Garth wrote:However, 6502.org forum posts have indicated that a good primer on stacks is in order, so I plan to be working on that, albeit slowly (unless I reach another lull in my job). Note that it's "stacks" (plural), not just the page-1 hardware stack, but virtual stacks too. Actually "primer" might not be the best name, because although it will start with the definition and the very basics, it will work its way up gradually into more advanced stuff, including a more complete explanation of how stacks are used to assemble or compile nestable program structures, as you see near the bottom of the list below.
I came across this again now as I was looking for something else, and realized I should post an update. The stacks treatise is up, at http://wilsonminesco.com/stacks/index.html . Chapter 17 has further explanation on how to form the program structures using a stack in the assembler itself. Near the end, there's a nestable CASE structure example where you can mouse over individual lines and get a box that tells what the assembler is doing on that line.

Relating to the multitasking mentioned above, I have posted an article about simple methods for multitasking without a multitasking OS, for systems that lack the resources to implement a multitasking OS, or where hard realtime requirements would rule one out anyway, at http://wilsonminesco.com/multitask/ . In the last half of it, there are a few larger examples of the program structures in assembly language.

Finally, also related to something above, I have an article at http://wilsonminesco.com/AssyDefense/ called "Assembly Language: Still Relevant Today."
http://WilsonMinesCo.com/ lots of 6502 resources

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Re: program-structure macros for PIC16 & 6502

Post by brad » Sat Jan 23, 2016 7:15 am

Nice work again there Garth, I like the quote on your defence of assembly page "Assembly Language: Still Relevant Today
(No, it won't ever be dead.)"

Which is true isn't it - each cpu has its own instruction set which is the assembly listing!

Have you implemented your multitasking methods for anything you have designed with work?

Garth
I practically live here!
I practically live here!
Posts: 220
Joined: Wed Jan 16, 2013 1:17 pm
Contact:

Re: program-structure macros for PIC16 & 6502

Post by Garth » Sat Jan 23, 2016 8:18 am

brad wrote:Nice work again there Garth
Thankyou!
Have you implemented your multitasking methods for anything you have designed with work?
Yes. The company I work for makes high-end intercoms for private aircraft, and the first one I (as the designer) put a microprocessor in to monitor the constantly changing signals, control the many features, and interface to the control panels, was essentially multitasking, but rather poorly structured. Things slowly progressed in subsequent projects, but the multitasking and program structures both really came out strong in an unrelated quasi-medical device we did in 2014. It feels really good to get that degree of organization and clarity and control in the code, in assembly language where you can get performance way beyond what others thought possible given the hardware.

For a lesser degree on the multitasking scale, I have used the alarms on my HP-41cx calculator (shown in the article) since the late 1980's, and later, on my 65c02 workbench computer which I use as kind of a Swiss army knife of the workbench, for example to stop what it's doing and measure and print out a bunch of voltages every fifteen minutes and then go back to what it was doing before. There can be lots of different alarms pending for different tasks, each on its own schedule.
http://WilsonMinesCo.com/ lots of 6502 resources

User avatar
brad
Site Admin
Site Admin
Posts: 2576
Joined: Fri Mar 26, 2010 10:30 pm

Re: program-structure macros for PIC16 & 6502

Post by brad » Sun Jan 31, 2016 12:59 pm

Fantastic! Thanks for the extra info :) How great to be able to implement your own way of doing things when designing a product for your company. Especially when it is done without wasteful code.

Garth
I practically live here!
I practically live here!
Posts: 220
Joined: Wed Jan 16, 2013 1:17 pm
Contact:

Re: program-structure macros for PIC16 & 6502

Post by Garth » Sun Jan 31, 2016 1:34 pm

How great to be able to implement your own way of doing things when designing a product for your company.
Since 1985, I've been working for a couple of tiny companies where much of the time I was the only engineer, so I could do things pretty much however I wanted. I have had at least a couple of these experiences:
Dilbert1.jpg
Dilbert1.jpg (55.1 KiB) Viewed 7409 times
There are advantages to being the whole department, but it also means that if I can't figure something out, I'm stuck. I don't have problems with that in terms of math and using parts I already know, but I do have trouble if I have to use another company's part if the 200-page data sheet isn't clear on something. That happened a few years ago with a bluetooth module. The company thought they had made it really easy for those of us who have not devoted our last several years to bluetooth; yet if you want to do something they hadn't thought of, you're sunk. The applications engineers would say, "Oh, you just use this AT command to put it into mode <xyz>..." and I had to say, "I've been through the 200-page data sheet twice now and I still cannot find anything about mode <xyz> or whether I need it." They sent me sample code that supposedly would do what I wanted, but it didn't work and it became clear they had no concept of our application. I had to tell the boss I was giving up on it.

More recently I've been trying to get a Displaytech graphic LCD going on the SPI. It responds to a couple of commands but not to most, and Displaytech's technical customer support seems pretty worthless. Most questions on their forum go unanswered, and my own wouldn't even post even though I'm signed in, and they don't answer email either. I need to rattle their cage next week. [Edit: I got it going. I had one bit wrong in one of the set-up instructions. I have a demo video a few seconds long at http://wilsonminesco.com/6502primer/Dis ... 8Ademo.mp4 where I just use a random number generator to get endpoints of segments, then connects the ends of each with a straight line, and refresh the display every 25 random segments.]
http://WilsonMinesCo.com/ lots of 6502 resources

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest