Do you see any areas of improvement here?

Go To Last Post
83 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I finally got some code written for this last night.  I'm messing around with the idea of making a processor trainer emulator like they had in the 1970's like the SDK-85.  It is going to be all all through hole project, so I'm going to use the ATMEGA1284 which has 16K SRAM.  Hopefully 15K of this will be available for emulation.  Probably will have emulation for the 8080 and 8085, but also the Z80 if I can ever figure out its crazy opcode table.

 

It is going to also drive 6 seven segment displays and process a 4 row 6 column matrix keypad.  I'm not going to put in diodes for the keypad, so because of ghosting and masking, I'm not going to process 3 or more keys being pressed at the same time.  That still leaves 1 or 2 keys pressed at a time and I want it to handle very fast key typing so it will tolerate one key still pressed and another added before the original key is released.  So you could press 0, then 1, then release 0, then 2, and it would type 012,  I'm taking a two layered approach to this so the ISR will do what the ISR must do and a main loop function will process the 24 bit bitmap of key presses into actual keys later.  Basically the ISR feeds one buffer and then the processinput() function in the main loop processes that buffer into a different buffer containing the processed keys.  The ISR runs at 600 Hz to give me 6 displays at 100 Hz, and it debounces keys for 30ms (10ms * 3).  It also uses a second timer to turn off the display early if the user doesn't want full brightness.

 

I've tried the keyboard bitmap with a __uint24 as well, and in some areas it does well, but in other areas it doesn't, so I'm back to using 3 uint8_t's to hold the 24 bits for the 24 keys.

 

Any thoughts on what I can improve to reduce cycle count in this ISR?

 

#define INPUT_BUFFER_SIZE 32
#define KEY_BUFFER_SIZE 16

volatile uint8_t display[6],shift,displayupdate,brightness=1;

volatile uint8_t keybuffer[KEY_BUFFER_SIZE],keyeventcount,keybufferin,keybufferout;
volatile uint8_t inputbuffer1[INPUT_BUFFER_SIZE],inputbuffer2[INPUT_BUFFER_SIZE],inputbuffer3[INPUT_BUFFER_SIZE],inputeventcount,inputbufferin,inputbufferout;

const __flash uint8_t brightness_table[8]={14,29,44,59,74,89,104,119};

const __flash uint8_t hexfont[16]={63,6,91,79,102,109,125,7,127,111,119,124,57,94,121,113};

const __flash uint8_t bitsset[256]={
                                     0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
                                     1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                                     1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                                     2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                     1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                                     2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                     2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                     3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                                     1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
                                     2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                     2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                     3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                                     2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
                                     3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                                     3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
                                     4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
                                   };

 

ISR(TIMER0_COMPA_vect) //600 Hz = 1.667 ms
  {
    static uint8_t column,ldisplay[6],inputdebouncecount,input[3],inputlast[3],inputstate[3];

    //reset watchdog
    wdt_reset();

    //disable display
    PORTC=0x00;

    //keyboard enable column
    if (column<4)
      DDRB|=_BV(column+4);
    else DDRD|=_BV(column);

    //keyboard sample row
    if (column%2==0)
      input[column/2]=~PINB & 0x0f;
    else input[column/2]|=(~PINB & 0x0f)<<4;

    //keyboard disable column
    DDRB=0;
    DDRD=0;

    //update for the next display
    PORTA=ldisplay[column];

    //enable active display
    PORTC=_BV(column+2);

    //advance column
    column++;
    if (column==6)
      {
        //start over
        column=0;

        //turn on the shift decimal point if shifted
        if (shift)
          PORTA|=0x80;

        //if we need to update out ldisplay from the global one
        if (displayupdate)
          {
            displayupdate=0;
            ldisplay[0]=display[0];
            ldisplay[1]=display[1];
            ldisplay[2]=display[2];
            ldisplay[3]=display[3];
            ldisplay[4]=display[4];
            ldisplay[5]=display[5];
          }

        //debounce keypad
        if (inputlast[0]==input[0] && inputlast[1]==input[1] && inputlast[2]==input[2])
          inputdebouncecount++;
        else
          {
            inputlast[0]=input[0];
            inputlast[1]=input[1];
            inputlast[2]=input[2];
            inputdebouncecount=1;
          }

        //process into buffer
        if (inputdebouncecount>=3 && (inputstate[0]!=input[0] || inputstate[1]!=input[1] || inputstate[2]!=input[2])) //debounce 30ma
          {
            if (inputeventcount<INPUT_BUFFER_SIZE)
              {
                inputbuffer1[inputbufferin]=input[0];
                inputbuffer2[inputbufferin]=input[1];
                inputbuffer3[inputbufferin]=input[2];
                inputbufferin++;
                if (inputbufferin>=INPUT_BUFFER_SIZE)
                  inputbufferin=0;
                inputeventcount++;
              }

            //update inputstate
            inputstate[0]=input[0];
            inputstate[1]=input[1];
            inputstate[2]=input[2];
          }
      }

    //if brightness is not maximum, enable timer to turn it off to dim display
    if (brightness<7)
      {
        //clear timer
        TCNT2=0;

        //set time length
        OCR2A=brightness_table[brightness];

        //start timer
        TCCR2B=_BV(CS22) | _BV(CS21);
      }
  }

ISR(TIMER2_COMPA_vect)
  {
    //disable all displays
    PORTC=0x00;

    //turn off timer
    TCCR2B=0;
  }

LSS:

 

ISR(TIMER0_COMPA_vect) //600 Hz = 1.667 ms
  {
 518:	1f 92       	push	r1
 51a:	0f 92       	push	r0
 51c:	0f b6       	in	r0, 0x3f	; 63
 51e:	0f 92       	push	r0
 520:	11 24       	eor	r1, r1
 522:	0b b6       	in	r0, 0x3b	; 59
 524:	0f 92       	push	r0
 526:	2f 93       	push	r18
 528:	3f 93       	push	r19
 52a:	8f 93       	push	r24
 52c:	9f 93       	push	r25
 52e:	ef 93       	push	r30
 530:	ff 93       	push	r31
    static uint8_t column,ldisplay[6],inputdebouncecount,input[3],inputlast[3],inputstate[3];

    //reset watchdog
    wdt_reset();
 532:	a8 95       	wdr

    //disable display
    PORTC=0x00;
 534:	18 b8       	out	0x08, r1	; 8

    //keyboard enable column
    if (column<4)
 536:	20 91 12 01 	lds	r18, 0x0112	; 0x800112 <column.1819>
 53a:	24 30       	cpi	r18, 0x04	; 4
 53c:	58 f4       	brcc	.+22     	; 0x554 <__vector_16+0x3c>
      DDRB|=_BV(column+4);
 53e:	34 b1       	in	r19, 0x04	; 4
 540:	2c 5f       	subi	r18, 0xFC	; 252
 542:	81 e0       	ldi	r24, 0x01	; 1
 544:	90 e0       	ldi	r25, 0x00	; 0
 546:	01 c0       	rjmp	.+2      	; 0x54a <__vector_16+0x32>
 548:	88 0f       	add	r24, r24
 54a:	2a 95       	dec	r18
 54c:	ea f7       	brpl	.-6      	; 0x548 <__vector_16+0x30>
 54e:	83 2b       	or	r24, r19
 550:	84 b9       	out	0x04, r24	; 4
 552:	09 c0       	rjmp	.+18     	; 0x566 <__vector_16+0x4e>
    else DDRD|=_BV(column);
 554:	3a b1       	in	r19, 0x0a	; 10
 556:	81 e0       	ldi	r24, 0x01	; 1
 558:	90 e0       	ldi	r25, 0x00	; 0
 55a:	01 c0       	rjmp	.+2      	; 0x55e <__vector_16+0x46>
 55c:	88 0f       	add	r24, r24
 55e:	2a 95       	dec	r18
 560:	ea f7       	brpl	.-6      	; 0x55c <__vector_16+0x44>
 562:	83 2b       	or	r24, r19
 564:	8a b9       	out	0x0a, r24	; 10

    //keyboard sample row
    if (column%2==0)
 566:	80 91 12 01 	lds	r24, 0x0112	; 0x800112 <column.1819>
 56a:	e8 2f       	mov	r30, r24
 56c:	e6 95       	lsr	r30
 56e:	80 fd       	sbrc	r24, 0
 570:	07 c0       	rjmp	.+14     	; 0x580 <__vector_16+0x68>
      input[column/2]=~PINB & 0x0f;
 572:	83 b1       	in	r24, 0x03	; 3
 574:	f0 e0       	ldi	r31, 0x00	; 0
 576:	e1 5f       	subi	r30, 0xF1	; 241
 578:	fe 4f       	sbci	r31, 0xFE	; 254
 57a:	80 95       	com	r24
 57c:	8f 70       	andi	r24, 0x0F	; 15
 57e:	0e c0       	rjmp	.+28     	; 0x59c <__vector_16+0x84>
    else input[column/2]|=(~PINB & 0x0f)<<4;
 580:	83 b1       	in	r24, 0x03	; 3
 582:	f0 e0       	ldi	r31, 0x00	; 0
 584:	e1 5f       	subi	r30, 0xF1	; 241
 586:	fe 4f       	sbci	r31, 0xFE	; 254
 588:	90 e0       	ldi	r25, 0x00	; 0
 58a:	80 95       	com	r24
 58c:	90 95       	com	r25
 58e:	24 e0       	ldi	r18, 0x04	; 4
 590:	88 0f       	add	r24, r24
 592:	99 1f       	adc	r25, r25
 594:	2a 95       	dec	r18
 596:	e1 f7       	brne	.-8      	; 0x590 <__vector_16+0x78>
 598:	90 81       	ld	r25, Z
 59a:	89 2b       	or	r24, r25
 59c:	80 83       	st	Z, r24

    //keyboard disable column
    DDRB=0;
 59e:	14 b8       	out	0x04, r1	; 4
    DDRD=0;
 5a0:	1a b8       	out	0x0a, r1	; 10

    //update for the next display
    PORTA=ldisplay[column];
 5a2:	e0 91 12 01 	lds	r30, 0x0112	; 0x800112 <column.1819>
 5a6:	f0 e0       	ldi	r31, 0x00	; 0
 5a8:	e7 5f       	subi	r30, 0xF7	; 247
 5aa:	fe 4f       	sbci	r31, 0xFE	; 254
 5ac:	80 81       	ld	r24, Z
 5ae:	82 b9       	out	0x02, r24	; 2

    //enable active display
    PORTC=_BV(column+2);
 5b0:	20 91 12 01 	lds	r18, 0x0112	; 0x800112 <column.1819>
 5b4:	2e 5f       	subi	r18, 0xFE	; 254
 5b6:	81 e0       	ldi	r24, 0x01	; 1
 5b8:	90 e0       	ldi	r25, 0x00	; 0
 5ba:	01 c0       	rjmp	.+2      	; 0x5be <__vector_16+0xa6>
 5bc:	88 0f       	add	r24, r24
 5be:	2a 95       	dec	r18
 5c0:	ea f7       	brpl	.-6      	; 0x5bc <__vector_16+0xa4>
 5c2:	88 b9       	out	0x08, r24	; 8

    //advance column
    column++;
 5c4:	80 91 12 01 	lds	r24, 0x0112	; 0x800112 <column.1819>
 5c8:	8f 5f       	subi	r24, 0xFF	; 255
    if (column==6)
 5ca:	86 30       	cpi	r24, 0x06	; 6
 5cc:	19 f0       	breq	.+6      	; 0x5d4 <__vector_16+0xbc>

    //enable active display
    PORTC=_BV(column+2);

    //advance column
    column++;
 5ce:	80 93 12 01 	sts	0x0112, r24	; 0x800112 <column.1819>
 5d2:	7f c0       	rjmp	.+254    	; 0x6d2 <__vector_16+0x1ba>
    if (column==6)
      {
        //start over
        column=0;
 5d4:	10 92 12 01 	sts	0x0112, r1	; 0x800112 <column.1819>

        //turn on the shift decimal point if shifted
        if (shift)
 5d8:	80 91 16 01 	lds	r24, 0x0116	; 0x800116 <shift>
 5dc:	81 11       	cpse	r24, r1
          PORTA|=0x80;
 5de:	17 9a       	sbi	0x02, 7	; 2

        //if we need to update out ldisplay from the global one
        if (displayupdate)
 5e0:	80 91 42 01 	lds	r24, 0x0142	; 0x800142 <displayupdate>
 5e4:	88 23       	and	r24, r24
 5e6:	d1 f0       	breq	.+52     	; 0x61c <__vector_16+0x104>
          {
            displayupdate=0;
 5e8:	10 92 42 01 	sts	0x0142, r1	; 0x800142 <displayupdate>
            ldisplay[0]=display[0];
 5ec:	80 91 2b 01 	lds	r24, 0x012B	; 0x80012b <display>
 5f0:	80 93 09 01 	sts	0x0109, r24	; 0x800109 <ldisplay.1820>
            ldisplay[1]=display[1];
 5f4:	80 91 2c 01 	lds	r24, 0x012C	; 0x80012c <display+0x1>
 5f8:	80 93 0a 01 	sts	0x010A, r24	; 0x80010a <ldisplay.1820+0x1>
            ldisplay[2]=display[2];
 5fc:	80 91 2d 01 	lds	r24, 0x012D	; 0x80012d <display+0x2>
 600:	80 93 0b 01 	sts	0x010B, r24	; 0x80010b <ldisplay.1820+0x2>
            ldisplay[3]=display[3];
 604:	80 91 2e 01 	lds	r24, 0x012E	; 0x80012e <display+0x3>
 608:	80 93 0c 01 	sts	0x010C, r24	; 0x80010c <ldisplay.1820+0x3>
            ldisplay[4]=display[4];
 60c:	80 91 2f 01 	lds	r24, 0x012F	; 0x80012f <display+0x4>
 610:	80 93 0d 01 	sts	0x010D, r24	; 0x80010d <ldisplay.1820+0x4>
            ldisplay[5]=display[5];
 614:	80 91 30 01 	lds	r24, 0x0130	; 0x800130 <display+0x5>
 618:	80 93 0e 01 	sts	0x010E, r24	; 0x80010e <ldisplay.1820+0x5>
          }

        //debounce keypad
        if (inputlast[0]==input[0] && inputlast[1]==input[1] && inputlast[2]==input[2])
 61c:	20 91 0f 01 	lds	r18, 0x010F	; 0x80010f <input.1822>
 620:	30 91 06 01 	lds	r19, 0x0106	; 0x800106 <inputlast.1823>
 624:	90 91 10 01 	lds	r25, 0x0110	; 0x800110 <input.1822+0x1>
 628:	80 91 11 01 	lds	r24, 0x0111	; 0x800111 <input.1822+0x2>
 62c:	32 13       	cpse	r19, r18
 62e:	0c c0       	rjmp	.+24     	; 0x648 <__vector_16+0x130>
 630:	30 91 07 01 	lds	r19, 0x0107	; 0x800107 <inputlast.1823+0x1>
 634:	39 13       	cpse	r19, r25
 636:	08 c0       	rjmp	.+16     	; 0x648 <__vector_16+0x130>
 638:	30 91 08 01 	lds	r19, 0x0108	; 0x800108 <inputlast.1823+0x2>
 63c:	38 13       	cpse	r19, r24
 63e:	04 c0       	rjmp	.+8      	; 0x648 <__vector_16+0x130>
          inputdebouncecount++;
 640:	30 91 05 01 	lds	r19, 0x0105	; 0x800105 <inputdebouncecount.1821>
 644:	3f 5f       	subi	r19, 0xFF	; 255
 646:	07 c0       	rjmp	.+14     	; 0x656 <__vector_16+0x13e>
        else
          {
            inputlast[0]=input[0];
 648:	20 93 06 01 	sts	0x0106, r18	; 0x800106 <inputlast.1823>
            inputlast[1]=input[1];
 64c:	90 93 07 01 	sts	0x0107, r25	; 0x800107 <inputlast.1823+0x1>
            inputlast[2]=input[2];
 650:	80 93 08 01 	sts	0x0108, r24	; 0x800108 <inputlast.1823+0x2>
            inputdebouncecount=1;
 654:	31 e0       	ldi	r19, 0x01	; 1
 656:	30 93 05 01 	sts	0x0105, r19	; 0x800105 <inputdebouncecount.1821>
          }

        //process into buffer
        if ((inputstate[0]!=input[0] || inputstate[1]!=input[1] || inputstate[2]!=input[2]) && inputdebouncecount>=3)
 65a:	30 91 02 01 	lds	r19, 0x0102	; 0x800102 <__data_end>
 65e:	23 13       	cpse	r18, r19
 660:	08 c0       	rjmp	.+16     	; 0x672 <__vector_16+0x15a>
 662:	30 91 03 01 	lds	r19, 0x0103	; 0x800103 <__data_end+0x1>
 666:	39 13       	cpse	r19, r25
 668:	04 c0       	rjmp	.+8      	; 0x672 <__vector_16+0x15a>
 66a:	30 91 04 01 	lds	r19, 0x0104	; 0x800104 <__data_end+0x2>
 66e:	38 17       	cp	r19, r24
 670:	81 f1       	breq	.+96     	; 0x6d2 <__vector_16+0x1ba>
 672:	30 91 05 01 	lds	r19, 0x0105	; 0x800105 <inputdebouncecount.1821>
 676:	33 30       	cpi	r19, 0x03	; 3
 678:	60 f1       	brcs	.+88     	; 0x6d2 <__vector_16+0x1ba>
          {
            if (inputeventcount<INPUT_BUFFER_SIZE)
 67a:	30 91 31 01 	lds	r19, 0x0131	; 0x800131 <inputeventcount>
 67e:	30 31       	cpi	r19, 0x10	; 16
 680:	10 f5       	brcc	.+68     	; 0x6c6 <__vector_16+0x1ae>
              {
                inputbuffer1[inputbufferin]=input[0];
 682:	e0 91 18 01 	lds	r30, 0x0118	; 0x800118 <inputbufferin>
 686:	f0 e0       	ldi	r31, 0x00	; 0
 688:	ed 5b       	subi	r30, 0xBD	; 189
 68a:	fe 4f       	sbci	r31, 0xFE	; 254
 68c:	20 83       	st	Z, r18
                inputbuffer2[inputbufferin]=input[1];
 68e:	e0 91 18 01 	lds	r30, 0x0118	; 0x800118 <inputbufferin>
 692:	f0 e0       	ldi	r31, 0x00	; 0
 694:	ed 5a       	subi	r30, 0xAD	; 173
 696:	fe 4f       	sbci	r31, 0xFE	; 254
 698:	90 83       	st	Z, r25
                inputbuffer3[inputbufferin]=input[2];
 69a:	e0 91 18 01 	lds	r30, 0x0118	; 0x800118 <inputbufferin>
 69e:	f0 e0       	ldi	r31, 0x00	; 0
 6a0:	ee 5c       	subi	r30, 0xCE	; 206
 6a2:	fe 4f       	sbci	r31, 0xFE	; 254
 6a4:	80 83       	st	Z, r24
                inputbufferin++;
 6a6:	30 91 18 01 	lds	r19, 0x0118	; 0x800118 <inputbufferin>
 6aa:	3f 5f       	subi	r19, 0xFF	; 255
 6ac:	30 93 18 01 	sts	0x0118, r19	; 0x800118 <inputbufferin>
                if (inputbufferin>=INPUT_BUFFER_SIZE)
 6b0:	30 91 18 01 	lds	r19, 0x0118	; 0x800118 <inputbufferin>
 6b4:	30 31       	cpi	r19, 0x10	; 16
 6b6:	10 f0       	brcs	.+4      	; 0x6bc <__vector_16+0x1a4>
                  inputbufferin=0;
 6b8:	10 92 18 01 	sts	0x0118, r1	; 0x800118 <inputbufferin>
                inputeventcount++;
 6bc:	30 91 31 01 	lds	r19, 0x0131	; 0x800131 <inputeventcount>
 6c0:	3f 5f       	subi	r19, 0xFF	; 255
 6c2:	30 93 31 01 	sts	0x0131, r19	; 0x800131 <inputeventcount>
              }

            //update inputstate
            inputstate[0]=input[0];
 6c6:	20 93 02 01 	sts	0x0102, r18	; 0x800102 <__data_end>
            inputstate[1]=input[1];
 6ca:	90 93 03 01 	sts	0x0103, r25	; 0x800103 <__data_end+0x1>
            inputstate[2]=input[2];
 6ce:	80 93 04 01 	sts	0x0104, r24	; 0x800104 <__data_end+0x2>
          }
      }

    //if brightness is not maximum, enable timer to turn it off to dim display
    if (brightness<7)
 6d2:	80 91 00 01 	lds	r24, 0x0100	; 0x800100 <__DATA_REGION_ORIGIN__>
 6d6:	87 30       	cpi	r24, 0x07	; 7
 6d8:	68 f4       	brcc	.+26     	; 0x6f4 <__vector_16+0x1dc>
      {
        //clear timer
        TCNT2=0;
 6da:	10 92 b2 00 	sts	0x00B2, r1	; 0x8000b2 <__TEXT_REGION_LENGTH__+0x7e00b2>

        //set time length
        OCR2A=brightness_table[brightness];
 6de:	e0 91 00 01 	lds	r30, 0x0100	; 0x800100 <__DATA_REGION_ORIGIN__>
 6e2:	f0 e0       	ldi	r31, 0x00	; 0
 6e4:	e4 53       	subi	r30, 0x34	; 52
 6e6:	fe 4f       	sbci	r31, 0xFE	; 254
 6e8:	84 91       	lpm	r24, Z
 6ea:	80 93 b3 00 	sts	0x00B3, r24	; 0x8000b3 <__TEXT_REGION_LENGTH__+0x7e00b3>

        //start timer
        TCCR2B=_BV(CS22) | _BV(CS21);
 6ee:	86 e0       	ldi	r24, 0x06	; 6
 6f0:	80 93 b1 00 	sts	0x00B1, r24	; 0x8000b1 <__TEXT_REGION_LENGTH__+0x7e00b1>
      }
  }
 6f4:	ff 91       	pop	r31
 6f6:	ef 91       	pop	r30
 6f8:	9f 91       	pop	r25
 6fa:	8f 91       	pop	r24
 6fc:	3f 91       	pop	r19
 6fe:	2f 91       	pop	r18
 700:	0f 90       	pop	r0
 702:	0b be       	out	0x3b, r0	; 59
 704:	0f 90       	pop	r0
 706:	0f be       	out	0x3f, r0	; 63
 708:	0f 90       	pop	r0
 70a:	1f 90       	pop	r1
 70c:	18 95       	reti

0000070e <__vector_9>:

ISR(TIMER2_COMPA_vect)
  {
 70e:	1f 92       	push	r1
 710:	0f 92       	push	r0
 712:	0f b6       	in	r0, 0x3f	; 63
 714:	0f 92       	push	r0
 716:	11 24       	eor	r1, r1
    //disable all displays
    PORTC=0x00;
 718:	18 b8       	out	0x08, r1	; 8

    //turn off timer
    TCCR2B=0;
 71a:	10 92 b1 00 	sts	0x00B1, r1	; 0x8000b1 <__TEXT_REGION_LENGTH__+0x7e00b1>
  }
 71e:	0f 90       	pop	r0
 720:	0f be       	out	0x3f, r0	; 63
 722:	0f 90       	pop	r0
 724:	1f 90       	pop	r1
 726:	18 95       	reti

 

Last Edited: Thu. May 21, 2020 - 12:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe it's just me but that looks like a lot of processing in an ISR? Does all that stuff really have to wait for ISR "tick time" before the data processing can be done ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I completely agree, but what can be pulled out of it?  Grabbing the 4 bits from each of the 6 columns needs to happen as well as proper debouncing.

 

I suppose I could do away with the ldisplay and just have it display the global volatile display variable, but you might end up with a half and half frame that way although for a 10ms LED pass I'm not sure one could really see it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
I'm messing around with the idea of making a processor trainer emulator like they had in the 1970's like the SDK-85.
Cool!

alank2 wrote:
It is going to be all all through hole project, so I'm going to use the ATMEGA1284 which has 16K SRAM.
fyi, AVR DA with 128KB/16KB is in PDIP-28 though would need a port extender to reach to 40 pins.

PTC so could go cap touch ... welcome to this century wink

 


Another mega1284 in DIP board though would add your operator interface :

PCB-AVR1284-3U | Atmel DIP40 AVR DevBoard | BusBoard Prototype Systems

 

AVR128DA28 - 8-bit Microcontrollers due to https://www.avrfreaks.net/forum/what-are-avr28da128-avr32da128-avr48da128-avr64da128?page=1#comment-2882716

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't presume to know how you are going to implement the emulator; however, it would seem to me that within the ISR you just set some flags saying time to scan keys, time to update the display, etc.

Then in the main loop when (I presume) you are processing opcodes for the target processor check the flags and process the various actions. YMMV

 

David

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

gchapman - what is AVR DA?  I'm using every single pin of the 1284 right now (it is amazing how fast 32 i/o's go when you are doing a seven segment display and a keypad.  I weighed choosing to combine the columns of the keypad and display, but I had a display with a diode leakage problem once that was enough to overcome the weakish pullups in the AVR and I had just enough pins to keep them separate.

 

I was going to just use some tactile buttons at first, but I found out there is such a thing as a relegendable keycap that works with Cherry MX switches.  I can print a key label and it fits within the key.

 

frog_jr - certainly no emulation code will be within the ISR! :)  One of the reasons I scan the keyboard in the ISR is for consistency, I can get 24 bits for the keys every 10ms and I can debounce them in say 30ms.

 

I did have a few more thoughts on how I could lessen the ISR execution time:

 

test sending random values to the displays as fast as possible in the main loop
try with and without the ldisplay to see what the difference might look like

could the dimming set time length be moved out of the ISR?

would a switch at enable column be faster?
  could combining enable active display with the switch be helpful?

could getting the 4 bits first for keypad scanning and then stuffing them into a variable be faster?

can something be done to copy 3 or 6 bytes from one structure to another faster?

 

I'm attaching the keypad (my wife thinks the font could be improved).  The keys are spaced apart for easy cutting, but they will be like a keypad all together.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I see the DA AVR now.  Now, a DIP-40 AVR with more SRAM like 32K would be something I'd probably switch to if it existed.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:

I see the DA AVR now.  Now, a DIP-40 AVR with more SRAM like 32K would be something I'd probably switch to if it existed.

 

No sign of a DA series in DIP. Newest part in DIP is the mega4809 but that has less memory than the 1284P.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1


alank2 wrote:

I'm messing around with the idea of making a processor trainer emulator like they had in the 1970's like the SDK-85.

 

My SDK-85...

 

 

...soon to be tidied, tested, and listed on eBay.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ahhh Brian, you know you don't want to sell that fine piece of history!  I love those keys.  Get one of those shadow boxes and mount it on the wall or something!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

alank2 wrote:
I'm messing around with the idea of making a processor trainer emulator like they had in the 1970's like the SDK-85.  It is going to be all all through hole project,

Is there a need for a 8080/z80/8085 trainer, or is this a personal project not for commercial use?

Jim

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is no need for it other than being a fun thing to make after from computing history.  Certainly a personal project, but I may sell it as a kit for someone who likes this sort of thing and doesn't mind soldering it together.

 

It will have couple of serial ports and run Altair 8K BASIC too.  It will have limited storage though in the form of an i2c EEPROM - just save and load 15K chunks of sram.

Last Edited: Thu. May 21, 2020 - 03:29 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That output code is very stupid!   (it make a loop for <<4 on a uint8_t)

 

Which optimizing mode do you use ?

try with -O2 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is set for -Os right now - I'll try that and see what it does to it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ATxmega384C3 and ATxmega384D3 have 32KB local SRAM though this is the best can recall (900mil wide between DIL pins on a 1100mil wide PCBA versus 600mil wide DIP)

MT-DB-X3 Atmel AVR XMEGA 64-pin A3U / A3BU / C3 / D3 USB development board - Development Boards

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks gchapman - I'm very familiar with the xmega384c3 and it was on my short list until I decided to go the all through hole direction with it.

 

sparrow2 - I'll attach the interrupt with -O2 for you to look through as well if you like.

 

ALSO - if anyone remembers my question about inline functions not being inline last week - it is the -Os which would require the force option clawson mentioned.  At -O2, they are inlining properly without any sort of force.

 

ISR(TIMER0_COMPA_vect) //600 Hz = 1.667 ms
  {
    56fe:	1f 92       	push	r1
    5700:	0f 92       	push	r0
    5702:	0f b6       	in	r0, 0x3f	; 63
    5704:	0f 92       	push	r0
    5706:	11 24       	eor	r1, r1
    5708:	0b b6       	in	r0, 0x3b	; 59
    570a:	0f 92       	push	r0
    570c:	2f 93       	push	r18
    570e:	3f 93       	push	r19
    5710:	4f 93       	push	r20
    5712:	5f 93       	push	r21
    5714:	6f 93       	push	r22
    5716:	7f 93       	push	r23
    5718:	8f 93       	push	r24
    571a:	9f 93       	push	r25
    571c:	ef 93       	push	r30
    571e:	ff 93       	push	r31
    static uint8_t column,ldisplay[6],inputdebouncecount,input[3],inputlast[3],inputstate[3];

    //reset watchdog
    wdt_reset();
    5720:	a8 95       	wdr

    //disable display
    PORTC=0x00;
    5722:	18 b8       	out	0x08, r1	; 8

    //keyboard enable column
    if (column<4)
    5724:	80 91 12 02 	lds	r24, 0x0212	; 0x800212 <column.1871>
    5728:	84 30       	cpi	r24, 0x04	; 4
    572a:	08 f0       	brcs	.+2      	; 0x572e <__vector_16+0x30>
    572c:	67 c0       	rjmp	.+206    	; 0x57fc <__vector_16+0xfe>
      DDRB|=_BV(column+4);
    572e:	44 b1       	in	r20, 0x04	; 4
    5730:	8c 5f       	subi	r24, 0xFC	; 252
    5732:	21 e0       	ldi	r18, 0x01	; 1
    5734:	30 e0       	ldi	r19, 0x00	; 0
    5736:	b9 01       	movw	r22, r18
    5738:	02 c0       	rjmp	.+4      	; 0x573e <__vector_16+0x40>
    573a:	66 0f       	add	r22, r22
    573c:	77 1f       	adc	r23, r23
    573e:	8a 95       	dec	r24
    5740:	e2 f7       	brpl	.-8      	; 0x573a <__vector_16+0x3c>
    5742:	cb 01       	movw	r24, r22
    5744:	84 2b       	or	r24, r20
    5746:	84 b9       	out	0x04, r24	; 4
    else DDRD|=_BV(column);

    //keyboard sample row
    if (column%2==0)
    5748:	e0 91 12 02 	lds	r30, 0x0212	; 0x800212 <column.1871>
      input[column/2]=~PINB & 0x0f;
    574c:	83 b1       	in	r24, 0x03	; 3
    if (column<4)
      DDRB|=_BV(column+4);
    else DDRD|=_BV(column);

    //keyboard sample row
    if (column%2==0)
    574e:	e0 fd       	sbrc	r30, 0
    5750:	44 c0       	rjmp	.+136    	; 0x57da <__vector_16+0xdc>
      input[column/2]=~PINB & 0x0f;
    5752:	e6 95       	lsr	r30
    5754:	f0 e0       	ldi	r31, 0x00	; 0
    5756:	e1 5f       	subi	r30, 0xF1	; 241
    5758:	fd 4f       	sbci	r31, 0xFD	; 253
    575a:	80 95       	com	r24
    575c:	8f 70       	andi	r24, 0x0F	; 15
    575e:	80 83       	st	Z, r24
    else input[column/2]|=(~PINB & 0x0f)<<4;

    //keyboard disable column
    DDRB=0;
    5760:	14 b8       	out	0x04, r1	; 4
    DDRD=0;
    5762:	1a b8       	out	0x0a, r1	; 10

    //update for the next display
    PORTA=ldisplay[column];
    5764:	e0 91 12 02 	lds	r30, 0x0212	; 0x800212 <column.1871>
    5768:	f0 e0       	ldi	r31, 0x00	; 0
    576a:	e7 5f       	subi	r30, 0xF7	; 247
    576c:	fd 4f       	sbci	r31, 0xFD	; 253
    576e:	80 81       	ld	r24, Z
    5770:	82 b9       	out	0x02, r24	; 2

    //enable active display
    PORTC=_BV(column+2);
    5772:	20 91 12 02 	lds	r18, 0x0212	; 0x800212 <column.1871>
    5776:	2e 5f       	subi	r18, 0xFE	; 254
    5778:	81 e0       	ldi	r24, 0x01	; 1
    577a:	90 e0       	ldi	r25, 0x00	; 0
    577c:	01 c0       	rjmp	.+2      	; 0x5780 <__vector_16+0x82>
    577e:	88 0f       	add	r24, r24
    5780:	2a 95       	dec	r18
    5782:	ea f7       	brpl	.-6      	; 0x577e <__vector_16+0x80>
    5784:	88 b9       	out	0x08, r24	; 8

    //advance column
    column++;
    5786:	80 91 12 02 	lds	r24, 0x0212	; 0x800212 <column.1871>
    578a:	8f 5f       	subi	r24, 0xFF	; 255
    if (column==6)
    578c:	86 30       	cpi	r24, 0x06	; 6
    578e:	09 f4       	brne	.+2      	; 0x5792 <__vector_16+0x94>
    5790:	42 c0       	rjmp	.+132    	; 0x5816 <__vector_16+0x118>

    //enable active display
    PORTC=_BV(column+2);

    //advance column
    column++;
    5792:	80 93 12 02 	sts	0x0212, r24	; 0x800212 <column.1871>
            inputstate[2]=input[2];
          }
      }

    //if brightness is not maximum, enable timer to turn it off to dim display
    if (brightness<7)
    5796:	80 91 00 01 	lds	r24, 0x0100	; 0x800100 <__data_start>
    579a:	87 30       	cpi	r24, 0x07	; 7
    579c:	68 f4       	brcc	.+26     	; 0x57b8 <__vector_16+0xba>
      {
        //clear timer
        TCNT2=0;
    579e:	10 92 b2 00 	sts	0x00B2, r1	; 0x8000b2 <__TEXT_REGION_LENGTH__+0x7e00b2>

        //set time length
        OCR2A=brightness_table[brightness];
    57a2:	e0 91 00 01 	lds	r30, 0x0100	; 0x800100 <__data_start>
    57a6:	f0 e0       	ldi	r31, 0x00	; 0
    57a8:	e4 53       	subi	r30, 0x34	; 52
    57aa:	fc 4f       	sbci	r31, 0xFC	; 252
    57ac:	84 91       	lpm	r24, Z
    57ae:	80 93 b3 00 	sts	0x00B3, r24	; 0x8000b3 <__TEXT_REGION_LENGTH__+0x7e00b3>

        //start timer
        TCCR2B=_BV(CS22) | _BV(CS21);
    57b2:	86 e0       	ldi	r24, 0x06	; 6
    57b4:	80 93 b1 00 	sts	0x00B1, r24	; 0x8000b1 <__TEXT_REGION_LENGTH__+0x7e00b1>
      }
  }
    57b8:	ff 91       	pop	r31
    57ba:	ef 91       	pop	r30
    57bc:	9f 91       	pop	r25
    57be:	8f 91       	pop	r24
    57c0:	7f 91       	pop	r23
    57c2:	6f 91       	pop	r22
    57c4:	5f 91       	pop	r21
    57c6:	4f 91       	pop	r20
    57c8:	3f 91       	pop	r19
    57ca:	2f 91       	pop	r18
    57cc:	0f 90       	pop	r0
    57ce:	0b be       	out	0x3b, r0	; 59
    57d0:	0f 90       	pop	r0
    57d2:	0f be       	out	0x3f, r0	; 63
    57d4:	0f 90       	pop	r0
    57d6:	1f 90       	pop	r1
    57d8:	18 95       	reti
    else DDRD|=_BV(column);

    //keyboard sample row
    if (column%2==0)
      input[column/2]=~PINB & 0x0f;
    else input[column/2]|=(~PINB & 0x0f)<<4;
    57da:	e6 95       	lsr	r30
    57dc:	f0 e0       	ldi	r31, 0x00	; 0
    57de:	e1 5f       	subi	r30, 0xF1	; 241
    57e0:	fd 4f       	sbci	r31, 0xFD	; 253
    57e2:	90 e0       	ldi	r25, 0x00	; 0
    57e4:	80 95       	com	r24
    57e6:	90 95       	com	r25
    57e8:	82 95       	swap	r24
    57ea:	92 95       	swap	r25
    57ec:	90 7f       	andi	r25, 0xF0	; 240
    57ee:	98 27       	eor	r25, r24
    57f0:	80 7f       	andi	r24, 0xF0	; 240
    57f2:	98 27       	eor	r25, r24
    57f4:	90 81       	ld	r25, Z
    57f6:	89 2b       	or	r24, r25
    57f8:	80 83       	st	Z, r24
    57fa:	b2 cf       	rjmp	.-156    	; 0x5760 <__vector_16+0x62>
    PORTC=0x00;

    //keyboard enable column
    if (column<4)
      DDRB|=_BV(column+4);
    else DDRD|=_BV(column);
    57fc:	4a b1       	in	r20, 0x0a	; 10
    57fe:	21 e0       	ldi	r18, 0x01	; 1
    5800:	30 e0       	ldi	r19, 0x00	; 0
    5802:	b9 01       	movw	r22, r18
    5804:	02 c0       	rjmp	.+4      	; 0x580a <__vector_16+0x10c>
    5806:	66 0f       	add	r22, r22
    5808:	77 1f       	adc	r23, r23
    580a:	8a 95       	dec	r24
    580c:	e2 f7       	brpl	.-8      	; 0x5806 <__vector_16+0x108>
    580e:	cb 01       	movw	r24, r22
    5810:	84 2b       	or	r24, r20
    5812:	8a b9       	out	0x0a, r24	; 10
    5814:	99 cf       	rjmp	.-206    	; 0x5748 <__vector_16+0x4a>
    //advance column
    column++;
    if (column==6)
      {
        //start over
        column=0;
    5816:	10 92 12 02 	sts	0x0212, r1	; 0x800212 <column.1871>

        //turn on the shift decimal point if shifted
        if (shift)
    581a:	80 91 34 02 	lds	r24, 0x0234	; 0x800234 <shift>
    581e:	81 11       	cpse	r24, r1
          PORTA|=0x80;
    5820:	17 9a       	sbi	0x02, 7	; 2

        //if we need to update out ldisplay from the global one
        if (displayupdate)
    5822:	80 91 70 3e 	lds	r24, 0x3E70	; 0x803e70 <displayupdate>
    5826:	81 11       	cpse	r24, r1
    5828:	14 c0       	rjmp	.+40     	; 0x5852 <__vector_16+0x154>
            ldisplay[4]=display[4];
            ldisplay[5]=display[5];
          }

        //debounce keypad
        if (inputlast[0]==input[0] && inputlast[1]==input[1] && inputlast[2]==input[2])
    582a:	80 91 06 02 	lds	r24, 0x0206	; 0x800206 <inputlast.1875>
    582e:	90 91 0f 02 	lds	r25, 0x020F	; 0x80020f <input.1874>
    5832:	89 17       	cp	r24, r25
    5834:	49 f1       	breq	.+82     	; 0x5888 <__vector_16+0x18a>
    5836:	20 91 10 02 	lds	r18, 0x0210	; 0x800210 <input.1874+0x1>
    583a:	30 91 11 02 	lds	r19, 0x0211	; 0x800211 <input.1874+0x2>
          inputdebouncecount++;
        else
          {
            inputlast[0]=input[0];
    583e:	90 93 06 02 	sts	0x0206, r25	; 0x800206 <inputlast.1875>
            inputlast[1]=input[1];
    5842:	20 93 07 02 	sts	0x0207, r18	; 0x800207 <inputlast.1875+0x1>
            inputlast[2]=input[2];
    5846:	30 93 08 02 	sts	0x0208, r19	; 0x800208 <inputlast.1875+0x2>
            inputdebouncecount=1;
    584a:	81 e0       	ldi	r24, 0x01	; 1
    584c:	80 93 05 02 	sts	0x0205, r24	; 0x800205 <inputdebouncecount.1873>
    5850:	a2 cf       	rjmp	.-188    	; 0x5796 <__vector_16+0x98>
          PORTA|=0x80;

        //if we need to update out ldisplay from the global one
        if (displayupdate)
          {
            displayupdate=0;
    5852:	10 92 70 3e 	sts	0x3E70, r1	; 0x803e70 <displayupdate>
            ldisplay[0]=display[0];
    5856:	80 91 49 3e 	lds	r24, 0x3E49	; 0x803e49 <display>
    585a:	80 93 09 02 	sts	0x0209, r24	; 0x800209 <ldisplay.1872>
            ldisplay[1]=display[1];
    585e:	80 91 4a 3e 	lds	r24, 0x3E4A	; 0x803e4a <display+0x1>
    5862:	80 93 0a 02 	sts	0x020A, r24	; 0x80020a <ldisplay.1872+0x1>
            ldisplay[2]=display[2];
    5866:	80 91 4b 3e 	lds	r24, 0x3E4B	; 0x803e4b <display+0x2>
    586a:	80 93 0b 02 	sts	0x020B, r24	; 0x80020b <ldisplay.1872+0x2>
            ldisplay[3]=display[3];
    586e:	80 91 4c 3e 	lds	r24, 0x3E4C	; 0x803e4c <display+0x3>
    5872:	80 93 0c 02 	sts	0x020C, r24	; 0x80020c <ldisplay.1872+0x3>
            ldisplay[4]=display[4];
    5876:	80 91 4d 3e 	lds	r24, 0x3E4D	; 0x803e4d <display+0x4>
    587a:	80 93 0d 02 	sts	0x020D, r24	; 0x80020d <ldisplay.1872+0x4>
            ldisplay[5]=display[5];
    587e:	80 91 4e 3e 	lds	r24, 0x3E4E	; 0x803e4e <display+0x5>
    5882:	80 93 0e 02 	sts	0x020E, r24	; 0x80020e <ldisplay.1872+0x5>
    5886:	d1 cf       	rjmp	.-94     	; 0x582a <__vector_16+0x12c>
          }

        //debounce keypad
        if (inputlast[0]==input[0] && inputlast[1]==input[1] && inputlast[2]==input[2])
    5888:	40 91 07 02 	lds	r20, 0x0207	; 0x800207 <inputlast.1875+0x1>
    588c:	20 91 10 02 	lds	r18, 0x0210	; 0x800210 <input.1874+0x1>
    5890:	42 13       	cpse	r20, r18
    5892:	d3 cf       	rjmp	.-90     	; 0x583a <__vector_16+0x13c>
    5894:	50 91 08 02 	lds	r21, 0x0208	; 0x800208 <inputlast.1875+0x2>
    5898:	30 91 11 02 	lds	r19, 0x0211	; 0x800211 <input.1874+0x2>
    589c:	53 13       	cpse	r21, r19
    589e:	cf cf       	rjmp	.-98     	; 0x583e <__vector_16+0x140>
          inputdebouncecount++;
    58a0:	90 91 05 02 	lds	r25, 0x0205	; 0x800205 <inputdebouncecount.1873>
    58a4:	9f 5f       	subi	r25, 0xFF	; 255
    58a6:	90 93 05 02 	sts	0x0205, r25	; 0x800205 <inputdebouncecount.1873>
            inputlast[2]=input[2];
            inputdebouncecount=1;
          }

        //process into buffer
        if (inputdebouncecount>=3 && (inputstate[0]!=input[0] || inputstate[1]!=input[1] || inputstate[2]!=input[2])) //debounce 30ma
    58aa:	93 30       	cpi	r25, 0x03	; 3
    58ac:	08 f4       	brcc	.+2      	; 0x58b0 <__vector_16+0x1b2>
    58ae:	73 cf       	rjmp	.-282    	; 0x5796 <__vector_16+0x98>
    58b0:	90 91 02 02 	lds	r25, 0x0202	; 0x800202 <__data_end>
    58b4:	89 17       	cp	r24, r25
    58b6:	69 f1       	breq	.+90     	; 0x5912 <__vector_16+0x214>
          {
            if (inputeventcount<INPUT_BUFFER_SIZE)
    58b8:	90 91 4f 3e 	lds	r25, 0x3E4F	; 0x803e4f <inputeventcount>
    58bc:	90 32       	cpi	r25, 0x20	; 32
    58be:	10 f5       	brcc	.+68     	; 0x5904 <__vector_16+0x206>
              {
                inputbuffer1[inputbufferin]=input[0];
    58c0:	e0 91 36 02 	lds	r30, 0x0236	; 0x800236 <inputbufferin>
    58c4:	f0 e0       	ldi	r31, 0x00	; 0
    58c6:	ef 58       	subi	r30, 0x8F	; 143
    58c8:	f1 4c       	sbci	r31, 0xC1	; 193
    58ca:	80 83       	st	Z, r24
                inputbuffer2[inputbufferin]=input[1];
    58cc:	e0 91 36 02 	lds	r30, 0x0236	; 0x800236 <inputbufferin>
    58d0:	f0 e0       	ldi	r31, 0x00	; 0
    58d2:	ef 56       	subi	r30, 0x6F	; 111
    58d4:	f1 4c       	sbci	r31, 0xC1	; 193
    58d6:	40 83       	st	Z, r20
                inputbuffer3[inputbufferin]=input[2];
    58d8:	e0 91 36 02 	lds	r30, 0x0236	; 0x800236 <inputbufferin>
    58dc:	f0 e0       	ldi	r31, 0x00	; 0
    58de:	e0 5b       	subi	r30, 0xB0	; 176
    58e0:	f1 4c       	sbci	r31, 0xC1	; 193
    58e2:	50 83       	st	Z, r21
                inputbufferin++;
    58e4:	90 91 36 02 	lds	r25, 0x0236	; 0x800236 <inputbufferin>
    58e8:	9f 5f       	subi	r25, 0xFF	; 255
    58ea:	90 93 36 02 	sts	0x0236, r25	; 0x800236 <inputbufferin>
                if (inputbufferin>=INPUT_BUFFER_SIZE)
    58ee:	90 91 36 02 	lds	r25, 0x0236	; 0x800236 <inputbufferin>
    58f2:	90 32       	cpi	r25, 0x20	; 32
    58f4:	10 f0       	brcs	.+4      	; 0x58fa <__vector_16+0x1fc>
                  inputbufferin=0;
    58f6:	10 92 36 02 	sts	0x0236, r1	; 0x800236 <inputbufferin>
                inputeventcount++;
    58fa:	90 91 4f 3e 	lds	r25, 0x3E4F	; 0x803e4f <inputeventcount>
    58fe:	9f 5f       	subi	r25, 0xFF	; 255
    5900:	90 93 4f 3e 	sts	0x3E4F, r25	; 0x803e4f <inputeventcount>
              }

            //update inputstate
            inputstate[0]=input[0];
    5904:	80 93 02 02 	sts	0x0202, r24	; 0x800202 <__data_end>
            inputstate[1]=input[1];
    5908:	40 93 03 02 	sts	0x0203, r20	; 0x800203 <__data_end+0x1>
            inputstate[2]=input[2];
    590c:	50 93 04 02 	sts	0x0204, r21	; 0x800204 <__data_end+0x2>
    5910:	42 cf       	rjmp	.-380    	; 0x5796 <__vector_16+0x98>
            inputlast[2]=input[2];
            inputdebouncecount=1;
          }

        //process into buffer
        if (inputdebouncecount>=3 && (inputstate[0]!=input[0] || inputstate[1]!=input[1] || inputstate[2]!=input[2])) //debounce 30ma
    5912:	90 91 03 02 	lds	r25, 0x0203	; 0x800203 <__data_end+0x1>
    5916:	49 13       	cpse	r20, r25
    5918:	cf cf       	rjmp	.-98     	; 0x58b8 <__vector_16+0x1ba>
    591a:	90 91 04 02 	lds	r25, 0x0204	; 0x800204 <__data_end+0x2>
    591e:	59 13       	cpse	r21, r25
    5920:	cb cf       	rjmp	.-106    	; 0x58b8 <__vector_16+0x1ba>
    5922:	39 cf       	rjmp	.-398    	; 0x5796 <__vector_16+0x98>

00005924 <__vector_9>:
        TCCR2B=_BV(CS22) | _BV(CS21);
      }
  }

ISR(TIMER2_COMPA_vect)
  {
    5924:	1f 92       	push	r1
    5926:	0f 92       	push	r0
    5928:	0f b6       	in	r0, 0x3f	; 63
    592a:	0f 92       	push	r0
    592c:	11 24       	eor	r1, r1
    //disable all displays
    PORTC=0x00;
    592e:	18 b8       	out	0x08, r1	; 8

    //turn off timer
    TCCR2B=0;
    5930:	10 92 b1 00 	sts	0x00B1, r1	; 0x8000b1 <__TEXT_REGION_LENGTH__+0x7e00b1>
  }
    5934:	0f 90       	pop	r0
    5936:	0f be       	out	0x3f, r0	; 63
    5938:	0f 90       	pop	r0
    593a:	1f 90       	pop	r1
    593c:	18 95       	reti

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


There's always the DA128 Curiosity Nano, but I think we're getting away from the original design brief.

 

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

_BV(x) macro is still using a loop.  Should I replace this with a lookup array of some sort?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Brian:  I thought about some of the DIP modules that are SMD, but it just doesn't have the same look as the good ole DIP-40.  I'm may even try to apply a heavy miter to make traces look hand drawn.  We'll see how it turns out.

 

Emulation code is now running on it - unscientific stopwatch testing shows it at 2.214 MHz emulation speed which is what I was hoping for.  The AVR clock is 18.432 MHz, so this is even better (8.325 : 1) than my other testing on win32 and DOS.  Hopefully it will have a similar number when using a timer and not my by hand stopwatch measurement.  My goal is emulation at 2 MHz or faster, so it looks like that should be doable.

 

i8080 running 8080exm test on P3 700 MHz
DOS (cycle counting off) = 72.909 MHz (9.60 : 1)
XP WIN32 (cycle counting on) = 100.174 MHz (6.99 : 1)

i8080 running 8080exm test on 486 DX2 66 MHz
DOS (cycle counting off) = 6.337 MHz (10.52 : 1)

NT4 WIN32 (cycle counting on) = 4.900 MHz (13.61 : 1) (overhead of NT on limited CPU probably the cause! or perhaps the 486 is just not all that optimized for 32bit as the P3?)

 

i8080 emulated on AVR 8 bit:  (I make it output RST every time it resets)

RST
RST
RST
8080 instruction exerciser
dad <b,d,h,sp>................  PASS! crc is:14474ba6
aluop nn......................  PASS! crc is:9e922f9e
aluop <b,c,d,e,h,l,m,a>.......

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Get one of those shadow boxes and mount it on the wall or something!

Make a fine wall clock/temperature gauge!!

 

How about the 1802 processor on an Elf board...used to have one of those Kim1 boards

also, the Rockwell AIM-65 (6502)...Istill have the books

 

edit:  added elf board

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Fri. May 22, 2020 - 08:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

computing a variable bit shift at run time for an AVR can be a 'heavy' operation. On an Arm, it's a single instruction as it has a barrel shifter. 

 

You have a number of choices as to how you address this-

1. if you have full control over the port (as in your multiplex function uses the port exclusively) you can simply load the required value.

2. you can keep a variable with the column bit that you shift- 

 

uint8_t colSel;

 

top of loop:

colSel = (1 << 4);

 

 

colSel <<=1;  //for the next column

//then fiddle DDR

 

3. use a lookup table - this is a variation on #1

 

 

As an aside - kicking the watchdog in a timer isr is next to useless as it is almost guaranteed to happen. The protection you are expecting from the watchdog will not be there. A more robust solution is to put some logic to whether the watchdog gets kicked - specific parts of your code must do something in order for the watchdog kick to occur. If your code works on a superloop, then the watchdog gets kicked there. If anything upsets the superloop - bam! The watchdog kicks in.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, so I've optimized and optimized the ISR.  I am using a Saleae to measure 5 seconds and then add a measurement to see the average duty cycle, min positive width, and max positive width on a pin that is set when the ISR begins and cleared when it ends.

 

I've reduced and reduced it, but I can't see anything else to optimize.  Can you guys find anything else?

 

I would sorely like to find a way to reduce the input debouncing section...

 

ISR(TIMER0_COMPA_vect) //600 Hz = 1.667 ms
  {
    static uint8_t column,inputdebouncecount,input[3],inputlast[3],inputstate[3];

    //debug
    PORTD|=_BV(6);

    wdt_reset();                          //reset watchdog

    PORTC=0x00;                           //disable display

    //keyboard enable column
    switch(column)
      {
        case 0 :
          PORTA=display[0];               //update data for the next display
          DDRB|=_BV(4);                   //enable keyboard column
          PORTC|=_BV(2);                   //enable display column
          input[0]=~PINB & 0x0f;          //grab row
          column=1;
          break;

        case 1 :
          PORTA=display[1];               //update data for the next display
          DDRB|=_BV(5);                   //enable keyboard column
          PORTC|=_BV(3);                   //enable display column
          input[0]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
          column=2;
          break;

        case 2 :
          PORTA=display[2];               //update data for the next display
          DDRB|=_BV(6);                   //enable keyboard column
          PORTC|=_BV(4);                   //enable display column
          input[1]=~PINB & 0x0f;          //grab row
          column=3;
          break;

        case 3 :
          PORTA=display[3];               //update data for the next display
          DDRB|=_BV(7);                   //enable keyboard column
          PORTC|=_BV(5);                   //enable display column
          input[1]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
          column=4;
          break;

        case 4 :
          PORTA=display[4];               //update data for the next display
          DDRD|=_BV(4);                   //enable keyboard column
          PORTC|=_BV(6);                   //enable display column
          input[2]=~PINB & 0x0f;          //grab row
          column=5;
          break;

        case 5 :
          PORTA=display[5] | shift;               //update data for the next display
          DDRD|=_BV(5);                   //enable keyboard column
          PORTC|=_BV(7);                   //enable display column
          input[2]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
          column=0;

          //process key
          if (inputlast[0]==input[0] && inputlast[1]==input[1] && inputlast[2]==input[2])
            {
              inputdebouncecount++;

              //process into buffer
              if (inputdebouncecount==2 && (inputstate[0]!=input[0] || inputstate[1]!=input[1] || inputstate[2]!=input[2])) //debounce 30ms
                {
                  if (inputeventcount<INPUT_BUFFER_SIZE)
                    {
                      inputbuffer1[inputbufferin]=input[0];
                      inputbuffer2[inputbufferin]=input[1];
                      inputbuffer3[inputbufferin]=input[2];

                      inputbufferin++;
                      if (inputbufferin>=INPUT_BUFFER_SIZE)
                        inputbufferin=0;
                      inputeventcount++;
                    }

                  //update inputstate
                  inputstate[0]=input[0];
                  inputstate[1]=input[1];
                  inputstate[2]=input[2];
                }
            }
          else
            {
              inputlast[0]=input[0];
              inputlast[1]=input[1];
              inputlast[2]=input[2];

              inputdebouncecount=0;
            }
          break;
      }

    //keyboard disable column
    DDRB=0;
    DDRD=_BV(6) | _BV(7);

    //if brightness is not maximum, enable timer to turn it off to dim display
    if (OCR2A<119)
      {
        //clear timer
        TCNT2=0;

        //start timer
        TCCR2B=_BV(CS22) | _BV(CS21);
      }

    //debug
    PORTD&=~_BV(6);
  }

LSS:

 

ISR(TIMER0_COMPA_vect) //600 Hz = 1.667 ms
  {
 5c4:	1f 92       	push	r1
 5c6:	0f 92       	push	r0
 5c8:	0f b6       	in	r0, 0x3f	; 63
 5ca:	0f 92       	push	r0
 5cc:	11 24       	eor	r1, r1
 5ce:	0b b6       	in	r0, 0x3b	; 59
 5d0:	0f 92       	push	r0
 5d2:	2f 93       	push	r18
 5d4:	3f 93       	push	r19
 5d6:	4f 93       	push	r20
 5d8:	5f 93       	push	r21
 5da:	8f 93       	push	r24
 5dc:	9f 93       	push	r25
 5de:	ef 93       	push	r30
 5e0:	ff 93       	push	r31
    static uint8_t column,inputdebouncecount,input[3],inputlast[3],inputstate[3];

    //debug
    PORTD|=_BV(6);
 5e2:	5e 9a       	sbi	0x0b, 6	; 11

    wdt_reset();                          //reset watchdog
 5e4:	a8 95       	wdr

    PORTC=0x00;                           //disable display
 5e6:	18 b8       	out	0x08, r1	; 8

    //keyboard enable column
    switch(column)
 5e8:	80 91 0a 01 	lds	r24, 0x010A	; 0x80010a <column.1879>
 5ec:	82 30       	cpi	r24, 0x02	; 2
 5ee:	09 f4       	brne	.+2      	; 0x5f2 <__vector_16+0x2e>
 5f0:	8d c0       	rjmp	.+282    	; 0x70c <__vector_16+0x148>
 5f2:	08 f4       	brcc	.+2      	; 0x5f6 <__vector_16+0x32>
 5f4:	47 c0       	rjmp	.+142    	; 0x684 <__vector_16+0xc0>
 5f6:	84 30       	cpi	r24, 0x04	; 4
 5f8:	09 f4       	brne	.+2      	; 0x5fc <__vector_16+0x38>
 5fa:	5a c0       	rjmp	.+180    	; 0x6b0 <__vector_16+0xec>
 5fc:	08 f4       	brcc	.+2      	; 0x600 <__vector_16+0x3c>
 5fe:	74 c0       	rjmp	.+232    	; 0x6e8 <__vector_16+0x124>
 600:	85 30       	cpi	r24, 0x05	; 5
 602:	21 f5       	brne	.+72     	; 0x64c <__vector_16+0x88>
          input[2]=~PINB & 0x0f;          //grab row
          column=5;
          break;

        case 5 :
          PORTA=display[5] | shift;               //update data for the next display
 604:	90 91 28 3d 	lds	r25, 0x3D28	; 0x803d28 <display+0x5>
 608:	80 91 0e 01 	lds	r24, 0x010E	; 0x80010e <shift>
 60c:	89 2b       	or	r24, r25
 60e:	82 b9       	out	0x02, r24	; 2
          DDRD|=_BV(5);                   //enable keyboard column
 610:	55 9a       	sbi	0x0a, 5	; 10
          PORTC|=_BV(7);                   //enable display column
 612:	47 9a       	sbi	0x08, 7	; 8
          input[2]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
 614:	83 b1       	in	r24, 0x03	; 3
 616:	80 95       	com	r24
 618:	82 95       	swap	r24
 61a:	80 7f       	andi	r24, 0xF0	; 240
 61c:	90 91 09 01 	lds	r25, 0x0109	; 0x800109 <input.1881+0x2>
 620:	89 2b       	or	r24, r25
 622:	80 93 09 01 	sts	0x0109, r24	; 0x800109 <input.1881+0x2>
          column=0;
 626:	10 92 0a 01 	sts	0x010A, r1	; 0x80010a <column.1879>

          //process key
          if (inputlast[0]==input[0] && inputlast[1]==input[1] && inputlast[2]==input[2])
 62a:	30 91 04 01 	lds	r19, 0x0104	; 0x800104 <inputlast.1882>
 62e:	90 91 07 01 	lds	r25, 0x0107	; 0x800107 <input.1881>
 632:	39 17       	cp	r19, r25
 634:	09 f4       	brne	.+2      	; 0x638 <__vector_16+0x74>
 636:	78 c0       	rjmp	.+240    	; 0x728 <__vector_16+0x164>
 638:	20 91 08 01 	lds	r18, 0x0108	; 0x800108 <input.1881+0x1>
                  inputstate[2]=input[2];
                }
            }
          else
            {
              inputlast[0]=input[0];
 63c:	90 93 04 01 	sts	0x0104, r25	; 0x800104 <inputlast.1882>
              inputlast[1]=input[1];
 640:	20 93 05 01 	sts	0x0105, r18	; 0x800105 <inputlast.1882+0x1>
              inputlast[2]=input[2];
 644:	80 93 06 01 	sts	0x0106, r24	; 0x800106 <inputlast.1882+0x2>

              inputdebouncecount=0;
 648:	10 92 03 01 	sts	0x0103, r1	; 0x800103 <inputdebouncecount.1880>
            }
          break;
      }

    //keyboard disable column
    DDRB=0;
 64c:	14 b8       	out	0x04, r1	; 4
    DDRD=_BV(6) | _BV(7);
 64e:	80 ec       	ldi	r24, 0xC0	; 192
 650:	8a b9       	out	0x0a, r24	; 10

    //if brightness is not maximum, enable timer to turn it off to dim display
    if (OCR2A<119)
 652:	80 91 b3 00 	lds	r24, 0x00B3	; 0x8000b3 <__TEXT_REGION_LENGTH__+0x7e00b3>
 656:	87 37       	cpi	r24, 0x77	; 119
 658:	28 f4       	brcc	.+10     	; 0x664 <__vector_16+0xa0>
      {
        //clear timer
        TCNT2=0;
 65a:	10 92 b2 00 	sts	0x00B2, r1	; 0x8000b2 <__TEXT_REGION_LENGTH__+0x7e00b2>

        //start timer
        TCCR2B=_BV(CS22) | _BV(CS21);
 65e:	86 e0       	ldi	r24, 0x06	; 6
 660:	80 93 b1 00 	sts	0x00B1, r24	; 0x8000b1 <__TEXT_REGION_LENGTH__+0x7e00b1>
      }

    //debug
    PORTD&=~_BV(6);
 664:	5e 98       	cbi	0x0b, 6	; 11
  }
 666:	ff 91       	pop	r31
 668:	ef 91       	pop	r30
 66a:	9f 91       	pop	r25
 66c:	8f 91       	pop	r24
 66e:	5f 91       	pop	r21
 670:	4f 91       	pop	r20
 672:	3f 91       	pop	r19
 674:	2f 91       	pop	r18
 676:	0f 90       	pop	r0
 678:	0b be       	out	0x3b, r0	; 59
 67a:	0f 90       	pop	r0
 67c:	0f be       	out	0x3f, r0	; 63
 67e:	0f 90       	pop	r0
 680:	1f 90       	pop	r1
 682:	18 95       	reti
    wdt_reset();                          //reset watchdog

    PORTC=0x00;                           //disable display

    //keyboard enable column
    switch(column)
 684:	88 23       	and	r24, r24
 686:	11 f1       	breq	.+68     	; 0x6cc <__vector_16+0x108>
 688:	81 30       	cpi	r24, 0x01	; 1
 68a:	01 f7       	brne	.-64     	; 0x64c <__vector_16+0x88>
          input[0]=~PINB & 0x0f;          //grab row
          column=1;
          break;

        case 1 :
          PORTA=display[1];               //update data for the next display
 68c:	80 91 24 3d 	lds	r24, 0x3D24	; 0x803d24 <display+0x1>
 690:	82 b9       	out	0x02, r24	; 2
          DDRB|=_BV(5);                   //enable keyboard column
 692:	25 9a       	sbi	0x04, 5	; 4
          PORTC|=_BV(3);                   //enable display column
 694:	43 9a       	sbi	0x08, 3	; 8
          input[0]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
 696:	83 b1       	in	r24, 0x03	; 3
 698:	80 95       	com	r24
 69a:	82 95       	swap	r24
 69c:	80 7f       	andi	r24, 0xF0	; 240
 69e:	90 91 07 01 	lds	r25, 0x0107	; 0x800107 <input.1881>
 6a2:	89 2b       	or	r24, r25
 6a4:	80 93 07 01 	sts	0x0107, r24	; 0x800107 <input.1881>
          column=2;
 6a8:	82 e0       	ldi	r24, 0x02	; 2
 6aa:	80 93 0a 01 	sts	0x010A, r24	; 0x80010a <column.1879>
          break;
 6ae:	ce cf       	rjmp	.-100    	; 0x64c <__vector_16+0x88>
          input[1]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
          column=4;
          break;

        case 4 :
          PORTA=display[4];               //update data for the next display
 6b0:	80 91 27 3d 	lds	r24, 0x3D27	; 0x803d27 <display+0x4>
 6b4:	82 b9       	out	0x02, r24	; 2
          DDRD|=_BV(4);                   //enable keyboard column
 6b6:	54 9a       	sbi	0x0a, 4	; 10
          PORTC|=_BV(6);                   //enable display column
 6b8:	46 9a       	sbi	0x08, 6	; 8
          input[2]=~PINB & 0x0f;          //grab row
 6ba:	83 b1       	in	r24, 0x03	; 3
 6bc:	80 95       	com	r24
 6be:	8f 70       	andi	r24, 0x0F	; 15
 6c0:	80 93 09 01 	sts	0x0109, r24	; 0x800109 <input.1881+0x2>
          column=5;
 6c4:	85 e0       	ldi	r24, 0x05	; 5
 6c6:	80 93 0a 01 	sts	0x010A, r24	; 0x80010a <column.1879>
          break;
 6ca:	c0 cf       	rjmp	.-128    	; 0x64c <__vector_16+0x88>

    //keyboard enable column
    switch(column)
      {
        case 0 :
          PORTA=display[0];               //update data for the next display
 6cc:	80 91 23 3d 	lds	r24, 0x3D23	; 0x803d23 <display>
 6d0:	82 b9       	out	0x02, r24	; 2
          DDRB|=_BV(4);                   //enable keyboard column
 6d2:	24 9a       	sbi	0x04, 4	; 4
          PORTC|=_BV(2);                   //enable display column
 6d4:	42 9a       	sbi	0x08, 2	; 8
          input[0]=~PINB & 0x0f;          //grab row
 6d6:	83 b1       	in	r24, 0x03	; 3
 6d8:	80 95       	com	r24
 6da:	8f 70       	andi	r24, 0x0F	; 15
 6dc:	80 93 07 01 	sts	0x0107, r24	; 0x800107 <input.1881>
          column=1;
 6e0:	81 e0       	ldi	r24, 0x01	; 1
 6e2:	80 93 0a 01 	sts	0x010A, r24	; 0x80010a <column.1879>
          break;
 6e6:	b2 cf       	rjmp	.-156    	; 0x64c <__vector_16+0x88>
          input[1]=~PINB & 0x0f;          //grab row
          column=3;
          break;

        case 3 :
          PORTA=display[3];               //update data for the next display
 6e8:	80 91 26 3d 	lds	r24, 0x3D26	; 0x803d26 <display+0x3>
 6ec:	82 b9       	out	0x02, r24	; 2
          DDRB|=_BV(7);                   //enable keyboard column
 6ee:	27 9a       	sbi	0x04, 7	; 4
          PORTC|=_BV(5);                   //enable display column
 6f0:	45 9a       	sbi	0x08, 5	; 8
          input[1]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
 6f2:	83 b1       	in	r24, 0x03	; 3
 6f4:	80 95       	com	r24
 6f6:	82 95       	swap	r24
 6f8:	80 7f       	andi	r24, 0xF0	; 240
 6fa:	90 91 08 01 	lds	r25, 0x0108	; 0x800108 <input.1881+0x1>
 6fe:	89 2b       	or	r24, r25
 700:	80 93 08 01 	sts	0x0108, r24	; 0x800108 <input.1881+0x1>
          column=4;
 704:	84 e0       	ldi	r24, 0x04	; 4
 706:	80 93 0a 01 	sts	0x010A, r24	; 0x80010a <column.1879>
          break;
 70a:	a0 cf       	rjmp	.-192    	; 0x64c <__vector_16+0x88>
          input[0]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
          column=2;
          break;

        case 2 :
          PORTA=display[2];               //update data for the next display
 70c:	80 91 25 3d 	lds	r24, 0x3D25	; 0x803d25 <display+0x2>
 710:	82 b9       	out	0x02, r24	; 2
          DDRB|=_BV(6);                   //enable keyboard column
 712:	26 9a       	sbi	0x04, 6	; 4
          PORTC|=_BV(4);                   //enable display column
 714:	44 9a       	sbi	0x08, 4	; 8
          input[1]=~PINB & 0x0f;          //grab row
 716:	83 b1       	in	r24, 0x03	; 3
 718:	80 95       	com	r24
 71a:	8f 70       	andi	r24, 0x0F	; 15
 71c:	80 93 08 01 	sts	0x0108, r24	; 0x800108 <input.1881+0x1>
          column=3;
 720:	83 e0       	ldi	r24, 0x03	; 3
 722:	80 93 0a 01 	sts	0x010A, r24	; 0x80010a <column.1879>
          break;
 726:	92 cf       	rjmp	.-220    	; 0x64c <__vector_16+0x88>
          PORTC|=_BV(7);                   //enable display column
          input[2]|=(uint8_t)((~PINB & 0x0f)<<4);    //grab row
          column=0;

          //process key
          if (inputlast[0]==input[0] && inputlast[1]==input[1] && inputlast[2]==input[2])
 728:	40 91 05 01 	lds	r20, 0x0105	; 0x800105 <inputlast.1882+0x1>
 72c:	20 91 08 01 	lds	r18, 0x0108	; 0x800108 <input.1881+0x1>
 730:	42 13       	cpse	r20, r18
 732:	84 cf       	rjmp	.-248    	; 0x63c <__vector_16+0x78>
 734:	50 91 06 01 	lds	r21, 0x0106	; 0x800106 <inputlast.1882+0x2>
 738:	85 13       	cpse	r24, r21
 73a:	80 cf       	rjmp	.-256    	; 0x63c <__vector_16+0x78>
            {
              inputdebouncecount++;
 73c:	90 91 03 01 	lds	r25, 0x0103	; 0x800103 <inputdebouncecount.1880>
 740:	9f 5f       	subi	r25, 0xFF	; 255
 742:	90 93 03 01 	sts	0x0103, r25	; 0x800103 <inputdebouncecount.1880>

              //process into buffer
              if (inputdebouncecount==2 && (inputstate[0]!=input[0] || inputstate[1]!=input[1] || inputstate[2]!=input[2])) //debounce 30ms
 746:	92 30       	cpi	r25, 0x02	; 2
 748:	09 f0       	breq	.+2      	; 0x74c <__vector_16+0x188>
 74a:	80 cf       	rjmp	.-256    	; 0x64c <__vector_16+0x88>
 74c:	90 91 00 01 	lds	r25, 0x0100	; 0x800100 <__DATA_REGION_ORIGIN__>
 750:	39 17       	cp	r19, r25
 752:	69 f1       	breq	.+90     	; 0x7ae <__vector_16+0x1ea>
                {
                  if (inputeventcount<INPUT_BUFFER_SIZE)
 754:	90 91 29 3d 	lds	r25, 0x3D29	; 0x803d29 <inputeventcount>
 758:	90 32       	cpi	r25, 0x20	; 32
 75a:	10 f5       	brcc	.+68     	; 0x7a0 <__vector_16+0x1dc>
                    {
                      inputbuffer1[inputbufferin]=input[0];
 75c:	e0 91 10 01 	lds	r30, 0x0110	; 0x800110 <inputbufferin>
 760:	f0 e0       	ldi	r31, 0x00	; 0
 762:	e6 5b       	subi	r30, 0xB6	; 182
 764:	f2 4c       	sbci	r31, 0xC2	; 194
 766:	30 83       	st	Z, r19
                      inputbuffer2[inputbufferin]=input[1];
 768:	e0 91 10 01 	lds	r30, 0x0110	; 0x800110 <inputbufferin>
 76c:	f0 e0       	ldi	r31, 0x00	; 0
 76e:	e6 59       	subi	r30, 0x96	; 150
 770:	f2 4c       	sbci	r31, 0xC2	; 194
 772:	40 83       	st	Z, r20
                      inputbuffer3[inputbufferin]=input[2];
 774:	e0 91 10 01 	lds	r30, 0x0110	; 0x800110 <inputbufferin>
 778:	f0 e0       	ldi	r31, 0x00	; 0
 77a:	e6 5d       	subi	r30, 0xD6	; 214
 77c:	f2 4c       	sbci	r31, 0xC2	; 194
 77e:	80 83       	st	Z, r24

                      inputbufferin++;
 780:	90 91 10 01 	lds	r25, 0x0110	; 0x800110 <inputbufferin>
 784:	9f 5f       	subi	r25, 0xFF	; 255
 786:	90 93 10 01 	sts	0x0110, r25	; 0x800110 <inputbufferin>
                      if (inputbufferin>=INPUT_BUFFER_SIZE)
 78a:	90 91 10 01 	lds	r25, 0x0110	; 0x800110 <inputbufferin>
 78e:	90 32       	cpi	r25, 0x20	; 32
 790:	10 f0       	brcs	.+4      	; 0x796 <__vector_16+0x1d2>
                        inputbufferin=0;
 792:	10 92 10 01 	sts	0x0110, r1	; 0x800110 <inputbufferin>
                      inputeventcount++;
 796:	90 91 29 3d 	lds	r25, 0x3D29	; 0x803d29 <inputeventcount>
 79a:	9f 5f       	subi	r25, 0xFF	; 255
 79c:	90 93 29 3d 	sts	0x3D29, r25	; 0x803d29 <inputeventcount>
                    }

                  //update inputstate
                  inputstate[0]=input[0];
 7a0:	30 93 00 01 	sts	0x0100, r19	; 0x800100 <__DATA_REGION_ORIGIN__>
                  inputstate[1]=input[1];
 7a4:	40 93 01 01 	sts	0x0101, r20	; 0x800101 <__DATA_REGION_ORIGIN__+0x1>
                  inputstate[2]=input[2];
 7a8:	80 93 02 01 	sts	0x0102, r24	; 0x800102 <__DATA_REGION_ORIGIN__+0x2>
 7ac:	4f cf       	rjmp	.-354    	; 0x64c <__vector_16+0x88>
          if (inputlast[0]==input[0] && inputlast[1]==input[1] && inputlast[2]==input[2])
            {
              inputdebouncecount++;

              //process into buffer
              if (inputdebouncecount==2 && (inputstate[0]!=input[0] || inputstate[1]!=input[1] || inputstate[2]!=input[2])) //debounce 30ms
 7ae:	90 91 01 01 	lds	r25, 0x0101	; 0x800101 <__DATA_REGION_ORIGIN__+0x1>
 7b2:	49 13       	cpse	r20, r25
 7b4:	cf cf       	rjmp	.-98     	; 0x754 <__vector_16+0x190>
 7b6:	90 91 02 01 	lds	r25, 0x0102	; 0x800102 <__DATA_REGION_ORIGIN__+0x2>
 7ba:	89 13       	cpse	r24, r25
 7bc:	cb cf       	rjmp	.-106    	; 0x754 <__vector_16+0x190>
 7be:	46 cf       	rjmp	.-372    	; 0x64c <__vector_16+0x88>

000007c0 <__vector_9>:
    //debug
    PORTD&=~_BV(6);
  }

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First how do you make the emulator C or ASM ?

 

If ASM where do you place the registers of the 8080?

 

Reason for asking is about what to use the low registers for r2-r15.

 

In your case version you don't really need the index of input etc. so if they are normal uint8_t placed in low registers it will go way faster.

But again I would probably use those for the emulator.

 

for #21 :

How about the 1802 processor...used to have one of those Kim1 boards

also, the Rockwell AIM-65 (6502)...iIstill have the books

 

? Kim1 is also a 6502

 

 

Some time back I was playing with some code so you could emulate a AVR on a AVR (don't ask) written in ASM, And from that I would guess that it will/should take in the ballpark of 18 clk for the simple 4 clk instructions (if all 8080 registers is in AVR low registers), so that should be about a 4MHz 8080. (the problem with the AVR was that all instructions is 16bit, on the other hand all flags are handled correct)   

Last Edited: Fri. May 22, 2020 - 07:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, I left the ELF behind at the old processor station!

How about the 1802 processor on an ELF board...used to have one of those Kim1 boards

also, the Rockwell AIM-65 (6502)...I still have the books

 

Those were the good old days of switch flipping...or paper tape if you were lucky.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 - emulator is written in C.

 

avrcandies - I've wanted to make a binary control panel machine too, but the pain of flipping switches in binary is too great!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My overnight test had the uart wire come unplugged so I missed the results!  I restarted it and:

 

RESET
8080 instruction exerciser
dad <b,d,h,sp>................  PASS! crc is:14474ba6
aluop nn......................  PASS! crc is:9e922f9e
aluop <b,c,d,e,h,l,m,a>.......  PASS! crc is:cf762c86
<daa,cma,stc,cmc>.............  PASS! crc is:bb3f030c
<inr,dcr> a...................  PASS! crc is:adb6460e
<inr,dcr> b...................  PASS! crc is:83ed1345
<inx,dcx> b...................  PASS! crc is:f79287cd
<inr,dcr> c...................  PASS! crc is:e5f6721b
<inr,dcr> d...................  PASS! crc is:15b5579a
<inx,dcx> d...................  PASS! crc is:7f4e2501
<inr,dcr> e...................  PASS! crc is:cf2ab396
<inr,dcr> h...................  PASS! crc is:12b2952c
<inx,dcx> h...................  PASS! crc is:9f2b23c0
<inr,dcr> l...................  PASS! crc is:ff57d356
<inr,dcr> m...................  PASS! crc is:92e963bd
<inx,dcx> sp..................  PASS! crc is:d5702fab
lhld nnnn.....................  PASS! crc is:a9c3d5cb
shld nnnn.....................  PASS! crc is:e8864f26
lxi <b,d,h,sp>,nnnn...........  PASS! crc is:fcf46e12
ldax <b,d>....................  PASS! crc is:2b821d5f
mvi <b,c,d,e,h,l,m,a>,nn......  PASS! crc is:eaa72044
mov <bcdehla>,<bcdehla>.......  PASS! crc is:10b58cee
sta nnnn / lda nnnn...........  PASS! crc is:ed57af72
<rlc,rrc,ral,rar>.............  PASS! crc is:e0d89235
stax <b,d>....................  PASS! crc is:2b0471e9
Tests completetime 11891.32

This is 23803464422 i8080 cycles in 11891.32 seconds or 2.00175 MHz emulation speed...

 

I'm attaching a picture of the keys.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

you should try to force your compiler to place a and f in registers. (and probably also bc de hl ).

 

how you do it depends of your c compiler (they can all do it, but have different ways).

 

add

if it's GCC it's relative simple (read the help), but you also need to tell the compiler not to generate "normal" code that also use those registers.  

Last Edited: Fri. May 22, 2020 - 04:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks sparrow2 - is it using the register keyword?  Is it a program wide thing as in I can say use this register for this a global variable uin8_t accumulator always?  That would be cool if it would work that way.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, I found this:

 

6.47.5.1 Defining Global Register Variables

 

You can define a global register variable and associate it with a specified register like this:

register int *foo asm ("r12");

in the AVR's case I'm assuming it should be uint8_t, but how do you know which register to use that won't interfere so much with the way gcc usually uses them?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

-ffixed-12 (or whatever register number) but be warned libc may contain code already built to use r12 so grep the lss.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I get the grep part of your post clawson, but where do I put -ffixed-12?  If I have more than one is it "-ffixed-12 -ffixed-13"?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The compiler works it way down, so don't just pick a registers, start from r2 and up (GCC need control of r0 and r1).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks sparrow2.

 

It looks like it works with a bitfield too, so that will be good for the flags:

 

register struct
  {
    uint8_t a:1;
    uint8_t b:1;

  } z asm ("r13");

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

the chip you use has 3 GPIORn registers, that should be used for flags. (The AVR can direct set and clr one bit), it can't do it on the lower 16 registers.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It looks like GPIOR0 is at 0x1E (0x3E) - I think the bit instructions will work on it.  I could use GPIOR1 for A then.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My guess is that A should be in a normal register, and when you "execute" and instruction A should be in high register.

But F could probably be placed in a GPIORn. One of the things that cost a lot of time (and in general no use) is updating the P flag. (A hack could be to have last result where P was generated and then only calc. P when needed)

   

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've got a table I am doing a lookup to pull in the parity flag.

 

Is there any way any register can be treated as a register pair?

 

register uint16_t accum asm ("r13");  asm ("r14");

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Since GPIOR0 is not a register like r13, is there a better way to use GPIOR0 as my bitfield than this:

 

typedef struct
  {
        uint8_t carry    : 1;
        uint8_t x1       : 1;
        uint8_t parity   : 1;
        uint8_t x3       : 1;
        uint8_t auxcarry : 1;
        uint8_t x5       : 1;
        uint8_t zero     : 1;
        uint8_t sign     : 1;
  } flags;

#define i80_flags (*(flags*)&GPIOR0)

Then I can do:

i80_flags.sign=1;

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry for 3 posts in a row!  This expands on post #38.

 

I use this to reference B or C or BC together as a uint16_t:

 

typedef union
  {
    struct
      {
        uint8_t l,h;
      } b;
    uint16_t w;
  } i80_regpair;

Is there any way this structure can be put into registers?  If I only dealt with B and C separately then I could see how it would work, but when I had to deal with them together, what then?  Just cast them as a uint16_t like this?

 

*(uint16_t*)(b <<8 | c)+=0x1234;

 

But, is there a way to do it the other way around - let's say I have a uint16_t value.  Can I assign the result of it to two uint8_t's in one statement?

 

Last Edited: Sat. May 23, 2020 - 12:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You just declare a 16 bit variable at a register (and it will also use the next), as I remember they have to start at a even register number (the way the AVR use register pairs).

 

And I will again point out that you should start at r2 !  , by using higher register numbers I fear that you block the compilers ability to generate (semi)efficient code.   

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't know if any help but on "normal" AVR's like the 1284  r2 also is RAM addr 2. So with things like load to BC DE HL can be controlled via a pointers, even if placed in registers.

 

 

add:

From #38

I've got a table I am doing a lookup to pull in the parity flag.

But unless the table is placed in RAM the compiler has change Z, so even if the LPM only take 3 clk then it will take about 10-12 clk for the hole thing, (mostly the value in Z can't be reused).

Last Edited: Sat. May 23, 2020 - 10:49 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

-ffixed-N goes on the command line when the compiler is invoked. If you are building from inside an IDE like AS7 then in the project properties for C/C++ just add the option under "Miscellaneous"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 - I tried a uint16_t with register, but it failed because I used an odd numbered register - thanks for pointing that out.

 

clawson - thanks I found it.

 

I appreciate the help!  This gives me more to test and try today - it takes 3 hours to run through the entire cpu test, so it is a start it and wait for results thing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm starting with r2 and going up.

 

I moved all the regs (A, BC, DE, HL, SP, and PC) into AVR registers r2-r12), and put flags into GPIOR0.  Running a test to see the performance now.

 

Some results - I wonder if the small differences between these methods means there are other places that need optimization.  I'll dig into the LSS and see if anything jumps out!

 

before optimization        23803464422/11891.32/1e6 = 2.00218 MHz

no more pointer passing    23803464422/11899.72/1e6 = 2.00034 MHz
(using function returns instead)

flags in a uint8_t         23803464422/12139.84/1e6 = 1.96077 MHz
(flags were separate uint8_t's before)'

flags in GPIOR0            23803464422/11791.95/1e6 = 2.01862 MHz
regs for A BC DE HL	(odd combining method)

flags in GPIOR0            23803464422/11708.55/1e6 = 2.03300 MHz
regs for A only

flags in GPIOR0            23803464422/11860.72/1e6 = 2.00692 MHz
A in GPIOR1

ALL in regs including      <testing>
pc/sp now properly in
AVR registers, flasg
still in GPIOR0

 

Last Edited: Sat. May 23, 2020 - 05:09 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As the code itself isn't  (presumably?) tied specifically to AVR, build a version for an x86 target then use something like gprof or Valgrind to analyze where the heavy lifting is then concentrate on that for the AVR target build.

Last Edited: Sat. May 23, 2020 - 06:12 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So when you say the speed is about 2MHz does that just mean it for the total time, and not trying to make the different instructions speed to be correct relative to each other ?

 

The slow instructions run relative faster. The problem is the fast "simple" instructions that take 4 clk but change the flags. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Correct clawson - I tried to write the emulation code so that it would compile well under different platforms - it compiles under WIN32 and DOS too with pretty decent results.  I was pretty happy with how it does on the AVR because I haven't really done any platform optimizing on it so far.  I'll have to search for gprof/Valgrind - these are profilers presumably?  I'm going to dig into the LSS on the emulation code and see if anything jumps out as being inefficient.

 

sparrow2 - it is an overall speed after running the CPU test which is 23,803,464,422 clocks on a real 8080.  So what I do is run the test and measure the time it took to run.  As I am emulating at the instruction level and not the cycle level, each instruction will add its proper number of cycles to the cycle counter.  You are exactly right that some instructions are much more penalized than others if they have to set the flags, or complicated instructions like the DAA instruction which tries to fix BCD addition.  The difference between logic and parallel execution and sequential code can be pretty big sometimes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Gprof is the profiling part if gcc. Basically you build the code with extended gcc options so it adds annotation points. When you run the binary it spews logging info. Then the separate gprof tool can use the data to build a profile.

 

Valgrind is an EXTENSIVE dev tool for PC software. It can do all sorts with "plugins". It's really a virtual machine but one with "hooks" in the virtual x86 CPU so it can trace all that is executed. That includes stuff like memory allocations (perhaps its main use?) but it can track opcode execution and report things like where is the CPU spending all it's time (which becomes your target area for optimization).

Last Edited: Sat. May 23, 2020 - 06:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'll have to check those out clawson.

 

BTW - my latest test was by far the best results:

 

I moved all the regs (A, BC, DE,      23803464422/9967.06/1e6 = 2.38821 MHz
HL, SP, and PC) into AVR registers
r2-r12), and put flags into GPIOR0.

here are the regs now:

 

#ifdef __GNUC__
  //AVR regs
  register uint8_t i80_a asm ("r12");
  #define i80_f (*(i80_flags*)&GPIOR0) //i80_flags i80_f;
  register i80_regpair i80_bc asm ("r2");
  register i80_regpair i80_de asm ("r4");
  register i80_regpair i80_hl asm ("r6");
  register uint16_t i80_sp asm ("r8");
  register uint16_t i80_pc asm ("r10");
#else
  //DOS or WIN32 regs
  uint8_t i80_a;
  i80_flags i80_f;
  i80_regpair i80_bc;
  i80_regpair i80_de;
  i80_regpair i80_hl;
  uint16_t i80_sp;
  uint16_t i80_pc;
#endif

 

 

Last Edited: Sat. May 23, 2020 - 10:20 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One small test could be to place A in r16 , and perhaps F in r17. this make some immediate instructions on A faster, but perhaps other things will slow down because the compiler would like to use those.registers.  

Last Edited: Sat. May 23, 2020 - 10:11 PM

Pages