📄 main.c
字号:
{ uint8 i; uint8 res=0U; // NOTE: The most significant bit is transferred first in both directions. for(i=0; i<8; i++) { res<<=1; // SCK L->H (rising edge) latches data. // Wait for SCK going HIGH or PD3 going HIGH. for(;;) { if(INT1_LEVEL()) return(0x100U); if(SCK_LEVEL()) break; } // Read input. if(RXD_LEVEL()) res|=1; // Set new output. if(to_send & (0x80U>>i)) SET_TXD_HIGH(); else SET_TXD_LOW(); // Wait for SCK H->L or PD3 going HIGH. // Output data is valid at the H->L transition of the clock. for(;;) { if(INT1_LEVEL()) return(0x100U); if(!SCK_LEVEL()) break; } } return(res);}static void ReadHandleInput(){ // This means we read the input from the RxD line (PD0) respecing the // externally-provided serial clock SCK (PD4). // We can output data on the TxD line (PD1). // NOTE: As soon as PD3 is pulled HIGH again, we leave this routine. // If there was no complete command received within this time, // we just ignore it. // While PD3 is LOW. while(!INT1_LEVEL()) { uint16 rv=SerialIOByte(0x00); uint8 stat=rv>>8; if(stat) return; uint8 cmd=rv&0xffU; switch(cmd) { // In order to sent the clock speed, send 2 bytes: // First: CMD_CKGEN_SET_CLOCK_SPEED, then the clock speed in // multiples of 50kS/s. Only certain discrete values are // permissible. case CMD_CKGEN_SET_CLOCK_SPEED: { rv=SerialIOByte(CMD_CKGEN_SET_CLOCK_SPEED); stat=rv>>8; if(stat) return; clock_speed=rv&0xffU; } break; default: break; } }}int main(void){ Initialize(); StartSampleClock(); // ## For testing: simply pull the clock1 LOW to have all samples stored: ## //cbi(PORTB,2); //for(;;); // Enable interrupts globally: sei(); for(;;) { // Run the sampler... // We leave if PD3 is pulled low. This means that there is something // to read. ClockGeneratorLoop(); // Handle the input from the RxD and SCK lines. ReadHandleInput(); } // Never reached. return(0);}//------------------------------------------------------------------------------ // Unused clock speeds: #if 0 // This will store every 3rd sample: (3.3 MS) SampleClockSync(); for(;;) { cbi(PORTB,2); sbi(PORTB,2); }#elif 0 // This will store 2/3 of all samples: (6.7 MS) SampleClockSync(); for(;;) { sbi(PORTB,2); cbi(PORTB,2); }#elif 0 // clock1 (PB2): Set up timer0 in CTC mode. Prescaler to 1: OCR0A=0x01; // 0x00 TCNT0=0; // WGM2:0=7 (fast PWM with TOP=OCR0A) TCCR0A=0x42U; // 01000010 <-- COM0A1:0, WGM00:1 TCCR0B=0x01U; // 00000001 SampleClockSync(); TCNT0=1; for(;;);#endif // Other cruft: #if 0 // clock1 (PB2): Set up timer0 in CTC mode: // Prescaler to 1: OCR0A=0x0; // 0x00 TCNT0=0; TCCR0A=0x42U; // 01000010 <-- COM0A1:0, WGM00:1 TCCR0B=0x01U; // 00000001 TCNT0=0; // Enable interrupt for test purpose. //sbi(TIMSK,TOIE0); // overflow //sbi(TIMSK,/*OCIE0A*/0); // overflow ????#endif// HERE is the old version without inline assembly. // NOTE that the SampleClockSync() was not working properly (since it // caused tiny clock gaps). #if 0#define SampleClockSync() do { TCNT1=0xcdU; } while(0)static void ClockGeneratorLoop(){ // Main loop. This runs until PD3 is pulled LOW thereby stopping sampling. if(!INT1_LEVEL()) return; switch(clock_speed) { case 0: // 0kS // This will store NO samples at all. SampleClockSync(); sbi(PORTB,2); for(;;) { if(!INT1_LEVEL()) break; // <-- This is 1 clock cycle! } break; case 1: // 50kS // This will store every 200th sample: (50 kS) SampleClockSync(); for(;;) { cbi(PORTB,2); sbi(PORTB,2); nop(); // 98 -> 200 uint8 cnt=98; while(cnt--) { nop(); } // This is one clock cycle if placed at the end of the loop! if(!INT1_LEVEL()) break; } break; case 2: // 100kS // This will store every 100th sample: (100 kS) SampleClockSync(); for(;;) { cbi(PORTB,2); sbi(PORTB,2); nop(); // 48 -> 100 uint8 cnt=48; while(cnt--) { nop(); } // This is one clock cycle if placed at the end of the loop! if(!INT1_LEVEL()) break; } break; case 5: // 250kS // This will store every 40th sample: (250 kS) SampleClockSync(); for(;;) { cbi(PORTB,2); sbi(PORTB,2); nop(); // 6 -> 16 // 7 -> 18 // 8 -> 20 // n -> 2*n+4 // 18 -> 40 uint8 cnt=18; while(cnt--) { nop(); } // This is one clock cycle if placed at the end of the loop! if(!INT1_LEVEL()) break; } break; case 10: // 500kS // This will store every 20th sample: (500 kS) SampleClockSync(); asm("sleep"); for(;;) { cbi(PORTB,2); sbi(PORTB,2); nop(); uint8 cnt=8; while(cnt--) { nop(); } // This is one clock cycle if placed at the end of the loop! if(!INT1_LEVEL()) break; } break; case 20: // 1MS // This will store every 10th sample: (1 MS) SampleClockSync(); for(;;) { cbi(PORTB,2); sbi(PORTB,2); nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop(); nop();nop(); // This is one clock cycle if placed at the end of the loop! if(!INT1_LEVEL()) break; } break; case 50: // 2.5MS // This will store every 4th sample: (2.5 MS) SampleClockSync(); for(;;) { cbi(PORTB,2); sbi(PORTB,2); nop(); // This is one clock cycle if placed at the end of the loop! if(!INT1_LEVEL()) break; } break; case 100: // 5MS // This will store every 2nd sample: (5 MS) // clock1 (PB2): Set up timer0 in CTC mode. Prescaler to 1: OCR0A=0x01; // 0x00 TCNT0=0; TCCR0A=0x42U; // 01000010 <-- COM0A1:0, WGM00:1 TCCR0B=0x01U; // 00000001 SampleClockSync(); TCNT0=1; for(;;) { if(!INT1_LEVEL()) break; // <-- This is 1 clock cycle! } break; case 200: // 10MS // This will store all samples: (10 MS) SampleClockSync(); cbi(PORTB,2); // Sample until INT1 goes LOW. while(INT1_LEVEL()); break; default: // This is an error. // Don't sample: sbi(PORTB,2); // Already HIGH but be sure. // Wait for INT1 to go LOW. while(INT1_LEVEL()); break; } // Stop recording: This works for sampling modes based on internal counter. TCCR0B=0x0U; TCCR0A=0x4U; OCR0A=0x0; // No recording: This works for all sampling modes not using the // internal counter. sbi(PORTB,2);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -