main.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. //
  2. // ^ Vcc MSP430G2452 GND ^ Vcc ^ Vcc
  3. // | /-------------\ | | |
  4. // +--- -| Vcc U GND |- ---+ | | 47 k === 100 nF
  5. // 0 -| P1.0 XTAL |- ------+ Crystal | | |
  6. // 1 -| P1.1 XTAL |- --|O|-+ 32768 Hz | --- GND
  7. // 2 -| P1.2 TEST |- -------------------|--o TEST +--------+
  8. // 3 -| P1.3 ~RST |- -------------------+--o ~RST | |
  9. // 4 -| P1.4 P1.7 |- BUTTON_1 connected to Vcc | === 10 uF
  10. // 5 -| P1.5 P1.6 |---------------------------------+ |
  11. // 6 -| P2.0 P2.5 |- BUTTON_2 connected to Vcc | LED - /| Coil-
  12. // 7 -| P2.1 P2.4 |- SR_RCK (latch clock) / \|/ | | | Speaker
  13. // SR_SI -| P2.2 P2.3 |- SR_SCK (shift clock) v/ --- - \| (16 R)
  14. // \-------------/ v | |
  15. // 0..7 LED row select --- GND --- GND
  16. //
  17. //
  18. // Vcc Vcc +----------------+ Vcc
  19. // ^ SI RCK ^ | Vcc ^ | RCK ^
  20. // | Al | GND | SCK | | | Ar | GND | SCK |
  21. // | | | | | | | | | | | | | | | |
  22. // /------------------------\ /------------------------\
  23. // |Vcc QA SI OE RST H | |Vcc QA SI OE RST H |
  24. // |> MC74HC595 | |> MC74HC595 |
  25. // |QB QC QD QE QF QG QH GND| |QB QC QD QE QF QG QH GND|
  26. // \------------------------/ \------------------------/
  27. // | | | | | | | | | | | | | | | |
  28. // Bl Cl Dl El Fl Gl Hl GND Br Cr Dr Er Fr Gr Hr GND
  29. // (left 8 LED columns) (right 8 LED columns)
  30. //
  31. //
  32. // A B C D E F G H
  33. // 0 o o o o o o o o * A C *
  34. // 1 o o o o o o o o 4 * F *
  35. // 2 o o o o o o o o 2 * * 3 the label is on
  36. // 3 o o o o o o o o * D H * the right side:
  37. // 4 o o o o o o o o 7 * * 5 (LD788BS-SS22)
  38. // 5 o o o o o o o o * B * 6
  39. // 6 o o o o o o o o 1 * G *
  40. // 7 o o o o o o o o 0 * E *
  41. //
  42. // 0..7 (-) cathode pin assignment as
  43. // A..H (+) anode seen from the top
  44. #include <stdint.h>
  45. #include <msp430g2452.h>
  46. #include "glyphs.h"
  47. #include "tune.h"
  48. #define SR_SI BIT2 // Serial Data Input
  49. #define SR_SCK BIT3 // Clock Input
  50. #define SR_RCK BIT4 // Storage Register Clock Input
  51. #define BUZZER BIT6
  52. #define BUTTON_1 BIT7
  53. #define BUTTON_2 BIT5
  54. #define DISPLAYING_LIMIT 3 // Seconds
  55. #define SHINING_LIMIT 60 // Seconds
  56. #define SHINING_WARN_TICKS 4
  57. static uint8_t fb[ 16 ]; // LED frame buffer
  58. static volatile uint8_t ticks = 0, seconds = 0, minutes = 0, hours = 0;
  59. static volatile uint8_t alarm_hour = 0, alarm_minute = 0;
  60. static volatile uint8_t ticks_at_button_press = 0;
  61. static volatile uint8_t displaying_watchdog = 0;
  62. static volatile uint8_t shining_watchdog = 0;
  63. static volatile bool alarm_is_active = false;
  64. static volatile bool go_to_sleep = false;
  65. static volatile bool tick_happened = false;
  66. static volatile uint16_t tune_index = 0;
  67. static volatile uint8_t tune_count = 0;
  68. enum TState { SLEEPING, SHINING,
  69. TIME_DISPLAYING, TIME_HOUR_EDITING, TIME_MINUTE_EDITING,
  70. ALARM_DISPLAYING, ALARM_HOUR_EDITING, ALARM_MINUTE_EDITING,
  71. ALARM_IS_ACTIVE_DISPLAYING, ALARM_IS_ACTIVE_EDITING,
  72. BLINKING, PLAYING };
  73. static volatile TState state = TIME_DISPLAYING;
  74. static void config_registers()
  75. {
  76. WDTCTL = WDTPW | WDTHOLD;
  77. DCOCTL = CALDCO_16MHZ;
  78. BCSCTL1 = CALBC1_16MHZ;
  79. BCSCTL3 |= LFXT1S_0 | XCAP_3; // Use Crystal as ACLK + 12.5 pF caps
  80. WDTCTL = WDT_ADLY_16; // Interval timer mode using ACLK clock source
  81. IE1 |= WDTIE;
  82. P1OUT = 0x00;
  83. P2OUT = 0x00;
  84. P1DIR = 0xFF & ~BUTTON_1 & ~BUZZER; // All output except BUTTON_1 and BUZZER
  85. P2DIR = 0xFF & ~BUTTON_2; // All output except BUTTON_2
  86. P1OUT &= ~BUTTON_1; // select resistor to be pull-down
  87. P2OUT &= ~BUTTON_2;
  88. P1REN |= BUTTON_1; // enable resistor
  89. P2REN |= BUTTON_2;
  90. //P1IES &= ~BUTTON_1; // select the positive edge (low -> high transition) to cause an interrupt
  91. //P2IES &= ~BUTTON_2;
  92. //P1IFG &= ~BUTTON_1; // Clear any pending interrupt flags
  93. //P2IFG &= ~BUTTON_2;
  94. //P1IE |= BUTTON_1; // enable button interrupt
  95. //P2IE |= BUTTON_2;
  96. P1SEL |= BIT6; // enable Timer0_A Out1 function
  97. TACCTL1 = OUTMOD_7; // Reset/set |~~|_____
  98. TACTL = TASSEL_2 | MC_1 | TACLR; // SMCLK + Up mode + Clear timer
  99. TACCR0 = 1; // period
  100. TACCR1 = 0; // 2 is permanent on, 0 is off when TACCR0 is 1.
  101. }
  102. static uint8_t shift_row( int8_t y )
  103. {
  104. uint8_t on_led_count = 0;
  105. P2OUT &= ~SR_RCK;
  106. for ( uint8_t x = 0; x < 16; ++x ) {
  107. P2OUT &= ~SR_SCK;
  108. if ( fb[ 15 - x ] & ( 0x01 << y ) ) {
  109. P2OUT |= SR_SI;
  110. ++on_led_count;
  111. } else {
  112. P2OUT &= ~SR_SI;
  113. }
  114. P2OUT |= SR_SCK;
  115. }
  116. return on_led_count;
  117. }
  118. static void select_row( int8_t y )
  119. {
  120. // Turn all rows off:
  121. P1OUT |= 0x3F;
  122. P2OUT |= 0x03;
  123. // Strobe columns:
  124. P2OUT |= SR_RCK;
  125. // Select respective row:
  126. if ( y >= 0 ) {
  127. if ( y < 6 ) {
  128. P1OUT &= ~( 0x01 << y );
  129. } else {
  130. P2OUT &= ~( 0x01 << ( y - 6 ) );
  131. }
  132. }
  133. }
  134. static void sleep()
  135. {
  136. // Set columns low:
  137. P2OUT &= ~SR_RCK;
  138. for ( uint8_t x = 0; x < 16; ++x ) {
  139. P2OUT &= ~SR_SCK;
  140. P2OUT &= ~SR_SI;
  141. P2OUT |= SR_SCK;
  142. }
  143. // Strobe columns:
  144. P2OUT |= SR_RCK;
  145. // Set rows low:
  146. P1OUT &= ~0x3F;
  147. P2OUT &= ~0x03;
  148. // Set the rest low:
  149. P2OUT &= ~( SR_SI | SR_SCK | SR_RCK );
  150. TACCR0 = 1;
  151. TACCR1 = 0; // Discharge the 10 uF capacitor, otherwise the
  152. __delay_cycles( 16000 ); // device consumes over 40 uA in sleep mode.
  153. // Change Buzzer to input:
  154. P1DIR &= ~BUZZER;
  155. // Go to sleep:
  156. LPM3;
  157. }
  158. static void clear_fb()
  159. {
  160. for ( uint8_t i = 0; i < sizeof( fb ); ++i ) {
  161. fb[ i ] = 0;
  162. }
  163. }
  164. static void on_fb()
  165. {
  166. fb[ 0 ] = 0x00;
  167. fb[ 1 ] = 0x3C;
  168. fb[ 2 ] = 0x24;
  169. fb[ 3 ] = 0x3C;
  170. fb[ 4 ] = 0x42;
  171. fb[ 5 ] = 0x81;
  172. fb[ 6 ] = 0xFF;
  173. fb[ 7 ] = 0x00;
  174. fb[ 8 ] = 0x00;
  175. fb[ 9 ] = 0x24;
  176. fb[ 10 ] = 0x18;
  177. fb[ 11 ] = 0x42;
  178. fb[ 12 ] = 0x3C;
  179. fb[ 13 ] = 0x81;
  180. fb[ 14 ] = 0x7E;
  181. fb[ 15 ] = 0x00;
  182. }
  183. static void off_fb()
  184. {
  185. fb[ 0 ] = 0x00;
  186. fb[ 1 ] = 0x3C;
  187. fb[ 2 ] = 0x24;
  188. fb[ 3 ] = 0x3C;
  189. fb[ 4 ] = 0x42;
  190. fb[ 5 ] = 0x81;
  191. fb[ 6 ] = 0xFF;
  192. fb[ 7 ] = 0x00;
  193. fb[ 8 ] = 0x00;
  194. fb[ 9 ] = 0x42;
  195. fb[ 10 ] = 0x24;
  196. fb[ 11 ] = 0x18;
  197. fb[ 12 ] = 0x18;
  198. fb[ 13 ] = 0x24;
  199. fb[ 14 ] = 0x42;
  200. fb[ 15 ] = 0x00;
  201. }
  202. static void render_fb()
  203. {
  204. const bool is_off_interval = ( ticks - ticks_at_button_press + 64 ) % 64 > 32;
  205. if ( ( state == PLAYING && ticks > 32 ) ||
  206. ( state == ALARM_IS_ACTIVE_EDITING && is_off_interval ) )
  207. {
  208. clear_fb();
  209. return;
  210. }
  211. uint8_t hour, minute;
  212. bool display_blinking_point = false;
  213. switch ( state ) {
  214. case TIME_DISPLAYING:
  215. case TIME_HOUR_EDITING:
  216. case TIME_MINUTE_EDITING:
  217. case BLINKING:
  218. case PLAYING:
  219. hour = hours;
  220. minute = minutes;
  221. display_blinking_point = true;
  222. break;
  223. case ALARM_DISPLAYING:
  224. case ALARM_HOUR_EDITING:
  225. case ALARM_MINUTE_EDITING:
  226. hour = alarm_hour;
  227. minute = alarm_minute;
  228. break;
  229. }
  230. if ( state == ALARM_IS_ACTIVE_DISPLAYING || state == ALARM_IS_ACTIVE_EDITING ) {
  231. if ( alarm_is_active ) {
  232. on_fb();
  233. } else {
  234. off_fb();
  235. }
  236. } else {
  237. uint8_t digit_1 = hour / 10;
  238. uint8_t digit_2 = hour % 10;
  239. uint8_t digit_3 = minute / 10;
  240. uint8_t digit_4 = minute % 10;
  241. if ( ( state == TIME_HOUR_EDITING || state == ALARM_HOUR_EDITING ) && is_off_interval ) {
  242. digit_1 = digit_2 = 10; // none
  243. } else if ( digit_1 == 0 ) {
  244. digit_1 = 10; // none
  245. }
  246. if ( ( state == TIME_MINUTE_EDITING || state == ALARM_MINUTE_EDITING ) && is_off_interval ) {
  247. digit_3 = digit_4 = 10; // none
  248. }
  249. fb[ 0 ] = glyph[ digit_1 ][ 0 ];
  250. fb[ 1 ] = glyph[ digit_1 ][ 1 ];
  251. fb[ 2 ] = glyph[ digit_1 ][ 2 ];
  252. fb[ 3 ] = 0;
  253. fb[ 4 ] = glyph[ digit_2 ][ 0 ];
  254. fb[ 5 ] = glyph[ digit_2 ][ 1 ];
  255. fb[ 6 ] = glyph[ digit_2 ][ 2 ];
  256. fb[ 7 ] = 0;
  257. fb[ 8 ] = 0;
  258. fb[ 9 ] = glyph[ digit_3 ][ 0 ];
  259. fb[ 10 ] = glyph[ digit_3 ][ 1 ];
  260. fb[ 11 ] = glyph[ digit_3 ][ 2 ];
  261. fb[ 12 ] = 0;
  262. fb[ 13 ] = glyph[ digit_4 ][ 0 ];
  263. fb[ 14 ] = glyph[ digit_4 ][ 1 ];
  264. fb[ 15 ] = glyph[ digit_4 ][ 2 ];
  265. if ( display_blinking_point && ticks < 32 ) {
  266. fb[ seconds >> 2 ] |= 192;
  267. }
  268. if ( alarm_is_active ) {
  269. fb[ 15 ] |= 192;
  270. }
  271. }
  272. }
  273. static void display_fb()
  274. {
  275. for ( int8_t y = 7; y >= 0; --y ) {
  276. uint8_t on_led_count = shift_row( y ) + 2; // Without adding some value, single dots are to dark.
  277. const uint8_t max_led_count = 14;
  278. if ( on_led_count > max_led_count ) {
  279. on_led_count = max_led_count;
  280. }
  281. select_row( y );
  282. const uint16_t delay = 357; // 16E6 / ( 300 * 14(=max_led_count) ) / 8 rows = 400.16 Hz
  283. for ( uint8_t i = 0; i < on_led_count; ++i ) {
  284. __delay_cycles( delay );
  285. }
  286. select_row( -1 );
  287. for ( uint8_t i = 0; i < max_led_count - on_led_count; ++i ) {
  288. __delay_cycles( delay );
  289. }
  290. }
  291. }
  292. int main( void )
  293. {
  294. config_registers();
  295. clear_fb();
  296. _enable_interrupts();
  297. while ( true ) {
  298. if ( go_to_sleep ) {
  299. go_to_sleep = false;
  300. state = SLEEPING;
  301. sleep();
  302. }
  303. if ( tick_happened ) {
  304. tick_happened = false;
  305. switch ( state ) {
  306. case SHINING:
  307. if ( shining_watchdog + SHINING_WARN_TICKS > SHINING_LIMIT ) {
  308. TACCR1 = ticks == 0 ? 0 : 2;
  309. }
  310. break;
  311. case BLINKING:
  312. if ( seconds < 30 ) {
  313. TACCR1 = seconds % 2 ? 0 : 2;
  314. } else {
  315. TACCR1 = ( ticks & 0x0F ) == 0 ? 2 : 0;
  316. }
  317. break;
  318. case PLAYING:
  319. if ( ( ticks & 0x01 ) == 0 ) {
  320. const uint16_t period = scale[ tune[ tune_index ] ];
  321. TACCR0 = period;
  322. TACCR1 = period >> 1;
  323. ++tune_index;
  324. if ( tune_index == sizeof( tune ) ) {
  325. tune_index = 0; // be kind, rewind :)
  326. ++tune_count;
  327. if ( tune_count == 2 ) {
  328. tune_count = 0 ;
  329. go_to_sleep = true; // All attempts were in vain.
  330. }
  331. }
  332. }
  333. break;
  334. }
  335. render_fb();
  336. }
  337. if ( state != SHINING ) {
  338. display_fb(); // Does busy waiting.
  339. }
  340. }
  341. }
  342. #pragma vector = WDT_VECTOR
  343. __interrupt void WDT_ISR( void )
  344. {
  345. // called 64 times per second. Consumes about 2.6 uA @ 3.3 V. Device works down to 2.4 V.
  346. tick_happened = true;
  347. ++ticks;
  348. if ( ticks == 64 ) {
  349. ticks = 0;
  350. ++seconds;
  351. if ( seconds == 60 ) {
  352. seconds = 0;
  353. ++minutes;
  354. if ( minutes == 60 ) {
  355. minutes = 0;
  356. ++hours;
  357. if ( hours == 24 ) {
  358. hours = 0;
  359. //seconds = 1; // correction for too slow quarz
  360. __delay_cycles( 16000000 ); // correction for too fast quarz
  361. }
  362. }
  363. if ( alarm_is_active && hours == alarm_hour && minutes == alarm_minute ) {
  364. state = BLINKING;
  365. P1DIR |= BUZZER;
  366. TACCR0 = 1;
  367. TACCR1 = 0; // 2 is permanent on, 0 is off when TACCR0 is 1.
  368. LPM3_EXIT;
  369. } else if ( state == BLINKING ) {
  370. state = PLAYING; // Play a delightful tune.
  371. tune_index = 0;
  372. }
  373. }
  374. switch ( state ) {
  375. case TIME_DISPLAYING:
  376. case ALARM_IS_ACTIVE_DISPLAYING:
  377. case ALARM_DISPLAYING:
  378. ++displaying_watchdog;
  379. if ( displaying_watchdog > DISPLAYING_LIMIT ) {
  380. go_to_sleep = true;
  381. }
  382. break;
  383. case SHINING:
  384. ++shining_watchdog;
  385. if ( shining_watchdog > SHINING_LIMIT ) {
  386. go_to_sleep = true;
  387. }
  388. break;
  389. }
  390. }
  391. enum TButtonState { RELEASED, PRESSED, HELD };
  392. static volatile TButtonState button1_state = RELEASED;
  393. if ( ( P1IN & BUTTON_1 ) == BUTTON_1 ) {
  394. if ( button1_state == RELEASED ) {
  395. button1_state = PRESSED;
  396. switch ( state ) {
  397. case SLEEPING:
  398. state = TIME_DISPLAYING;
  399. LPM3_EXIT;
  400. break;
  401. case SHINING:
  402. if ( shining_watchdog + SHINING_WARN_TICKS > SHINING_LIMIT ) {
  403. shining_watchdog = 0;
  404. } else {
  405. go_to_sleep = true;
  406. }
  407. break;
  408. case TIME_DISPLAYING:
  409. state = alarm_is_active ? ALARM_DISPLAYING : ALARM_IS_ACTIVE_DISPLAYING;
  410. break;
  411. case ALARM_IS_ACTIVE_DISPLAYING:
  412. case ALARM_DISPLAYING:
  413. go_to_sleep = true;
  414. break;
  415. case TIME_HOUR_EDITING:
  416. hours = ++hours;
  417. if ( hours == 24 ) {
  418. hours = 0;
  419. }
  420. break;
  421. case TIME_MINUTE_EDITING:
  422. minutes = ++minutes;
  423. if ( minutes == 60 ) {
  424. minutes = 0;
  425. }
  426. seconds = 0;
  427. ticks = 0;
  428. break;
  429. case ALARM_IS_ACTIVE_EDITING:
  430. alarm_is_active ^= 1;
  431. break;
  432. case ALARM_HOUR_EDITING:
  433. alarm_hour = ++alarm_hour;
  434. if ( alarm_hour == 24 ) {
  435. alarm_hour = 0;
  436. }
  437. break;
  438. case ALARM_MINUTE_EDITING:
  439. alarm_minute = alarm_minute + 5;
  440. if ( alarm_minute == 60 ) {
  441. alarm_minute = 0;
  442. }
  443. break;
  444. case BLINKING:
  445. case PLAYING:
  446. go_to_sleep = true;
  447. break;
  448. }
  449. displaying_watchdog = 0;
  450. ticks_at_button_press = ticks;
  451. } else if ( button1_state == HELD && ( ( ticks & 0x07 ) == 0 ) ) {
  452. switch ( state ) {
  453. case TIME_HOUR_EDITING:
  454. hours = ++hours;
  455. if ( hours == 24 ) {
  456. hours = 0;
  457. }
  458. break;
  459. case TIME_MINUTE_EDITING:
  460. minutes = ++minutes;
  461. if ( minutes == 60 ) {
  462. minutes = 0;
  463. }
  464. seconds = 0;
  465. ticks = 0;
  466. break;
  467. case ALARM_HOUR_EDITING:
  468. alarm_hour = ++alarm_hour;
  469. if ( alarm_hour == 24 ) {
  470. alarm_hour = 0;
  471. }
  472. break;
  473. case ALARM_MINUTE_EDITING:
  474. alarm_minute = alarm_minute + 5;
  475. if ( alarm_minute == 60 ) {
  476. alarm_minute = 0;
  477. }
  478. break;
  479. }
  480. displaying_watchdog = 0;
  481. ticks_at_button_press = ticks;
  482. } else if ( ( ticks - ticks_at_button_press + 64 ) % 64 > 24 ) {
  483. button1_state = HELD;
  484. }
  485. } else {
  486. button1_state = RELEASED;
  487. }
  488. static volatile TButtonState button2_state = RELEASED;
  489. if ( ( P2IN & BUTTON_2 ) == BUTTON_2 ) {
  490. if ( button2_state == RELEASED ) {
  491. button2_state = PRESSED;
  492. bool start_blinking_with_OFF_period = true;
  493. switch ( state ) {
  494. case SLEEPING:
  495. state = SHINING; // Consumes about 20 mA in SHINING state.
  496. P1DIR |= BUZZER;
  497. TACCR0 = 1;
  498. TACCR1 = 2; // 2 is permanent on, 0 is off when TACCR0 is 1.
  499. shining_watchdog = 0;
  500. LPM3_EXIT;
  501. break;
  502. case SHINING:
  503. if ( shining_watchdog + SHINING_WARN_TICKS > SHINING_LIMIT ) {
  504. shining_watchdog = 0;
  505. } else {
  506. go_to_sleep = true;
  507. }
  508. break;
  509. case TIME_DISPLAYING:
  510. state = TIME_HOUR_EDITING;
  511. break;
  512. case TIME_HOUR_EDITING:
  513. state = TIME_MINUTE_EDITING;
  514. break;
  515. case TIME_MINUTE_EDITING:
  516. state = TIME_DISPLAYING;
  517. break;
  518. case ALARM_DISPLAYING:
  519. start_blinking_with_OFF_period = false;
  520. // Fall through intended.
  521. case ALARM_IS_ACTIVE_DISPLAYING:
  522. state = ALARM_IS_ACTIVE_EDITING;
  523. break;
  524. case ALARM_IS_ACTIVE_EDITING:
  525. state = alarm_is_active ? ALARM_HOUR_EDITING : ALARM_IS_ACTIVE_DISPLAYING;
  526. start_blinking_with_OFF_period = false;
  527. break;
  528. case ALARM_HOUR_EDITING:
  529. state = ALARM_MINUTE_EDITING;
  530. break;
  531. case ALARM_MINUTE_EDITING:
  532. //state = ALARM_IS_ACTIVE_DISPLAYING;
  533. state = ALARM_DISPLAYING;
  534. break;
  535. case BLINKING:
  536. case PLAYING:
  537. go_to_sleep = true;
  538. break;
  539. }
  540. displaying_watchdog = 0;
  541. if ( start_blinking_with_OFF_period ) {
  542. //ticks_at_button_press = ( ticks + 31 ) % 64; // immediately off for 1/2 second ____|~~~~|____|~~
  543. ticks_at_button_press = ( ticks + 16 ) % 64; // first off time is 1/4 second __|~~~~|____|~~~~
  544. } else {
  545. //ticks_at_button_press = ticks; // immediately on for 1/2 second ~~~~|____|~~~~|__
  546. ticks_at_button_press = ( ticks + 48 ) % 64; // 1/4 second delay before blinking starts ~~|____|~~~~|____
  547. }
  548. }
  549. } else {
  550. button2_state = RELEASED;
  551. }
  552. // The interrupt flag is cleared automatically.
  553. }
  554. #pragma vector = PORT1_VECTOR
  555. __interrupt void PORT1_ISR( void )
  556. {
  557. //P1IFG &= ~BUTTON_1; // clear the interrupt flag
  558. }
  559. #pragma vector = PORT2_VECTOR
  560. __interrupt void PORT2_ISR( void )
  561. {
  562. //P2IFG &= ~BUTTON_2; // clear the interrupt flag
  563. }
  564. #pragma vector = USI_VECTOR
  565. __interrupt void USI_ISR( void ) {}
  566. #pragma vector = ADC10_VECTOR
  567. __interrupt void ADC10_ISR( void ) {}
  568. #pragma vector = TIMER0_A1_VECTOR
  569. __interrupt void TIMER0_A1_ISR( void ) {}
  570. #pragma vector = TIMER0_A0_VECTOR
  571. __interrupt void TIMER0_A0_ISR( void ) {}
  572. #pragma vector = COMPARATORA_VECTOR
  573. __interrupt void COMPARATORA_ISR( void ) {}
  574. #pragma vector = NMI_VECTOR
  575. __interrupt void NMI_ISR( void ) {}