⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spokepov.lss

📁 旋转16个LED灯控制程序
💻 LSS
📖 第 1 页 / 共 3 页
字号:

spokepov.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000004e6  00000000  00000000  00000094  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000022  00800060  000004e6  0000057a  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          0000000f  00800082  00800082  0000059c  2**0
                  ALLOC
  3 .noinit       00000000  00800091  00800091  0000059c  2**0
                  CONTENTS
  4 .eeprom       00000000  00810000  00810000  0000059c  2**0
                  CONTENTS
  5 .stab         00000354  00000000  00000000  0000059c  2**2
                  CONTENTS, READONLY, DEBUGGING
  6 .stabstr      00000084  00000000  00000000  000008f0  2**0
                  CONTENTS, READONLY, DEBUGGING
  7 .debug_aranges 00000028  00000000  00000000  00000974  2**0
                  CONTENTS, READONLY, DEBUGGING
  8 .debug_pubnames 0000017a  00000000  00000000  0000099c  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .debug_info   000004ac  00000000  00000000  00000b16  2**0
                  CONTENTS, READONLY, DEBUGGING
 10 .debug_abbrev 000001d3  00000000  00000000  00000fc2  2**0
                  CONTENTS, READONLY, DEBUGGING
 11 .debug_line   00000476  00000000  00000000  00001195  2**0
                  CONTENTS, READONLY, DEBUGGING
 12 .debug_str    000001fb  00000000  00000000  0000160b  2**0
                  CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:

00000000 <__vectors>:
   0:	12 c0       	rjmp	.+36     	; 0x26 <__ctors_end>
   2:	5f c0       	rjmp	.+190    	; 0xc2 <__vector_1>
   4:	f4 c0       	rjmp	.+488    	; 0x1ee <__vector_2>
   6:	28 c0       	rjmp	.+80     	; 0x58 <__bad_interrupt>
   8:	50 c1       	rjmp	.+672    	; 0x2aa <__vector_4>
   a:	26 c0       	rjmp	.+76     	; 0x58 <__bad_interrupt>
   c:	27 c0       	rjmp	.+78     	; 0x5c <__vector_6>
   e:	24 c0       	rjmp	.+72     	; 0x58 <__bad_interrupt>
  10:	23 c0       	rjmp	.+70     	; 0x58 <__bad_interrupt>
  12:	22 c0       	rjmp	.+68     	; 0x58 <__bad_interrupt>
  14:	21 c0       	rjmp	.+66     	; 0x58 <__bad_interrupt>
  16:	20 c0       	rjmp	.+64     	; 0x58 <__bad_interrupt>
  18:	1f c0       	rjmp	.+62     	; 0x58 <__bad_interrupt>
  1a:	1e c0       	rjmp	.+60     	; 0x58 <__bad_interrupt>
  1c:	1d c0       	rjmp	.+58     	; 0x58 <__bad_interrupt>
  1e:	1c c0       	rjmp	.+56     	; 0x58 <__bad_interrupt>
  20:	1b c0       	rjmp	.+54     	; 0x58 <__bad_interrupt>
  22:	1a c0       	rjmp	.+52     	; 0x58 <__bad_interrupt>
  24:	19 c0       	rjmp	.+50     	; 0x58 <__bad_interrupt>

00000026 <__ctors_end>:
  26:	11 24       	eor	r1, r1
  28:	1f be       	out	0x3f, r1	; 63
  2a:	cf ed       	ldi	r28, 0xDF	; 223
  2c:	cd bf       	out	0x3d, r28	; 61

0000002e <__do_copy_data>:
  2e:	10 e0       	ldi	r17, 0x00	; 0
  30:	a0 e6       	ldi	r26, 0x60	; 96
  32:	b0 e0       	ldi	r27, 0x00	; 0
  34:	e6 ee       	ldi	r30, 0xE6	; 230
  36:	f4 e0       	ldi	r31, 0x04	; 4
  38:	03 c0       	rjmp	.+6      	; 0x40 <.do_copy_data_start>

0000003a <.do_copy_data_loop>:
  3a:	c8 95       	lpm
  3c:	31 96       	adiw	r30, 0x01	; 1
  3e:	0d 92       	st	X+, r0

00000040 <.do_copy_data_start>:
  40:	a2 38       	cpi	r26, 0x82	; 130
  42:	b1 07       	cpc	r27, r17
  44:	d1 f7       	brne	.-12     	; 0x3a <.do_copy_data_loop>

00000046 <__do_clear_bss>:
  46:	10 e0       	ldi	r17, 0x00	; 0
  48:	a2 e8       	ldi	r26, 0x82	; 130
  4a:	b0 e0       	ldi	r27, 0x00	; 0
  4c:	01 c0       	rjmp	.+2      	; 0x50 <.do_clear_bss_start>

0000004e <.do_clear_bss_loop>:
  4e:	1d 92       	st	X+, r1

00000050 <.do_clear_bss_start>:
  50:	a1 39       	cpi	r26, 0x91	; 145
  52:	b1 07       	cpc	r27, r17
  54:	e1 f7       	brne	.-8      	; 0x4e <.do_clear_bss_loop>
  56:	fc c1       	rjmp	.+1016   	; 0x450 <main>

00000058 <__bad_interrupt>:
  58:	d3 cf       	rjmp	.-90     	; 0x0 <__vectors>

0000005a <get_line>:
// text are stored here (and hopefully don't use much ram!)

/* The lines that will be displayed on the SpokePOV							*/

void get_line(uint8_t *buff, uint16_t line_num) {
  5a:	08 95       	ret

0000005c <__vector_6>:

  uint8_t *lines;
  
  
  lines = 
		"                "
		"   Episode IV   "
		"   A New Hope   "
		"                "
		" It is a period "
		" of civil war.  "
		"                "
		"                "
		;

}

// TIMER0 interrupt handler.  This runs about every 3ms
// AFAICT.  It increments the hall_debounce and sensor_timer
// values until they pin.

// QUESTION: what's with the setting and clearing of PORTB0?
// According to the wiring diagram, it isn't connected to
// anything.  Is this vestigial code from when you were using
// Pin Change Interrupts?  Or is it debugger code so you
// can monitor the pins and tell when something happens.

SIGNAL (SIG_TIMER0_OVF) {
  5c:	1f 92       	push	r1
  5e:	0f 92       	push	r0
  60:	0f b6       	in	r0, 0x3f	; 63
  62:	0f 92       	push	r0
  64:	11 24       	eor	r1, r1
  66:	2f 93       	push	r18
  68:	8f 93       	push	r24
  6a:	9f 93       	push	r25

  // *** PORTB |= 0x1;

  if (hall_debounce != 0xFF)
  6c:	80 91 8a 00 	lds	r24, 0x008A
  70:	8f 3f       	cpi	r24, 0xFF	; 255
  72:	29 f0       	breq	.+10     	; 0x7e <__vector_6+0x22>
    hall_debounce++;
  74:	80 91 8a 00 	lds	r24, 0x008A
  78:	8f 5f       	subi	r24, 0xFF	; 255
  7a:	80 93 8a 00 	sts	0x008A, r24
  
  if (sensor_timer != 0xFFFF)
  7e:	80 91 8b 00 	lds	r24, 0x008B
  82:	90 91 8c 00 	lds	r25, 0x008C
  86:	8f 5f       	subi	r24, 0xFF	; 255
  88:	9f 4f       	sbci	r25, 0xFF	; 255
  8a:	49 f0       	breq	.+18     	; 0x9e <__vector_6+0x42>
    sensor_timer++;
  8c:	80 91 8b 00 	lds	r24, 0x008B
  90:	90 91 8c 00 	lds	r25, 0x008C
  94:	01 96       	adiw	r24, 0x01	; 1
  96:	90 93 8c 00 	sts	0x008C, r25
  9a:	80 93 8b 00 	sts	0x008B, r24
  9e:	9f 91       	pop	r25
  a0:	8f 91       	pop	r24
  a2:	2f 91       	pop	r18
  a4:	0f 90       	pop	r0
  a6:	0f be       	out	0x3f, r0	; 63
  a8:	0f 90       	pop	r0
  aa:	1f 90       	pop	r1
  ac:	18 95       	reti

000000ae <delay_ms>:

  // *** PORTB &= ~0x1;

}

// As we sweep around the circle, we display 256 radial pixel
// lines, once per TIMER1 interrupt.  This is broken down into
// 16 16-pixel wide characters, and we have two characters
// stacked vertically.  To save time, we keep track of the
// character number, pixel number (in the character), and
// pointers into the eeprom for each of the two chars being
// displayed.

volatile uint16_t topChar = 0;		// top character being displayed (address in EEPROM of data)
volatile uint16_t botChar = 0;		// bottom character being displayed
volatile uint8_t charNum = 0;		// character number
volatile uint8_t pixelNum = 0;		// pixel number
volatile uint8_t clean = 0;			// have these values been changed outside TIMER1?

// This routine gets called every time the pixel timer runs down;
// in other words, once per "scan line", 256 times per revolution
// of the SpokePOV.  Its purpose is to update the LEDs.

SIGNAL (SIG_TIMER1_COMPA) {

  uint16_t tChar;					// local copies of the values
  uint16_t bChar;
  uint8_t cNum;
  uint8_t pNum;

  uint8_t cCode;					// character code to display
  
  // When an interrupt routine is called, interrupts are disabled.
  // but it's important to let other interrupts interrupt us, so
  // they need to be re-enabled.
	
  sei();

  // *** PORTB |= 0x2;

  // Copy the volatile variables into their local equivalents
  
  tChar = topChar;
  bChar = botChar;
  cNum = charNum;
  pNum = pixelNum;

  // If it has been less than STANDBY_TIMEOUT seconds since the last time we
  // got a Hall Effect sensor update, then proceed as normal and
  // update the LEDs.
  
  // QUESTION: what is F_CPU?
  
  if (sensor_timer < ((F_CPU/NUM_PIXELS)/256 * STANDBY_TIMEOUT)) {    
    
    // *** PORTA |= 0x1;
    
    // The first thing we do is increment our character position; this
    // is done here to avoid code duplication.  This means that the
    // Hall Effect interrupt routine must set them up so they "wrap"
    // into the first valid values.
    
    // Move to the next pixel in the character
    
    pNum++;
    
    // If we have moved off the edge of the character, then
    // we need to move to the next character
    
    if (pNum == 16) {
    
      pNum = 0;					// reset to first pixel
      cNum = (cNum+1) % 16;		// move, with wrap, to next character position
      
      // Now we need to reset the pointers to the correct addresses
      // in the EEPROM for the characters they display.  The earlier
      // decision to store these in a format that makes them display
      // nicely on the original SpokePOV software makes this a little
      // bit difficult.
      
      cCode = topLine[cNum]-32;		// character number for the top char, 0-95
      
      // In the character set, 2 characters are stored vertically stacked.
      // So each group of 2 characters takes up 64 bytes (4x16).
      
      tChar = ((cCode >> 1) << 6) | ( (cCode & 0x01) << 1 );
      
      // tChar = 1024UL;	// debug, should be an @
      
      // Ditto for bChar...
      
      cCode = botLine[cNum]-32;
      
      bChar = ((cCode >> 1) << 6) | ( (cCode & 0x01) << 1 );
    
      // bChar = tChar + 2;		// debug, should display A
      
    } else {
    
      // If we haven't wrapped around a character boundary, we just move
      // to the next line in the character set, which is 4 pixels offset
      // in each case
      
      tChar += 4;
      bChar += 4;
      
    }
     
    // Unfortunately, we can't do the cute "read from the EEPROM right
    // into the LEDs trick" that limor can do in SpokePOV.  We have to
    // read the data into the ATMEL and then write it out.
    
    spieeprom_read(tChar,fleds+2,2);	// the top 2 bytes
    spieeprom_read(bChar,fleds,2);		// and the bottom 2
    
    clock_leds();						// and send them to the LEDs
    
    // Now we increment the variables.  However, we
    // only do it IF haven't been touched by some other part
    // of the code while we were displaying the pixels.  Also, we
    // turn interrupts off so that nobody else can touch them
    // while we are at it
    
    cli();
    
    if (clean) {

	  topChar = tChar;
	  botChar = bChar;
	  charNum = cNum;
	  pixelNum = pNum;
      
    } else {
    
      // Since we didn't update the data, we know it was changed, and
      // we know that next time, we CAN update the data.  So everything
      // is clean now!
      
      clean = 1;
      
    }

    sei();
    
    // *** PORTA &= ~0x1;
    
  } else {
    
    // We have not seen the magnet in a while, so turn off the
    // pixel timer...
    
    // *** PORTA |= 0x2;

    // Turn off this pixel timer
    // Question: this is different from the code in SIG_INT1.  Why?
    
    cli();
    TCCR1B &= ~0x7;
    sei();

    // Turn off all but one LED
    
    set_led(2);

    // *** PORTA &= ~0x2;
  }

  // *** PORTB &= ~0x2;
  
}

// Interrupt 0 executes when the button is pressed.

// QUESTION: unlike the pixel output interrupt, this one
// doesn't sei().  Why?

SIGNAL (SIG_INT0) {
  
  uint16_t timer;

  // *** PORTB |= 0x4;
  
  // Twiddle our thumbs until the user releases the
  // button - but measure how long he takes...
  
  timer = 0;
  while (! (BUTTON_PIN & _BV(BUTTON))) {
    timer++;
    delay_ms(1);
  }
  
  // A short (<500ms) press will just restart the watchdog
  // timer.  I think this explains the structure of the
  // main() function; it doesn't have a loop to keep it
  // listening for commands if it times out, but pressing
  // the button will restart it.
  
  // We do expect that the button will be down at least
  // a small period of time...
  
  if (timer > BUTTON_DEBOUNCE) {
  
  	// If a quick press...
  	
    if (timer < 500UL) {
      
      // Re-enable the watchdog timer, then loop until
      // it fires off.
      
      WDTCSR = _BV(WDE);
      while (1);
      
    } else {
      
      // We want to shut everything down.  Setting sensor_timer
      // to the pin value will cause both the communications
      // loop and the regular timeout loop in the main() to
      // give up, which results in the device going to sleep.
      
      sensor_timer = 0xFFFF;
      
    }
  }
  
  // *** PORTB &= ~0x4;

}

// Interrupt 1 executes when the hall effect sensor fires

// QUESTION: unlike the pixel output interrupt, this one
// doesn't sei().  Why?

SIGNAL (SIG_INT1) {
  
  // *** PORTB |= 0x8;

  // The first issue we need to deal with when the hall-effect
  // sensor tells us it sees the magnet is to avoid doing any
  // processing if we get an interrupt too soon after the previous
  // interrupt.
  
  // hall_debounce is incremented by TIMER0, which fires every 3ms
  // or so.  At the current setting of 4, this means that at least
  // 15ms must elapse per trigger, which translates to about 4000
  // rpm.
  
  if (hall_debounce > HALL_DEBOUNCE_THRESH) {
    stopcomputertx = 1;

  // We know the number of ms since the last hall sensor trigger
  // and there are 128 radial 'pixels' per sweep so divide to get
  // the necessary ms between the pixel interrupts
    
  // QUESTION: 128 or 256?
    
  // Then we just make TIMER1 trigger at that rate!
    
  // Reset the Timer Count Register for TIMER1 to 0, so it will
  // begin counting up.
    
  TCNT1 = 0;
    
  // sensor_timer contains the number of TIMER0 interrupts since
  // the last time we updated TIMER1.  If it has a reasonable
  // value, then we use it to reset the TIMER1 clock.
    
  if ((sensor_timer < 0xFF) && (sensor_timer > 0x3)) {
    
    // TIMER1 works differently from TIMER0.  It's a 16-bit timer
    // that apparently increments at the system clock rate.
    //
    // Because TIMER0 increments at 1/256 of the clock rate, and
    // fires the interrupt only when it overflows, sensor_timer
    // is incremented once ever 256*256 cycles.
    //
    // We want TIMER1 to fire off 256 times around the loop, so
    // we can display 256 lines of pixels.  We do this by putting
    // sensor_timer into the high byte of TIMER1's comparator
    // value, and the residual of TIMER0 (what it's counted up

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -