📄 spokepov.lss
字号:
spokepov.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 000007da 00000000 00000000 00000094 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000002 00800060 000007da 0000086e 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000013 00800062 00800062 00000870 2**0
ALLOC
3 .noinit 00000000 00800075 00800075 00000870 2**0
CONTENTS
4 .eeprom 00000000 00810000 00810000 00000870 2**0
CONTENTS
5 .stab 00000354 00000000 00000000 00000870 2**2
CONTENTS, READONLY, DEBUGGING
6 .stabstr 00000084 00000000 00000000 00000bc4 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_aranges 00000028 00000000 00000000 00000c48 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_pubnames 000001f6 00000000 00000000 00000c70 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_info 000005d8 00000000 00000000 00000e66 2**0
CONTENTS, READONLY, DEBUGGING
10 .debug_abbrev 000001f2 00000000 00000000 0000143e 2**0
CONTENTS, READONLY, DEBUGGING
11 .debug_line 00000767 00000000 00000000 00001630 2**0
CONTENTS, READONLY, DEBUGGING
12 .debug_str 00000263 00000000 00000000 00001d97 2**0
CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:
00000000 <__vectors>:
0: 12 c0 rjmp .+36 ; 0x26 <__ctors_end>
2: 60 c0 rjmp .+192 ; 0xc4 <__vector_1>
4: 17 c1 rjmp .+558 ; 0x234 <__vector_2>
6: 28 c0 rjmp .+80 ; 0x58 <__bad_interrupt>
8: ab c1 rjmp .+854 ; 0x360 <__vector_4>
a: 26 c0 rjmp .+76 ; 0x58 <__bad_interrupt>
c: 26 c0 rjmp .+76 ; 0x5a <__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: ea ed ldi r30, 0xDA ; 218
36: f7 e0 ldi r31, 0x07 ; 7
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 36 cpi r26, 0x62 ; 98
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 e6 ldi r26, 0x62 ; 98
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: a5 37 cpi r26, 0x75 ; 117
52: b1 07 cpc r27, r17
54: e1 f7 brne .-8 ; 0x4e <.do_clear_bss_loop>
56: 5b c2 rjmp .+1206 ; 0x50e <main>
00000058 <__bad_interrupt>:
58: d3 cf rjmp .-90 ; 0x0 <__vectors>
0000005a <__vector_6>:
// 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) {
5a: 1f 92 push r1
5c: 0f 92 push r0
5e: 0f b6 in r0, 0x3f ; 63
60: 0f 92 push r0
62: 11 24 eor r1, r1
64: 2f 93 push r18
66: 8f 93 push r24
68: 9f 93 push r25
PORTB |= 0x1;
6a: c0 9a sbi 0x18, 0 ; 24
if (hall_debounce != 0xFF)
6c: 80 91 69 00 lds r24, 0x0069
70: 8f 3f cpi r24, 0xFF ; 255
72: 29 f0 breq .+10 ; 0x7e <__vector_6+0x24>
hall_debounce++;
74: 80 91 69 00 lds r24, 0x0069
78: 8f 5f subi r24, 0xFF ; 255
7a: 80 93 69 00 sts 0x0069, r24
if (sensor_timer != 0xFFFF)
7e: 80 91 6a 00 lds r24, 0x006A
82: 90 91 6b 00 lds r25, 0x006B
86: 8f 5f subi r24, 0xFF ; 255
88: 9f 4f sbci r25, 0xFF ; 255
8a: 49 f0 breq .+18 ; 0x9e <__vector_6+0x44>
sensor_timer++;
8c: 80 91 6a 00 lds r24, 0x006A
90: 90 91 6b 00 lds r25, 0x006B
94: 01 96 adiw r24, 0x01 ; 1
96: 90 93 6b 00 sts 0x006B, r25
9a: 80 93 6a 00 sts 0x006A, r24
PORTB &= ~0x1;
9e: c0 98 cbi 0x18, 0 ; 24
a0: 9f 91 pop r25
a2: 8f 91 pop r24
a4: 2f 91 pop r18
a6: 0f 90 pop r0
a8: 0f be out 0x3f, r0 ; 63
aa: 0f 90 pop r0
ac: 1f 90 pop r1
ae: 18 95 reti
000000b0 <delay_ms>:
}
// The current EEPROM address gets incremented by 4 (the number of
// bytes in a pixel line) each time the pixel timer fires. This
// steps us through the bitmap we need to display.
volatile uint16_t curr_eeprom_addr = 0;
// 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 eepromaddr; // local copy of the eprom address
// 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;
// We need a local copy of the EEPROM address because we
// muck with it a bit.
eepromaddr = curr_eeprom_addr;
// 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;
// Since cur_eeprom_addr can go past a 1K boundary depending on
// the rotation offset, we need to modulo it to a 0-1023 value.
eepromaddr %= NUM_PIXELS * 4;
// Then the bytes we want to plonk into the LEDs will be this
// address, plus the animation offset (0,1024,2048 or 3072).
// This routine is in eeprom.c. As far as I can tell, it's doing
// a really cute trick, causing the EEPROM to send the desired
// pixel bytes to both the ATMEL and the pixel shift registers
// at the same time.
spieeprom_read_into_leds(eepromaddr + anim_eeprom_offset, FRONT);
// If we are mirroring the image onto the backside LEDs, then we
// have to output the lines of pixels in reverse order
if (mirror) {
spieeprom_read_into_leds(anim_eeprom_offset + (1024UL-eepromaddr), BACK);
} else {
// Otherwise, currently, turn off the backside LEDs
LATCH_SELECT_PORT |= _BV(BACK);
NOP; NOP; NOP; NOP;
LATCH_SELECT_PORT &= ~_BV(BACK);
}
// Now we increment the curr_eeprom_addr variable. However, we
// only do it IF it hasn't already 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 it while
// we are updating it.
cli();
if (eepromaddr == (curr_eeprom_addr%(NUM_PIXELS*4))) {
curr_eeprom_addr = eepromaddr+4;
}
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, FRONT);
set_led(2, BACK);
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;
#ifdef ANIMATE
// increment the animation timer, and move
// to the next image every animation_time rotations
if (anim_timer != animation_time) {
anim_timer++;
} else {
anim_timer = 0;
anim_eeprom_offset += 1024;
}
#endif
// 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
// to since the last time sensor_timer was incremented) into
// the low byte, effectively a fractional value!
//
// Since TIMER0 is incrementing at 1/256 of the rate of TIMER1,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -