Advertisement
fixed_it

OTSM test code

Dec 2nd, 2016
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.12 KB | None | 0 0
  1. /*
  2.     Typical driver layout.
  3.  
  4.              ---
  5.            -|   |- VCC
  6.        OTC -|   |- Voltage ADC
  7.     Star 3 -|   |- PWM (FET)
  8.        GND -|   |- PWM (1x7135)
  9.              ---
  10.  
  11.              ---
  12.        PB5 -|1 8|- VCC
  13.        PB3 -|2 7|- PB2
  14.        PB4 -|3 6|- PB1
  15.        GND -|4 5|- PB0
  16.              ---
  17. */
  18.  
  19. #if defined(__AVR_ATtiny13A__)
  20. #   define F_CPU 4800000UL
  21. #else
  22. #   define F_CPU 8000000UL
  23. #endif
  24.  
  25. #define ADC_PRESCALER_MASK (~(uint8_t)((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)))
  26. /* 1/128 for 62.5 kHz operation */
  27. #define ADC_PRESCALER_128 ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0))
  28. /* 1/64 */
  29. #define ADC_PRESCALER_64 ((1 << ADPS2) | (1 << ADPS1) | (0 << ADPS0))
  30. /* 1/8 */
  31. #define ADC_PRESCALER_8 ((0 << ADPS2) | (1 << ADPS1) | (1 << ADPS0))
  32.  
  33. #include <avr/io.h>
  34. #include <avr/eeprom.h>
  35. #include <avr/interrupt.h>
  36. #include <avr/pgmspace.h>
  37. #include <avr/sleep.h>
  38. #include <util/delay.h>
  39.  
  40. /* Fuses */
  41. #if defined(__AVR_ATtiny13A__)
  42. /*
  43.     low fuse:
  44.     - Enable programming & download.
  45.     - 4 ms startup delay.
  46.     - 4.8 MHz clock.
  47.     high fuse:
  48.     - Enable Brown-Out Detection at 1.8V.
  49. */
  50. FUSES =
  51. {
  52.     .low = FUSE_SPIEN & FUSE_SUT1 & FUSE_CKSEL1,
  53.     .high = FUSE_BODLEVEL0
  54. };
  55. #elif defined(__AVR_ATtiny25__)
  56. /*
  57.     low fuse:
  58.     - 4 ms startup delay.
  59.     - 8 MHz clock
  60.     high fuse:
  61.     - Enable programming & download.
  62.     - Enable Brown-Out Detection at 1.8V.
  63. */
  64. FUSES =
  65. {
  66.     .low = FUSE_SUT1 & FUSE_CKSEL3 & FUSE_CKSEL2 & FUSE_CKSEL0,
  67.     .high = FUSE_SPIEN & FUSE_BODLEVEL0,
  68.     .extended = EFUSE_DEFAULT
  69. };
  70. #else
  71. #error no fuse definitions
  72. #endif
  73.  
  74. /* #include "../include/cell_levels.h" */
  75. #ifndef __cell_levels_h
  76. #define __cell_levels_h
  77.  
  78. /*
  79.     Macros for the cell voltage readout with the ADC from a two resistor
  80.     voltage divider. Resistor values should be specified with no more than 4
  81.     digits to avoid overflow. So a 4.7k/19k pair can be specified as 47/190
  82.     or as 470/1900.
  83.  
  84.     The diode drop before voltage divider should be specified in units of 10 mV.
  85. */
  86.  
  87. #include <stdint.h>
  88.  
  89. #if defined(DRIVER_BLFA6)
  90. /* Driver in the BLF-A6 / astrolux S1. 65B / 223 resistors -> 4.64k / 22k */
  91. #define VCC_DIV_R1 464ul
  92. #define VCC_DIV_R2 2200ul
  93. #define VCC_DIV_DIODE_DROP 0ul
  94. #elif defined(DRIVER_MTN17DDm)
  95. /*
  96.     MTN-17DDm driver. Uses 4.7k / 19.1k. Has voltage divider after reverse
  97.     polarity diode which drops about 140 mV (measured).
  98. */
  99. #define VCC_DIV_R1 470ul
  100. #define VCC_DIV_R2 1910ul
  101. #define VCC_DIV_DIODE_DROP 14ul
  102. #else
  103. /* Generic values (4.7k/19k). */
  104. #define VCC_DIV_R1 470ul
  105. #define VCC_DIV_R2 1900ul
  106. #define VCC_DIV_DIODE_DROP 0ul
  107. #endif
  108.  
  109. /*
  110.     8-bit ADC value from voltage, as a 3 digit value (ie. 385 for 3.85V).
  111. */
  112. #define ADC8_FROM_CELL_V( vcc ) ((uint8_t)((uint32_t)(vcc) * VCC_DIV_R1 * 255ul / (110ul * (VCC_DIV_R1 + VCC_DIV_R2))))
  113. #define ADC8_CELL_DIODE_DROP ADC8_FROM_CELL_V( VCC_DIV_DIODE_DROP )
  114.  
  115. #endif
  116.  
  117. /* #include "../include/portability.h" */
  118. #ifndef __portability_h
  119. #define __portability_h
  120.  
  121. /*
  122.     I'm using macros here because even inline static functions somehow add to
  123.     code size.
  124. */
  125. #if defined(__AVR_ATtiny13A__)
  126.  
  127. #   define watchdog_interrupt_enable() \
  128.     do { WDTCR |= (1 << WDTIE); } while(0)
  129.  
  130. #   define watchdog_interrupt_disable() \
  131.     do { WDTCR &= ~(1 << WDTIE); } while(0)
  132.  
  133. #else
  134.  
  135. #   define watchdog_interrupt_enable() \
  136.     do { WDTCR |= (1 << WDIE); } while(0)
  137.  
  138. #   define watchdog_interrupt_disable() \
  139.     do { WDTCR &= ~(1 << WDIE); } while(0)
  140.  
  141. #endif
  142.  
  143. #endif
  144.  
  145. volatile uint8_t g_have_power;
  146. volatile uint8_t g_wdt_count;
  147. volatile uint8_t g_flash_count;
  148.  
  149. /* flash the 7135 channel to say we're running */
  150. static
  151. void flash()
  152. {
  153.     PORTB |= (1 << PORTB0);
  154.     _delay_ms( 10 );
  155.     PORTB &= ~(1 << PORTB0);
  156. }
  157.  
  158. /* Watchdog interrupt. */
  159. ISR( WDT_vect )
  160. {
  161.     /* Count time. */
  162.     ++g_wdt_count;
  163.     /* If power is out, start ADC. */
  164.     if( !g_have_power )
  165.     {
  166.         ADCSRA |= (1 << ADSC);
  167.         sei();
  168.         set_sleep_mode( SLEEP_MODE_IDLE );
  169.         sleep_mode();
  170.     }
  171. }
  172.  
  173. /* ADC interrupt. */
  174. ISR( ADC_vect )
  175. {
  176.     uint8_t cell_level = ADCH;
  177.     if( cell_level < ADC8_FROM_CELL_V( 200 ) )
  178.     {
  179.         /* power's out */
  180.         if( g_have_power )
  181.         {
  182.             /* This is new. Start counting. */
  183.             g_wdt_count = 0;
  184.             g_have_power = 0;
  185.             /* Enable recursive interrupt. */
  186.             sei();
  187.             /* Make ADC run faster. */
  188.             ADCSRA &= ADC_PRESCALER_MASK;
  189.             ADCSRA = ADC_PRESCALER_8;
  190.             /* Go to sleep. */
  191.             while( g_have_power == 0 )
  192.             {
  193.                 set_sleep_mode( SLEEP_MODE_PWR_DOWN );
  194.                 sleep_mode();
  195.             }
  196.         }
  197.         else
  198.         {
  199.             /*
  200.                 Power was already out. Nothing to do here. We're 3 interrupts
  201.                 deep at this point so we'll return to the WDT interrupt which
  202.                 will return to this interrupt (in the loop above) which will
  203.                 put us back to sleep.
  204.             */
  205.         }
  206.     }
  207.     else
  208.     {
  209.         /* we have power */
  210.         if( g_have_power )
  211.         {
  212.             /* We already had power. Just start the next conversion. */
  213.             ADCSRA |= (1 << ADSC);
  214.         }
  215.         else
  216.         {
  217.             /* Power was restored. */
  218.             g_have_power = 1;
  219.             /* Tell main loop to flash the delay. */
  220.             g_flash_count = g_wdt_count;
  221.             /* Restore regular ADC speed. */
  222.             ADCSRA &= ADC_PRESCALER_MASK;
  223.             ADCSRA = ADC_PRESCALER_64;
  224.         }
  225.     }
  226. }
  227.  
  228. int main(void)
  229. {
  230.     g_have_power = 1;
  231.  
  232.     /* initialize ADC to read cell level on ADC1 (PB2) */
  233.     /* disable digital input */
  234.     DIDR0 |= (1 << ADC1D);
  235.     /* internal 1.1V ref, left adjusted, ADC1 (PB2) */
  236. #if defined(__AVR_ATtiny13A__)
  237.     ADMUX = (1 << REFS0) | (1 << ADLAR) | (1 << MUX0);
  238. #else
  239.     ADMUX = (1 << REFS1) | (1 << ADLAR) | (1 << MUX0);
  240. #endif
  241.     /* ADC prescaler for normal operation */
  242.     ADCSRA = ADC_PRESCALER_64;
  243.  
  244.     /* Also disable digital input on OTC pin. */
  245.     DIDR0 |= (1 << ADC3D);
  246.  
  247.     /* enable 7135 output */
  248.     DDRB |= (1 << DDB0);
  249.  
  250.     /* big flash to show we rebooted */
  251.     PORTB |= (1 << PORTB0);
  252.     _delay_ms( 200 );
  253.     PORTB &= ~(1 << PORTB0);
  254.  
  255.     /* enable watchdog interrupt every 0.125s */
  256.     watchdog_interrupt_enable();
  257.     WDTCR |= (1 << WDP1) | (1 << WDP0) ;
  258.  
  259.     /* enable ADC interrupt */
  260.     ADCSRA |= (1 << ADIE);
  261.     sei();
  262.  
  263.     /* enable ADC, start conversion */
  264.     ADCSRA |= (1 << ADEN) | (1 << ADSC);
  265.  
  266.     while( 1 == 1 )
  267.     {
  268.         /* main loop */
  269.         if( g_flash_count > 0 )
  270.         {
  271.             --g_flash_count;
  272.             flash();
  273.             _delay_ms( 500 );
  274.         }
  275.     }
  276. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement