Advertisement
Guest User

tacdrv.c

a guest
Apr 7th, 2015
399
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.00 KB | None | 0 0
  1. //
  2. // TacDrv 0.1
  3. //
  4. // License: Public Domain, if DrJones approve :)
  5. //
  6. // For use in 105c type drivers
  7. //
  8.  
  9. #define F_CPU 4800000    // CPU: 4.8MHz  PWM: 9.4kHz   ####### use low fuse: 0x75 #######
  10.  
  11. // Mode values
  12. #define LO 20 // Light output, 0-255
  13. #define MID 120
  14. #define FULL 255 // Full output, no PWM
  15. #define STROBE 254 // Just a dummy number for id, must not be used for other modes
  16. #define STROBE_ON 33 // Strobe frequency should be 10-20hz, default 15hz (1000ms/15hz, 33ms on/off)
  17. #define STROBE_OFF 33
  18.  
  19. // Modes, edit as you want
  20. #define MODES LO, MID, FULL, STROBE
  21.  
  22. #define NOMEM        // deactivate mode memory.
  23. #define LOCKTIME 7   // time in 1/8 s until a mode gets locked, e.g. 12/8=1.5s
  24. #define BATTMON  125 // enable battery monitoring with this threshold
  25.  
  26. #define outpin 1
  27. #define PWM OCR0B  // PWM-value
  28. #define adcpin 2
  29. #define adcchn 1
  30. #define portinit() do{ DDRB=(1<<outpin); PORTB=0xff-(1<<outpin)-(1<<adcpin);  }while(0)
  31.  
  32. #include <avr/pgmspace.h>
  33. #define byte uint8_t
  34. #define word uint16_t
  35.  
  36. PROGMEM byte modes[]={ MODES };
  37.  
  38. #include <avr/io.h>
  39. #include <util/delay.h>
  40. #include <avr/interrupt.h>
  41. #include <avr/sleep.h>
  42. #include <avr/eeprom.h>
  43.  
  44. #define WDTIME 0b01000011  //125ms
  45.  
  46. #define sleepinit() do{ WDTCR=WDTIME; sei(); MCUCR=(MCUCR &~0b00111000)|0b00100000; }while(0) //WDT-int and Idle-Sleep
  47.  
  48. #define SLEEP asm volatile ("SLEEP")
  49.  
  50. #define pwminit() do{ TCCR0A=0b00100001; TCCR0B=0b00000001; }while(0)  //chan A, phasePWM, clk/1  ->2.35kHz@1.2MHz
  51.  
  52. #define adcinit() do{ ADMUX =0b01100000|adcchn; ADCSRA=0b11000100; }while(0) //ref1.1V, left-adjust, ADC1/PB2; enable, start, clk/16
  53. #define adcread() do{ ADCSRA|=64; while (ADCSRA&64); }while(0)
  54. #define adcresult ADCH
  55.  
  56. #define ADCoff ADCSRA&=~(1<<7) //ADC off (enable=0);
  57. #define ADCon  ADCSRA|=(1<<7)  //ADC on
  58. #define ACoff  ACSR|=(1<<7)    //AC off (disable=1)
  59. #define ACon   ACSR&=~(1<<7)   //AC on  (disable=0)
  60.  
  61. volatile byte mypwm=0;
  62. volatile byte ticks=0;
  63. volatile byte mode=0;
  64. byte pmode=50;
  65.  
  66. byte eep[32];  //EEPROM buffer
  67. byte eepos=0;
  68.  
  69. byte lowbattcounter=0;
  70.  
  71. void eepsave(byte data) {  //central method for writing (with wear leveling)
  72.   byte oldpos=eepos;
  73.   eepos=(eepos+1)&31;  //wear leveling, use next cell
  74.   EEARL=eepos; EEDR=data; EECR=32+4; EECR=32+4+2;  //WRITE  //32:write only (no erase)  4:enable  2:go
  75.   while(EECR & 2); //wait for completion
  76.   EEARL=oldpos;           EECR=16+4; EECR=16+4+2;  //ERASE  //16:erase only (no write)  4:enable  2:go
  77. }
  78.  
  79. ISR(WDT_vect) {  //WatchDogTimer interrupt
  80.   if (ticks<255) ticks++;
  81.   if (ticks==LOCKTIME)
  82.   #ifdef NOMEM
  83.     eepsave(0);  //current mode locked -> next time start over, no memory.
  84.   #else
  85.     eepsave(mode);
  86.   #endif
  87.  
  88.   #ifdef BATTMON //code to check voltage and ramp down
  89.    adcread();
  90.    if (adcresult<BATTMON) { if (++lowbattcounter>8) {mypwm=(mypwm>>1)+3;lowbattcounter=0;} }
  91.    else lowbattcounter=0;
  92.   #endif
  93. }
  94.  
  95. inline void getmode(void) {  //read current mode from EEPROM and write next mode
  96.  
  97.   eeprom_read_block(&eep, 0, 32);                     //read block
  98.   while((eep[eepos]==0xff) && (eepos<32)) eepos++;    //find mode byte
  99.   if (eepos<32) mode=eep[eepos];
  100.   else eepos=0;
  101.  
  102.   byte next=0;
  103.   if (mode==0) next=1; //skip 1st mode if memory is 1st mode already
  104.  
  105.   if (mode & 0x80) {  //last on-time was short
  106.     mode&=0x7f;   if (mode>=sizeof(modes)) mode=0;
  107.     next=mode+1;  if (next>=sizeof(modes)) next=0;
  108.   }
  109.  
  110.   eepsave(next|0x80); //write next mode, with short-on marker
  111. }
  112.  
  113. int main(void) {
  114.  
  115.   portinit();
  116.   sleepinit();
  117.   ACoff;
  118.   #ifdef BATTMON
  119.     adcinit();
  120.   #else
  121.     ADCoff;
  122.   #endif
  123.   pwminit();
  124.  
  125.   getmode();  //get current mode number from EEPROM
  126.   byte i=0;
  127.   pmode=pgm_read_byte(&modes[mode]);  //get actual PWM value (or special mode code)
  128.  
  129.   switch(pmode){
  130.     case STROBE:  mypwm=255; while(1){ PWM=mypwm; _delay_ms(STROBE_ON); PWM=0; _delay_ms(STROBE_OFF); } break;
  131.  
  132.     default:   mypwm=pmode; while(1){PWM=mypwm;SLEEP;}  //all other: us as PWM value
  133.  
  134.   }
  135.   return 0;
  136. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement