📄 spokepov.lss
字号:
spokepov.elf: file format elf32-avr
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000786 00000000 00000000 00000094 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000008 00800060 00000786 0000081a 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000047 00800068 00800068 00000822 2**0
ALLOC
3 .noinit 00000000 008000af 008000af 00000822 2**0
CONTENTS
4 .eeprom 00000000 00810000 00810000 00000822 2**0
CONTENTS
5 .stab 00000354 00000000 00000000 00000824 2**2
CONTENTS, READONLY, DEBUGGING
6 .stabstr 00000084 00000000 00000000 00000b78 2**0
CONTENTS, READONLY, DEBUGGING
7 .debug_aranges 00000028 00000000 00000000 00000bfc 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_pubnames 0000020d 00000000 00000000 00000c24 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_info 0000060b 00000000 00000000 00000e31 2**0
CONTENTS, READONLY, DEBUGGING
10 .debug_abbrev 000001ce 00000000 00000000 0000143c 2**0
CONTENTS, READONLY, DEBUGGING
11 .debug_line 000005d9 00000000 00000000 0000160a 2**0
CONTENTS, READONLY, DEBUGGING
12 .debug_str 0000028e 00000000 00000000 00001be3 2**0
CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:
00000000 <__vectors>:
0: 24 c0 rjmp .+72 ; 0x4a <__init>
2: 83 c1 rjmp .+774 ; 0x30a <__vector_1>
4: c0 c1 rjmp .+896 ; 0x386 <__vector_2>
6: 3a c0 rjmp .+116 ; 0x7c <__bad_interrupt>
8: a3 c0 rjmp .+326 ; 0x150 <__vector_4>
a: 38 c0 rjmp .+112 ; 0x7c <__bad_interrupt>
c: 5f c0 rjmp .+190 ; 0xcc <__vector_6>
e: 36 c0 rjmp .+108 ; 0x7c <__bad_interrupt>
10: 35 c0 rjmp .+106 ; 0x7c <__bad_interrupt>
12: 34 c0 rjmp .+104 ; 0x7c <__bad_interrupt>
14: 33 c0 rjmp .+102 ; 0x7c <__bad_interrupt>
16: 32 c0 rjmp .+100 ; 0x7c <__bad_interrupt>
18: 31 c0 rjmp .+98 ; 0x7c <__bad_interrupt>
1a: 30 c0 rjmp .+96 ; 0x7c <__bad_interrupt>
1c: 2f c0 rjmp .+94 ; 0x7c <__bad_interrupt>
1e: 2e c0 rjmp .+92 ; 0x7c <__bad_interrupt>
20: 2d c0 rjmp .+90 ; 0x7c <__bad_interrupt>
22: 2c c0 rjmp .+88 ; 0x7c <__bad_interrupt>
24: 2b c0 rjmp .+86 ; 0x7c <__bad_interrupt>
00000026 <__ctors_end>:
26: 00 19 sub r16, r0
...
00000029 <lines>:
29: 20 20 20 52 45 56 20 43 4f 55 4e 54 3a 20 20 20 REV COUNT:
39: 20 20 20 20 20 20 30 30 30 30 20 20 20 20 20 20 0000
...
0000004a <__init>:
4a: 11 24 eor r1, r1
4c: 1f be out 0x3f, r1 ; 63
4e: cf ed ldi r28, 0xDF ; 223
50: cd bf out 0x3d, r28 ; 61
00000052 <__do_copy_data>:
52: 10 e0 ldi r17, 0x00 ; 0
54: a0 e6 ldi r26, 0x60 ; 96
56: b0 e0 ldi r27, 0x00 ; 0
58: e6 e8 ldi r30, 0x86 ; 134
5a: f7 e0 ldi r31, 0x07 ; 7
5c: 03 c0 rjmp .+6 ; 0x64 <.do_copy_data_start>
0000005e <.do_copy_data_loop>:
5e: c8 95 lpm
60: 31 96 adiw r30, 0x01 ; 1
62: 0d 92 st X+, r0
00000064 <.do_copy_data_start>:
64: a8 36 cpi r26, 0x68 ; 104
66: b1 07 cpc r27, r17
68: d1 f7 brne .-12 ; 0x5e <.do_copy_data_loop>
0000006a <__do_clear_bss>:
6a: 10 e0 ldi r17, 0x00 ; 0
6c: a8 e6 ldi r26, 0x68 ; 104
6e: b0 e0 ldi r27, 0x00 ; 0
70: 01 c0 rjmp .+2 ; 0x74 <.do_clear_bss_start>
00000072 <.do_clear_bss_loop>:
72: 1d 92 st X+, r1
00000074 <.do_clear_bss_start>:
74: af 3a cpi r26, 0xAF ; 175
76: b1 07 cpc r27, r17
78: e1 f7 brne .-8 ; 0x72 <.do_clear_bss_loop>
7a: db c2 rjmp .+1462 ; 0x632 <main>
0000007c <__bad_interrupt>:
7c: c1 cf rjmp .-126 ; 0x0 <__vectors>
0000007e <clock_scroll>:
// Sends 4 bytes + sCount extra bits over the serial link
// to implement smooth scrolling. Can be used with a 0
// parameter to just send out the regular 4 bytes.
void clock_scroll(uint8_t sCount) {
7e: cf 93 push r28
80: c8 2f mov r28, r24
// First, send the basic 4 bytes, they go no matter what
spi_transfer(fleds[0]);
82: 80 91 89 00 lds r24, 0x0089
86: 43 d3 rcall .+1670 ; 0x70e <spi_transfer>
spi_transfer(fleds[1]);
88: 80 91 8a 00 lds r24, 0x008A
8c: 40 d3 rcall .+1664 ; 0x70e <spi_transfer>
spi_transfer(fleds[2]);
8e: 80 91 8b 00 lds r24, 0x008B
92: 3d d3 rcall .+1658 ; 0x70e <spi_transfer>
spi_transfer(fleds[3]);
94: 80 91 8c 00 lds r24, 0x008C
98: 3a d3 rcall .+1652 ; 0x70e <spi_transfer>
// If there is anything to do..
if (sCount != 0) {
9a: cc 23 and r28, r28
9c: 79 f0 breq .+30 ; 0xbc <clock_scroll+0x3e>
// If we have < 8 bits to transfer
if (sCount < 8) {
9e: c8 30 cpi r28, 0x08 ; 8
a0: 20 f4 brcc .+8 ; 0xaa <clock_scroll+0x2c>
// Then that is all that we need to do
spi_transfer_n(fleds[4],sCount);
a2: 6c 2f mov r22, r28
a4: 80 91 8d 00 lds r24, 0x008D
a8: 08 c0 rjmp .+16 ; 0xba <clock_scroll+0x3c>
} else {
// First latch out the full first 8 bits
spi_transfer(fleds[4]);
aa: 80 91 8d 00 lds r24, 0x008D
ae: 2f d3 rcall .+1630 ; 0x70e <spi_transfer>
// How many bits left to do?
sCount = sCount - 8;
b0: c8 50 subi r28, 0x08 ; 8
if (sCount != 0) {
b2: 21 f0 breq .+8 ; 0xbc <clock_scroll+0x3e>
spi_transfer_n(fleds[5],sCount);
b4: 6c 2f mov r22, r28
b6: 80 91 8e 00 lds r24, 0x008E
ba: 1b d3 rcall .+1590 ; 0x6f2 <spi_transfer_n>
}
}
}
// finally, latch the bits into the LEDS
LATCH_SELECT_PORT |= _BV(FRONT);
bc: 94 9a sbi 0x12, 4 ; 18
...
NOP; NOP; NOP; NOP;
LATCH_SELECT_PORT &= ~_BV(FRONT);
c6: 94 98 cbi 0x12, 4 ; 18
c8: cf 91 pop r28
ca: 08 95 ret
000000cc <__vector_6>:
}
// TIMER0 interrupt handler. This runs about every 8ms
// 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) {
cc: 1f 92 push r1
ce: 0f 92 push r0
d0: 0f b6 in r0, 0x3f ; 63
d2: 0f 92 push r0
d4: 11 24 eor r1, r1
d6: 2f 93 push r18
d8: 8f 93 push r24
da: 9f 93 push r25
// *** PORTB |= 0x1;
if (hall_debounce != 0xFF)
dc: 80 91 86 00 lds r24, 0x0086
e0: 8f 3f cpi r24, 0xFF ; 255
e2: 29 f0 breq .+10 ; 0xee <__stack+0xf>
hall_debounce++;
e4: 80 91 86 00 lds r24, 0x0086
e8: 8f 5f subi r24, 0xFF ; 255
ea: 80 93 86 00 sts 0x0086, r24
if (sensor_timer != 0xFFFF)
ee: 80 91 87 00 lds r24, 0x0087
f2: 90 91 88 00 lds r25, 0x0088
f6: 8f 5f subi r24, 0xFF ; 255
f8: 9f 4f sbci r25, 0xFF ; 255
fa: 49 f0 breq .+18 ; 0x10e <__stack+0x2f>
sensor_timer++;
fc: 80 91 87 00 lds r24, 0x0087
100: 90 91 88 00 lds r25, 0x0088
104: 01 96 adiw r24, 0x01 ; 1
106: 90 93 88 00 sts 0x0088, r25
10a: 80 93 87 00 sts 0x0087, r24
#if NUM_LINES > 0
// Increment the line timers - we only need to do this
// if we are scrolling
line_timer_l++; // increment the low byte
10e: 80 91 62 00 lds r24, 0x0062
112: 8f 5f subi r24, 0xFF ; 255
114: 80 93 62 00 sts 0x0062, r24
if (line_timer_l == 0) { // if we wrapped around, then
118: 80 91 62 00 lds r24, 0x0062
11c: 88 23 and r24, r24
11e: 29 f4 brne .+10 ; 0x12a <__stack+0x4b>
line_timer_h++; // increment the high byte as well
120: 80 91 70 00 lds r24, 0x0070
124: 8f 5f subi r24, 0xFF ; 255
126: 80 93 70 00 sts 0x0070, r24
12a: 9f 91 pop r25
12c: 8f 91 pop r24
12e: 2f 91 pop r18
130: 0f 90 pop r0
132: 0f be out 0x3f, r0 ; 63
134: 0f 90 pop r0
136: 1f 90 pop r1
138: 18 95 reti
0000013a <set_all>:
}
#endif
// *** PORTB &= ~0x1;
}
// Hack - I used to copy the topChar, etc. variables into local
// variables in the TIMER1 routine, but I am running out of stack space. So instead
// I'm going to keep interrupts off during this routine and
// use the regular versions. To make it easy to do this I'm
// remapping the local variables with defines.
// #define USE_LOCAL_TIMER1 1
// If USE_LOCAL_TIMER1 is not defined, then the TIMER1 routine will not
// enable interrupts.
// 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.
// This code has to be fast enough to complete execution before
// it gets interrupted again - and it must not make any subroutine
// calls, since that'll mess up the stack and cause the entire
// system to reset.
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
#ifdef USE_LOCAL_TIMER1
volatile uint8_t clean = 0; // have these values been changed outside TIMER1?
#endif
#ifdef SMOOTHSCROLL
volatile uint16_t scrollChar = 0; // extra scroll character
#endif
// 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) {
uint8_t cCode; // character code to display
#ifdef USE_LOCALUSE_LOCAL_TIMER1
uint16_t tChar; // local copies of the values
uint16_t bChar;
uint8_t cNum;
uint8_t pNum;
#ifdef SMOOTHSCROLL
uint16_t sChar; // extra scroll character
#endif
// 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();
// Copy the volatile variables into their local equivalents
tChar = topChar;
bChar = botChar;
cNum = charNum;
pNum = pixelNum;
#ifdef SMOOTHSCROLL
sChar = scrollChar;
#endif
#else
#define tChar topChar
#define bChar botChar
#define cNum charNum
#define pNum pixelNum
#define sChar scrollChar
#endif
// 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) & 0x0F; // 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 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -