6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue Jun 04, 2024 10:13 am

All times are UTC




Post new topic Reply to topic  [ 52 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
PostPosted: Mon Jul 27, 2015 7:46 am 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 485
Location: Switzerland
Here the result of my "investigations". As proposed by bogax only IRQ is used for the data input, A is intialised with 1 to get the carry as the done status for a byte and NMI starts the bootloader. And as I suggested I use an additional input (I call it A5 although it is not connected to the address A5 but to the data input). That selects one of two code options for the IRQ routine (one using SEC and one using CLC). The code itself is position independent so it does not matter that I use $FFC0 as the first starting address for the first incarnation (a macro would do the job much nicer in case you need to change the code, but I was lazy). You need to duplicate the vectors, to make sure they are the same regardless of the state of A5 (data). And also it saves product terms.

Code:
BOOTLOADER = $00


   *=$FFC0
RESETROUTINE0
   LDX #$00   ; Init byte storing index
   LDA #$01   ; Init bit counting
   BNE   *

IRQROUTINE0   
   CLC   
   ROL   
   BCC FINISH
   STA BOOTLOADER, X   ; Finish one byte of transfer 
   INX   
FINISH0
   RTI
   *=$FFDA
   
   .word BOOTLOADER
   .word RESETROUTINE
   .word IRQROUTINE

   *=$FFE0
RESETROUTINE
   LDX #$00   ; Init byte storing index
   LDA #$01   ; Init bit counting
   BNE   *

IRQROUTINE   
   SEC   
   ROL   
   BCC FINISH
   STA BOOTLOADER, X   ; Finish one byte of transfer 
   INX   
FINISH
   RTI
     
   *=$FFFA
   
   .word BOOTLOADER
   .word RESETROUTINE
   .word IRQROUTINE
   


I use 64TASS to assemble the code and use hexdump to convert it to the table I then use in WinCUPL
Code:
64tass -c -b bootloader.asm -o bootloader.bin
hexdump -e '"[%02.2_ax] => "' -e '1/1 "<h<%02X;" "\n"' -v  bootloader.bin


If someone could tell me the trick to produce ' instead of using the < and then change them all in the editor I would appreciate. But that's only a minor production step. Then I take this output and create the following PLD for WinCUPL

Code:
Name     bootloader ;
PartNo   00 ;
Date     26.07.2015 ;
Revision 01 ;
Designer cbscpe ;
Company  none;
Assembly None ;
Location  ;
Device   g16v8;

/* *************** INPUT PINS *********************/
PIN   2  =  A0                     ; /*                                 */
PIN   3  =  A1                     ; /*                                 */
PIN   4  =  A2                     ; /*                                 */
PIN   5  =  A3                     ; /*                                 */
PIN   6  =  A4                     ; /*                                 */
PIN   7  =  A5                     ; /*                                 */
PIN  11  = !OE                     ; /*                                 */

/* *************** OUTPUT PINS *********************/
PIN   12  =  D0                     ; /*                                 */
PIN   13  =  D1                     ; /*                                 */
PIN   14  =  D2                     ; /*                                 */
PIN   15  =  D3                     ; /*                                 */
PIN   16  =  D4                     ; /*                                 */
PIN   17  =  D5                     ; /*                                 */
PIN   18  =  D6                     ; /*                                 */
PIN   19  =  D7                     ; /*                                 */


FIELD   ADDR = [A5..0];
FIELD DATA = [D7..0];

[D7..0].oe = OE;

TABLE ADDR => DATA {
[00] => 'h'A2;
[01] => 'h'00;
[02] => 'h'A9;
[03] => 'h'01;
[04] => 'h'D0;
[05] => 'h'FE;
[06] => 'h'18;
[07] => 'h'2A;
[08] => 'h'90;
[09] => 'h'23;
[0a] => 'h'95;
[0b] => 'h'00;
[0c] => 'h'E8;
[0d] => 'h'40;
[0e] => 'h'00;
[0f] => 'h'00;
[10] => 'h'00;
[11] => 'h'00;
[12] => 'h'00;
[13] => 'h'00;
[14] => 'h'00;
[15] => 'h'00;
[16] => 'h'00;
[17] => 'h'00;
[18] => 'h'00;
[19] => 'h'00;
[1a] => 'h'00;
[1b] => 'h'00;
[1c] => 'h'E0;
[1d] => 'h'FF;
[1e] => 'h'E6;
[1f] => 'h'FF;
[20] => 'h'A2;
[21] => 'h'00;
[22] => 'h'A9;
[23] => 'h'01;
[24] => 'h'D0;
[25] => 'h'FE;
[26] => 'h'38;
[27] => 'h'2A;
[28] => 'h'90;
[29] => 'h'03;
[2a] => 'h'95;
[2b] => 'h'00;
[2c] => 'h'E8;
[2d] => 'h'40;
[2e] => 'h'00;
[2f] => 'h'00;
[30] => 'h'00;
[31] => 'h'00;
[32] => 'h'00;
[33] => 'h'00;
[34] => 'h'00;
[35] => 'h'00;
[36] => 'h'00;
[37] => 'h'00;
[38] => 'h'00;
[39] => 'h'00;
[3a] => 'h'00;
[3b] => 'h'00;
[3c] => 'h'E0;
[3d] => 'h'FF;
[3e] => 'h'E6;
[3f] => 'h'FF;
}



This is successfully converted to a JED file. Assuming no WinCUPL bug that's it. You can consult the DOC file to see the resulting equations. In other words, yes you can use a GAL as a bootstrap PROM and a GAL16V8 does the job. And as I don't need the SO this will work using either a 6502 or a W65C816. One could even try to use a different bootloader address, there is room enough for another byte for the STA absolute,X instruction and by carefully select the address only a few additional PTs will be used.

Cheers

Peter


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 27, 2015 7:50 am 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 485
Location: Switzerland
Oh I found a minor error (a macro would have avoided that). The first BCC must go to FINISH0 else we end at nomansland in zeropage. It's even worse as it wasted an additional PT of the GAL.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 27, 2015 1:53 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 485
Location: Switzerland
And another bug (you never find the last but only the second last bug), I need to init A again in the IRQ after a byte has been received.

Code:
;
;   Special Bootloader that fits into a GAL16V8.
;
;   Assemble
;      ~/sbc65xxx/64tass/64tass -c -b bootloader.asm -L bootloader.lst -o bootloader.bin
;
;   Convert to table for WinCUPL
;      hexdump -e '"[%02.2_ax] => "' -e '1/1 "%02X;" "\n"' -v  bootloader.bin
;

BOOTLOADER   =   $8000

   *   =   $FFC0
RESETROUTINE0
   LDX      #$00         ; Init byte storing index
   LDA      #$01         ; Init bit counting
   BNE      *

IRQROUTINE0   
   CLC   
   ROL   
   BCC      FINISH0
   STA      BOOTLOADER, X   ; Finish one byte of transfer 
   INX
   LDA      #1
FINISH0
   RTI
   *   =   $FFDA
   
   .word   BOOTLOADER
   .word   RESETROUTINE
   .word   IRQROUTINE

   *   =   $FFE0
RESETROUTINE
   LDX      #$00         ; Init byte storing index
   LDA      #$01         ; Init bit counting
   BNE      *

IRQROUTINE   
   SEC   
   ROL   
   BCC      FINISH
   STA      BOOTLOADER, X   ; Finish one byte of transfer 
   INX   
   LDA      #1
FINISH
   RTI
     
   *   =   $FFFA
   
   .word   BOOTLOADER
   .word   RESETROUTINE
   .word   IRQROUTINE
   


And this changes of course the table in the PLD a little bit

Code:
Name     bootloader ;
PartNo   00 ;
Date     26.07.2015 ;
Revision 01 ;
Designer csbcpe ;
Company  company;
Assembly None ;
Location  ;
Device   g16v8;

/* *************** INPUT PINS *********************/
PIN   2  =  A0                     ; /*                                 */
PIN   3  =  A1                     ; /*                                 */
PIN   4  =  A2                     ; /*                                 */
PIN   5  =  A3                     ; /*                                 */
PIN   6  =  A4                     ; /*                                 */
PIN   7  =  A5                     ; /*                                 */
PIN  11  = !OE                     ; /*                                 */

/* *************** OUTPUT PINS *********************/
PIN   12  =  D0                     ; /*                                 */
PIN   13  =  D1                     ; /*                                 */
PIN   14  =  D2                     ; /*                                 */
PIN   15  =  D3                     ; /*                                 */
PIN   16  =  D4                     ; /*                                 */
PIN   17  =  D5                     ; /*                                 */
PIN   18  =  D6                     ; /*                                 */
PIN   19  =  D7                     ; /*                                 */


FIELD   ADDR = [A5..0];
FIELD DATA = [D7..0];

[D7..0].oe = OE;

TABLE ADDR => DATA {
[00] => A2;
[01] => 00;
[02] => A9;
[03] => 01;
[04] => D0;
[05] => FE;
[06] => 18;
[07] => 2A;
[08] => 90;
[09] => 06;
[0a] => 9D;
[0b] => 00;
[0c] => 80;
[0d] => E8;
[0e] => A9;
[0f] => 01;
[10] => 40;
[11] => 00;
[12] => 00;
[13] => 00;
[14] => 00;
[15] => 00;
[16] => 00;
[17] => 00;
[18] => 00;
[19] => 00;
[1a] => 00;
[1b] => 80;
[1c] => E0;
[1d] => FF;
[1e] => E6;
[1f] => FF;
[20] => A2;
[21] => 00;
[22] => A9;
[23] => 01;
[24] => D0;
[25] => FE;
[26] => 38;
[27] => 2A;
[28] => 90;
[29] => 06;
[2a] => 9D;
[2b] => 00;
[2c] => 80;
[2d] => E8;
[2e] => A9;
[2f] => 01;
[30] => 40;
[31] => 00;
[32] => 00;
[33] => 00;
[34] => 00;
[35] => 00;
[36] => 00;
[37] => 00;
[38] => 00;
[39] => 00;
[3a] => 00;
[3b] => 80;
[3c] => E0;
[3d] => FF;
[3e] => E6;
[3f] => FF;

}



Also just found out that HEX is the default in WinCUPL so I don't need the 'h' prefix. In any case the design still fits, now one output requires 6 PTs, so still one left for a further bug.

Cheers

Peter


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 27, 2015 2:01 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
@cbscpe : What does BNE * does? I'm not familiar with that syntax.. Is it just a placeholder for page wrapping branch?


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 27, 2015 3:14 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 485
Location: Switzerland
* is place holder for the program counter in this assembler. In other words

Code:
      BNE    *


is the same as

Code:
HERE    BNE    HERE


It's just the eternal loop of the main program.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 27, 2015 7:55 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
I just missed the point that single NMI invocation actually was somewhat jump to the loaded bootloader. Now it makes sense.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jul 27, 2015 11:58 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3363
Location: Ontario, Canada
cbscpe wrote:
an additional input [...] selects one of two code options for the IRQ routine (one using SEC and one using CLC).
I like this bit especially. The "memory" changes its apparent contents, from SEC to CLC, according to a signal from an external source. This eliminates any need for the program to test that signal in the usual fashion. The program outcome is implicitly modified by the SEC or CLC. Nice work on that (and the WinCUPL), Peter!

It's not a technique limited to GALs. The latter part of this post (after "Slightly OT") describes an EPROM that changes its apparent contents according to a signal from an external source.

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 29, 2015 12:06 am 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
@cbscpe : You don't clear interrupt flag at the beginning of the code. IRQs will be inhibited that way.

Here is my take to the stuff. I didn't want to introduce another input to the GAL as I would be using S.O. anyway for a little bit of speed.

Here is my code, S.O. signals end of each byte, IRQ and NMI stores 1 and 0 into accumulator respectively. I also manually modified PLD source for WinCUPL to optimize it. The issue is, I didn't get the expected result out of it. I don't have 65c02 so single stepping is a big no. I used the trick previously I used to test rom & ram access. I only have 32k ram, ROM decodes to $E000-$FFFF, Ram decodes to $0000-$7FFF. I have a 3 to 8 decoder so I use additional decoding signals to interrupt arduino. $8000-$9FFF -> Int 0, $A000-$BFFF -> Int 1. I do access these locations to transmit information to arduino. This previously worked well and what I used to test my apartment style boards for errors.

Can you spot any apparent error in below setup?

Contents of boot loader (6502Bootloaderx.65s)
Code:
BOOTLOADER = $00


   *=$FFE0
   .BYTE 0, 0, 0, 0, 0, 0, 0, 0 ; Will be replaced by Do not care bytes.
RESETROUTINE
   LDX #$00   ; Init byte storing index
   CLI      ; Enable Interrupts
   SEC      ; Set Carry for IRQ (IRQ pulls from stack)
NEXT
   CLV
   BVC *
   STA BOOTLOADER,X
   INX
   BNE NEXT
   JMP BOOTLOADER
      
NMIROUTINE   
   ASL
   RTI
   
IRQROUTINE   
   ROL
   RTI   
            
   *=$FFFA
   
   .WORD NMIROUTINE
   .WORD RESETROUTINE
   .WORD IRQROUTINE   
   


PLD code (Data pins reversed as I created a board out of this and aligned Data pins to 6502 data bus locations)

Code:
Name     bootloader ;
PartNo   00 ;
Date     27.07.2015 ;
Revision 01 ;
Designer i_r_on ;
Company  none;
Assembly None ;
Location  ;
Device   g16v8;

/* *************** INPUT PINS *********************/
PIN   2  =  A0                     ; /*                                 */
PIN   3  =  A1                     ; /*                                 */
PIN   4  =  A2                     ; /*                                 */
PIN   5  =  A3                     ; /*                                 */
PIN   6  =  A4                     ; /*                                 */
PIN  11  = !OE                     ; /*                                 */

/* *************** OUTPUT PINS *********************/
PIN   12  =  D7                     ; /*                                 */
PIN   13  =  D6                     ; /*                                 */
PIN   14  =  D5                     ; /*                                 */
PIN   15  =  D4                     ; /*                                 */
PIN   16  =  D3                     ; /*                                 */
PIN   17  =  D2                     ; /*                                 */
PIN   18  =  D1                     ; /*                                 */
PIN   19  =  D0                     ; /*                                 */

FIELD   ADDR = [A4..0];
FIELD DATA = [D7..0];

[D7..0].oe = OE;

TABLE ADDR => DATA {
[00] => 'h'xx;
[01] => 'h'xx;
[02] => 'h'xx;
[03] => 'h'xx;
[04] => 'h'xx;
[05] => 'h'xx;
[06] => 'h'xx;
[07] => 'h'xx;
[08] => 'h'a2;
[09] => 'h'00;
[0a] => 'h'58;
[0b] => 'h'38;
[0c] => 'h'b8;
[0d] => 'h'50;
[0e] => 'h'fe;
[0f] => 'h'95;
[10] => 'h'00;
[11] => 'h'e8;
[12] => 'h'd0;
[13] => 'h'f8;
[14] => 'h'4c;
[15] => 'h'0x;
[16] => 'h'00;
[17] => 'h'0a;
[18] => 'h'40;
[19] => 'h'2a;
[1a] => 'b'xxx10111;
[1b] => 'b'11xxxxxx;
[1c] => 'h'xxx01000;
[1d] => 'b'11xxxxxx;
[1e] => 'h'xxx11001;
[1f] => 'b'11xxxxxx;
}



Second stage loader of the test routine (2ndBootloader.65s)

Code:
PAYLOADADDRESS = $7000
   *=$0000
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   NOP
   SEI
   CLV
   CLD
   LDX #$FF
   TXS   
   CLI
   INX
NEXT   
   LDA PAYLOAD,X
   STA PAYLOADADDRESS,X
   INX
   BNE NEXT
   JMP PAYLOADADDRESS

   *=$002F
   .BYTE 0
PAYLOAD   
   ;Actual Payload will be appended here...
   ;Above code copies payload to PAYLOADADDRESS and controls
   ;transfer there.



Actual test routine (MainPayload.65s)
Code:
   *=$7000   

                   
;TEST STACK ACCESS
   LDA #$99
   PHA
   LDA #$00
   PLA
   CMP #$99
   BNE FAIL
   JSR SENDBYTE ; Send $99 as a success status for stack test
   JMP ZEROPAGETEST
FAIL
   LDA #$CC
   JSR SENDBYTE

ZEROPAGETEST
   LDX #00
   ; Write $77 through $00 to $FF
   LDA #$77
NEXTLOC   
   STA $00, X
   INX
   BNE NEXTLOC
   ; Try to read $77 through $00 to $FF   
   LDA #$00
   LDX #$00
NEXTLOCREAD
   LDA $00, X
   CMP #$77
   BNE FAILZEROPAGE
   INX
   BNE NEXTLOCREAD
   
   ; Zero page test success
   LDA #$99
   JSR SENDBYTE
   JMP MEMTEST
   ; Zero page test fail
FAILZEROPAGE
   LDA #$CC
   JSR SENDBYTE

MEMTEST
   LDY #$00
   LDA #$00
   STA $FB
   LDA #$7F
   STA $FC
NEXTPAGE
   LDA #$01
INCURPAGE
   STA ($FB), Y
   CLC   
   ADC #$01
   INY
   BNE INCURPAGE
   DEC $FC
   BNE NEXTPAGE

; Read to test
   LDY #$00
   LDA #$00
   STA $FB
   LDA #$7F
   STA $FC
NEXTPAGEREAD
   LDA #$01
INCURPAGEREAD
   CMP ($FB), Y   
   BNE MEMTESTFAIL
   CLC
   ADC #$01
   INY
   BNE INCURPAGEREAD
   DEC $FC
   BNE NEXTPAGEREAD

   LDA #$99
   JSR SENDBYTE
   JMP ENDLESS   
MEMTESTFAIL
   LDA #$CC
   JSR SENDBYTE
   CLV
ENDLESS   
   BVC ENDLESS


SENDBYTE
NEXT
   LDY #$08   
SINGLEBITSEND
   LDX #$40
CONSUMETIME
   DEX
   BNE CONSUMETIME
   ROL
   BCS ONE
   STA $8000   
   JMP NEXTBIT   
ONE
   STA $A000
NEXTBIT
   DEY
   BNE SINGLEBITSEND   
   RTS



So I compile all of this to create under 256 bytes code like this,

Code:
64tass -c -b 6502BootLoader3.65s -o 6502BootLoader3.65s.bin
64tass -c -b 2ndbootloader.65s -o 2ndbootloader.65s.bin
64tass -c -b MainPayload.65s -o MainPayload.65s.bin
copy 2ndBootloader.65s.bin + MainPayload.65s.bin Bootloader.bin /b
bin2h  -cz bootloader <Bootloader.bin > Bootloader.h


And here is relevant part of my arduino code,
Code:
void TransmitByteSpecial(unsigned char val) {   
    unsigned char mask = 0x80;
       
    for (int i = 0; i<8; i++) {
        if (val & mask) {
            //Transmit 1
            digitalWrite(IRQ, LOW);
            delayMicroseconds(5); //Wait 5 micro seconds for interrupt to trigger (approx. 5 cycles)
            digitalWrite(IRQ, HIGH);
            delayMicroseconds(40);  //Wait 40 micro seconds for interrupt to finish it's job (approx. 40 cycles)

        } else {
            //Transmit 0
            digitalWrite(NMI, LOW);
            delayMicroseconds(5); //Wait 5 micro seconds for interrupt to trigger (approx. 5 cycles)
            digitalWrite(NMI, HIGH);
            delayMicroseconds(40);  //Wait 40 micro seconds for interrupt to finish it's job (approx. 40 cycles)

        }
        mask = mask>>1;
    }
   
    //  [Interrupt enclosure end(wait before byte storage)]
    digitalWrite(SO, LOW);
    delayMicroseconds(5); //Wait LOOP BVC  LOOP on 6502 side
    digitalWrite(SO, HIGH);     
    delayMicroseconds(100);
}

void LoaderTest2() {
    delay(1000);   
    attachInterrupt(0, serialInputZero ,FALLING);     
    attachInterrupt(1, serialInputOne  ,FALLING);     
    delay(1000);
    Reset6502();   
    delay(250);   
    for (int i = 0;i<256;i++) {
      if (i<bootloader_size) {
        TransmitByteSpecial(bootloader[i]);
      } else {
        TransmitByteSpecial(0);
      }
    }
   
    delay(5000);
    Serial.println();
    Serial.println(F("Test is dones, detaching interrupts!"));           
    detachInterrupt(0);     
    detachInterrupt(1);         
}





Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 29, 2015 8:43 am 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 485
Location: Switzerland
Hi i_r_on

thanks for spotting the missing CLI. Fortunately this still fits in the design of the GAL. I will however stick with my solution, as I don't have a 6502 but only a 65C816 which has no SO. In any case, I went over your code and I think this will work.

You say you did not get the expected result, what was the issue? Looking at the many don't cares you have added I assume you had excess number of product terms for some bits. Good trick.

I have one suggestion for your newest solution, why do you still stick to the three phase bootstrap? Now as you have some bytes left you could place BOOTLOADER wherever you want. So you do not have to move the code around. I tried with BOOTLOADER = $7000 and it still fits into the design (although all 7 PTs of D3, D4, D5 and D6 are used).

Cheers

Peter


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 29, 2015 9:21 am 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
@cbspe : I guess I found my problem. I overuse don't care bits I think.
Code:
[1a] => 'b'xxx10111;  /* fits into A0-A7 so it's ok for A7, A6 and A5 to have any value */
[1b] => 'b'11xxxxxx;  /* I decode CS for ROM as $E000-$FFFF. I should have written : 'b'111xxxxx' */


Actually for second stage loader thing I thought it like you but getting PLD code to compile successfully was a bit of trial and error. I just postponed using a bigger payload loader.

If it fails compiling, how do you see which other PTs are used the least?


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 29, 2015 10:30 am 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 485
Location: Switzerland
H i_r_on,

in the .doc file created by WinCUPL you see at the bottom a summary of the PTs used, here I only show a extract of it. Have a look at it it is very informative

Code:
===============================================================================
                                 Symbol Table
===============================================================================

Pin Variable                                    Pterms   Max     Min   
Pol   Name              Ext     Pin     Type     Used   Pterms  Level   
--- --------            ---     ---     ----    ------  ------  -----   

    A0                          2        V        -       -       -     
    A1                          3        V        -       -       -     
    A2                          4        V        -       -       -     
    A3                          5        V        -       -       -     
    A4                          6        V        -       -       -     
    A5                          7        V        -       -       -     
    ADDR                        0        F        -       -       -     
    D0                          12       V        4       7       2     
    D0                  oe      12       X        1       1       1     
    D1                          13       V        4       7       2     
    D1                  oe      13       X        1       1       1     
    D2                          14       V        3       7       2     
    D2                  oe      14       X        1       1       1     
    D3                          15       V        7       7       2     
    D3                  oe      15       X        1       1       1     
    D4                          16       V        7       7       2     
    D4                  oe      16       X        1       1       1     
    D5                          17       V        7       7       2     
    D5                  oe      17       X        1       1       1     
    D6                          18       V        7       7       2     
    D6                  oe      18       X        1       1       1     
    D7                          19       V        5       7       2     
    D7                  oe      19       X        1       1       1     
    DATA                        0        F        -       -       -     
 !  OE                          11       V        -       -       -     


LEGEND    D : default variable         F : field      G : group
          I : intermediate variable    N : node       M : extended node
          U : undefined                V : variable   X : extended variable
          T : function



You actually see also the created equations and more useful stuff. As you see there are in fact 8 PTs per OLMC, but as we need one for the /OE this leaves only 7 PTs for the logic. Please be aware that between compile runs of WinCUPL the .doc file is not updated in the editor should have it open. You need to close and re-open it to see the results of the latest run. Just close it and open it by double-clicking on the .doc file in the navigator window at the right hand of the screen. Also you can observe the usage by shifting using different start addresses for the various routines. So you can switch the order of the RESET, NMI and IRQ routine and you could also check if placing dummy bytes in between helps reducing the number of PTs used.

I would be interested if you manage to put a bootloader into the GAL that allows more than 256bytes. Perhaps using STA (PTR),Y.


Cheers

Peter


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 29, 2015 11:51 am 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 485
Location: Switzerland
Hi i_r_on

if you want to analyze the usage of PTs you can replace the device "g16v8" with "virtual". This will create a DOC file with all equations regardless how many PTs would be used. Of course no JED is created. But to find what needs to be optimized this is the easiest way to find which outputs would require more than the available 7 PTs.

Peter


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 29, 2015 1:42 pm 
Offline

Joined: Mon Jul 20, 2015 6:34 pm
Posts: 62
cbscpe wrote:
I would be interested if you manage to put a bootloader into the GAL that allows more than 256bytes. Perhaps using STA (PTR),Y.
Cheers

Peter


Yes that would be possible using Y indirect indexed addressing. I'll see if I can optimize it further with that virtual device option. But it would be very difficult I guess with 16v8.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 29, 2015 2:59 pm 
Offline
User avatar

Joined: Sun Oct 13, 2013 2:58 pm
Posts: 485
Location: Switzerland
Hi i_r_on,

using my approach, with one bit modifying the instruction and using the NMI to jump to the loaded ROM the following code fits in 32 bytes and the resulting design fits into a GAL16V8.

Code:
;
;   Special Bootloader that fits into a GAL16V8.
;
;   Assemble
;      ~/sbc65xxx/64tass/64tass -c -b bootloaderv3.asm -L bootloaderv3.lst -o bootloaderv3.bin
;
;   Convert to table for WinCUPL
;      hexdump -e '"[%02.2_ax] => "' -e '1/1 "%02X;" "\n"' -v  bootloaderv3.bin
;

BOOTLOADER   =   $7000
PTR         =   $0

   *   =   $FFC0
   
RESETROUTINE0
   LDY      #0                  ; Init Index Register
   STY      PTR                  ; Set low byte of pionter
   LDA      #>BOOTLOADER         ; Get High byte of ROM
   STA      PTR+1               ; Set high byte of pointer
   LDA      #1                  ; Init Akku
   CLI                        ; Enable Interrupts
   BNE      *                  ; And wait forever

IRQROUTINE0   
   ASL                        ; Two incarnation this is 0 bit
   BCC      FIN0               ; Not yet done a byte
   STA      (PTR), Y            ; Store byte
   LDA      #1                  ; Init Akku
   INY                        ; Next Index
   BNE      FIN0               ; No overflow
   INC      PTR+1               ; Increment high byte of pointer
FIN0                        ; do no overflow check (no space)
   RTI                        ; Done

   *   =   $FFDA

   .word   BOOTLOADER   
   .word   RESETROUTINE
   .word   IRQROUTINE
;
;
;
   *   =   $FFE0
RESETROUTINE
   LDY      #0                  ; Init Index Register
   STY      PTR                  ; Set low byte of pionter
   LDA      #>BOOTLOADER         ; Get High byte of ROM
   STA      PTR+1               ; Set high byte of pointer
   LDA      #1                  ; Init Akku
   CLI                        ; Enable Interrupts
   BNE      *                  ; And wait forever

IRQROUTINE 
   ROL                        ; Two incarnation this is 0 bit
   BCC      FIN                ; Not yet done a byte
   STA      (PTR), Y            ; Store byte
   LDA      #1                  ; Init Akku
   INY                        ; Next Index
   BNE      FIN                ; No overflow
   INC      PTR+1               ; Increment high byte of pointer
FIN                         ; do no overflow check (no space)
   RTI                        ; Done
   *   =   $FFFA
   
   .word   BOOTLOADER
   .word   RESETROUTINE
   .word   IRQROUTINE


It's really a tight fit. But now I start to ask myself what happens after the image has been loaded and executed and an interrupt occurs. If I understand your design correct $E000..$FFFF always is the ROM which is the GAL. Or do you have some other mechanism? I would have added another GAL as an address decoder and a 128kbyte RAM instead of a 32kbyte RAM. I would also add a BOOT output to the arduino that changes the decoder. If the bit is set, reads always enable the GAL and writes enable always the RAM. If the bit is cleared the GAL is disabled and except for the IO range the RAM is enabled, optionally write-protect the upper part. Once you clear the bit another reset would then use the reset vector in the program image loaded into the RAM.

Peter


Top
 Profile  
Reply with quote  
PostPosted: Wed Jul 29, 2015 5:33 pm 
Offline

Joined: Thu Mar 03, 2011 5:56 pm
Posts: 278
cbscpe wrote:
Hi i_r_on,

using my approach, with one bit modifying the instruction and using the NMI to jump to the loaded ROM the following code fits in 32 bytes and the resulting design fits into a GAL16V8.

Code:
;
;   Special Bootloader that fits into a GAL16V8.
;
;   Assemble
;      ~/sbc65xxx/64tass/64tass -c -b bootloaderv3.asm -L bootloaderv3.lst -o bootloaderv3.bin
;
;   Convert to table for WinCUPL
;      hexdump -e '"[%02.2_ax] => "' -e '1/1 "%02X;" "\n"' -v  bootloaderv3.bin
;

BOOTLOADER   =   $7000
PTR         =   $0

   *   =   $FFC0
   
RESETROUTINE0
   LDY      #0                  ; Init Index Register
   STY      PTR                  ; Set low byte of pionter
   LDA      #>BOOTLOADER         ; Get High byte of ROM
   STA      PTR+1               ; Set high byte of pointer
   LDA      #1                  ; Init Akku
   CLI                        ; Enable Interrupts
   BNE      *                  ; And wait forever

IRQROUTINE0   
   ASL                        ; Two incarnation this is 0 bit
   BCC      FIN0               ; Not yet done a byte
   STA      (PTR), Y            ; Store byte
   LDA      #1                  ; Init Akku
   INY                        ; Next Index
   BNE      FIN0               ; No overflow
   INC      PTR+1               ; Increment high byte of pointer
FIN0                        ; do no overflow check (no space)
   RTI                        ; Done

   *   =   $FFDA

   .word   BOOTLOADER   
   .word   RESETROUTINE
   .word   IRQROUTINE
;
;
;
   *   =   $FFE0
RESETROUTINE
   LDY      #0                  ; Init Index Register
   STY      PTR                  ; Set low byte of pionter
   LDA      #>BOOTLOADER         ; Get High byte of ROM
   STA      PTR+1               ; Set high byte of pointer
   LDA      #1                  ; Init Akku
   CLI                        ; Enable Interrupts
   BNE      *                  ; And wait forever

IRQROUTINE 
   ROL                        ; Two incarnation this is 0 bit
   BCC      FIN                ; Not yet done a byte
   STA      (PTR), Y            ; Store byte
   LDA      #1                  ; Init Akku
   INY                        ; Next Index
   BNE      FIN                ; No overflow
   INC      PTR+1               ; Increment high byte of pointer
FIN                         ; do no overflow check (no space)
   RTI                        ; Done
   *   =   $FFFA
   
   .word   BOOTLOADER
   .word   RESETROUTINE
   .word   IRQROUTINE


It's really a tight fit. But now I start to ask myself what happens after the image has been loaded and executed and an interrupt occurs. If I understand your design correct $E000..$FFFF always is the ROM which is the GAL. Or do you have some other mechanism? I would have added another GAL as an address decoder and a 128kbyte RAM instead of a 32kbyte RAM. I would also add a BOOT output to the arduino that changes the decoder. If the bit is set, reads always enable the GAL and writes enable always the RAM. If the bit is cleared the GAL is disabled and except for the IO range the RAM is enabled, optionally write-protect the upper part. Once you clear the bit another reset would then use the reset vector in the program image loaded into the RAM.

Peter


If I have read the instruction tables right, there is only a single bit difference between the opcode for ASL and ROL (and also between CLC and SEC that you used in an earlier version). Would it be possible to have the input bit that chose between the two instruction sequences instead specify the single bit that differs between the two instructions (and thus between the two instruction sequences)?

Not sure if this makes for less resource usage in the PAL, though: you still have the same number of inputs, and the same number of output patterns.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 52 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 16 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: