📄 spokepov.lss
字号:
int main(void) {
5d4: cf ed ldi r28, 0xDF ; 223
5d6: d0 e0 ldi r29, 0x00 ; 0
5d8: de bf out 0x3e, r29 ; 62
5da: 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;
5dc: 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;
5de: 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
5e0: 8e e0 ldi r24, 0x0E ; 14
5e2: 81 bd out 0x21, r24 ; 33
// Initialize the various pins of the ATMEL, and set up
// the interrupts.
ioinit();
5e4: dc df rcall .-72 ; 0x59e <ioinit>
// Show that we are active.
set_all(~0x01);
5e6: 8e ef ldi r24, 0xFE ; 254
5e8: 0f de rcall .-994 ; 0x208 <set_all>
// enable the interrupts. I think this is not needed
// since it'll immediately be done by the loop, below.
sei();
5ea: 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");
5ec: 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) {
5ee: 80 91 82 00 lds r24, 0x0082
5f2: 8f 3f cpi r24, 0xFF ; 255
5f4: 71 f4 brne .+28 ; 0x612 <main+0x3e>
// Avoid pesky interruptions
cli();
5f6: f8 94 cli
// Turn off all LEDs - I guess LED 0 is one of the "invisible ones"
set_all(0xFF);
5f8: 07 de rcall .-1010 ; 0x208 <set_all>
// Turn off power to the Hall Effect sensor.
SENSOR_PORT &= ~_BV(SENSORPOWER);
5fa: 96 98 cbi 0x12, 6 ; 18
// Deselect EEPROM
SPIEE_CS_PORT |= _BV(SPIEE_CS); // pull CS high to deselect
5fc: 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);
5fe: 81 b5 in r24, 0x21 ; 33
600: 88 61 ori r24, 0x18 ; 24
602: 81 bd out 0x21, r24 ; 33
WDTCSR = 0;
604: 11 bc out 0x21, r1 ; 33
MCUCR |= _BV(SM1) | _BV(SM0) | _BV(SE);
606: 85 b7 in r24, 0x35 ; 53
608: 80 67 ori r24, 0x70 ; 112
60a: 85 bf out 0x35, r24 ; 53
// Re-enable interrupts so we can get the wakeup!
sei();
60c: 78 94 sei
// Go into sleep mode
asm("sleep");
60e: 88 95 sleep
610: ed cf rjmp .-38 ; 0x5ec <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();
612: 78 94 sei
614: eb cf rjmp .-42 ; 0x5ec <main+0x18>
00000616 <spi_transfer_n>:
// code space!
// Move n bits of data over the serial link
void spi_transfer_n(uint8_t c, uint8_t n) {
616: 96 2f mov r25, r22
// Stuff the byte to transfer into the serial data register
USIDR = c;
618: 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));
61a: 99 0f add r25, r25
61c: 80 e1 ldi r24, 0x10 ; 16
61e: 89 1b sub r24, r25
620: 80 64 ori r24, 0x40 ; 64
622: 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);
624: 76 99 sbic 0x0e, 6 ; 14
626: 04 c0 rjmp .+8 ; 0x630 <spi_transfer_n+0x1a>
628: 8b e1 ldi r24, 0x1B ; 27
62a: 8d b9 out 0x0d, r24 ; 13
62c: 76 9b sbis 0x0e, 6 ; 14
62e: fd cf rjmp .-6 ; 0x62a <spi_transfer_n+0x14>
630: 08 95 ret
00000632 <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;
632: 8f b9 out 0x0f, r24 ; 15
USISR = _BV(USIOIF);
634: 80 e4 ldi r24, 0x40 ; 64
636: 8e b9 out 0x0e, r24 ; 14
while ( (USISR & _BV(USIOIF)) == 0) {
USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
638: 76 99 sbic 0x0e, 6 ; 14
63a: 04 c0 rjmp .+8 ; 0x644 <spi_transfer+0x12>
63c: 8b e1 ldi r24, 0x1B ; 27
63e: 8d b9 out 0x0d, r24 ; 13
640: 76 9b sbis 0x0e, 6 ; 14
642: fd cf rjmp .-6 ; 0x63e <spi_transfer+0xc>
644: 08 95 ret
00000646 <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) {
646: ff 92 push r15
648: 0f 93 push r16
64a: 1f 93 push r17
64c: cf 93 push r28
64e: df 93 push r29
650: 08 2f mov r16, r24
652: 19 2f mov r17, r25
654: d7 2f mov r29, r23
656: c6 2f mov r28, r22
658: f4 2e mov r15, r20
uint8_t i;
SPIEE_CS_PORT &= ~_BV(SPIEE_CS); // pull CS low
65a: c4 98 cbi 0x18, 4 ; 24
...
NOP; NOP; NOP; NOP;
spi_transfer(SPI_EEPROM_READ); // send READ command
664: 83 e0 ldi r24, 0x03 ; 3
666: e5 df rcall .-54 ; 0x632 <spi_transfer>
spi_transfer(addr >> 8); // send high addr
668: 81 2f mov r24, r17
66a: 99 27 eor r25, r25
66c: e2 df rcall .-60 ; 0x632 <spi_transfer>
spi_transfer(addr & 0xFF); // send low a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -