You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

267 lines
7.0 KiB

  1. #include <stdbool.h>
  2. #include <avr/io.h>
  3. #include <avr/interrupt.h>
  4. #define F_CPU 20000000UL //20 MHz
  5. #include <util/delay.h>
  6. /* 7-Segment display: */
  7. #define NUM_DIGITS 3U //3 Digits
  8. #define DIGIT_TENS 2U //left
  9. #define DIGIT_ONES 1U //middle
  10. #define DIGIT_UNIT 0U //right
  11. #define SELECT_DIGIT(digit) (1U << digit)
  12. #define TEMP_MIN 0U
  13. #define TEMP_MAX 50U
  14. #define BUTTON_THRESHOLD 50U //software debounce
  15. /* Symbol indexes: */
  16. #define SYM_n 10U
  17. #define SYM_o 11U
  18. #define SYM_E 12U
  19. #define SYM_R 13U
  20. #define SYM_DEG_CELCIUS 14U
  21. #define SYM_P_P 15U
  22. #define SYM_OFF 16U
  23. #define SYM_DASH 17U
  24. /*
  25. 7-Segment Layout:
  26. A
  27. F B
  28. G
  29. E C
  30. D P
  31. Pin 7 6 5 4 3 2 1 0
  32. Segment A F B E D C G P
  33. */
  34. static uint8_t g_au8Symbols[18U] =
  35. {
  36. /* 00 */ 0b11111100U, //0 (ABCDEF)
  37. /* 01 */ 0b00100100U, //1 (BC)
  38. /* 02 */ 0b10111010U, //2 (ABDEG)
  39. /* 03 */ 0b10101110U, //3 (ABCDG)
  40. /* 04 */ 0b01100110U, //4 (BCFG)
  41. /* 05 */ 0b11001110U, //5 (ACDFG)
  42. /* 06 */ 0b11011110U, //6 (ACDEFG)
  43. /* 07 */ 0b10100100U, //7 (ABC)
  44. /* 08 */ 0b11111110U, //8 (ABCDEFG)
  45. /* 09 */ 0b11101110U, //9 (ABCDFG)
  46. /* 10 */ 0b00010110U, //n (CEG) SYM_n
  47. /* 11 */ 0b00011110U, //o (CDEG) SYM_o
  48. /* 12 */ 0b11011010U, //E (ADEFG) SYM_E
  49. /* 13 */ 0b00010010U, //r (EG) SYM_r
  50. /* 14 */ 0b10101101U, //degC (ABCDP) SYM_DEG_CELCIUS
  51. /* 15 */ 0b11110011U, //P. (ABEFGP) SYM_P_P
  52. /* 16 */ 0b00000000U, //OFF SYM_OFF
  53. /* 17 */ 0b00000010U //- (G) SYM_DASH
  54. };
  55. static uint8_t g_u8WaterTemperature = 24U; //Water temperature, default 24 degree celcius
  56. static uint8_t g_u8CountIncs = 0U; //'+' button counter
  57. static uint8_t g_u8CountDecs = 0U; //'-' button counter
  58. uint8_t g_u8ISRDigitSelect = 0U;
  59. uint8_t g_au8Digits[3U] =
  60. {
  61. SYM_OFF, //unit
  62. SYM_OFF, //ones
  63. SYM_OFF //tens
  64. };
  65. void vInit( void );
  66. void vSetValue( uint8_t u8Value, uint8_t u8Unit );
  67. void vSetDisplayDigits( uint8_t u8Tens, uint8_t u8Ones, uint8_t u8Unit );
  68. void vReadButtons( void );
  69. void vCalculate( void );
  70. /************************************************************************/
  71. /* Timer1 ISR - show values on display */
  72. /************************************************************************/
  73. ISR ( TIMER1_COMPA_vect )
  74. {
  75. PORTB = 0;
  76. PORTD = 0;
  77. _delay_us(2);
  78. PORTB = SELECT_DIGIT(g_u8ISRDigitSelect);
  79. PORTD = g_au8Symbols[g_au8Digits[g_u8ISRDigitSelect]];
  80. g_u8ISRDigitSelect++;
  81. if (g_u8ISRDigitSelect > 2U)
  82. {
  83. g_u8ISRDigitSelect = 0U;
  84. }
  85. }
  86. /************************************************************************/
  87. /* main() */
  88. /************************************************************************/
  89. int main(void)
  90. {
  91. /* Init I/O: */
  92. vInit();
  93. /* Set default value: */
  94. vSetDisplayDigits( SYM_DASH, SYM_DASH, SYM_DASH );
  95. /* wait 3 seconds */
  96. _delay_ms(3000);
  97. /* Set default value: */
  98. vSetValue( g_u8WaterTemperature, SYM_DEG_CELCIUS );
  99. while ( 1 )
  100. {
  101. vReadButtons();
  102. vCalculate();
  103. _delay_ms(3);
  104. }
  105. return 0;
  106. }
  107. /************************************************************************/
  108. /* Initialize inputs and outputs */
  109. /************************************************************************/
  110. void vInit( void )
  111. {
  112. /* Port D - Pins 0-7: Outputs */
  113. DDRD = 0b11111111U;
  114. /* Port B - Pins 0-2: Outputs */
  115. DDRB = 0b00000111U;
  116. /* Port C - Pins 4-5: Inputs with internal Pull-up */
  117. PORTC = 0b00110000U;
  118. /* 16-bit TIMER1 in CTC mode
  119. * prescaler = 8
  120. * 20 MHz / 8 = 2.5 MHz
  121. * Compare value = 2500 => 1 ms IRQ
  122. */
  123. TCCR1A = 0U;
  124. TCCR1B = (1<<WGM12) | (1<<CS11);
  125. OCR1A = 2500U;
  126. TIMSK1 |= (1<<OCIE1A);
  127. sei();
  128. return; //void
  129. }
  130. /************************************************************************/
  131. /* */
  132. /************************************************************************/
  133. void vDigitTest( void)
  134. {
  135. PORTB = SELECT_DIGIT(DIGIT_TENS);
  136. PORTD = 0xFF;
  137. _delay_ms(1000);
  138. PORTD = 0;
  139. _delay_ms(100);
  140. PORTB = SELECT_DIGIT(DIGIT_ONES);
  141. PORTD = 0xFF;
  142. _delay_ms(1000);
  143. PORTD = 0;
  144. _delay_ms(100);
  145. PORTB = SELECT_DIGIT(DIGIT_UNIT);
  146. PORTD = 0xFF;
  147. _delay_ms(1000);
  148. PORTD = 0;
  149. _delay_ms(100);
  150. return; //void
  151. }
  152. /************************************************************************/
  153. /* Set new values to be shown on display */
  154. /************************************************************************/
  155. void vSetValue( uint8_t u8Value, uint8_t u8Unit )
  156. {
  157. uint8_t u8Tmp = u8Value / 10U;
  158. vSetDisplayDigits(u8Tmp, u8Value - (u8Tmp * 10U), u8Unit);
  159. return; //void
  160. }
  161. /************************************************************************/
  162. /* Set display digits individually */
  163. /************************************************************************/
  164. void vSetDisplayDigits( uint8_t u8Tens, uint8_t u8Ones, uint8_t u8Unit )
  165. {
  166. g_au8Digits[DIGIT_TENS] = u8Tens;
  167. g_au8Digits[DIGIT_ONES] = u8Ones;
  168. g_au8Digits[DIGIT_UNIT] = u8Unit;
  169. return; //void
  170. }
  171. /************************************************************************/
  172. /* Read button status */
  173. /************************************************************************/
  174. void vReadButtons( void )
  175. {
  176. if ( !(PINC & (1<<PINC4)) ) //if button '+' pressed
  177. {
  178. g_u8CountIncs++;
  179. }
  180. else
  181. {
  182. g_u8CountIncs = 0U; //reset button counter
  183. }
  184. if ( !(PINC & (1<<PINC5)) ) //if button '-' pressed
  185. {
  186. g_u8CountDecs++;
  187. }
  188. else
  189. {
  190. g_u8CountDecs = 0U; //reset button counter
  191. }
  192. return; //void
  193. }
  194. /************************************************************************/
  195. /* */
  196. /************************************************************************/
  197. void vCalculate( void )
  198. {
  199. bool blChanged = false;
  200. if ( g_u8CountIncs > BUTTON_THRESHOLD )
  201. {
  202. g_u8WaterTemperature++;
  203. if ( g_u8WaterTemperature > TEMP_MAX )
  204. {
  205. g_u8WaterTemperature = TEMP_MIN;
  206. }
  207. blChanged = true;
  208. g_u8CountIncs = 0U; //reset increment counter
  209. }
  210. if ( g_u8CountDecs > BUTTON_THRESHOLD )
  211. {
  212. if ( g_u8WaterTemperature == TEMP_MIN )
  213. {
  214. g_u8WaterTemperature = TEMP_MAX;
  215. }
  216. else
  217. {
  218. g_u8WaterTemperature--;
  219. }
  220. blChanged = true;
  221. g_u8CountDecs = 0U; //reset decrement counter
  222. }
  223. if ( blChanged )
  224. {
  225. vSetValue( g_u8WaterTemperature, SYM_DEG_CELCIUS );
  226. }
  227. return; //void
  228. }