diff --git a/docs/diagrams/state_diagram.gaphor b/docs/diagrams/state_diagram.gaphor
new file mode 100644
index 0000000..a95414d
--- /dev/null
+++ b/docs/diagrams/state_diagram.gaphor
@@ -0,0 +1,2699 @@
+
+
+
+
+
+diagram {
+ /* line-style: sloppy 0.3; */
+}
+
+controlflow {
+ dash-style: 0;
+}
+
+
+
+
+
+Modellname hier eintragen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Ablauf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+reset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -63.3325267095356, 704.3999999999999)
+
+
+(0.0, 0.0)
+
+
+20.0
+
+
+20.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+State Machine
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+MSP430-StateMachine
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 8.0, 8.0)
+
+
+(-244.4958441384397, 0.0)
+
+
+1269.9964112440239
+
+
+1090.6165284444828
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 964.0223449626474, 377.1943371546741)
+
+
+[(-999.3548716721831, 345.2056628453259), (-918.0223449626474, 345.2056628453259)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+idle
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 37.99999999999999, 688.4000000000001)
+
+
+(0.0, 0.0)
+
+
+50.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 41.5, 76.80000000000001)
+
+
+(0.0, 0.0)
+
+
+97.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 393.39724202029396, 505.245117941848)
+
+
+[(-297.39724202029396, 217.154882058152), (-74.97622731113597, 217.154882058152), (-74.97622731113597, -280.07774097662934), (43.72938384182612, -280.0925817502037)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+B
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 20.0, 238.8)
+
+
+(0.0, 0.0)
+
+
+132.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 643.143217001042, 515.2616677405409)
+
+
+[(-158.14659113892185, -276.19423450621), (-160.87659113892187, -166.19423450621002)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1-9
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 1224.7708753118209, 192.0609942360434)
+
+
+[(-690.6442494497007, 9.666438998287447), (-653.9328056755969, 10.426382729175202), (-653.9328056755969, 33.106382729175266), (-690.6442494497007, 32.34643899828751)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A-D
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 1427.73323171514, 78.54009651752189)
+
+
+[(-880.1066058530198, 285.735336716809), (-856.8951620789159, 286.49528044769687), (-856.895162078916, 308.07928044769704), (-880.1066058530198, 307.31933671680906)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0-9
+
+
+
+
+
+
+
+
+
+
+select_count
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 387.6266258621201, 102.26743323433087)
+
+
+(0.0, 0.0)
+
+
+218.5401732597482
+
+
+321.71317763289477
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+select_count
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -186.34092585307778, 108.85295935581789)
+
+
+(-17.420949104009978, 0.0)
+
+
+211.01531575913464
+
+
+308.54212538992067
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 42.0, 76.80000000000007)
+
+
+(0.0, 0.0)
+
+
+50.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+B
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 38.513999999999996, 206.7470406441821)
+
+
+(0.0, 0.0)
+
+
+50.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 489.5561200877478, 513.2583577808024)
+
+
+[(-73.9294942256277, -141.28487196142697), (-141.5561200877478, -141.28487196142697), (-141.5561200877478, -216.13433573002413), (-293.47612008774774, -216.13433573002413)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+confirmed
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 110.08000000000007, 263.12402205077825)
+
+
+(0.0, 0.0)
+
+
+78.0
+
+
+59.44772460066565
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 448.15438091981633, 663.5066047611988)
+
+
+[(-291.07438091981635, -392.38258271042054), (-291.07438091981635, -450.4391715268679), (-11.027755057696254, -450.4391715268679)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A-D
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+door_open
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 20.5, 526.4)
+
+
+(0.0, 0.0)
+
+
+85.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 441.4766810540209, 672.1876145867328)
+
+
+[(-323.39668105402086, -371.33973023562174), (-357.48868105402084, -371.33973023562174), (-357.4886810540209, -137.78761458673284)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[door_opened]
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 220.4448154961932, 680.2008544256873)
+
+
+[(-191.9448154961932, -108.46085442568733), (-392.1669709364176, -108.46085442568733), (-392.16697093641756, -460.5478950698694), (-356.785741349271, -460.5478950698694)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A-D
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 160.34551670403462, 553.9923269621543)
+
+
+[(-275.1724425571124, -308.3393676063363), (-271.6664425571124, -230.39232696215436)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1-9
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 179.71084631484126, 540.6369272305632)
+
+
+[(-266.051772167919, -332.65396787474526), (-244.5898039023392, -332.65396787474526), (-244.58980390233924, -309.31396787474523), (-266.051772167919, -309.31396787474523)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A-D
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 74.20318843527397, 551.3212470158361)
+
+
+[(-189.03011428835177, -175.72124701583607), (-189.03011428835177, 9.078752984163884), (-45.70318843527397, 9.078752984163998)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 139.3259873559967, 990.4406496907525)
+
+
+[(-68.32598735599674, -404.0406496907525), (-68.32598735599669, -294.0406496907524)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[door_closed]
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 84.701519406319, 347.93376630251197)
+
+
+[(-174.5284452593968, 1.6662336974880532), (-124.20521750379442, 1.6662336974880532), (-124.20521750379442, 212.46623369748812), (-56.201519406318994, 212.96623369748804)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"*"
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 88.70813932579625, 203.0276792147518)
+
+
+[(-200.0290651788741, -9.374719858933844), (-200.0290651788741, -36.059579275295164), (-42.70813932579625, -36.059579275295164), (-42.70813932579614, 331.3723207852482)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"*"
+
+
+
+
+
+
+
+
+
+
+reset_transactions
+
+
+
+
+
+
+
+reset_transaction
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+append_transaction
+
+
+
+
+
+
+
+commit_transactions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0-9
+
+
+
+
+
+
+
+#
+
+
+
+
+
+
+
+
+
+
+append_transaction
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 148.1396681313753, 322.55850681248944)
+
+
+[(0.0, 8.013239838954462), (0.0, 27.041493187510582), (32.052959355817904, 27.041493187510582), (32.052959355817904, 8.013239838954462)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+*
+
+
+
+
+
+
+
+
+
+
+beep_invalid
+
+
+
+
+
+
+
+
+
+
+
+
+
+error
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 471.89671249199426, 688.4000000000001)
+
+
+(0.0, 0.0)
+
+
+50.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 87.37259935263717, 737.9114384649632)
+
+
+[(8.627400647362826, 0.0), (392.5241131393571, 0.0)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[door_opened]
+
+
+
+
+
+
+
+
+
+
+beep_alarm; audit_append
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 479.353581474827, 710.5328690152021)
+
+
+[(25.543131017167184, 37.867130984797996), (25.543131017167184, 70.7836185774313), (-408.3535814748271, 70.7836185774313), (-408.3535814748271, 37.867130984797996)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[door_closed]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+edit_stock
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 21.987999999999975, 862.70353963793)
+
+
+(0.0, 0.0)
+
+
+81.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 46.40788002783745, 738.485082295181)
+
+
+[(10.684319785272635, 9.914917704819118), (10.684319785272692, 132.21845734274905)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"*"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -216.12067557025176, 862.70353963793)
+
+
+(0.0, 0.0)
+
+
+71.0
+
+
+52.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -41.73775820066183, 906.7631189132248)
+
+
+[(71.7257582006618, -10.059579275294823), (-95.38291736958985, -10.059579275294823)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -246.075374094001, 825.7936719647736)
+
+
+[(60.93028835734205, 44.90986767315644), (60.93028835734205, -5.131424383112517), (90.14520574794861, -5.131424383112517), (90.14520574794861, 44.90986767315644)]
+
+
+
+
+
+
+
+
+
+
+A-D
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 38.39464018888299, 876.045699530566)
+
+
+[(-8.406640188883014, 10.684319785272692), (-49.41497900688597, 10.684319785272692), (-49.41497900688603, -138.1342610656028), (7.605359811117005, -138.1342610656028)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"*"
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 190.24448135224117, 319.3398715996364)
+
+
+[(5.835518647758903, -8.275000228027409), (33.85227366011213, -8.275000228027409), (33.85227366011213, 388.1727379692849), (-94.24448135224117, 388.1727379692849)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+*
+
+
+
+
+
+
+
+
+
+
+reset_transactions
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, 506.19903551328713, 428.4194200599975)
+
+
+[(0.0, 3.5611908072281153), (-1.3023230212929775, 267.9805799400026)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[door_opened]
+
+
+
+
+
+
+
+
+
+
+beep_alarm; audit_append
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+A-D
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+B
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -215.61203029881133, 963.9718205940161)
+
+
+(0.0, 0.0)
+
+
+71.7797497171739
+
+
+48.23858452867603
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -170.63743778763262, 910.8243190787935)
+
+
+[(-1.9832377826191419, 11.87922055913657), (-1.9832377826191419, 61.14750151522264)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1-9
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -150.25493728255827, 1003.2249880351305)
+
+
+[(14.42265670092084, 1.3588333670047632), (48.23858452867597, 1.3588333670047632), (48.23858452867597, -15.626583720557164), (14.42265670092084, -15.626583720557164)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0-9
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -53.22137172001912, 1058.2577393988308)
+
+
+[(-119.39930385023268, -38.04733427613871), (-119.39930385023268, 6.114750151522571), (124.22137172001914, 6.114750151522571), (124.22137172001918, -135.55419976090104)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+"*"
+
+
+
+
+
+
+
+
+
+
+False
+
+
+False
+
+
+
+
+
+(1.0, 0.0, 0.0, 1.0, -155.01085406707563, 1017.4927383886825)
+
+
+[(0.0, 2.71766673400964), (-0.9193142789767421, 16.985417087562155), (209.96877107313378, 16.98541708756204), (209.96877107313378, -94.78919875075246)]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#
+
+
+
+
+
+
+
+
+
+
+update_stock
+
+
+
+
\ No newline at end of file
diff --git a/docs/images/abstract.png b/docs/images/abstract.png
new file mode 100644
index 0000000..bcce645
Binary files /dev/null and b/docs/images/abstract.png differ
diff --git a/docs/images/state_diagram.png b/docs/images/state_diagram.png
new file mode 100644
index 0000000..7ecca00
Binary files /dev/null and b/docs/images/state_diagram.png differ
diff --git a/doxygen.conf b/doxygen.conf
index d571e7d..9d6674e 100644
--- a/doxygen.conf
+++ b/doxygen.conf
@@ -1096,7 +1096,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which Doxygen is
# run.
-EXCLUDE = driverlib/
+EXCLUDE = driverlib/ jsmn/ src/Board.h
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
diff --git a/src/door_sensor.c b/src/door_sensor.c
index 65878cb..465a596 100644
--- a/src/door_sensor.c
+++ b/src/door_sensor.c
@@ -1,3 +1,11 @@
+/**
+ * \file door_sensor.c
+ * \brief Implementation of the door sensor driver using MSP430 GPIO interrupts.
+ *
+ * This module configures a GPIO pin to detect door open/close events and invokes
+ * user-provided callbacks on confirmed state changes.
+ */
+
#include
#include
#include
@@ -5,32 +13,60 @@
#include "door_sensor.h"
#include "constants.h"
+/**\brief GPIO port used for the door sensor. */
#define SENSOR_PORT GPIO_PORT_P2
+/**\brief GPIO pin used for the door sensor. */
#define SENSOR_PIN GPIO_PIN0
+/**\brief Interrupt vector associated with the sensor port. */
#define SENSOR_VECTOR PORT2_VECTOR
-/** User callback invoked on confirmed key press */
+/**
+ * \brief Callback invoked when the door is detected as opened.
+ *
+ * User must supply a function matching this type to be notified of an open event.
+ */
static DoorOpenedCallback_t doorOpenedCallback = NULL;
+/**
+ * \brief Callback invoked when the door is detected as closed.
+ *
+ * User must supply a function matching this type to be notified of a close event.
+ */
static DoorClosedCallback_t doorClosedCallback = NULL;
+/**
+ * \brief Initialize the door sensor driver.
+ *
+ * Configures the GPIO pin for input with pull-up resistor and enables
+ * interrupts on the specified edge. Also stores the user-provided callbacks.
+ *
+ * \param ocb Function to call when the door opens (rising edge).
+ * \param ccb Function to call when the door closes (falling edge).
+ */
void door_init(DoorOpenedCallback_t ocb, DoorClosedCallback_t ccb) {
doorOpenedCallback = ocb;
doorClosedCallback = ccb;
/* Configure port as pull up with interrupt */
- GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P2, GPIO_PIN0);
- GPIO_clearInterrupt(GPIO_PORT_P2, GPIO_PIN0);
- GPIO_selectInterruptEdge(GPIO_PORT_P2, GPIO_PIN0, GPIO_LOW_TO_HIGH_TRANSITION);
- GPIO_enableInterrupt(GPIO_PORT_P2, GPIO_PIN0);
+ GPIO_setAsInputPinWithPullUpResistor(SENSOR_PORT, SENSOR_PIN);
+ GPIO_clearInterrupt(SENSOR_PORT, SENSOR_PIN);
+ GPIO_selectInterruptEdge(SENSOR_PORT, SENSOR_PIN, GPIO_LOW_TO_HIGH_TRANSITION);
+ GPIO_enableInterrupt(SENSOR_PORT, SENSOR_PIN);
/* Enable global interrupts */
__enable_interrupt();
}
+/**
+ * \brief Tracks the last known door state (open = true, closed = false).
+ */
volatile bool door_last_open = false;
/**
- * @brief Interrupt Service Routine for PORT2
+ * \brief ISR for PORT2 interrupt handling door sensor events.
+ *
+ * Detects whether the door is opening or closing based on interrupt edge,
+ * invokes the corresponding callback, and reconfigures the interrupt edge
+ * for the next transition.
*/
#pragma vector=SENSOR_VECTOR
__interrupt void SENSOR_ISR(void)
@@ -39,17 +75,19 @@ __interrupt void SENSOR_ISR(void)
if (status) {
if (door_last_open) {
+ /* Door was open, now closed */
if (doorClosedCallback)
doorClosedCallback();
- GPIO_selectInterruptEdge(GPIO_PORT_P2, GPIO_PIN0, GPIO_LOW_TO_HIGH_TRANSITION);
+ GPIO_selectInterruptEdge(SENSOR_PORT, SENSOR_PIN, GPIO_LOW_TO_HIGH_TRANSITION);
} else {
+ /* Door was closed, now opened */
if (doorOpenedCallback)
doorOpenedCallback();
- GPIO_selectInterruptEdge(GPIO_PORT_P2, GPIO_PIN0, GPIO_HIGH_TO_LOW_TRANSITION);
+ GPIO_selectInterruptEdge(SENSOR_PORT, SENSOR_PIN, GPIO_HIGH_TO_LOW_TRANSITION);
}
}
+ /* Clear the interrupt flag and toggle stored state */
GPIO_clearInterrupt(SENSOR_PORT, SENSOR_PIN);
-
door_last_open = !door_last_open;
}
diff --git a/src/door_sensor.h b/src/door_sensor.h
index 5b43318..45b8cc0 100644
--- a/src/door_sensor.h
+++ b/src/door_sensor.h
@@ -1,13 +1,38 @@
+/**
+ * \file door_sensor.h
+ * \brief Public interface for the door sensor driver.
+ *
+ * This header declares the callback types and initialization function
+ * for detecting door open and close events using GPIO interrupts.
+ */
+
#ifndef DOOR_H
#define DOOR_H
/**
- * @brief Callback invoked on a confirmed key press.
- * @param key ASCII character of the pressed key.
+ * \brief Callback type invoked when the door is detected as opened.
+ *
+ * This function is called by the driver on a confirmed open event.
*/
typedef void (*DoorOpenedCallback_t)(void);
+
+/**
+ * \brief Callback type invoked when the door is detected as closed.
+ *
+ * This function is called by the driver on a confirmed close event.
+ */
typedef void (*DoorClosedCallback_t)(void);
+/**
+ * \brief Initialize the door sensor driver.
+ *
+ * Configures the GPIO pin for input with pull-up resistor and enables
+ * interrupts on the door sensor line. The provided callbacks are invoked
+ * on door open and close events respectively.
+ *
+ * \param ocb User-provided callback to invoke on door open.
+ * \param ccb User-provided callback to invoke on door close.
+ */
void door_init(DoorOpenedCallback_t ocb, DoorClosedCallback_t ccb);
-#endif // DOOR_H
\ No newline at end of file
+#endif // DOOR_H
diff --git a/src/i2c.c b/src/i2c.c
index 2bfcc89..b036449 100644
--- a/src/i2c.c
+++ b/src/i2c.c
@@ -1,12 +1,13 @@
-/* ========================================================================== */
-/* I2C.c */
-/* ========================================================================== */
+/* File: i2c.c */
/**
- * @file I2C.c
- * @author wehrberger
- * @date 31.05.2025
+ * @file i2c.c
+ * @brief I²C master routines and missing standard C90 constants for MSP430FR2355.
*
- * @brief Implementierung eines minimalen blockierenden I²C-Master-Treibers.
+ * Implements byte-wise I²C transmit and single-register read with automatic
+ * STOP handling and interrupt-driven operation.
+ *
+ * @author (based on work by) Luis Wehrberger
+ * @date 2025-07-02
*/
#include "i2c.h"
@@ -14,104 +15,127 @@
#include
#include
-/** Pointer auf das aktuell zu übertragende Byte. */
-static char *packet;
+/** Pointer to the current transmit buffer. */
+static char *i2c_tx_buffer;
-/** Index des nächsten zu übertragenden Bytes. */
-static unsigned int dataCount;
+/** Number of bytes left to send (buffer length). */
+static unsigned int i2c_tx_length;
-/** Anzahl der Bytes in @ref packet. */
-static unsigned int packetLength;
+/** Index of the next byte to transmit. */
+static unsigned int i2c_tx_index;
-/** Speicher für das zuletzt vom ISR empfangene Byte. */
-static char dataIn;
+/** Last byte received by the ISR. */
+static char i2c_rx_byte;
-static volatile bool i2cDone = false;
+/** Flag set when I²C transfer completes (STOP or NACK). */
+static volatile bool i2c_transfer_complete = false;
+/**
+ * @brief Initialize USCI_B0 module for I²C master mode at 50 kHz.
+ *
+ * Configures SMCLK source, sets clock divider, 7-bit addressing,
+ * automatic STOP generation, port mapping for SDA/SCL, and enables
+ * relevant interrupts.
+ */
void i2c_init(void)
{
- // USCI in Reset setzen um Konfiguration zu ermöglichen
+ // Put eUSCI_B0 into reset state for configuration
UCB0CTLW0 |= UCSWRST;
- // SMCLK wählen und durch 20 teilen → 50 kHz SCL
+ // Select SMCLK and divide by 20 → 50 kHz SCL
UCB0CTLW0 |= UCSSEL_3;
- UCB0BRW = 50;
+ UCB0BRW = 50;
- // I²C Master, 7-Bit Adressierung
+ // Configure as I²C master with 7-bit addressing
UCB0CTLW0 |= UCMODE_3 | UCMST;
- // Automatischer STOP nach Byte-Zähler (UCB0TBCNT) erreicht Null
+ // Enable automatic STOP when byte counter (UCB0TBCNT) reaches zero
UCB0CTLW1 |= UCASTP_2;
- // Port-Mapping: P1.2 = SDA, P1.3 = SCL
+ // Assign P1.2 = SDA, P1.3 = SCL via port mapping
P1SEL1 &= ~(BIT2 | BIT3);
- P1SEL0 |= BIT2 | BIT3;
+ P1SEL0 |= (BIT2 | BIT3);
- // Modul aktivieren
+ // Release eUSCI_B0 for operation
UCB0CTLW0 &= ~UCSWRST;
- // Interrupts: RX, TX, STOP, NACK
+ // Enable RX, TX, STOP, and NACK interrupts
UCB0IE |= UCRXIE0 | UCTXIE0 | UCSTPIE | UCNACKIE;
__enable_interrupt();
}
+/**
+ * @brief Transmit a sequence of bytes to a given I²C slave.
+ *
+ * @param slaveAddress 7-bit I²C address of the slave device.
+ * @param data Pointer to data buffer to send.
+ * @param length Number of bytes to transmit.
+ */
void i2c_write(uint8_t slaveAddress, char data[], uint8_t length)
{
+ // Set target slave address
UCB0I2CSA = slaveAddress;
- packet = data;
- packetLength = length;
- dataCount = 0;
- // Master-Transmit-Modus
+ // Initialize transmit buffer and counters
+ i2c_tx_buffer = data;
+ i2c_tx_length = length;
+ i2c_tx_index = 0;
+
+ // Configure for master-transmit mode and set byte counter
UCB0CTLW0 |= UCTR;
- UCB0TBCNT = length;
+ UCB0TBCNT = length;
- // START generieren, dann schlafen bis STOP
+ // Generate START and wait for STOP flag in ISR
UCB0CTLW0 |= UCTXSTT;
- i2cDone = false;
- while (!i2cDone)
+ i2c_transfer_complete = false;
+ while (!i2c_transfer_complete)
{
- LPM3; // Warten auf STOP → ISR weckt uns auf
+ LPM3; // Enter low-power mode, will wake on STOP or NACK
}
}
-char i2c_read_reg(uint8_t slaveAddress, uint8_t registerAddress)
-{
- // Registeradresse zuerst senden
- char addressBuffer[1] = {registerAddress};
- i2c_write(slaveAddress, addressBuffer, 1);
-
- // In Empfangsmodus wechseln und 1 Byte anfordern
- UCB0CTLW0 &= ~UCTR;
- UCB0TBCNT = 1;
-
- UCB0CTLW0 |= UCTXSTT; // Repeated START
-
- i2cDone = false;
- while (!i2cDone)
- {
- LPM3; // Warten auf STOP → ISR weckt uns auf
- }
-
- return dataIn;
-}
-
-/* ========================================================================== */
-/* Interrupt Service Routine */
-/* ========================================================================== */
-
/**
- * @brief Vereinheitlichte ISR für alle USCI_B0 I²C-Ereignisse.
+ * @brief Read a single register byte from an I²C slave.
*
- * Nur vier Interrupt-Ursachen werden derzeit behandelt:
- * - UCNACKIFG : Kennzeichnet fehlendes ACK (nur Debug-Hook)
- * - UCSTPIFG : STOP erkannt → LPM3 verlassen
- * - UCRXIFG0 : Ein Byte empfangen
- * - UCTXIFG0 : Sendepuffer bereit für nächstes Byte
+ * Performs a write of the register address, followed by a repeated START
+ * to read one byte, with automatic STOP and interrupt-based wake-up.
*
- * Alle anderen Ursachen fallen durch zum default.
+ * @param slaveAddress 7-bit I²C address of the slave device.
+ * @param registerAddress Register address to read.
+ * @return Byte read from the register.
+ */
+char i2c_read_reg(uint8_t slaveAddress, uint8_t registerAddress)
+{
+ // Send register address first
+ char addr_buf[1] = { (char)registerAddress };
+ i2c_write(slaveAddress, addr_buf, 1);
+
+ // Switch to master-receive mode and request one byte
+ UCB0CTLW0 &= ~UCTR;
+ UCB0TBCNT = 1;
+
+ // Generate repeated START condition
+ UCB0CTLW0 |= UCTXSTT;
+
+ i2c_transfer_complete = false;
+ while (!i2c_transfer_complete)
+ {
+ LPM3; // Wait for ISR to clear STOP flag
+ }
+
+ return i2c_rx_byte;
+}
+
+/**
+ * @brief USCI_B0 I²C interrupt handler.
+ *
+ * Handles NACK, STOP, RX, and TX events:
+ * - NACK: terminate transfer and wake CPU
+ * - STOP: terminate transfer and wake CPU
+ * - RXBUF: store received byte
+ * - TXBUF: send next byte or reset index
*/
#pragma vector = EUSCI_B0_VECTOR
__interrupt void EUSCI_B0_I2C_ISR(void)
@@ -119,31 +143,34 @@ __interrupt void EUSCI_B0_I2C_ISR(void)
switch (__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG))
{
case USCI_I2C_UCNACKIFG:
- // NACK → CPU aufwecken (LPM3 verlassen)
- i2cDone = true;
+ // NACK received: signal completion and wake CPU
+ i2c_transfer_complete = true;
__bic_SR_register_on_exit(LPM3_bits);
break;
case USCI_I2C_UCSTPIFG:
- // STOP → CPU aufwecken (LPM3 verlassen)
- i2cDone = true;
+ // STOP condition detected: signal completion and wake CPU
+ i2c_transfer_complete = true;
__bic_SR_register_on_exit(LPM3_bits);
break;
case USCI_I2C_UCRXIFG0:
- // Empfangenes Byte speichern
- dataIn = UCB0RXBUF;
+ // Read received byte into buffer
+ i2c_rx_byte = UCB0RXBUF;
break;
case USCI_I2C_UCTXIFG0:
- // Nächstes Datenbyte senden oder Übertragung beenden
- UCB0TXBUF = packet[dataCount++];
- if (dataCount >= packetLength)
- dataCount = 0; // Für nächste Transaktion zurücksetzen
+ // Transmit next byte or reset index if done
+ UCB0TXBUF = i2c_tx_buffer[i2c_tx_index++];
+ if (i2c_tx_index >= i2c_tx_length)
+ {
+ // Reset index for subsequent transactions
+ i2c_tx_index = 0;
+ }
break;
default:
- // Unbehandelter Vektor – nichts zu tun
+ // Unhandled interrupts: no action
break;
}
-}
\ No newline at end of file
+}
diff --git a/src/i2c.h b/src/i2c.h
index f74dfc6..4d95a85 100644
--- a/src/i2c.h
+++ b/src/i2c.h
@@ -19,7 +19,7 @@
#include
/**
- * @brief Initialize the I2C module as master (SMCLK/20 → 50 kHz SCL).
+ * @brief Initialize the I2C module as master.
*/
void i2c_init(void);
diff --git a/src/keypad.c b/src/keypad.c
index 0570bbc..9968eb4 100644
--- a/src/keypad.c
+++ b/src/keypad.c
@@ -13,7 +13,7 @@
* - Wait for key release and debounce
* - Clear flags and re-enable column interrupts
*
- * @author
+ * @author Frederik Beimgraben
* @date 2025-07-02
*/
diff --git a/src/keypad.h b/src/keypad.h
index d391715..ebd1260 100644
--- a/src/keypad.h
+++ b/src/keypad.h
@@ -5,10 +5,7 @@
*
* Interrupt-driven scanning with callback on key press.
*
- * @authors
- * Frederik Beimgraben
- * Minh Dan Cam
- * Luis Meyer
+ * @author Frederik Beimgraben
* @date 2025-07-02
*/
diff --git a/src/lcd.c b/src/lcd.c
index 8b73843..422dc88 100644
--- a/src/lcd.c
+++ b/src/lcd.c
@@ -1,34 +1,65 @@
+/**
+ * \file lcd.c
+ * \brief I2C-based LCD driver for MSP430FR2355.
+ *
+ * This module provides initialization and basic control functions
+ * for a character LCD connected via an I2C expander. It supports
+ * 4-bit communication mode and includes routines for sending commands
+ * and data to the display.
+ */
+
#include "lcd.h"
-#include "i2c.h" /* Ihr I²C-Master-Treiber */
-#include /* für __delay_cycles() */
+#include "i2c.h" /**< I²C master driver */
+#include /**< MSP430 definitions for __delay_cycles() */
#include
-/* --- Interne Helfer: sendet eine 4-Bit-Halbnibble plus Control-Bits --- */
+/**
+ * \brief Send a 4-bit nibble with control flags over I2C to the LCD.
+ *
+ * This helper composes a byte containing the nibble (in the high 4 bits),
+ * the control signals (RS, RW, EN), and the backlight bit, then toggles
+ * the enable line to latch the data.
+ *
+ * \param nibble 4-bit data to send (lower nibble used).
+ * \param control Control flags (e.g., RS, R/W).
+ */
static void lcd_write_nibble(uint8_t nibble, uint8_t control)
{
char buf[1];
- /* High-Nibble in die oberen 4 Bits */
- buf[0] = (nibble << 4) | control | LCD_BACKLIGHT;
- /* EN=1 */
+ /* High nibble placed in upper data bits, include control and backlight */
+ buf[0] = (uint8_t)((nibble << 4) | control | LCD_BACKLIGHT);
+ /* Pulse EN high */
i2c_write(LCD_I2C_ADDR, buf, 1);
buf[0] |= LCD_ENABLE;
i2c_write(LCD_I2C_ADDR, buf, 1);
- __delay_cycles(500); /* ca. 50 µs @ 1 MHz */
- /* EN=0 */
- buf[0] &= ~LCD_ENABLE;
+ __delay_cycles(500); /**< ~50µs at 1MHz */
+ /* EN low */
+ buf[0] &= (char)~LCD_ENABLE;
i2c_write(LCD_I2C_ADDR, buf, 1);
__delay_cycles(500);
}
-/* Sendet ein volles Byte (2×4-Bit) als Befehl (RS=0) */
+/**
+ * \brief Send an 8-bit command to the LCD.
+ *
+ * Splits the command into two 4-bit nibbles and sends each with RS=0.
+ *
+ * \param cmd Command byte to send.
+ */
static void lcd_send_cmd(uint8_t cmd)
{
lcd_write_nibble(cmd >> 4, 0x00);
lcd_write_nibble(cmd & 0x0F, 0x00);
}
-/* Sendet ein volles Byte als Daten (RS=1) */
+/**
+ * \brief Send an 8-bit data value (character) to the LCD.
+ *
+ * Splits the data into two 4-bit nibbles and sends each with RS=1.
+ *
+ * \param data Data byte (character) to display.
+ */
static void lcd_send_data(uint8_t data)
{
lcd_write_nibble(data >> 4, LCD_RS);
@@ -37,10 +68,10 @@ static void lcd_send_data(uint8_t data)
void lcd_init(void)
{
- /* Wartezeit nach Power-Up */
- __delay_cycles(50000); /* ca. 50 ms */
+ /* Delay for LCD power-up (approx. 50 ms) */
+ __delay_cycles(50000);
- /* Initialsequenz 8-Bit-Befehle (3×) */
+ /* Initialization sequence in 8-bit mode: 3 pulses */
lcd_write_nibble(0x03, 0x00);
__delay_cycles(20000);
lcd_write_nibble(0x03, 0x00);
@@ -48,37 +79,57 @@ void lcd_init(void)
lcd_write_nibble(0x03, 0x00);
__delay_cycles(2000);
- /* In 4-Bit-Modus schalten */
+ /* Switch to 4-bit mode */
lcd_write_nibble(0x02, 0x00);
__delay_cycles(2000);
- /* Funktion: 4-Bit, 2 Zeilen, 5×8 Punkte */
+ /* Function set: 4-bit, 2 lines, 5x8 dots */
lcd_send_cmd(0x28);
/* Display off */
lcd_send_cmd(0x08);
- /* Clear */
+ /* Clear display */
lcd_send_cmd(0x01);
__delay_cycles(2000);
- /* Entry mode: Cursor++ */
+ /* Entry mode set: increment cursor */
lcd_send_cmd(0x06);
- /* Display on, Cursor off, Blink off */
+ /* Display on, cursor off, blink off */
lcd_send_cmd(0x0C);
}
void lcd_clear(void)
{
+ /**
+ * \brief Clear display and reset cursor.
+ *
+ * Sends the clear command and waits for the LCD to process it.
+ */
lcd_send_cmd(0x01);
__delay_cycles(2000);
}
void lcd_set_cursor(uint8_t row, uint8_t col)
{
+ /**
+ * \brief Set cursor to specified position.
+ *
+ * Calculates the DDRAM address based on row and column.
+ *
+ * \param row Row index (0 or 1).
+ * \param col Column index (0-15).
+ */
uint8_t addr = (row == 0 ? 0x00 : 0x40) + (col & 0x0F);
lcd_send_cmd(0x80 | addr);
}
void lcd_print(const char *str)
{
+ /**
+ * \brief Print a null-terminated string to the LCD.
+ *
+ * Iterates through the string and sends each character as data.
+ *
+ * \param str Pointer to a null-terminated C string.
+ */
while (*str)
{
lcd_send_data((uint8_t)*str++);
diff --git a/src/state_machine.h b/src/state_machine.h
index b18f493..5372897 100644
--- a/src/state_machine.h
+++ b/src/state_machine.h
@@ -6,9 +6,10 @@
* This module drives a keypad‐and‐LCD UI to select beverage types (A–D),
* choose quantities, confirm orders, detect door events, and edit stock levels.
*
- * @author Frederik Beimgraben
- * @author Minh Dan Cam
- * @author Luis Meyer
+ * @authors
+ * Frederik Beimgraben
+ * Minh Dan Cam
+ * Luis Meyer
* @date 2025-07-03
*/
diff --git a/src/timer.c b/src/timer.c
index 10950cc..3a9ba78 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -1,41 +1,70 @@
+/**
+ * \file timer.c
+ * \brief MSP430 Timer B driver and blocking delay implementation.
+ *
+ * This module provides a millisecond-level blocking delay function using
+ * low-power mode and global interrupts, as well as initialization for Timer B
+ * in up mode to generate periodic 1ms interrupts.
+ */
+
#include
#include
#include
#include "timer.h"
/**
- * @brief Führt eine blockierende Wartezeit aus.
- * @param ms Zeit in Millisekunden
+ * \brief Block execution for a given number of milliseconds.
+ *
+ * Implements a blocking delay by entering LPM0 and waking up via the
+ * Timer interrupt on each millisecond tick.
+ *
+ * \param ms Number of milliseconds to delay.
*/
void sleep(uint16_t ms) {
while (ms--) {
+ /* Enter low-power mode 0 with interrupts enabled */
__bis_SR_register(LPM0_bits + GIE);
+ /* No operation, wait for interrupt */
__no_operation();
}
}
+/**
+ * \brief Initialize Timer B0 in up mode to generate 1ms period interrupts.
+ *
+ * Configures Timer B0 to use SMCLK, no divider, and a period of 999 ticks
+ * to achieve a 1ms overflow (assuming 1MHz SMCLK). Enables CCR0 interrupt
+ * to exit low-power mode on each tick.
+ */
void init_timer(void) {
static Timer_B_initUpModeParam param = {0};
+ /* Select SMCLK as clock source */
param.clockSource = TIMER_B_CLOCKSOURCE_SMCLK;
+ /* No division: tick = 1MHz / 1 = 1MHz */
param.clockSourceDivider = TIMER_B_CLOCKSOURCE_DIVIDER_1;
- param.timerPeriod = 999; // wenn 1000 Taktimpulse gezählt
- // wurden, erfolgt ein Interrupt
- // Periodendauer somit 1ms
- param.timerInterruptEnable_TBIE =
- TIMER_B_TBIE_INTERRUPT_DISABLE; // no interrupt on 0x0000
+ /* Period = 999 -> interrupt every 1000 ticks => 1ms */
+ param.timerPeriod = 999;
+ /* Disable interrupt on timer rollover (TBIE) */
+ param.timerInterruptEnable_TBIE = TIMER_B_TBIE_INTERRUPT_DISABLE;
+ /* Enable CCR0 interrupt on timer compare match */
param.captureCompareInterruptEnable_CCR0_CCIE =
- TIMER_B_CAPTURECOMPARE_INTERRUPT_ENABLE; // interrupt on TRmax
+ TIMER_B_CAPTURECOMPARE_INTERRUPT_ENABLE;
+ /* Clear timer and start immediately */
param.timerClear = TIMER_B_DO_CLEAR;
param.startTimer = true;
- // start Timer:
+ /* Initialize and start Timer B0 in up mode */
Timer_B_initUpMode(TB0_BASE, ¶m);
}
-// TimerB0 Interrupt Vector (TBxIV) handler
+/**
+ * \brief ISR for Timer0_B0 (CCR0) comparison event.
+ *
+ * Exits low-power mode 0 to resume the sleeping function.
+ */
#pragma vector=TIMER0_B0_VECTOR
-__interrupt void TIMER0_B0_ISR(void)
-{
+__interrupt void TIMER0_B0_ISR(void) {
+ /* Clear LPM0 bits on exit to wake up CPU */
__bic_SR_register_on_exit(LPM0_bits);
}
diff --git a/src/timer.h b/src/timer.h
index 703f61e..b60dbad 100644
--- a/src/timer.h
+++ b/src/timer.h
@@ -1,7 +1,31 @@
+/**
+ * \file timer.h
+ * \brief Interface for millisecond delay and Timer B initialization on MSP430.
+ *
+ * This header declares functions for creating a blocking delay using low-power
+ * mode and for initializing Timer B0 in up mode to generate periodic 1ms interrupts.
+ */
+
#ifndef TIMER_H
#define TIMER_H
+/**
+ * \brief Block execution for a specified number of milliseconds.
+ *
+ * This function enters low-power mode 0 (LPM0) and wakes on each
+ * Timer B CCR0 interrupt to achieve an approximate millisecond delay.
+ *
+ * \param ms Number of milliseconds to sleep.
+ */
void sleep(uint16_t ms);
+
+/**
+ * \brief Initialize Timer B0 to generate 1ms interrupts.
+ *
+ * Configures Timer B0 with SMCLK as the clock source, no divider,
+ * and a period of 999 ticks (for a 1MHz clock) to create a 1ms interval.
+ * Enables CCR0 compare interrupt to wake from low-power mode on each tick.
+ */
void init_timer(void);
-#endif // TIMER_H
\ No newline at end of file
+#endif // TIMER_H