Facebook
From Giuseppe, 3 Years ago, written in C++.
Embed
Download Paste or View Raw
Hits: 244
  1. /*                  GONG MELODY GENERATOR
  2.  *Questo dispositivo consente di implementare la funzionalità "GONG" su una
  3.  *qualsiasi centrale anti intrusione. Detta funzionalità consiste nella
  4.  *emissione di una melodia ogni qualvolta un ingresso passa da chiuso
  5.  *(verso GND) ad aperto. Gli ingressi previsti sono due: Door e Window.
  6.  *Essi si riferiscono rispettivamente al sensore montato sul portoncino di
  7.  *ingresso ed alla serie di sensori installati nella protezione perimetrale
  8.  *delle finestre.  La riproduzione della melodia associata all'ingresso
  9.  *"Door" viene inibita per 30 minuti ogni volta che lo stesso passa da
  10.  *riposo ad intervenuto. Il timer è del tipo retriggerabile.
  11.  *La routine di gestione dei timer può gestire 4 timer ma ne è utilizzato
  12.  *soltanto uno. La riproduzione della melodia prende spunto da un lavoro di
  13.  *David Johnson-Davies - www.technoblogy.com - "Digital Music Box v2" 16/3/2016
  14.  */
  15.   //         ATtiny85 Gong generator for anti intrusion system
  16.   //                Author: Giuseppe Fiordaliso
  17.   //                    ATMEL ATTINY 85
  18.   //
  19.   //                      +- \/-+
  20.   // RST non usato  PB5  1|*    |8  Vcc
  21.   // Uscita LED(L)  PB3  2|     |7  PB2  Sensori Finestre
  22.   // Uscita B.F.    PB4  3|     |6  PB1  Sensore Porta
  23.   //                GND  4|     |5  PB0  Inserzione/Disins.
  24.   //                      +-----+
  25.   //
  26. #include <avr/io.h>
  27.  
  28. #define abl PB0         // PIN 5   Inserzione / Disinserzione dispositivo
  29. #define gate_pin PB1    // PIN 6   Sensore portoncino ingresso  (NC)
  30. #define window_pin PB2  // PIN 7   Linea sensori Finestre       (NC)
  31. #define LED PB3         // PIN 2   Uscita LOW durante il suono del Gong
  32.                         //         utile per comandare lo stand-by
  33.                         //         di un amplificatore tipo LM4819
  34. #define speakerPin PB4  // PIN 3   Uscita bassa frequenza suono melodia
  35.  
  36.  //
  37.  
  38. int Scale[] = {
  39.   680,  721,  764,  809,  857,  908,  962, 1020, 1080, 1144, 1212, 1284,
  40.  1361, 1442, 1528, 1618, 1715, 1817, 1925, 2039, 2160, 2289, 2425, 2569,
  41.  2722, 2884, 3055, 3237, 3429, 3633, 3849, 4078 };
  42.  
  43. const int Channels = 4;
  44. const int Tempo = 4;      // 4 = 4 beats per second (3 = 0,125 sec, 4 = 0,25 sec, 5 = 0,5 sec, 6 = 1 sec -  min = 0, max = 8)
  45. const int Decay = 10;      // Length of note decay; max 10
  46.  
  47. volatile unsigned int Acc[Channels];
  48. volatile unsigned int Freq[Channels];
  49. volatile unsigned int Amp[Channels];
  50. //
  51. /*
  52. // Play Big Ben
  53. // C -> DO, D -> RE, E -> MI, F -> FA, G ->SOL, A -> LA, B -> SI,
  54. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  55. //C D EF G A BC D EF G A BC D EF G
  56. 0b00000100000000000100000000000000,   // F  F
  57. 0b00000000000000000000000000000000,   //
  58. 0b00000000000000000000010000000000,   // A  
  59. 0b00000000000000000000000000000000,   //
  60. 0b10000000000000000001000000000000,   // G  C
  61. 0b00000000000000000000000000000000,   //
  62. 0b00000000000010000000000000000000,   // C
  63. 0b00000000000000000000000000000000,   //
  64. 0b00000000000000000000000000000000,   //
  65. 0b00000000000000000000000000000000,   //
  66. 0b10000000000010000000000000000000,   // C  C
  67. 0b00000000000000000000000000000000,   //
  68. 0b00000000000000000001000000000000,   // G
  69. 0b00000000000000000000000000000000,   //
  70. 0b00000100000000000000010000000000,   // A  F
  71. 0b00000000000000000000000000000000,   //
  72. 0b00000000000000000100000000000000,   // F
  73. 0b00000000000000000000000000000000,   //
  74. 0b00000000000000000000000000000000,   //
  75. 0b00000000000000000000000000000000,   //
  76. 0b00000000000000000000000000000000,   //
  77. 0b00000000000000000000000000000000,   //
  78. 0b00000000000000000000000000000000,   //
  79. 0b00000000000000000000000000000000,   //  
  80. 0b00000000000000000000000000000000,   //
  81. 0b00000100000000000000010000000000,   // A  F
  82. 0b00000000000000000000000000000000,   //
  83. 0b00000000000000000001000000000000,   // G
  84. 0b00000000000000000000000000000000,   //
  85. 0b10000000000000000100000000000000,   // F  C
  86. 0b00000000000000000000000000000000,   //
  87. 0b00000000000010000000000000000000,   // C
  88. 0b00000000000000000000000000000000,   //
  89. 0b00000000000000000000000000000000,   //
  90. 0b00000000000000000000000000000000,   //
  91. 0b10000000000010000000000000000000,   // C  C
  92. 0b00000000000000000000000000000000,   //
  93. 0b00000000000000000001000000000000,   // G
  94. 0b00000000000000000000000000000000,   //
  95. 0b00000100000000000000010000000000,   // A  F
  96. 0b00000000000000000000000000000000,   //
  97. 0b00000000000000000100000000000000,   // F
  98. 0b00000000000000000000000000000000,   //
  99. 0b00000000000000000000000000000000,   //
  100. 0b00000000000000000000000000000000,   //
  101. 0xFF}; // End of tune
  102. */
  103. /*
  104. // Play Happy Birthday
  105. // C -> DO, D -> RE, E -> MI, F -> FA, G ->SOL, A -> LA, B -> SI,
  106. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  107. //C D EF G A BC D EF G A BC D EF G
  108. 0b00000000000000000001000000000000,
  109. 0b00000000000000000001000000000000,
  110. 0b10000000000000000000010000000000,
  111. 0b00000000000000000000000000000000,
  112. 0b00001001000000000001000000000000,
  113. 0b00000000000000000000000000000000,
  114. 0b00000000000000000000000010000000,
  115. 0b00000000000000000000000000000000,
  116. 0b00100000000000000000000100000000,
  117. 0b00000000000000000000000000000000,
  118. 0b00000101000000000000000000000000,
  119. 0b00000000000000000000000000000000,
  120. 0b00000000000000000001000000000000,
  121. 0b00000000000000000001000000000000,
  122. 0b10000000000000000000010000000000,
  123. 0b00000000000000000000000000000000,
  124. 0b00000101000000000001000000000000,
  125. 0b00000000000000000000000000000000,
  126. 0b00000000000000000000000000100000,
  127. 0b00000000000000000000000000000000,
  128. 0b10000000000000000000000010000000,
  129. 0b00000000000000000000000000000000,
  130. 0b00001001000000000000000000000000,
  131. 0b00000000000000000000000000000000,
  132. 0b00000000000000000001000000000000,
  133. 0b00000000000000000001000000000000,
  134. 0b10000000000000000000000000000001,
  135. 0b00000000000000000000000000000000,
  136. 0b00100000000000000000000000001000,
  137. 0b00000000000000000000000000000000,
  138. 0b00001000000000000000000010000000,
  139. 0b00000000000000000000000000000000,
  140. 0b00000100000000000000000100000000,
  141. 0b00000000000000000000000000000000,
  142. 0b00000000000000000000010000000000,
  143. 0b00000000000000000000000000000000,
  144. 0b00000000000000000000000000000100,
  145. 0b00000000000000000000000000000100,
  146. 0b00000001000000000000000000001000,
  147. 0b00000000000000000000000000000000,
  148. 0b00000000000000000000000010000000,
  149. 0b00000000000000000000000000000000,
  150. 0b00000101000000000000000000100000,
  151. 0b00000000000000000000000000000000,
  152. 0b10001001000000000000000010000000,
  153. 0b00000000000000000000000000000000,   //
  154. 0b00000000000000000000000000000000,   //
  155. 0b00000000000000000000000000000000,   //  
  156. 0xFF}; // End of tune
  157. */
  158. const uint32_t tuneDoor[] PROGMEM = {
  159. // Play Big Ben
  160. // C -> DO, D -> RE, E -> MI, F -> FA, G ->SOL, A -> LA, B -> SI,
  161. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  162. //C D EF G A BC D EF G A BC D EF G
  163. 0b00001000000000001000000000000000,   // E
  164. 0b00000000000000000000000000000000,   //
  165. 0b10000000000010000000000000000000,   // C
  166. 0b00000000000000000000000000000000,   //
  167. 0b00100000000000100000000000000000,   // D
  168. 0b00000000000000000000000000000000,   //
  169. 0b00000001000000000000000000000000,   // G
  170. 0b00000000000000000000000000000000,   //
  171. 0b00000000000000000000000000000000,   //
  172. 0b00000000000000000000000000000000,   //
  173. 0b00000001000000000000000000000000,   // G
  174. 0b00000000000000000000000000000000,   //
  175. 0b00000000000000100000000000000000,   // D
  176. 0b00000000000000000000000000000000,   //
  177. 0b00000000000000001000000000000000,   // E
  178. 0b00000000000000000000000000000000,   //
  179. 0b00000000000010000000000000000000,   // C
  180. 0b00000000000000000000000000000000,   //
  181. 0b00000000000000000000000000000000,   //
  182. 0b00000000000000000000000000000000,   //
  183. 0b00000000000000000000000000000000,   //
  184. 0b00000000000000000000000000000000,   //
  185. 0b00000000000000000000000000000000,   //
  186. 0b00000000000000000000000000000000,   //  
  187. 0b00000000000000000000000000000000,   //
  188. 0b00000100000000001000000000000000,   // E
  189. 0b00000000000000000000000000000000,   //
  190. 0b00000000000010000000000000000000,   // C
  191. 0b00000000000000000000000000000000,   //
  192. 0b00000000000000100000000000000000,   // D
  193. 0b00000000000000000000000000000000,   //
  194. 0b00000001000000000000000000000000,   // G
  195. 0b00000000000000000000000000000000,   //
  196. 0b00000000000000000000000000000000,   //
  197. 0b00000000000000000000000000000000,   //
  198. 0b00000001000000000000000000000000,   // G
  199. 0b00000000000000000000000000000000,   //
  200. 0b00000000000000100000000000000000,   // D
  201. 0b00000000000000000000000000000000,   //
  202. 0b00000000000000001000000000000000,   // E
  203. 0b00000000000000000000000000000000,   //
  204. 0b00000000000010000000000000000000,   // C
  205. 0b00000000000000000000000000000000,   //
  206. 0b00000000000000000000000000000000,   //
  207. 0b00000000000000000000000000000000,   //  
  208. 0xFF}; // End of tune
  209.  
  210. /*
  211. // Play close encounters melody
  212. // C -> DO, D -> RE, E -> MI, F -> FA, G ->SOL, A -> LA, B -> SI,
  213. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  214. //C D EF G A BC D EF G A BC D EF G
  215. 0b00000000000000000000010000000000,   // A
  216. 0b00000000000000000000000000000000,   //
  217. 0b00000000000000000000000100000000,   // B
  218. 0b00000000000000000000000000000000,   //
  219. 0b00000000000000000001000000000000,   // G
  220. 0b00000000000000000000000000000000,   //
  221. 0b00000001000000000000000000000000,   // G<
  222. 0b00000000000000000000000000000000,   //
  223. 0b00000000000000100000000000000000,   // D
  224. 0b00000000000000000000000000000000,   //
  225. 0b00000000000000000000000000000000,   //
  226. 0b00000000000000000000000000000000,   //
  227. 0b00000000000000000000000000100000,   // D
  228. 0b00000000000000000000000000000000,   //
  229. 0b00000000000000000000000000001000,   // E
  230. 0b00000000000000000000000000000000,   //
  231. 0b00000000000000000000000010000000,   // C
  232. 0b00000000000000000000000000000000,   //
  233. 0b10000000000000000000000000000000,   // C<
  234. 0b00000000000000000000000000000000,   //
  235. 0b00000001000000000000000000000000,   // G<
  236. 0b00000000000000000000000000000000,   //
  237. 0b00000000000000000000000000000000,   //
  238. 0b00000000000000000000000000000000,   //
  239. 0xFF}; // End of tune
  240. //
  241. */
  242. /*
  243. const uint32_t tuneWindow[] PROGMEM = {
  244. // Play per un pugno di dollari
  245. // C -> DO, D -> RE, E -> MI, F -> FA, G ->SOL, A -> LA, B -> SI,
  246. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  247. //C D EF G A BC D EF G A BC D EF G
  248. 0b00000000000000000000000000000000,   //
  249. 0b00000000000000000000010000000000,   // A
  250. 0b00000000000000000000000000000000,   //
  251. 0b00000000000000000000000000100000,   // D>
  252. 0b00000000000000000000000000000000,   //
  253. 0b00000000000000000000000000000000,   //
  254. 0b00000000000000000000000000000000,   //
  255. 0b00000000000000000000000000000000,   //
  256. 0b00000000000000000000000000000000,   //
  257. 0b00000000000000000000000010000000,   // C>
  258. 0b00000000000000000000000000000000,   //
  259. 0b00000000000000000000010000000000,   // A
  260. 0b00000000000000000000000000000000,   //
  261. 0b00000000000000000000000000000000,   //
  262. 0b00000000000000000000000000000000,   //
  263. 0b00000000000000000001000000000000,   // G
  264. 0b00000000000000000000000000000000,   //
  265. 0b00000000000000000000010000000000,   // A
  266. 0b00000000000000000000000000000000,   //
  267. 0b00000000000000000000000000000000,   //
  268. 0b00000000000000000000000000000000,   //
  269. 0b00000000000000000001000000000000,   // G
  270. 0b00000000000000000000000000000000,   //
  271. 0b00000000000000100000000000000000,   // D
  272. 0b00000000000000000000000000000000,   //
  273. 0b00000000000000000000000000000000,   //
  274. 0b00000000000000000000000000000000,   //
  275. 0b00000000000000000000000000000000,   //
  276. 0xFF}; // End of tune
  277. */
  278. /*
  279.  *  C O N T I N U A Z I O N E
  280. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  281. //C D EF G A BC D EF G A BC D EF G
  282. 0b00000000000000000000010000000000,   // A
  283. 0b00000000000000000000000000000000,   //
  284. 0b00000000000000000000000000100000,   // D
  285. 0b00000000000000000000000000000000,   //
  286. 0b00000000000000000000000000000000,   //
  287. 0b00000000000000000000000000100000,   // D
  288. 0b00000000000000000000000000001000,   // E
  289. 0b00000000000000000000000000100000,   // D
  290. 0b00000000000000000000000000100000,   // D
  291. 0b00000000000000000000000000000000,   //
  292. 0b00000000000000000000000000001000,   // E
  293. 0b00000000000000000000000000000000,   //
  294. 0b00000000000000000000000000000100,   // F
  295. 0b00000000000000000000000000000000,   //
  296. 0b00000000000000000000010000000000,   // A
  297. 0b00000000000000000000000000000000,   //
  298. 0b00000000000000000000000000100000,   // D
  299. 0b00000000000000000000000000000000,   //
  300. 0b00000000000000000000000000000000,   //
  301. 0b00000000000000000000000000100000,   // D
  302. 0b00000000000000000000000000001000,   // E
  303. 0b00000000000000000000000000100000,   // D
  304. 0b00000000000000000000000000100000,   // D
  305. 0b00000000000000000000000000000000,   //
  306. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  307. //C D EF G A BC D EF G A BC D EF G
  308. 0b00000000000000000000000010000000,   //
  309. 0b00000000000000000000000000000000,   //
  310. 0b00000000000000000000010000000000,   //
  311. 0b00000000000000000000000000000000,   //
  312. 0b00000000000000000000010000000000,   //
  313. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  314. //C D EF G A BC D EF G A BC D EF G
  315. 0b00000000000000000000000000000000,   //
  316. 0b00000000000000000000000000000000,   //
  317. 0b00000000000000000000000000000000,   //
  318. 0b00000000000000000000000000000000,   //
  319. 0b00000000000000000000000000000000,   //
  320. 0b00000000000000000000000000000000,   //
  321. 0b00000000000000000000000000000000,   //
  322. 0b00000000000000000000000000000000,   //
  323. 0b00000000000000000000000000000000,   //
  324. 0b00000000000000000000000000000000,   //
  325. 0b00000000000000000000000000000000,   //
  326. 0b00000000000000000000000000000000,   //
  327. 0b00000000000000000000000000000000,   //
  328. 0b00000000000000000000000000000000,   //
  329. 0b00000000000000000000000000000000,   //
  330. 0b00000000000000000000000000000000,   //
  331. 0b00000000000000000000000000000000,   //
  332. 0b00000000000000000000000000000000,   //
  333. 0b00000000000000000000000000000000,   //
  334. 0b00000000000000000000000000000000,   //
  335. 0b00000000000000000000000000000000,   //
  336. 0b00000000000000000000000000000000,   //
  337. 0b00000000000000000000000000000000,   //
  338. 0b00000000000000000000000000000000,   //
  339. 0xFF}; // End of tune
  340. */
  341. const uint32_t tuneWindow[] PROGMEM = {
  342. // Play Morricone clock melody
  343. // C -> DO, D -> RE, E -> MI, F -> FA, G ->SOL, A -> LA, B -> SI,
  344. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  345. //C D EF G A BC D EF G A BC D EF G
  346. 0b00000000000010000000000100000000,   // C B
  347. 0b00000000000000000000000000000000,   //
  348. 0b00000000000000000000000000000000,   //
  349. 0b00000000000000000000000000000000,   //
  350. 0b00000000000000001000000000000000,   // E
  351. 0b00000000000000000000000000000000,   //
  352. 0b00000000000000000000000010000000,   // C>
  353. 0b00000000000000000000000000000000,   //
  354. 0b00000000000000001000010000000000,   // E A
  355. 0b00000000000000000000000000000000,   //
  356. 0b00000000000000000000000000000000,   //
  357. 0b00000000000000000000000000000000,   //
  358. 0b00000000000000001000000000000000,   // E
  359. 0b00000000000000000000000000000000,   //
  360. 0b00000000000000000000000010000000,   // C>
  361. 0b00000000000000000000000000000000,   //
  362. 0b00000000000010000000000100000000,   // C B
  363. 0b00000000000000000000000000000000,   //
  364. 0b00000000000000000000000000000000,   //
  365. 0b00000000000000000000000000000000,   //
  366. 0b00000000000000001000000000000000,   // E
  367. 0b00000000000000000000000000000000,   //
  368. 0b00000000000000000000000010000000,   // C>
  369. 0b00000000000000000000000000000000,   //
  370. 0b00000000000000001000010000000000,   // E A
  371. 0b00000000000000000000000000000000,   //
  372. 0b00000000000000000000000000000000,   //
  373. 0b00000000000000000000000000000000,   //
  374. 0b00000000000000001000000000000000,   // E
  375. 0b00000000000000000000000000000000,   //
  376. 0b00000000000000000000000000000000,   //
  377. 0b00000000000000000000000000000000,   //
  378. //
  379. //_*_*__*_*_*__*_*__*_*_*__*_*__*_
  380. //C D EF G A BC D EF G A BC D EF G
  381. 0b00000000000010000000000100000000,   // C B
  382. 0b00000000000000000000000000000000,   //
  383. 0b00000000000000000000000000000000,   //
  384. 0b00000000000000000000000000000000,   //
  385. 0b00000000000000001000000000000000,   // E
  386. 0b00000000000000000000000000000000,   //
  387. 0b00000000000000000000000010000000,   // C>
  388. 0b00000000000000000000000000000000,   //
  389. 0b00000000000000001000010000000000,   // E A
  390. 0b00000000000000000000000000000000,   //
  391. 0b00000000000000000000000000000000,   //
  392. 0b00000000000000000000000000000000,   //
  393. 0b00000000000000001000000000000000,   // E
  394. 0b00000000000000000000000000000000,   //
  395. 0b00000000000000000000000010000000,   // C>
  396. 0b00000000000000000000000000000000,   //
  397. 0b00000000000010000000000100000000,   // C B
  398. 0b00000000000000000000000000000000,   //
  399. 0b00000000000000000000000000000000,   //
  400. 0b00000000000000000000000000000000,   //
  401. 0b00000000000000001000000000000000,   // E
  402. 0b00000000000000000000000000000000,   //
  403. 0b00000000000000000000000010000000,   // C>
  404. 0b00000000000000000000000000000000,   //
  405. 0b00000000000000001000010000000000,   // E A
  406. 0b00000000000000000000000000000000,   //
  407. 0b00000000000000000000000000000000,   //
  408. 0b00000000000000000000000000000000,   //
  409. 0b00000000000000001000000000000000,   // E
  410. 0b00000000000000000000000000000000,   //
  411. 0b00000000000000000000000000000000,   //
  412. 0b00000000000000000000000000000000,   //
  413. //
  414. 0xFF}; // End of tune
  415. //
  416.  
  417. //Globals persist throughout tune
  418. int TunePtr = 0, Chan = 0;
  419. //
  420. #define abl PB0         // PIN 5 ATtiny85
  421. #define door_pin PB1    // PIN 6 ATtiny85
  422. #define window_pin PB2  // PIN 7 ATtiny85
  423. #define LED PB3         // PIN 2 ATtiny85
  424. #define speakerPin PB4  // PIN 3 ATtiny85
  425. // RESET non collegato     PIN 1 ATtiny85
  426. // + 5 V                   PIN 8 ATtiny85
  427. // GND                     PIN 4 ATtiny85
  428. //
  429. // *************   DICHIARAZIONE VARIABILI PER LA GESTIONE DEI TIMER    ************
  430. //
  431. volatile boolean tickFlag;
  432.  boolean ledState;
  433.  const int NTIMER             = 5;  // Numero di timer che si vogliono gestire
  434.  unsigned int timerpreset[NTIMER];
  435.  boolean startimer[NTIMER];
  436.  boolean runtimer[NTIMER];
  437.  boolean stoptimer[NTIMER];
  438.  boolean endtimer[NTIMER];
  439.  boolean abortimer[NTIMER];
  440.  unsigned int timercounter[NTIMER];
  441. //
  442. // *************         DICHIARAZIONE VARIABILI DEL PROGRAMMA          ************
  443. //
  444.  boolean Inserito;
  445.  boolean Open_door;
  446.  boolean Open_window;
  447.  boolean prev_Open_door;
  448.  boolean prev_Open_window;
  449.  boolean playDoor_flag;
  450.  boolean playWindow_flag;
  451.  volatile boolean playMelody_flag;
  452. //
  453. // *************          DICHIARAZIONE VARIABILI DEL PLAYER            ************
  454. //
  455. const uint32_t *puntatore;
  456.  
  457.  
  458. // **************                       S E T U P                       ************
  459.  
  460. void setup() {
  461.    // Abilita il PLL a 64 MHz e lo usa come sorgente di clock per il Timer1
  462.   PLLCSR = 1<<PCKE | 1<<PLLE;      
  463.  
  464.   // Setta il Timer 1 per utilizzarlo come generatore PWM
  465.   TIMSK = 0;                     // Timer interrupts OFF
  466.   TCCR1 = 1<<CS10;               // 1:1 prescaler asincrono
  467.   GTCCR = 1<<PWM1B | 2<<COM1B0;  // PWM basato su OCR1B, azzera l'uscita associata ad OC1B all'eguaglianza
  468.                                  // OC1B ->PB4
  469.   OCR1B = 128;
  470. //  DDRB = 1<<DDB4;                // Enable PWM output on pin 4
  471.  
  472.   // Set up Timer/Counter0 for 20kHz interrupt to output samples.
  473.   TCCR0A = 3<<WGM00;             // Fast PWM
  474.   TCCR0B = 1<<WGM02 | 2<<CS00;   // 1/8 prescale
  475.   OCR0A = 99;                    // Divide by 100
  476.   TIMSK = 1<<OCIE0A;             // Enable compare match, disable overflow
  477.  
  478.   // Set up Watchdog timer for 4 Hz interrupt for note output.
  479.   WDTCR = 1<<WDIE | Tempo<<WDP0; // imposta interrupt su Watchdog e prescaler WDT col valore di "Tempo"
  480.   //  
  481.  
  482.  pinMode(abl, INPUT_PULLUP);    
  483.  pinMode(door_pin, INPUT_PULLUP);
  484.  pinMode(window_pin, INPUT_PULLUP);
  485.  pinMode(LED, OUTPUT);
  486.  //
  487.  timerpreset[0]=6666;           // Tempo di inibizione gong porta di ingresso. (6666/54)/60 = 30 minuti
  488.  timerpreset[1]=37;             // 37 = 10 secondi            
  489.  timerpreset[2]=37;             // 37 = 10 secondi                        
  490.  timerpreset[3]=37;             // 37 = 10 secondi                      
  491.  timerpreset[4]=37;             // 37 = 10 secondi            
  492.    }
  493. //
  494. // *********************                 L O O P                ********************
  495. //
  496. void loop() {
  497. timermanager();                               // Routine di gestione dei timer
  498. Inserito = digitalRead(abl);                  // Leggi ingresso di inserzione dispositivo
  499. if (Inserito){                                // Se inserito analizza lo stato degli ingressi Door e Window
  500. prev_Open_door = Open_door;                   // Salva lo stato del ciclo precedente di Door
  501. prev_Open_window = Open_window;               // Salva lo stato del ciclo precedente di Window
  502. Open_door = digitalRead(door_pin);            // Leggi lo stato attuale di Door      
  503. Open_window = digitalRead (window_pin);       // Leggi lo stato attuale di Window
  504. Open_door = digitalRead (door_pin);           // Leggi lo stato attuale di Door
  505.   if (Open_window && !prev_Open_window){      // Se Window passa da riposo ad intervenuto
  506.     if (!playMelody_flag){                    // e non è in corso il Play di una melodia
  507.         puntatore = tuneWindow;               // dai lo start al play di tuneWindow
  508.         playMelody();
  509.     }
  510.   }      
  511.   if (Open_door && !prev_Open_door){          // La melodia relativa all'ingresso Door
  512.     if (!runtimer[0]){                        // viene avviata quando il relativo ingresso
  513.          puntatore = tuneDoor;                // passa da riposo ad intervenuto e non è in
  514.         playMelody();                         // corso il conteggio del tempo di inibizione
  515.     }                                         // suoneria. Dopo il Play viene avviato detto tempo
  516.    startimer[0] = true;                       // che attualmente è impostato a 30 minuti.
  517.   }                                           // Il conteggio del timer viene riavviato ad
  518. }                                             // ogni intervento dell'ingresso Door.
  519. else {                                        // Se il dispositivo è disinserito
  520.   playDoor_flag = false;                      // resetta tutti i flag
  521.   playWindow_flag = false;
  522.   playMelody_flag = false;
  523.   abortimer[0]=true;
  524.  }
  525. if (!playMelody_flag)                         // Se stai riproducendo una melodia, attiva
  526.   digitalWrite (LED, HIGH);                   // l'uscita di abilitazione dell'amplificatore
  527. }                                             // di B.F.
  528. //
  529. // **********************              END    LOOP          ************************
  530. //
  531. //
  532. // **********************              playMelody           ************************
  533.  
  534. void playMelody (){                        
  535.         digitalWrite (LED, LOW);
  536.         playMelody_flag = true;
  537.         TunePtr = 0, Chan = 0;
  538.         DDRB = DDRB | 0X10;
  539.   }
  540. //
  541. // **********************              timermanager          ***********************    
  542. /*
  543.  * ROUTINE DI GESTIONE DEI TIMER  "timermanager"
  544.  * La routine gestisce un numero di timer definito da
  545.  * "NTIMER". Il timer viene avviato settando a TRUE
  546.  * nel corso del programma il startimer[] corrispondente.
  547.  * La routine in questo caso carica timercounter[] con il
  548.  * valore di timerpreset[] e provvede poi a decrementarlo
  549.  * ogni volta che sono trascorsi i ms specificati da steptick
  550.  * quindi resetta startimer[], e setta runtimer[] per tutto
  551.  * il tempo in cui timercounter è > 0.
  552.  * Quando timercounter[] arriva a zero viene settato endtimer[]
  553.  * e viene resettato runtimer[]. E' a cura del programma
  554.  * chiamante resettare poi endtimer[].
  555.  */
  556.  //
  557.  void timermanager(){
  558.  // tickFlag viene settato dalla routine di servizio del WDT che scandisce anche la successione delle note
  559.  // della melodia. Nel caso di "Tempo = 4" questo avviene 4 volte al secondo. Per l'esattezza in un minuto 54 volte
  560.  if (tickFlag){                                  
  561.   tickFlag = false;                            
  562.       for (int i=0; i<NTIMER; i++){
  563.            if (startimer[i]==true){             // Controlla se c'è lo start del timer
  564.               timercounter[i] = (timerpreset[i]+1); // Se si carica il contatore con il
  565.               startimer[i]=false;               // valore di preset.
  566.               runtimer[i]=true;                 // Resetta startimer e setta runtimer
  567.               }
  568.            if (abortimer[i]){                   // se è richiesto l'abort azzera conteggio
  569.               timercounter[i] = 0;              // e resetta la richiesta di abort
  570.               runtimer[i] = false;
  571.               abortimer[i] = false;
  572.               }
  573.            if (!stoptimer[i]){                  // Se è richiesto lo stop salta aalla fine
  574.                if (timercounter[i]>0) {         // Se timercounter è maggiore di zero
  575.                    timercounter[i]--;           // decrementalo di uno quindi verifica se è
  576.                    if (timercounter[i] == 0){   // arrivato a zero. In tal caso setta endtimer[]
  577.                       runtimer[i] = false;      // e resetta runtimer[].
  578.                       endtimer[i] = true;
  579.                    }
  580.                }
  581.            }
  582.        }
  583.     }
  584. }
  585. // ****************    ROUTINE DI SERVIZIO ALL'INTERRUPT DEL WDT    ****************
  586. // Watchdog interrupt plays notes
  587. ISR(WDT_vect) {
  588.   sei();                            // Abilita interrupt
  589.                                     /* L'interruzione del watchdog ripristina automaticamente il timer del watchdog
  590.                                      *  in modo da provocare un reset al successivo interrupt; per evitare ciò è necessario
  591.                                      *  impostare il bit di interruzione prima dell'interruzione successiva:  */
  592.   WDTCR |= 1<<WDIE;
  593.   unsigned long Chord = pgm_read_dword(&puntatore[TunePtr]); // Analizza un nuovo step della sequenza
  594.   tickFlag = true;
  595.   if (Chord == 0xFF){
  596.     DDRB = DDRB & 0x2F ;
  597.     playMelody_flag = false;
  598.     return;                                                 // Se in questo step c'è "0XFF" allora sei a fine melodia
  599.   }
  600.   TunePtr++;                                                // Altrimenti incrementa puntatore allo step successivo
  601.                                                             // Analizza i singoli bit ovvero le singole note dello step
  602.   for (int Note = 0; Note < 32; Note++) {                   // 32 sono i bit che identificano ciascuna nota
  603.     if ((Chord & 0x80000000) != 0) {                        // Analizza il primo bit da sinistra e se è a 1
  604.       Freq[Chan] = Scale[Note];                             // assegna il valore corrispondente di scale[]
  605.       Amp[Chan] = 1<<(Decay+5);                        
  606.       Chan = (Chan + 1) % Channels;                         // Incrementa il canale in modo circolare (o, 1, 2, 3, 0, 1 ...)
  607.     }
  608.       Chord = Chord<<1;                                     // shifta di 1 a sx per analizzare il bit successivo
  609.     }
  610. }
  611. //
  612. // *************     ROUTINE DI SERVIZIO ALL'INTERRUPT DEL TIMER 0     *************
  613.             // Genera le onde quadre per le frequenze dei quattro canali
  614. ISR(TIMER0_COMPA_vect) {
  615.   signed char Temp, Mask, Env, Note, Sum=0;
  616.   for (int c = 0; c < Channels; c++) {
  617.       Acc[c] = Acc[c] + Freq[c];
  618.                                                             // L'inviluppo di ciascuna nota viene generato da un contatore
  619.       Amp[c] = Amp[c] - (Amp[c] != 0);                      // di ampiezza per ciascun canale, Amp [c], che viene ridotto
  620.                                                             // fino a raggiungere lo zero.
  621.       Temp = Acc[c] >> 8;                                   // L'onda quadra viene generata testando il bit superiore
  622.       Mask = Temp >> 7;                                     // dell'accumulatore per ciascun canale, Acc [c]
  623.                                                             // Mask è impostato su 0x00 se il bit è zero o 0xFF se è uno:
  624.       Env = Amp[c] >> Decay;                                // Infine, la nota è impostata su + o - dell'ampiezza corrente dell'inviluppo, Env
  625.       Note = (Env ^ Mask) + (Mask & 1);                     // Lo stesso che scrivere: "if (Mask != 0) Note = Env; else Note = - Env;"    
  626.       Sum = Sum + Note;
  627.   }
  628.   OCR1B = Sum + 128; // Compare register di TIMER 1
  629. }
  630.