stime.S 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. ;---------------------------------------------------------------------------;
  2. ; Simple time functions (C)ChaN,2005
  3. ;
  4. ; mktime() and gmtime() are sub-set of the functions defined in ANSI C.
  5. ; tm_isdst member is not returned and assumed as zero.
  6. ; mktime() does not change given tm structure and each members must be
  7. ; normalized or it returns -1.
  8. .nolist
  9. #include <avr/io.h>
  10. #ifdef SPM_PAGESIZE // The device has "lpm Rd,Z+" and "movw".
  11. .macro _MOVW dh,dl, sh,sl
  12. movw \dl, \sl
  13. .endm
  14. #else // The device does not have "lpm Rd,Z+" nor "movw".
  15. .macro _MOVW dh,dl, sh,sl
  16. mov \dl, \sl
  17. mov \dh, \sh
  18. .endm
  19. #endif
  20. .list
  21. .section .bss
  22. .global time_tm
  23. time_tm: ; Static tm structure
  24. .ds.w 9 ; { sec, min, hour, mday, mon, year, wday, yday, isdst }
  25. .section .text
  26. samurai:
  27. .dc.b 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  28. ;---------------------------------------------------------------------------;
  29. ; time_t mktime( struct tm *timeptr );
  30. ;
  31. ;Size: 89/88 words
  32. .global mktime
  33. .func mktime
  34. mktime:
  35. push YL
  36. push YH
  37. _MOVW YH,YL, r25,r24
  38. adiw YL, 12
  39. ldi r20, 138 ; (365..366) * tm_year
  40. rcall ldcp16
  41. clr r22
  42. clr r23
  43. ldi r19, 70
  44. 0: ldi XL, lo8(366)
  45. ldi XH, hi8(366)
  46. mov r21, r19
  47. andi r21, 3
  48. breq 1f
  49. sbiw XL, 1
  50. 1: cp r19, r18
  51. breq 2f
  52. brcc 91f
  53. add r22, XL
  54. adc r23, XH
  55. inc r19
  56. rjmp 0b
  57. 2:
  58. ldi r20, 12 ; + (28..31) * tm_mon
  59. rcall ldcp16
  60. ldi ZL, lo8(samurai)
  61. ldi ZH, hi8(samurai)
  62. ldi r19, 0
  63. 3: lpm
  64. adiw ZL, 1
  65. cpi r19, 1
  66. brne 4f
  67. cpse r21, r1
  68. dec r0
  69. 4: cp r19, r18
  70. brcc 5f
  71. add r22, r0
  72. adc r23, r1
  73. inc r19
  74. rjmp 3b
  75. 5:
  76. mov r20, r0 ; + tm_mday
  77. inc r20
  78. rcall ldcp16
  79. subi r18, 1
  80. brcs 91f
  81. add r22, r18
  82. adc r23, r1
  83. clr r24
  84. clr r25
  85. ; r25:r22 = days from orign
  86. ldi r20, 24 ; * 24 + tm_hour
  87. rcall ldcp16
  88. rcall muladd3208
  89. ldi r20, 60 ; * 60 + tm_min
  90. rcall ldcp16
  91. rcall muladd3208
  92. ldi r18, 60 ; * 60 + tm_sec
  93. rcall ldcp16
  94. rcall muladd3208
  95. rjmp 92f
  96. ldcp16: ld r19, -Y ; Load an item with error check (< r20)
  97. ld r18, -Y
  98. cp r18, r20
  99. cpc r19, r1
  100. brcs 93f
  101. pop r0
  102. pop r0
  103. 91: ldi r22, -1 ; parameter error
  104. ldi r23, -1
  105. ldi r24, -1
  106. ldi r25, -1
  107. 92: pop YH
  108. pop YL
  109. 93: ret
  110. muladd3208:
  111. ldi r21, 33 ; r25:r22 *= r20;
  112. sub r26, r26
  113. 0: brcc 1f
  114. add r26, r20
  115. 1: ror r26
  116. ror r25
  117. ror r24
  118. ror r23
  119. ror r22
  120. dec r21
  121. brne 0b
  122. add r22, r18 ; r25:r22 += r18;
  123. adc r23, r1
  124. adc r24, r1
  125. adc r25, r1
  126. ret
  127. .endfunc
  128. ;---------------------------------------------------------------------------;
  129. ; struct tm *gmtime( const time_t *timer );
  130. ;
  131. ;Size: 93/89 words
  132. .global gmtime
  133. .func gmtime
  134. gmtime:
  135. push YL
  136. push YH
  137. _MOVW ZH,ZL, r25,r24 ;r21:r18 = utc
  138. ldd r18, Z+0 ;
  139. ldd r19, Z+1 ;
  140. ldd r20, Z+2 ;
  141. ldd r21, Z+3 ;/
  142. clr YL ;Invalid time?
  143. clr YH ;
  144. sbrc r21, 7 ;
  145. rjmp 99f ;/
  146. ldi YL, lo8(time_tm)
  147. ldi YH, hi8(time_tm)
  148. ; r21:r18 = seconds from origin
  149. ldi r22, 60 ;tm_sec = % 60
  150. rcall div3208 ;
  151. std Y+0, r0 ;
  152. std Y+1, r1 ;/
  153. rcall div3208 ;tm_min = % 60
  154. std Y+2, r0 ;
  155. std Y+3, r1 ;/
  156. ldi r22, 24 ;tm_hour = % 24
  157. rcall div3208 ;
  158. std Y+4, r0 ;
  159. std Y+5, r1 ;/
  160. ; r19:r18 = days from origin
  161. _MOVW ZH,ZL, r19,r18
  162. subi r18, lo8(-4) ;tm_wday
  163. sbci r19, hi8(-4) ;
  164. ldi r22, 7 ;
  165. rcall div3208 ;
  166. std Y+12, r0 ;
  167. std Y+13, r1 ;/
  168. _MOVW r19,r18, ZH,ZL
  169. ldi XL, 70 ;tm_year
  170. 0: ldi ZL, lo8(366) ;
  171. ldi ZH, hi8(366) ;
  172. mov XH, XL ;
  173. andi XH, 3 ;
  174. breq 1f ;
  175. sbiw ZL, 1 ;
  176. 1: cp r18, ZL ;
  177. cpc r19, ZH ;
  178. brcs 2f ;
  179. sub r18, ZL ;
  180. sbc r19, ZH ;
  181. inc XL ;
  182. rjmp 0b ;
  183. 2: std Y+10, XL ;
  184. std Y+11, r1 ;/
  185. std Y+14, r18 ;tm_yday
  186. std Y+15, r19 ;/
  187. ; r19:r18 = days in year
  188. ldi ZL, lo8(samurai) ;tm_mon
  189. ldi ZH, hi8(samurai) ;
  190. clr XL ;
  191. 3: lpm ;
  192. adiw ZL, 1 ;
  193. cpi XL, 1 ;
  194. brne 4f ;
  195. cpse XH, r1 ;
  196. dec r0 ;
  197. 4: cp r18, r0 ;
  198. cpc r19, r1 ;
  199. brcs 5f ;
  200. sub r18, r0 ;
  201. sbc r19, r1 ;
  202. inc XL ;
  203. rjmp 3b ;
  204. 5: std Y+8, XL ;
  205. std Y+9, r1 ;/
  206. inc r18 ;tm_mday
  207. std Y+6, r18 ;
  208. std Y+7, r19 ;/
  209. 99: _MOVW r25,r24, YH,YL ;Return pointer to internal tm buffer
  210. pop YH
  211. pop YL
  212. ret
  213. div3208: ; r0 = r21:r18 % r22;
  214. clr r0 ; r21:r18 /= r22;
  215. ldi r23, 32
  216. 1: lsl r18
  217. rol r19
  218. rol r20
  219. rol r21
  220. rol r0
  221. cp r0, r22
  222. brcs 2f
  223. sub r0, r22
  224. inc r18
  225. 2: dec r23
  226. brne 1b
  227. ret
  228. .endfunc