skrupellos

main.c

Aug 29th, 2011
45
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "main.h"
  2.  
  3.  
  4. // This interrupt gets fired if the TX buffer is empty. Hence the interrupt
  5. // should only wake up the CPU, there is no need to implement an ISR.
  6. EMPTY_INTERRUPT(USART0_UDRE_vect);
  7.  
  8.  
  9. // This interrupt gets fired after 5 times \tau, when the capacitor is 99%
  10. // discharged.
  11. ISR(TIMER0_OVF_vect) {
  12.     discharging = false;
  13. }
  14.  
  15.  
  16. static int sendUart(char c, FILE *stream) {
  17.     // Automatically convert Unix into Win line endings
  18.     if (c == '\n') {
  19.         sendUart('\r', stream);
  20.     }
  21.    
  22.     // Sleep until the TX buffer is empty
  23.     cli();
  24.     while( !(UCSR0A & _BV(UDRE0)) ) {
  25.         sei();
  26.         sleep();
  27.     }
  28.    
  29.     // Put data into buffer, sends the data
  30.     UDR0 = c;
  31.    
  32.     return 0;
  33. }
  34.  
  35.  
  36. static FILE uartOut = FDEV_SETUP_STREAM(sendUart, NULL, _FDEV_SETUP_WRITE);
  37.  
  38.  
  39. uint16_t accuireCap(uint8_t samples) {
  40.     // ## INIT #################################################################
  41.     uint32_t sum = 0;
  42.     uint8_t swSamples = samples;
  43.    
  44.     // Both: Disable pull-up / Set to GND
  45.     CBI(PORT_UP, PIN_UP);
  46.     CBI(PORT_DOWN, PIN_DOWN);
  47.    
  48.     while(swSamples--) {
  49.         // ## RESET / EVALUATE #################################################
  50.         uint16_t hwSamples = 0;
  51.        
  52.         // Both: Output (GND)
  53.         SBI(DDR_UP,    PIN_UP);
  54.         SBI(DDR_DOWN,  PIN_DOWN);
  55.         // Both are now connected to GND directly
  56.        
  57.         discharging = true;
  58.        
  59.         // Reset the timer counter
  60.         TCNT0 = 0;
  61.        
  62.         enableTimer();
  63.         cli();
  64.         while(discharging) {
  65.             sei();
  66.             sleep();
  67.         }
  68.         disableTimer();
  69.        
  70.        
  71.         // ## SAMPLE ###########################################################
  72.         do {
  73.             // ==== Switch ports ===============================================
  74.             // Upper: Input
  75.             CBI(DDR_UP,   PIN_UP);
  76.             // Upper is now open
  77.            
  78.            
  79.             // Bottom: Set to Vcc / Enable pull-up
  80.             SBI(PORT_DOWN, PIN_DOWN);
  81.             // First:   Bottom is now connected to Vcc directly
  82.             // Further: Bottom is now connected to Vcc through a pull-up
  83.            
  84.             // Bottom: Output (Vcc)
  85.             SBI(DDR_DOWN, PIN_DOWN);
  86.             // Bottom is now connected to Vcc directly
  87.            
  88.            
  89.             // ==== Wait =======================================================
  90.             if(experience) {
  91.                 // http://www.avr-asm-tutorial.net/avr_de/zeitschleifen/
  92.                 // delay8.html
  93.                 // 21cc / 3 = 7
  94.                 uint8_t cnt;
  95.                 asm volatile(
  96.                     "ldi %0, 7     ; 1cc                      \n"
  97.                     "Loop:                                    \n\t"
  98.                     "dec %0        ; 1cc                      \n\t"
  99.                     "brne Loop     ; 2cc if ne 0, 1cc if eq 0 \n\t"
  100.                     : "=&w" (cnt)
  101.                 );
  102.             } else {
  103.                 asm volatile("nop");
  104.             }
  105.            
  106.            
  107.             // ==== Switch ports ===============================================
  108.             // Bottom: Input (pull-up)
  109.             CBI(DDR_DOWN, PIN_DOWN);
  110.             // Bottom is now connected to Vcc through a pull-up
  111.            
  112.             // Bottom: Disable pull-up / Set to GND
  113.             CBI(PORT_DOWN, PIN_DOWN);
  114.             // Bottom is now open
  115.            
  116.            
  117.             // Upper: Output (GND)
  118.             SBI(DDR_UP, PIN_UP);
  119.             // Upper is now connected to GND directly
  120.            
  121.            
  122.             // ==== Measure ====================================================
  123.             // The analog comparator result is available after 2cc. But
  124.             // incrementing hwSamples takes already longer.
  125.         } while(++hwSamples && (ACSR & _BV(ACO)));
  126.        
  127.         // Add the HW sampled value to the software sampled treating an overflow
  128.         // as a maximum.
  129.         if(hwSamples == 0) {
  130.             sum += 0xFFFF;
  131.         } else {
  132.             sum += hwSamples;
  133.         }
  134.     }
  135.    
  136.     // Return the averaged value
  137.     return sum / samples;
  138. }
  139.  
  140.  
  141. int main()
  142. {
  143.     // ==== Timer ==============================================================
  144.     // TCCR0A – Timer/Counter Control Register A
  145.     // WGM01:0: Waveform Generation Mode (Fast PWM)
  146.     TCCR0A = _BV(WGM01) | _BV(WGM00);
  147.    
  148.     // TCCR0B – Timer/Counter Control Register B
  149.     // WGM02: Waveform Generation Mode (Fast PWM)
  150.     TCCR0B = _BV(WGM02);
  151.    
  152.     // OCR0A – Output Compare Register A
  153.     // 64 * 34 = 2176
  154.     OCR0A = 34;
  155.    
  156.     // TIMSK0 – Timer/Counter Interrupt Mask Register
  157.     // TOIE0: Timer/Counter0 Overflow Interrupt Enable
  158.     TIMSK0 = _BV(TOIE0);
  159.    
  160.    
  161.     // ==== UART ===============================================================
  162.     // Set baud rate
  163.     UBRR0H = (unsigned char)(UBRR_VAL>>8);
  164.     UBRR0L = (unsigned char)UBRR_VAL;
  165.    
  166.     // UCSRnB: USART Control and Status Register n B
  167.     // UDRIEn: USART Data Register Empty Interrupt Enable n
  168.     // TXENn: Transmitter Enable n
  169.     UCSR0B = _BV(UDRIE0) | _BV(TXEN0);
  170.    
  171.    
  172.     // ==== Disable input buffers (Analog/Powersave) ===========================
  173.     // DIDR0 – Digital Input Disable Register 0
  174.     // Bit 7:0 – ADC7D:ADC0D: ADC7:0 Digital Input Disable
  175.     DIDR0 = 0xFF;
  176.    
  177.     // DIDR1 – Digital Input Disable Register 1
  178.     // Bit 1, 0 – AIN1D, AIN0D: AIN1, AIN0 Digital Input Disable
  179.     DIDR1 = 0x03;
  180.    
  181.     // DIDR2 – Digital Input Disable Register 2
  182.     // Bit 7:0 – ADC15D:ADC8D: ADC15:8 Digital Input Disable
  183.     DIDR2 = 0xFF;
  184.    
  185.    
  186.     // ==== STDOUT =============================================================
  187.     // Set STDOUT to an UART sink
  188.     stdout = &uartOut;
  189.    
  190.    
  191.     // ==== Debug port =========================================================
  192.     DDRA = 0xFF;
  193.     PORTA = 0xFF;
  194.    
  195.    
  196.     // ==== Arm the interrupts =================================================
  197.     sei();
  198.    
  199.    
  200.    
  201.     uint16_t history[HISTORY_LEN];
  202.     uint16_t *curHistoryItem = history;
  203.     uint8_t isInPeak = false;
  204.    
  205.     while(true) {
  206.         uint16_t cap, minCap, maxCap;
  207.         uint16_t *historyItem;
  208.         uint8_t i;
  209.        
  210.         // Append the current value to the history (ring buffer)
  211.         cap = accuireCap(SW_SAMPLES);
  212.         *curHistoryItem = cap;
  213.        
  214.         if(curHistoryItem == (history + HISTORY_LEN - 1)) {
  215.             curHistoryItem = history;
  216.         } else {
  217.             curHistoryItem++;
  218.         }
  219.        
  220.         // Get the min/max values from the history
  221.         historyItem = history;
  222.         minCap = 0xFFFF;
  223.         maxCap = 0x0000;
  224.        
  225.         for(i = HISTORY_LEN; i; i--) {
  226.             if(minCap > *historyItem) {
  227.                 minCap = *historyItem;
  228.             }
  229.            
  230.             if(maxCap < *historyItem) {
  231.                 maxCap = *historyItem;
  232.             }
  233.            
  234.             historyItem++;
  235.         }
  236.        
  237.         // Print a message if a touch is recognized
  238.         if(maxCap * THRESHOLD > cap) {
  239.             if(isInPeak == false) {
  240.                 printf("Blubb\n");
  241.                 isInPeak = true;
  242.             }
  243.         } else {
  244.             isInPeak = false;
  245.         }
  246.        
  247.         // Print some debug messages (you can copy&paste the to Excel; CSV)
  248.         printf("%5d; %5d; %5d; %5d; %5d; %5d\n",
  249.             cap, minCap, maxCap, maxCap - minCap, cap - minCap, maxCap - cap
  250.         );
  251.     }
  252. }
RAW Paste Data