📄 spokepov.lss
字号:
43e: 81 bb out 0x11, r24 ; 17
440: 8f ed ldi r24, 0xDF ; 223
442: 87 bb out 0x17, r24 ; 23
444: 80 e1 ldi r24, 0x10 ; 16
446: 88 bb out 0x18, r24 ; 24
448: 8c e4 ldi r24, 0x4C ; 76
44a: 82 bb out 0x12, r24 ; 18
44c: 98 e0 ldi r25, 0x08 ; 8
44e: 95 bf out 0x35, r25 ; 53
450: 80 ec ldi r24, 0xC0 ; 192
452: 8b bf out 0x3b, r24 ; 59
454: 10 be out 0x30, r1 ; 48
456: 84 e0 ldi r24, 0x04 ; 4
458: 83 bf out 0x33, r24 ; 51
45a: 89 b7 in r24, 0x39 ; 57
45c: 82 60 ori r24, 0x02 ; 2
45e: 89 bf out 0x39, r24 ; 57
460: 1f bc out 0x2f, r1 ; 47
462: 9e bd out 0x2e, r25 ; 46
464: 10 92 7c 00 sts 0x007C, r1
468: 10 92 7e 00 sts 0x007E, r1
46c: 10 92 7d 00 sts 0x007D, r1
470: 08 95 ret
00000472 <main>:
}
int main(void) {
472: cf ed ldi r28, 0xDF ; 223
474: d0 e0 ldi r29, 0x00 ; 0
476: de bf out 0x3e, r29 ; 62
478: cd bf out 0x3d, r28 ; 61
uint8_t cmd; // the reason we reset
// MCUSR is the MCU Status Register (page 40). It tells us
// why we reset, and a reset is the only way to get here.
cmd = MCUSR;
47a: 84 b7 in r24, 0x34 ; 52
// The first order of business is to tell the chip that
// we've got things under control.
MCUSR = 0;
47c: 14 be out 0x34, r1 ; 52
// Turn on watchdog timer immediately, this protects against
// a 'stuck' system by resetting it.
// WDTCSR is the Watchdog Timer Control Register (page 45).
// We set it so that it'll generate a watchdog interrupt
// every second. The idea is that if things mess up,
// the watchdog will kickstart us.
WDTCSR = _BV(WDE) | _BV(WDP2) | _BV(WDP1); // 1 second
47e: 8e e0 ldi r24, 0x0E ; 14
480: 81 bd out 0x21, r24 ; 33
// Initialize the various pins of the ATMEL, and set up
// the interrupts.
ioinit();
482: dc df rcall .-72 ; 0x43c <ioinit>
// Show that we are active.
set_all(~0x01);
484: 8e ef ldi r24, 0xFE ; 254
486: 59 de rcall .-846 ; 0x13a <set_all>
// enable the interrupts. I think this is not needed
// since it'll immediately be done by the loop, below.
sei();
488: 78 94 sei
// Loop until we timeout, at which point the ATMEL is
// put to sleep. If the communications routine timed
// out, or the user pressed the button for >500ms,
// then sensor_timer will be 0xFFFF and we'll immediately
// sleep.
// Change to for (;;) to see if it makes any difference
for (;;) {
// Reset the watchdog Timer.
//
// QUESTION: What's with toggling the PD0 output line here?
// it doesn't seem to be connected to anything according to
// the circuit diagram...
// *** PORTD |= 0x1;
asm("wdr");
48a: a8 95 wdr
// *** PORTD &= ~0x1;
// If the sensor_timer (incremented by TIMER0) maxes out
// (in about 3 minutes), then sleep everything.
if (sensor_timer.bytes.high_byte == 0xFF) {
48c: 80 91 7e 00 lds r24, 0x007E
490: 8f 3f cpi r24, 0xFF ; 255
492: 71 f4 brne .+28 ; 0x4b0 <main+0x3e>
// Avoid pesky interruptions
cli();
494: f8 94 cli
// Turn off all LEDs - I guess LED 0 is one of the "invisible ones"
set_all(0xFF);
496: 51 de rcall .-862 ; 0x13a <set_all>
// Turn off power to the Hall Effect sensor.
SENSOR_PORT &= ~_BV(SENSORPOWER);
498: 96 98 cbi 0x12, 6 ; 18
// Deselect EEPROM
SPIEE_CS_PORT |= _BV(SPIEE_CS); // pull CS high to deselect
49a: c4 9a sbi 0x18, 4 ; 24
// Turn off Watchdog (must be restarted when we get the wakeup)
// Wakeup will be via the button interrupt.
WDTCSR |= _BV(WDCE) | _BV(WDE);
49c: 81 b5 in r24, 0x21 ; 33
49e: 88 61 ori r24, 0x18 ; 24
4a0: 81 bd out 0x21, r24 ; 33
WDTCSR = 0;
4a2: 11 bc out 0x21, r1 ; 33
MCUCR |= _BV(SM1) | _BV(SM0) | _BV(SE);
4a4: 85 b7 in r24, 0x35 ; 53
4a6: 80 67 ori r24, 0x70 ; 112
4a8: 85 bf out 0x35, r24 ; 53
// Re-enable interrupts so we can get the wakeup!
sei();
4aa: 78 94 sei
// Go into sleep mode
asm("sleep");
4ac: 88 95 sleep
4ae: ed cf rjmp .-38 ; 0x48a <main+0x18>
} else {
// Do we have dynamic updating to do?
#ifdef DYNAMIC
uint8_t tBytes; // Number of bytes to transfer
// Use unions to overlay variables and save some space
union {
char *fPtr; // from pointer
var16bit divisor; // the divisor for RPM
} a;
union {
char *tPtr; // to pointer
char *divTable; // divisor table
} b;
// Update the dynamic data display
switch (dynamicType & 0xF0) {
#ifdef DYNAMIC_REVCOUNT // Rev counter compiled in?
case 0x10: // Rev counter
tBytes = 4; // number of bytes we'll move down below
a.fPtr = (char *)dynamicREV;
break; // gets put into dynamicBuffer in reverse order.
#endif
#ifdef DYNAMIC_RPM // RPM counter compiled in?
case 0x20:
// CODE NOT YET OPTIMIZED FOR SPACE.
// Initialize the RPM counter to 0
dynamicRPM[0]=dynamicRPM[1]=dynamicRPM[2] = '0';
// Get a copy of the TIMER1 value that we need to divide 732 by
a.divisor.word = OCR1A;
// Start out pointing to the SECOND element of the div732 array.
// We need to set to the second one because the min value of the
// OCR1A hibyte (max speed) is 01, and we'll do at most 7 shifts
// before we see a bit. But there are 8 bits after that that
// might get looked at, so the div732 table must be 8 entries long.
// We also add 2 so that we are pointing at the last byte of each
// entry.
b.divTable = (char *)(div732+5); // 3 bytes per entry
// Shift the divisor to the left and the divtable pointer to the
// right until the high bit of the divisor is set
while (a.divisor.bytes.high_byte < 0x80) {
a.divisor.word = a.divisor.word << 1;
b.divTable = b.divTable + 3;
}
// Once we have found the high bit, that tells us the fastest
// the device could possibly be rotating. Any other set bits in
// a.divisor mean that the RPM is lower. So what we do is clear
// the high bit and add in our partial sums only when the bits
// in the remainder are ** 0 **. Since we just cleared the
// high bit, it'll get counted. If all the bits are zero, all
// the sums will be added.
// NOTE: could be made smaller by using a.divisor.bytes.high_byte
// below, sacrificing a bit of accuracy at very high speeds.
a.divisor.word = a.divisor.word & 0x7FFF;
while (b.divTable > div732) {
if (a.divisor.bytes.high_byte < 0x80) {
// Add in the least significant bit. Since the table is actual
// byte values, we don't need to deal with an ascii conversion
dynamicRPM[0] = dynamicRPM[0] + pgm_read_byte(b.divTable--);
if (dynamicRPM[0] > '9') {
dynamicRPM[0] = dynamicRPM[0] - 10;
dynamicRPM[1]++;
}
// repeat for second byte...
dynamicRPM[1] = dynamicRPM[1] + pgm_read_byte(b.divTable--);
if (dynamicRPM[1] > '9') {
dynamicRPM[1] = dynamicRPM[1] - 10;
dynamicRPM[2]++;
}
// and for third, but no carry needed this time
dynamicRPM[2] = dynamicRPM[2] + pgm_read_byte(b.divTable--);
// At this point, we've already subtracted 3 from b.divTable, so we're
// ready to go for the next loop.
} else {
// But if we didn't add anything in, we need to shift b.divTable
b.divTable = b.divTable - 3;
}
// And finally move to the next bit
a.divisor.word = a.divisor.word << 1;
}
// And when that's all done, we just set up for the move
tBytes = 3;
a.fPtr = (char *)dynamicRPM;
break;
#endif
#ifdef DYNAMIC_TIME // Clock compiled in?
case 0x30: // Rev counter
tBytes = 8; // number of bytes we'll move down below
a.fPtr = (char *)dynamicTime;
break; // gets put into dynamicBuffer in reverse order.
#endif
default: // This will get executed if no dynamic data
tBytes = 0x00; // and will clear things.
}
// If we have bytes to transfer, and if the dynamic display
// is still active, then transfer the bytes into the display
cli();
if ( (dynamicType != 0x00) && (tBytes != 0x00) ) {
b.tPtr = (char *)dynamicPtr; // we now know dynamicPtr is valid
// Remember, dynamicPtr points to the last byte, so we
// copy bass ackwards!
for(;tBytes>0;tBytes--) {
*b.tPtr-- = *a.fPtr++;
}
}
#endif
sei();
4b0: 78 94 sei
4b2: eb cf rjmp .-42 ; 0x48a <main+0x18>
000004b4 <spi_transfer_n>:
// code space!
// Move n bits of data over the serial link
void spi_transfer_n(uint8_t c, uint8_t n) {
4b4: 96 2f mov r25, r22
// Stuff the byte to transfer into the serial data register
USIDR = c;
4b6: 8f b9 out 0x0f, r24 ; 15
// Set up the status register. On each state transition of
// the serial bus (up or down), the lower 4 bits will be
// incremented - so twice per bit. When that overflows,
// the transfer is done. So if they start out as 0, 8
// bits get moved. But if you start it out at a different
// value, you can move an arbitrary number of bits
USISR = _BV(USIOIF) | (16 - (n<<1));
4b8: 99 0f add r25, r25
4ba: 80 e1 ldi r24, 0x10 ; 16
4bc: 89 1b sub r24, r25
4be: 80 64 ori r24, 0x40 ; 64
4c0: 8e b9 out 0x0e, r24 ; 14
// While the transfer has not finished
while ( (USISR & _BV(USIOIF)) == 0) {
// Send out another bit
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
4c2: 76 99 sbic 0x0e, 6 ; 14
4c4: 04 c0 rjmp .+8 ; 0x4ce <spi_transfer_n+0x1a>
4c6: 8b e1 ldi r24, 0x1B ; 27
4c8: 8d b9 out 0x0d, r24 ; 13
4ca: 76 9b sbis 0x0e, 6 ; 14
4cc: fd cf rjmp .-6 ; 0x4c8 <spi_transfer_n+0x14>
4ce: 08 95 ret
000004d0 <spi_transfer>:
//NOP; // slow down so that the eeprom isnt overwhelmed
}
}
// Move 4 bytes over the serial link (to the 1K/4K EEPROM or the
// LED shift registers, or both!). This code does things "blind",
// clocking 16 times, to transfer the data as fast as possible.
void spi_transfer(uint8_t c) {
USIDR = c;
4d0: 8f b9 out 0x0f, r24 ; 15
USISR = _BV(USIOIF);
4d2: 80 e4 ldi r24, 0x40 ; 64
4d4: 8e b9 out 0x0e, r24 ; 14
while ( (USISR & _BV(USIOIF)) == 0) {
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
4d6: 76 99 sbic 0x0e, 6 ; 14
4d8: 04 c0 rjmp .+8 ; 0x4e2 <spi_transfer+0x12>
4da: 8b e1 ldi r24, 0x1B ; 27
4dc: 8d b9 out 0x0d, r24 ; 13
4de: 76 9b sbis 0x0e, 6 ; 14
4e0: fd cf rjmp .-6 ; 0x4dc <spi_transfer+0xc>
4e2: 08 95 ret
000004e4 <spieeprom_read>:
//NOP; // slow down so that the eeprom isnt overwhelmed
}
// The byte read, if any, will be in USIDR
}
void spieeprom_read(uint16_t addr, uint8_t *buff, uint8_t len) {
4e4: ff 92 push r15
4e6: 0f 93 push r16
4e8: 1f 93 push r17
4ea: cf 93 push r28
4ec: df 93 push r29
4ee: 08 2f mov r16, r24
4f0: 19 2f mov r17, r25
4f2: d7 2f mov r29, r23
4f4: c6 2f mov r28, r22
4f6: f4 2e mov r15, r20
uint8_t i;
SPIEE_CS_PORT &= ~_BV(SPIEE_CS); // pull CS low
4f8: c4 98 cbi 0x18, 4 ; 24
...
NOP; NOP; NOP; NOP;
spi_transfer(SPI_EEPROM_READ); // send READ command
502: 83 e0 ldi r24, 0x03 ; 3
504: e5 df rcall .-54 ; 0x4d0 <spi_transfer>
spi_transfer(addr >> 8); // send high addr
506: 81 2f mov r24, r17
508: 99 27 eor r25, r25
50a: e2 df rcall .-60 ; 0x4d0 <spi_transfer>
spi_transfer(addr & 0xFF); // send low addr
50c: 80 2f mov r24, r16
50e: e0 df rcall .-64 ; 0x4d0 <spi_transfer>
for (i=0; i<len; i++) { // read in the right number of
510: 00 e0 ldi r16, 0x00 ; 0
512: 0f 15 cp r16, r15
514: 30 f4 brcc .+12 ; 0x522 <spieeprom_read+0x3e>
spi_transfer(0); // bits, then move to buff[]
516: 80 e0 ldi r24, 0x00 ; 0
518: db df rcall .-74 ; 0x4d0 <spi_transfer>
buff[i] = USIDR;
51a: 8f b1 in r24, 0x0f ; 15
51c: 89 93 st Y+, r24
51e: 0f 5f subi r16, 0xFF ; 255
520: f8 cf rjmp .-16 ; 0x512 <spieeprom_read+0x2e>
}
SPIEE_CS_PORT |= _BV(SPIEE_CS); // pull CS high
522: c4 9a sbi 0x18, 4 ; 24
524: df 91 pop r29
526: cf 91 pop r28
528: 1f 91 pop r17
52a: 0f 91 pop r16
52c: ff 90 pop r15
52e: 08 95 ret
00000530 <memcpy_P>:
530: e6 2f mov r30, r22
532: f7 2f mov r31, r23
534: a8 2f mov r26, r24
536: b9 2f mov r27, r25
538: 03 c0 rjmp .+6 ; 0x540 <memcpy_P+0x10>
53a: c8 95 lpm
53c: 31 96 adiw r30, 0x01 ; 1
53e: 0d 92 st X+, r0
540: 41 50 subi r20, 0x01 ; 1
542: 50 40 sbci r21, 0x00 ; 0
544: d0 f7 brcc .-12 ; 0x53a <memcpy_P+0xa>
546: 08 95 ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -