test
Dependents: Telemetria_RX_SD_GPS_copy Telemetria_RX_SD_GPS Telemetria_TX Telemetria_TX ... more
Arduino-mbed-APIs/arduino-mbed.cpp@76:79f8ca9c8025, 2017-07-27 (annotated)
- Committer:
- Helmut Tschemernjak
- Date:
- Thu Jul 27 11:47:46 2017 +0200
- Revision:
- 76:79f8ca9c8025
- Parent:
- 75:7330dd86cdea
- Child:
- 77:7f227a4dffe6
Disable Arduino sleep code when using SerialUSB because
the sleep kills the USB
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Helmut Tschemernjak | 46:e78a1d0391ac | 1 | /* |
Helmut Tschemernjak | 65:b2d98328fcba | 2 | * The file is Licensed under the Apache License, Version 2.0 |
Helmut Tschemernjak | 46:e78a1d0391ac | 3 | * (c) 2017 Helmut Tschemernjak |
Helmut Tschemernjak | 46:e78a1d0391ac | 4 | * 30826 Garbsen (Hannover) Germany |
Helmut Tschemernjak | 46:e78a1d0391ac | 5 | */ |
Helmut Tschemernjak | 46:e78a1d0391ac | 6 | |
Helmut Tschemernjak | 65:b2d98328fcba | 7 | #ifdef ARDUINO |
Helmut Tschemernjak | 65:b2d98328fcba | 8 | |
Helmut Tschemernjak | 65:b2d98328fcba | 9 | using namespace std; |
Helmut Tschemernjak | 65:b2d98328fcba | 10 | |
Helmut Tschemernjak | 65:b2d98328fcba | 11 | #include "arduino-mbed.h" |
Helmut Tschemernjak | 75:7330dd86cdea | 12 | #include "arduino-util.h" |
Helmut Tschemernjak | 65:b2d98328fcba | 13 | |
Helmut Tschemernjak | 75:7330dd86cdea | 14 | Stream *ser; |
Helmut Tschemernjak | 75:7330dd86cdea | 15 | void InitSerial(Stream *serial) { |
Helmut Tschemernjak | 75:7330dd86cdea | 16 | ser = serial; |
Helmut Tschemernjak | 75:7330dd86cdea | 17 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 18 | |
Helmut Tschemernjak | 65:b2d98328fcba | 19 | static void pinInt00(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 20 | static void pinInt01(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 21 | static void pinInt02(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 22 | static void pinInt03(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 23 | static void pinInt04(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 24 | static void pinInt05(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 25 | static void pinInt06(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 26 | static void pinInt07(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 27 | static void pinInt08(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 28 | static void pinInt09(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 29 | static void pinInt10(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 30 | static void pinInt11(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 31 | static void pinInt12(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 32 | static void pinInt13(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 33 | static void pinInt14(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 34 | static void pinInt15(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 35 | static void pinInt16(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 36 | static void pinInt17(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 37 | static void pinInt18(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 38 | static void pinInt19(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 39 | static void pinInt20(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 40 | static void pinInt21(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 41 | static void pinInt22(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 42 | static void pinInt23(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 43 | static void pinInt24(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 44 | static void pinInt25(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 45 | static void pinInt26(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 46 | static void pinInt27(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 47 | static void pinInt28(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 48 | static void pinInt29(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 49 | static void pinInt30(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 50 | static void pinInt31(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 51 | static void pinInt32(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 52 | static void pinInt33(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 53 | static void pinInt34(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 54 | static void pinInt35(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 55 | static void pinInt36(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 56 | static void pinInt37(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 57 | static void pinInt38(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 58 | static void pinInt39(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 59 | static void pinInt40(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 60 | static void pinInt41(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 61 | static void pinInt42(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 62 | static void pinInt43(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 63 | static void pinInt44(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 64 | static void pinInt45(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 65 | static void pinInt46(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 66 | static void pinInt47(void); |
Helmut Tschemernjak | 46:e78a1d0391ac | 67 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 68 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 69 | |
Helmut Tschemernjak | 65:b2d98328fcba | 70 | #define MAX_MCU_PINS 48 |
Helmut Tschemernjak | 65:b2d98328fcba | 71 | class InterruptIn; |
Helmut Tschemernjak | 65:b2d98328fcba | 72 | struct intPtrTable { |
Helmut Tschemernjak | 65:b2d98328fcba | 73 | void (*func)(void); |
Helmut Tschemernjak | 65:b2d98328fcba | 74 | InterruptIn *context; |
Helmut Tschemernjak | 65:b2d98328fcba | 75 | } intPtrTable[MAX_MCU_PINS] = { |
Helmut Tschemernjak | 65:b2d98328fcba | 76 | { pinInt00, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 77 | { pinInt01, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 78 | { pinInt02, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 79 | { pinInt03, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 80 | { pinInt04, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 81 | { pinInt05, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 82 | { pinInt06, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 83 | { pinInt07, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 84 | { pinInt08, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 85 | { pinInt09, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 86 | { pinInt10, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 87 | { pinInt11, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 88 | { pinInt12, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 89 | { pinInt13, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 90 | { pinInt14, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 91 | { pinInt15, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 92 | { pinInt16, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 93 | { pinInt17, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 94 | { pinInt18, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 95 | { pinInt19, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 96 | { pinInt20, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 97 | { pinInt21, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 98 | { pinInt22, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 99 | { pinInt23, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 100 | { pinInt24, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 101 | { pinInt25, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 102 | { pinInt26, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 103 | { pinInt27, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 104 | { pinInt28, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 105 | { pinInt29, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 106 | { pinInt30, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 107 | { pinInt31, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 108 | { pinInt32, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 109 | { pinInt33, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 110 | { pinInt34, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 111 | { pinInt35, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 112 | { pinInt36, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 113 | { pinInt37, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 114 | { pinInt38, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 115 | { pinInt39, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 116 | { pinInt40, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 117 | { pinInt41, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 118 | { pinInt42, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 119 | { pinInt43, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 120 | { pinInt44, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 121 | { pinInt45, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 122 | { pinInt46, NULL }, |
Helmut Tschemernjak | 65:b2d98328fcba | 123 | { pinInt47, NULL } |
Helmut Tschemernjak | 65:b2d98328fcba | 124 | }; // our max MCUs pins |
Helmut Tschemernjak | 46:e78a1d0391ac | 125 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 126 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 127 | |
Helmut Tschemernjak | 65:b2d98328fcba | 128 | static void pinInt00(void) { InterruptIn::_irq_handler(intPtrTable[0].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 129 | static void pinInt01(void) { InterruptIn::_irq_handler(intPtrTable[1].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 130 | static void pinInt02(void) { InterruptIn::_irq_handler(intPtrTable[2].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 131 | static void pinInt03(void) { InterruptIn::_irq_handler(intPtrTable[3].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 132 | static void pinInt04(void) { InterruptIn::_irq_handler(intPtrTable[4].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 133 | static void pinInt05(void) { InterruptIn::_irq_handler(intPtrTable[5].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 134 | static void pinInt06(void) { InterruptIn::_irq_handler(intPtrTable[6].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 135 | static void pinInt07(void) { InterruptIn::_irq_handler(intPtrTable[7].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 136 | static void pinInt08(void) { InterruptIn::_irq_handler(intPtrTable[8].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 137 | static void pinInt09(void) { InterruptIn::_irq_handler(intPtrTable[9].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 138 | static void pinInt10(void) { InterruptIn::_irq_handler(intPtrTable[10].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 139 | static void pinInt11(void) { InterruptIn::_irq_handler(intPtrTable[11].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 140 | static void pinInt12(void) { InterruptIn::_irq_handler(intPtrTable[12].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 141 | static void pinInt13(void) { InterruptIn::_irq_handler(intPtrTable[13].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 142 | static void pinInt14(void) { InterruptIn::_irq_handler(intPtrTable[14].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 143 | static void pinInt15(void) { InterruptIn::_irq_handler(intPtrTable[15].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 144 | static void pinInt16(void) { InterruptIn::_irq_handler(intPtrTable[16].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 145 | static void pinInt17(void) { InterruptIn::_irq_handler(intPtrTable[17].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 146 | static void pinInt18(void) { InterruptIn::_irq_handler(intPtrTable[18].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 147 | static void pinInt19(void) { InterruptIn::_irq_handler(intPtrTable[19].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 148 | static void pinInt20(void) { InterruptIn::_irq_handler(intPtrTable[20].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 149 | static void pinInt21(void) { InterruptIn::_irq_handler(intPtrTable[21].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 150 | static void pinInt22(void) { InterruptIn::_irq_handler(intPtrTable[22].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 151 | static void pinInt23(void) { InterruptIn::_irq_handler(intPtrTable[23].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 152 | static void pinInt24(void) { InterruptIn::_irq_handler(intPtrTable[24].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 153 | static void pinInt25(void) { InterruptIn::_irq_handler(intPtrTable[25].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 154 | static void pinInt26(void) { InterruptIn::_irq_handler(intPtrTable[26].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 155 | static void pinInt27(void) { InterruptIn::_irq_handler(intPtrTable[27].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 156 | static void pinInt28(void) { InterruptIn::_irq_handler(intPtrTable[28].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 157 | static void pinInt29(void) { InterruptIn::_irq_handler(intPtrTable[29].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 158 | static void pinInt30(void) { InterruptIn::_irq_handler(intPtrTable[30].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 159 | static void pinInt31(void) { InterruptIn::_irq_handler(intPtrTable[31].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 160 | static void pinInt32(void) { InterruptIn::_irq_handler(intPtrTable[32].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 161 | static void pinInt33(void) { InterruptIn::_irq_handler(intPtrTable[33].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 162 | static void pinInt34(void) { InterruptIn::_irq_handler(intPtrTable[34].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 163 | static void pinInt35(void) { InterruptIn::_irq_handler(intPtrTable[35].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 164 | static void pinInt36(void) { InterruptIn::_irq_handler(intPtrTable[36].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 165 | static void pinInt37(void) { InterruptIn::_irq_handler(intPtrTable[37].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 166 | static void pinInt38(void) { InterruptIn::_irq_handler(intPtrTable[38].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 167 | static void pinInt39(void) { InterruptIn::_irq_handler(intPtrTable[39].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 168 | static void pinInt40(void) { InterruptIn::_irq_handler(intPtrTable[40].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 169 | static void pinInt41(void) { InterruptIn::_irq_handler(intPtrTable[41].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 170 | static void pinInt42(void) { InterruptIn::_irq_handler(intPtrTable[42].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 171 | static void pinInt43(void) { InterruptIn::_irq_handler(intPtrTable[43].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 172 | static void pinInt44(void) { InterruptIn::_irq_handler(intPtrTable[44].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 173 | static void pinInt45(void) { InterruptIn::_irq_handler(intPtrTable[45].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 174 | static void pinInt46(void) { InterruptIn::_irq_handler(intPtrTable[46].context); } |
Helmut Tschemernjak | 65:b2d98328fcba | 175 | static void pinInt47(void) { InterruptIn::_irq_handler(intPtrTable[47].context); } |
Helmut Tschemernjak | 46:e78a1d0391ac | 176 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 177 | |
Helmut Tschemernjak | 65:b2d98328fcba | 178 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 179 | |
Helmut Tschemernjak | 65:b2d98328fcba | 180 | void |
Helmut Tschemernjak | 65:b2d98328fcba | 181 | InterruptIn::rise(Callback<void()> func) { |
Helmut Tschemernjak | 65:b2d98328fcba | 182 | if (_gpioPin >= MAX_MCU_PINS-1) |
Helmut Tschemernjak | 65:b2d98328fcba | 183 | return; |
Helmut Tschemernjak | 65:b2d98328fcba | 184 | if (func) { |
Helmut Tschemernjak | 65:b2d98328fcba | 185 | _func = func; |
Helmut Tschemernjak | 65:b2d98328fcba | 186 | intPtrTable[_gpioPin].context = this; |
Helmut Tschemernjak | 69:d440a5b04708 | 187 | attachInterrupt(MYdigitalPinToInterrupt(_gpioPin), intPtrTable[_gpioPin].func, RISING); |
Helmut Tschemernjak | 65:b2d98328fcba | 188 | } else { |
Helmut Tschemernjak | 65:b2d98328fcba | 189 | _func = InterruptIn::donothing; |
Helmut Tschemernjak | 65:b2d98328fcba | 190 | intPtrTable[_gpioPin].context = NULL; |
Helmut Tschemernjak | 65:b2d98328fcba | 191 | detachInterrupt(_gpioPin); |
Helmut Tschemernjak | 46:e78a1d0391ac | 192 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 193 | }; |
Helmut Tschemernjak | 46:e78a1d0391ac | 194 | |
Helmut Tschemernjak | 65:b2d98328fcba | 195 | void |
Helmut Tschemernjak | 65:b2d98328fcba | 196 | InterruptIn::fall(Callback<void()> func) { |
Helmut Tschemernjak | 65:b2d98328fcba | 197 | if (func) { |
Helmut Tschemernjak | 65:b2d98328fcba | 198 | _func = func; |
Helmut Tschemernjak | 65:b2d98328fcba | 199 | intPtrTable[_gpioPin].context = this; |
Helmut Tschemernjak | 69:d440a5b04708 | 200 | attachInterrupt(MYdigitalPinToInterrupt(_gpioPin), intPtrTable[_gpioPin].func, FALLING); |
Helmut Tschemernjak | 65:b2d98328fcba | 201 | } else { |
Helmut Tschemernjak | 65:b2d98328fcba | 202 | _func = InterruptIn::donothing; |
Helmut Tschemernjak | 65:b2d98328fcba | 203 | intPtrTable[_gpioPin].context = NULL; |
Helmut Tschemernjak | 65:b2d98328fcba | 204 | detachInterrupt(_gpioPin); |
Helmut Tschemernjak | 46:e78a1d0391ac | 205 | } |
Helmut Tschemernjak | 46:e78a1d0391ac | 206 | } |
Helmut Tschemernjak | 46:e78a1d0391ac | 207 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 208 | |
Helmut Tschemernjak | 65:b2d98328fcba | 209 | #define MAX_TIMEOUTS 10 |
Helmut Tschemernjak | 65:b2d98328fcba | 210 | class Timeout; |
Helmut Tschemernjak | 65:b2d98328fcba | 211 | struct TimeoutVector { |
Helmut Tschemernjak | 65:b2d98328fcba | 212 | Timeout *timer; |
Helmut Tschemernjak | 65:b2d98328fcba | 213 | } TimeOuts[MAX_TIMEOUTS]; |
Helmut Tschemernjak | 65:b2d98328fcba | 214 | |
Helmut Tschemernjak | 65:b2d98328fcba | 215 | |
Helmut Tschemernjak | 65:b2d98328fcba | 216 | #if defined(__SAMD21G18A__) || defined(__SAMD21J18A__) |
Helmut Tschemernjak | 65:b2d98328fcba | 217 | /* |
Helmut Tschemernjak | 65:b2d98328fcba | 218 | * __SAMD21J18A__ is the SamD21 Explained Board |
Helmut Tschemernjak | 65:b2d98328fcba | 219 | * __SAMD21G18A__ is Genuino Zero-Board (compatible with the LoRa board) |
Helmut Tschemernjak | 65:b2d98328fcba | 220 | */ |
Helmut Tschemernjak | 65:b2d98328fcba | 221 | |
Helmut Tschemernjak | 65:b2d98328fcba | 222 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 223 | * see tcc.h is automatically included from: |
Helmut Tschemernjak | 65:b2d98328fcba | 224 | * Arduino15/packages/arduino/tools/CMSIS-Atmel/1.1.0/CMSIS/ |
Helmut Tschemernjak | 65:b2d98328fcba | 225 | * Device/ATMEL/samd21/include/component/tcc.h |
Helmut Tschemernjak | 66:fbb2da34bd9a | 226 | * See also tcc.c (ASF/mbed, e.g. Tcc_get_count_value) |
Helmut Tschemernjak | 65:b2d98328fcba | 227 | */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 228 | static void initTimer(Tcc *t); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 229 | static uint32_t getTimerCount(Tcc *t); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 230 | |
Helmut Tschemernjak | 67:d3afd803f40d | 231 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 232 | * The Atmel D21 has three TCC timer, other models have more. |
Helmut Tschemernjak | 67:d3afd803f40d | 233 | */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 234 | static const struct TCC_config { |
Helmut Tschemernjak | 65:b2d98328fcba | 235 | Tcc *tcc_ptr; |
Helmut Tschemernjak | 65:b2d98328fcba | 236 | IRQn_Type tcc_irq; |
Helmut Tschemernjak | 65:b2d98328fcba | 237 | uint8_t nbits; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 238 | } TCC_data[] { |
Helmut Tschemernjak | 65:b2d98328fcba | 239 | { TCC0, TCC0_IRQn, 24 }, |
Helmut Tschemernjak | 65:b2d98328fcba | 240 | { TCC1, TCC1_IRQn, 24 }, |
Helmut Tschemernjak | 65:b2d98328fcba | 241 | { TCC2, TCC2_IRQn, 16 }, |
Helmut Tschemernjak | 66:fbb2da34bd9a | 242 | { NULL, (IRQn_Type)NULL, 0 } |
Helmut Tschemernjak | 65:b2d98328fcba | 243 | }; |
Helmut Tschemernjak | 67:d3afd803f40d | 244 | |
Helmut Tschemernjak | 67:d3afd803f40d | 245 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 246 | * We preferably use the TCC timers because it supports 24-bit counters |
Helmut Tschemernjak | 67:d3afd803f40d | 247 | * versus TC Timer which supports only 8 or 16 bit counters |
Helmut Tschemernjak | 67:d3afd803f40d | 248 | * TCC0/1/2 timer work on the D21 using Arduino. |
Helmut Tschemernjak | 67:d3afd803f40d | 249 | */ |
Helmut Tschemernjak | 67:d3afd803f40d | 250 | #define USE_TCC_TIMEOUT 0 // 0=TCC0, 1=TTC1, 2=TTC2 (see TCC_data) |
Helmut Tschemernjak | 66:fbb2da34bd9a | 251 | #define USE_TCC_TICKER 1 |
Helmut Tschemernjak | 66:fbb2da34bd9a | 252 | |
Helmut Tschemernjak | 67:d3afd803f40d | 253 | |
Helmut Tschemernjak | 67:d3afd803f40d | 254 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 255 | * every 21333 ns equals one tick (1/(48000000/1024)) // prescaler 1024, 48 MHz |
Helmut Tschemernjak | 67:d3afd803f40d | 256 | * every 61035 ns equals one tick (1/(32768/2)) // prescaler 2, 32 kHz |
Helmut Tschemernjak | 67:d3afd803f40d | 257 | * COUNT*DIVIDER*SECS until interrupt |
Helmut Tschemernjak | 67:d3afd803f40d | 258 | * CPU 48 MHz = (65536*1024)/1.398636s |
Helmut Tschemernjak | 67:d3afd803f40d | 259 | * RTC 32 kHz = (65536*2)/4.0s |
Helmut Tschemernjak | 67:d3afd803f40d | 260 | */ |
Helmut Tschemernjak | 67:d3afd803f40d | 261 | #define NS_PER_CLOCK_CPU 21333 // ns secs per clock |
Helmut Tschemernjak | 67:d3afd803f40d | 262 | #define NS_PER_CLOCK_RTC 61035 // ns secs per clock |
Helmut Tschemernjak | 67:d3afd803f40d | 263 | |
Helmut Tschemernjak | 67:d3afd803f40d | 264 | #define NS_PER_CLOCK NS_PER_CLOCK_RTC |
Helmut Tschemernjak | 66:fbb2da34bd9a | 265 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 266 | /* ----------------- TICKER TIMER CODE ----------------------*/ |
Helmut Tschemernjak | 67:d3afd803f40d | 267 | |
Helmut Tschemernjak | 67:d3afd803f40d | 268 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 269 | * The global ns_counter contains the time in ns from the last time |
Helmut Tschemernjak | 67:d3afd803f40d | 270 | * the counter has been wrapped. It cannot be used directly because the |
Helmut Tschemernjak | 67:d3afd803f40d | 271 | * current counter has to be added fore using it. Use instead |
Helmut Tschemernjak | 67:d3afd803f40d | 272 | * ns_getTicker(), us_ ns_getTicker(), ms_getTicker() |
Helmut Tschemernjak | 67:d3afd803f40d | 273 | */ |
Helmut Tschemernjak | 67:d3afd803f40d | 274 | |
Helmut Tschemernjak | 67:d3afd803f40d | 275 | uint64_t ticker_ns; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 276 | static bool initTickerDone = false; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 277 | |
Helmut Tschemernjak | 70:1d496aae2819 | 278 | uint32_t s_getTicker(void) |
Helmut Tschemernjak | 70:1d496aae2819 | 279 | { |
Helmut Tschemernjak | 70:1d496aae2819 | 280 | long long ns = ns_getTicker(); |
Helmut Tschemernjak | 70:1d496aae2819 | 281 | ns /= (long long)1000000000; // to secs |
Helmut Tschemernjak | 70:1d496aae2819 | 282 | |
Helmut Tschemernjak | 70:1d496aae2819 | 283 | int secs = ns; |
Helmut Tschemernjak | 70:1d496aae2819 | 284 | return secs; |
Helmut Tschemernjak | 70:1d496aae2819 | 285 | } |
Helmut Tschemernjak | 70:1d496aae2819 | 286 | |
Helmut Tschemernjak | 70:1d496aae2819 | 287 | |
Helmut Tschemernjak | 67:d3afd803f40d | 288 | uint32_t ms_getTicker(void) |
Helmut Tschemernjak | 67:d3afd803f40d | 289 | { |
Helmut Tschemernjak | 67:d3afd803f40d | 290 | uint32_t us = us_getTicker(); |
Helmut Tschemernjak | 67:d3afd803f40d | 291 | |
Helmut Tschemernjak | 67:d3afd803f40d | 292 | us /= 1000; // to ms |
Helmut Tschemernjak | 67:d3afd803f40d | 293 | return us; |
Helmut Tschemernjak | 67:d3afd803f40d | 294 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 295 | |
Helmut Tschemernjak | 67:d3afd803f40d | 296 | uint32_t us_getTicker(void) |
Helmut Tschemernjak | 67:d3afd803f40d | 297 | { |
Helmut Tschemernjak | 67:d3afd803f40d | 298 | long long ns = ns_getTicker(); |
Helmut Tschemernjak | 67:d3afd803f40d | 299 | |
Helmut Tschemernjak | 67:d3afd803f40d | 300 | ns /= (long long)1000; // to us |
Helmut Tschemernjak | 67:d3afd803f40d | 301 | uint32_t us = ns & 0xffffffff; |
Helmut Tschemernjak | 67:d3afd803f40d | 302 | |
Helmut Tschemernjak | 67:d3afd803f40d | 303 | return us; |
Helmut Tschemernjak | 67:d3afd803f40d | 304 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 305 | |
Helmut Tschemernjak | 67:d3afd803f40d | 306 | |
Helmut Tschemernjak | 67:d3afd803f40d | 307 | uint64_t ns_getTicker(void) |
Helmut Tschemernjak | 66:fbb2da34bd9a | 308 | { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 309 | Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 310 | if (!initTickerDone) { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 311 | initTimer(t); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 312 | initTickerDone = true; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 313 | |
Helmut Tschemernjak | 67:d3afd803f40d | 314 | // set counter top to max 16 bit for testing |
Helmut Tschemernjak | 67:d3afd803f40d | 315 | // t->PER.bit.PER = 0xffff; |
Helmut Tschemernjak | 67:d3afd803f40d | 316 | // while (t->SYNCBUSY.bit.PER == 1); // wait for sync |
Helmut Tschemernjak | 66:fbb2da34bd9a | 317 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 318 | t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC |
Helmut Tschemernjak | 66:fbb2da34bd9a | 319 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 67:d3afd803f40d | 320 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 321 | |
Helmut Tschemernjak | 67:d3afd803f40d | 322 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 323 | * if we are called from the interrupt level, the counter contains |
Helmut Tschemernjak | 67:d3afd803f40d | 324 | * somehow wrong data, therfore we needs to read it twice. |
Helmut Tschemernjak | 67:d3afd803f40d | 325 | * Another option was to add a little wait (loop 500x) |
Helmut Tschemernjak | 67:d3afd803f40d | 326 | * in the TCC_TIMEOUT interrupt handler. |
Helmut Tschemernjak | 67:d3afd803f40d | 327 | */ |
Helmut Tschemernjak | 67:d3afd803f40d | 328 | if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) // check if we are in the interrupt |
Helmut Tschemernjak | 67:d3afd803f40d | 329 | getTimerCount(t); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 330 | |
Helmut Tschemernjak | 67:d3afd803f40d | 331 | uint64_t counter_us = (uint64_t)NS_PER_CLOCK * (uint64_t)getTimerCount(t); |
Helmut Tschemernjak | 67:d3afd803f40d | 332 | uint64_t ns = ticker_ns + counter_us; |
Helmut Tschemernjak | 67:d3afd803f40d | 333 | |
Helmut Tschemernjak | 67:d3afd803f40d | 334 | return ns; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 335 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 336 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 337 | #if USE_TCC_TICKER == 0 |
Helmut Tschemernjak | 66:fbb2da34bd9a | 338 | void TCC0_Handler() |
Helmut Tschemernjak | 66:fbb2da34bd9a | 339 | #elif USE_TCC_TICKER == 1 |
Helmut Tschemernjak | 66:fbb2da34bd9a | 340 | void TCC1_Handler() |
Helmut Tschemernjak | 66:fbb2da34bd9a | 341 | #elif USE_TCC_TICKER == 2 |
Helmut Tschemernjak | 66:fbb2da34bd9a | 342 | void TCC2_Handler() |
Helmut Tschemernjak | 66:fbb2da34bd9a | 343 | #endif |
Helmut Tschemernjak | 66:fbb2da34bd9a | 344 | { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 345 | Tcc *t = TCC_data[USE_TCC_TICKER].tcc_ptr; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 346 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 347 | * Overflow means the timer top exeeded |
Helmut Tschemernjak | 66:fbb2da34bd9a | 348 | */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 349 | if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt |
Helmut Tschemernjak | 66:fbb2da34bd9a | 350 | t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag |
Helmut Tschemernjak | 75:7330dd86cdea | 351 | // ser->println("T_OVF"); |
Helmut Tschemernjak | 67:d3afd803f40d | 352 | |
Helmut Tschemernjak | 67:d3afd803f40d | 353 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 354 | * reading the count once is needed, otherwise |
Helmut Tschemernjak | 67:d3afd803f40d | 355 | * it will not wrap correct. |
Helmut Tschemernjak | 67:d3afd803f40d | 356 | */ |
Helmut Tschemernjak | 67:d3afd803f40d | 357 | getTimerCount(t); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 358 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 359 | int bits = TCC_data[USE_TCC_TICKER].nbits; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 360 | int maxCounts = (uint32_t)(1<<bits); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 361 | |
Helmut Tschemernjak | 67:d3afd803f40d | 362 | ticker_ns += (uint64_t)NS_PER_CLOCK * (uint64_t)maxCounts; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 363 | } |
Helmut Tschemernjak | 66:fbb2da34bd9a | 364 | if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt |
Helmut Tschemernjak | 66:fbb2da34bd9a | 365 | t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag |
Helmut Tschemernjak | 75:7330dd86cdea | 366 | // ser->println("T_MC0"); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 367 | } |
Helmut Tschemernjak | 66:fbb2da34bd9a | 368 | } |
Helmut Tschemernjak | 66:fbb2da34bd9a | 369 | |
Helmut Tschemernjak | 67:d3afd803f40d | 370 | /* ----------------- SUPPORT CODE FOR TCC TIMERS----------------------*/ |
Helmut Tschemernjak | 65:b2d98328fcba | 371 | |
Helmut Tschemernjak | 65:b2d98328fcba | 372 | static bool initTimerDone = false; |
Helmut Tschemernjak | 65:b2d98328fcba | 373 | |
Helmut Tschemernjak | 67:d3afd803f40d | 374 | static void initTimer(Tcc *t) |
Helmut Tschemernjak | 67:d3afd803f40d | 375 | { |
Helmut Tschemernjak | 65:b2d98328fcba | 376 | |
Helmut Tschemernjak | 67:d3afd803f40d | 377 | /* |
Helmut Tschemernjak | 67:d3afd803f40d | 378 | * enable clock for TCC, see gclk.h |
Helmut Tschemernjak | 67:d3afd803f40d | 379 | * GCLK_CLKCTRL_GEN_GCLK0 for 48 Mhz CPU |
Helmut Tschemernjak | 67:d3afd803f40d | 380 | * GCLK_CLKCTRL_GEN_GCLK1 for 32k extern crystal XOSC32K (ifdef CRYSTALLESS) |
Helmut Tschemernjak | 67:d3afd803f40d | 381 | * GCLK_CLKCTRL_GEN_GCLK1 for 32k internal OSC32K |
Helmut Tschemernjak | 67:d3afd803f40d | 382 | * see Arduino: arduino/hardware/samd/1.6.15/cores/arduino/startup.c |
Helmut Tschemernjak | 67:d3afd803f40d | 383 | * Use TCC_CTRLA_PRESCALER_DIV1024 for for 48 Mhz clock |
Helmut Tschemernjak | 67:d3afd803f40d | 384 | * Use TCC_CTRLA_PRESCALER_DIV2 for 32k clock |
Helmut Tschemernjak | 67:d3afd803f40d | 385 | */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 386 | if (t == TCC0 || t == TCC1) { |
Helmut Tschemernjak | 67:d3afd803f40d | 387 | REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_TCC0_TCC1); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 388 | } else if (t == TCC2) { |
Helmut Tschemernjak | 67:d3afd803f40d | 389 | REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK1 | GCLK_CLKCTRL_ID_TCC2_TC3_Val); |
Helmut Tschemernjak | 46:e78a1d0391ac | 390 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 391 | while (GCLK->STATUS.bit.SYNCBUSY == 1); // wait for sync |
Helmut Tschemernjak | 65:b2d98328fcba | 392 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 393 | t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TCC |
Helmut Tschemernjak | 66:fbb2da34bd9a | 394 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 65:b2d98328fcba | 395 | |
Helmut Tschemernjak | 67:d3afd803f40d | 396 | t->CTRLA.reg |= (TCC_CTRLA_PRESCALER_DIV2 | TCC_CTRLA_RUNSTDBY); // Set perscaler |
Helmut Tschemernjak | 65:b2d98328fcba | 397 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 398 | t->WAVE.reg |= TCC_WAVE_WAVEGEN_NFRQ; // Set wave form configuration |
Helmut Tschemernjak | 66:fbb2da34bd9a | 399 | while (t->SYNCBUSY.bit.WAVE == 1); // wait for sync |
Helmut Tschemernjak | 65:b2d98328fcba | 400 | |
Helmut Tschemernjak | 67:d3afd803f40d | 401 | t->PER.bit.PER = 0xffffff; // set counter top to max 24 bit |
Helmut Tschemernjak | 66:fbb2da34bd9a | 402 | while (t->SYNCBUSY.bit.PER == 1); // wait for sync |
Helmut Tschemernjak | 65:b2d98328fcba | 403 | |
Helmut Tschemernjak | 65:b2d98328fcba | 404 | // the compare counter TC->CC[0].reg will be set in the startTimer |
Helmut Tschemernjak | 65:b2d98328fcba | 405 | // after the timeout calculation is known. |
Helmut Tschemernjak | 65:b2d98328fcba | 406 | |
Helmut Tschemernjak | 65:b2d98328fcba | 407 | // Interrupts |
Helmut Tschemernjak | 66:fbb2da34bd9a | 408 | t->INTENSET.reg = 0; // disable all interrupts |
Helmut Tschemernjak | 66:fbb2da34bd9a | 409 | t->INTENSET.bit.OVF = 1; // enable overfollow |
Helmut Tschemernjak | 66:fbb2da34bd9a | 410 | t->INTENSET.bit.MC0 = 1; // enable compare match to CC0 |
Helmut Tschemernjak | 65:b2d98328fcba | 411 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 412 | const struct TCC_config *cp = &TCC_data[0]; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 413 | while (cp->tcc_ptr) { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 414 | if (cp->tcc_ptr == t) { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 415 | NVIC_EnableIRQ(cp->tcc_irq); // Enable InterruptVector |
Helmut Tschemernjak | 66:fbb2da34bd9a | 416 | break; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 417 | } |
Helmut Tschemernjak | 66:fbb2da34bd9a | 418 | cp++; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 419 | } |
Helmut Tschemernjak | 46:e78a1d0391ac | 420 | } |
Helmut Tschemernjak | 46:e78a1d0391ac | 421 | |
Helmut Tschemernjak | 67:d3afd803f40d | 422 | #if 0 |
Helmut Tschemernjak | 67:d3afd803f40d | 423 | // Atmel ASF Code |
Helmut Tschemernjak | 67:d3afd803f40d | 424 | static uint32_t getTimerCount(Tcc *t) |
Helmut Tschemernjak | 67:d3afd803f40d | 425 | { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 426 | uint32_t last_cmd; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 427 | /* Wait last command done */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 428 | do { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 429 | while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 430 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 431 | last_cmd = t->CTRLBSET.reg & TCC_CTRLBSET_CMD_Msk; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 432 | if (TCC_CTRLBSET_CMD_NONE == last_cmd) { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 433 | /* Issue read command and break */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 434 | t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 435 | break; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 436 | } else if (TCC_CTRLBSET_CMD_READSYNC == last_cmd) { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 437 | /* Command have been issued */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 438 | break; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 439 | } |
Helmut Tschemernjak | 66:fbb2da34bd9a | 440 | } while (1); |
Helmut Tschemernjak | 65:b2d98328fcba | 441 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 442 | while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 443 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 444 | return t->COUNT.reg; |
Helmut Tschemernjak | 46:e78a1d0391ac | 445 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 446 | #endif |
Helmut Tschemernjak | 67:d3afd803f40d | 447 | |
Helmut Tschemernjak | 67:d3afd803f40d | 448 | |
Helmut Tschemernjak | 67:d3afd803f40d | 449 | static uint32_t getTimerCount(Tcc *t) |
Helmut Tschemernjak | 67:d3afd803f40d | 450 | { |
Helmut Tschemernjak | 67:d3afd803f40d | 451 | |
Helmut Tschemernjak | 67:d3afd803f40d | 452 | noInterrupts(); |
Helmut Tschemernjak | 67:d3afd803f40d | 453 | |
Helmut Tschemernjak | 67:d3afd803f40d | 454 | while (t->SYNCBUSY.bit.CTRLB); /* Wait for sync */ |
Helmut Tschemernjak | 67:d3afd803f40d | 455 | |
Helmut Tschemernjak | 67:d3afd803f40d | 456 | t->CTRLBSET.bit.CMD = TCC_CTRLBSET_CMD_READSYNC_Val; /* Issue read command and break */ |
Helmut Tschemernjak | 67:d3afd803f40d | 457 | |
Helmut Tschemernjak | 67:d3afd803f40d | 458 | while (t->SYNCBUSY.bit.COUNT); /* Wait for sync */ |
Helmut Tschemernjak | 67:d3afd803f40d | 459 | |
Helmut Tschemernjak | 67:d3afd803f40d | 460 | uint32_t count = t->COUNT.reg; |
Helmut Tschemernjak | 67:d3afd803f40d | 461 | |
Helmut Tschemernjak | 67:d3afd803f40d | 462 | interrupts(); |
Helmut Tschemernjak | 67:d3afd803f40d | 463 | |
Helmut Tschemernjak | 67:d3afd803f40d | 464 | return count; |
Helmut Tschemernjak | 67:d3afd803f40d | 465 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 466 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 467 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 468 | static void stopTimer(Tcc *t) |
Helmut Tschemernjak | 46:e78a1d0391ac | 469 | { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 470 | t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC |
Helmut Tschemernjak | 66:fbb2da34bd9a | 471 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 66:fbb2da34bd9a | 472 | } |
Helmut Tschemernjak | 66:fbb2da34bd9a | 473 | |
Helmut Tschemernjak | 67:d3afd803f40d | 474 | |
Helmut Tschemernjak | 67:d3afd803f40d | 475 | /* ----------------- TIMEOUT TIMER CODE ----------------------*/ |
Helmut Tschemernjak | 67:d3afd803f40d | 476 | |
Helmut Tschemernjak | 67:d3afd803f40d | 477 | static void startTimer(Tcc *t, uint64_t delay_ns) |
Helmut Tschemernjak | 66:fbb2da34bd9a | 478 | { |
Helmut Tschemernjak | 67:d3afd803f40d | 479 | if (!initTimerDone) { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 480 | initTimer(t); // initial setup with stopped timer |
Helmut Tschemernjak | 67:d3afd803f40d | 481 | initTimerDone = true; |
Helmut Tschemernjak | 67:d3afd803f40d | 482 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 483 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 484 | stopTimer(t); // avoid timer interrupts while calculating |
Helmut Tschemernjak | 46:e78a1d0391ac | 485 | |
Helmut Tschemernjak | 65:b2d98328fcba | 486 | /* |
Helmut Tschemernjak | 65:b2d98328fcba | 487 | * every 21333 ns equals one tick (1/(48000000/1024)) |
Helmut Tschemernjak | 65:b2d98328fcba | 488 | * COUNT*DIVIDER*SECS until interrupt |
Helmut Tschemernjak | 65:b2d98328fcba | 489 | * 48 Mhz = (65536*1024)/1.398636s |
Helmut Tschemernjak | 65:b2d98328fcba | 490 | */ |
Helmut Tschemernjak | 67:d3afd803f40d | 491 | uint64_t nclocks = (uint64_t)delay_ns; |
Helmut Tschemernjak | 67:d3afd803f40d | 492 | nclocks /= (uint64_t)NS_PER_CLOCK; |
Helmut Tschemernjak | 65:b2d98328fcba | 493 | int nCounts = nclocks; |
Helmut Tschemernjak | 65:b2d98328fcba | 494 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 495 | int bits = TCC_data[USE_TCC_TIMEOUT].nbits; |
Helmut Tschemernjak | 65:b2d98328fcba | 496 | int maxCounts = (uint32_t)(1<<bits)-1; |
Helmut Tschemernjak | 46:e78a1d0391ac | 497 | |
Helmut Tschemernjak | 65:b2d98328fcba | 498 | if (nCounts > maxCounts) // if count exceeds timer capacity |
Helmut Tschemernjak | 65:b2d98328fcba | 499 | nCounts = maxCounts; // set the largest posible count. |
Helmut Tschemernjak | 66:fbb2da34bd9a | 500 | if (nCounts <= 0) |
Helmut Tschemernjak | 65:b2d98328fcba | 501 | nCounts = 1; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 502 | t->CC[0].bit.CC = nCounts; |
Helmut Tschemernjak | 66:fbb2da34bd9a | 503 | while (t->SYNCBUSY.bit.CC0 == 1); // wait for sync |
Helmut Tschemernjak | 46:e78a1d0391ac | 504 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 505 | t->CTRLA.reg |= TCC_CTRLA_ENABLE ; // Enable TC |
Helmut Tschemernjak | 66:fbb2da34bd9a | 506 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 67:d3afd803f40d | 507 | #if 0 |
Helmut Tschemernjak | 75:7330dd86cdea | 508 | ser->print(ms_getTicker(), DEC); |
Helmut Tschemernjak | 75:7330dd86cdea | 509 | ser->print(" startTimer: nCounts="); |
Helmut Tschemernjak | 75:7330dd86cdea | 510 | ser->println(nCounts, DEC); |
Helmut Tschemernjak | 65:b2d98328fcba | 511 | #endif |
Helmut Tschemernjak | 46:e78a1d0391ac | 512 | } |
Helmut Tschemernjak | 46:e78a1d0391ac | 513 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 514 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 515 | #if USE_TCC_TIMEOUT == 0 |
Helmut Tschemernjak | 65:b2d98328fcba | 516 | void TCC0_Handler() |
Helmut Tschemernjak | 66:fbb2da34bd9a | 517 | #elif USE_TCC_TIMEOUT == 1 |
Helmut Tschemernjak | 65:b2d98328fcba | 518 | void TCC1_Handler() |
Helmut Tschemernjak | 66:fbb2da34bd9a | 519 | #elif USE_TCC_TIMEOUT == 2 |
Helmut Tschemernjak | 65:b2d98328fcba | 520 | void TCC2_Handler() |
Helmut Tschemernjak | 65:b2d98328fcba | 521 | #endif |
Helmut Tschemernjak | 65:b2d98328fcba | 522 | { |
Helmut Tschemernjak | 66:fbb2da34bd9a | 523 | Tcc *t = TCC_data[USE_TCC_TIMEOUT].tcc_ptr; |
Helmut Tschemernjak | 67:d3afd803f40d | 524 | uint64_t nsecs = ns_getTicker(); |
Helmut Tschemernjak | 65:b2d98328fcba | 525 | |
Helmut Tschemernjak | 65:b2d98328fcba | 526 | /* |
Helmut Tschemernjak | 65:b2d98328fcba | 527 | * Overflow means the max timer exeeded, we need restart the timer |
Helmut Tschemernjak | 65:b2d98328fcba | 528 | * Interrupts and |
Helmut Tschemernjak | 65:b2d98328fcba | 529 | */ |
Helmut Tschemernjak | 66:fbb2da34bd9a | 530 | if (t->INTFLAG.bit.OVF == 1) { // A overflow caused the interrupt |
Helmut Tschemernjak | 66:fbb2da34bd9a | 531 | t->INTFLAG.bit.OVF = 1; // writing a one clears the flag ovf flag |
Helmut Tschemernjak | 65:b2d98328fcba | 532 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 533 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 534 | if (t->INTFLAG.bit.MC0 == 1) { // A compare to cc0 caused the interrupt |
Helmut Tschemernjak | 75:7330dd86cdea | 535 | //ser->print("MC0\r\n"); |
Helmut Tschemernjak | 66:fbb2da34bd9a | 536 | t->INTFLAG.bit.MC0 = 1; // writing a one clears the MCO (match capture) flag |
Helmut Tschemernjak | 65:b2d98328fcba | 537 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 538 | |
Helmut Tschemernjak | 66:fbb2da34bd9a | 539 | t->CTRLA.reg &= ~TCC_CTRLA_ENABLE; // Disable TC |
Helmut Tschemernjak | 66:fbb2da34bd9a | 540 | while (t->SYNCBUSY.bit.ENABLE == 1); // wait for sync |
Helmut Tschemernjak | 65:b2d98328fcba | 541 | |
Helmut Tschemernjak | 65:b2d98328fcba | 542 | for (int i = 0; i < MAX_TIMEOUTS-1; i++) { |
Helmut Tschemernjak | 65:b2d98328fcba | 543 | struct TimeoutVector *tvp = &TimeOuts[i]; |
Helmut Tschemernjak | 67:d3afd803f40d | 544 | if (tvp->timer && nsecs >= tvp->timer->_timeout) { |
Helmut Tschemernjak | 65:b2d98328fcba | 545 | Timeout *saveTimer = tvp->timer; |
Helmut Tschemernjak | 65:b2d98328fcba | 546 | tvp->timer = NULL; |
Helmut Tschemernjak | 65:b2d98328fcba | 547 | Timeout::_irq_handler(saveTimer); |
Helmut Tschemernjak | 65:b2d98328fcba | 548 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 549 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 550 | /* |
Helmut Tschemernjak | 65:b2d98328fcba | 551 | * we need to restart the timer for remaining interrupts |
Helmut Tschemernjak | 67:d3afd803f40d | 552 | * Another reason is that we stopped this counter, in case there are |
Helmut Tschemernjak | 67:d3afd803f40d | 553 | * remaining counts, we need to re-schedule the counter. |
Helmut Tschemernjak | 65:b2d98328fcba | 554 | */ |
Helmut Tschemernjak | 67:d3afd803f40d | 555 | Timeout::restart(); |
Helmut Tschemernjak | 65:b2d98328fcba | 556 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 557 | |
Helmut Tschemernjak | 67:d3afd803f40d | 558 | |
Helmut Tschemernjak | 65:b2d98328fcba | 559 | #endif // D21 TCC Timer |
Helmut Tschemernjak | 65:b2d98328fcba | 560 | |
Helmut Tschemernjak | 65:b2d98328fcba | 561 | void |
Helmut Tschemernjak | 65:b2d98328fcba | 562 | Timeout::insert(void) |
Helmut Tschemernjak | 65:b2d98328fcba | 563 | { |
Helmut Tschemernjak | 65:b2d98328fcba | 564 | noInterrupts(); |
Helmut Tschemernjak | 65:b2d98328fcba | 565 | for (int i = 0; i < MAX_TIMEOUTS-1; i++) { |
Helmut Tschemernjak | 65:b2d98328fcba | 566 | struct TimeoutVector *tvp = &TimeOuts[i]; |
Helmut Tschemernjak | 65:b2d98328fcba | 567 | if (tvp->timer == NULL) { |
Helmut Tschemernjak | 65:b2d98328fcba | 568 | tvp->timer = this; |
Helmut Tschemernjak | 65:b2d98328fcba | 569 | break; |
Helmut Tschemernjak | 65:b2d98328fcba | 570 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 571 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 572 | interrupts(); |
Helmut Tschemernjak | 65:b2d98328fcba | 573 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 574 | |
Helmut Tschemernjak | 65:b2d98328fcba | 575 | void |
Helmut Tschemernjak | 65:b2d98328fcba | 576 | Timeout::remove(void) |
Helmut Tschemernjak | 65:b2d98328fcba | 577 | { |
Helmut Tschemernjak | 65:b2d98328fcba | 578 | noInterrupts(); |
Helmut Tschemernjak | 65:b2d98328fcba | 579 | for (int i = 0; i < MAX_TIMEOUTS-1; i++) { |
Helmut Tschemernjak | 65:b2d98328fcba | 580 | struct TimeoutVector *tvp = &TimeOuts[i]; |
Helmut Tschemernjak | 65:b2d98328fcba | 581 | if (tvp->timer == this) { |
Helmut Tschemernjak | 65:b2d98328fcba | 582 | tvp->timer = NULL; |
Helmut Tschemernjak | 65:b2d98328fcba | 583 | break; |
Helmut Tschemernjak | 65:b2d98328fcba | 584 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 585 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 586 | interrupts(); |
Helmut Tschemernjak | 65:b2d98328fcba | 587 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 588 | |
Helmut Tschemernjak | 65:b2d98328fcba | 589 | |
Helmut Tschemernjak | 65:b2d98328fcba | 590 | void |
Helmut Tschemernjak | 67:d3afd803f40d | 591 | Timeout::restart() |
Helmut Tschemernjak | 65:b2d98328fcba | 592 | { |
Helmut Tschemernjak | 67:d3afd803f40d | 593 | Tcc *t = TCC_data[USE_TCC_TIMEOUT].tcc_ptr; |
Helmut Tschemernjak | 67:d3afd803f40d | 594 | uint64_t timeout = ~0; |
Helmut Tschemernjak | 65:b2d98328fcba | 595 | |
Helmut Tschemernjak | 65:b2d98328fcba | 596 | /* |
Helmut Tschemernjak | 65:b2d98328fcba | 597 | * find the lowest timeout value which is our the next timeout |
Helmut Tschemernjak | 65:b2d98328fcba | 598 | * zero means stop the timer. |
Helmut Tschemernjak | 65:b2d98328fcba | 599 | */ |
Helmut Tschemernjak | 65:b2d98328fcba | 600 | noInterrupts(); |
Helmut Tschemernjak | 65:b2d98328fcba | 601 | for (int i = 0; i < MAX_TIMEOUTS-1; i++) { |
Helmut Tschemernjak | 65:b2d98328fcba | 602 | struct TimeoutVector *tvp = &TimeOuts[i]; |
Helmut Tschemernjak | 67:d3afd803f40d | 603 | if (tvp->timer) { |
Helmut Tschemernjak | 67:d3afd803f40d | 604 | if (tvp->timer->_timeout < timeout) { |
Helmut Tschemernjak | 67:d3afd803f40d | 605 | timeout = tvp->timer->_timeout; |
Helmut Tschemernjak | 65:b2d98328fcba | 606 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 607 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 608 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 609 | interrupts(); |
Helmut Tschemernjak | 65:b2d98328fcba | 610 | |
Helmut Tschemernjak | 67:d3afd803f40d | 611 | if (timeout == (uint64_t)~0) { |
Helmut Tschemernjak | 67:d3afd803f40d | 612 | stopTimer(t); |
Helmut Tschemernjak | 65:b2d98328fcba | 613 | return; |
Helmut Tschemernjak | 65:b2d98328fcba | 614 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 615 | |
Helmut Tschemernjak | 67:d3afd803f40d | 616 | uint64_t nsecs = ns_getTicker(); |
Helmut Tschemernjak | 65:b2d98328fcba | 617 | |
Helmut Tschemernjak | 67:d3afd803f40d | 618 | if (timeout > nsecs) { |
Helmut Tschemernjak | 67:d3afd803f40d | 619 | startTimer(t, (uint64_t)timeout - (uint64_t)nsecs); |
Helmut Tschemernjak | 65:b2d98328fcba | 620 | return; |
Helmut Tschemernjak | 65:b2d98328fcba | 621 | } else { |
Helmut Tschemernjak | 67:d3afd803f40d | 622 | startTimer(t, (uint64_t)1); // just one nsec to trigger interrrupt |
Helmut Tschemernjak | 65:b2d98328fcba | 623 | } |
Helmut Tschemernjak | 65:b2d98328fcba | 624 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 625 | |
Helmut Tschemernjak | 67:d3afd803f40d | 626 | /* ----------------- D21 sleep() and deepsleep() code ----------------------*/ |
Helmut Tschemernjak | 67:d3afd803f40d | 627 | |
Helmut Tschemernjak | 67:d3afd803f40d | 628 | void sleep(void) |
Helmut Tschemernjak | 67:d3afd803f40d | 629 | { |
Helmut Tschemernjak | 75:7330dd86cdea | 630 | /* |
Helmut Tschemernjak | 75:7330dd86cdea | 631 | * If we use the native USB port our Serial is SerialUSB |
Helmut Tschemernjak | 75:7330dd86cdea | 632 | * and if the SerialUSB and connected we should |
Helmut Tschemernjak | 75:7330dd86cdea | 633 | * not enter into sleep mode because this kills the Arduino USB emulation |
Helmut Tschemernjak | 75:7330dd86cdea | 634 | */ |
Helmut Tschemernjak | 75:7330dd86cdea | 635 | if (ser && ser == (Stream *)&SerialUSB) { |
Helmut Tschemernjak | 76:79f8ca9c8025 | 636 | __WFI(); |
Helmut Tschemernjak | 76:79f8ca9c8025 | 637 | return; |
Helmut Tschemernjak | 76:79f8ca9c8025 | 638 | // USB->CTRLA.bit.ENABLE = 0; |
Helmut Tschemernjak | 76:79f8ca9c8025 | 639 | // USB->HOST.CTRLA.reg = 0; |
Helmut Tschemernjak | 76:79f8ca9c8025 | 640 | // USB->HOST.CTRLA.bit.ENABLE &= USB_CTRLA_ENABLE; |
Helmut Tschemernjak | 75:7330dd86cdea | 641 | } |
Helmut Tschemernjak | 75:7330dd86cdea | 642 | |
Helmut Tschemernjak | 76:79f8ca9c8025 | 643 | |
Helmut Tschemernjak | 67:d3afd803f40d | 644 | #if 1 // (SAMD20 || SAMD21) |
Helmut Tschemernjak | 67:d3afd803f40d | 645 | /* Errata: Make sure that the Flash does not power all the way down |
Helmut Tschemernjak | 67:d3afd803f40d | 646 | * when in sleep mode. */ |
Helmut Tschemernjak | 67:d3afd803f40d | 647 | NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; |
Helmut Tschemernjak | 67:d3afd803f40d | 648 | #endif |
Helmut Tschemernjak | 70:1d496aae2819 | 649 | uint32_t saved_ms = ms_getTicker(); |
Helmut Tschemernjak | 70:1d496aae2819 | 650 | SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // disbale SysTick |
Helmut Tschemernjak | 70:1d496aae2819 | 651 | |
Helmut Tschemernjak | 67:d3afd803f40d | 652 | SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; // clear deep sleep |
Helmut Tschemernjak | 67:d3afd803f40d | 653 | PM->SLEEP.reg = 2; // SYSTEM_SLEEPMODE_IDLE_2 IDLE 2 sleep mode. |
Helmut Tschemernjak | 67:d3afd803f40d | 654 | |
Helmut Tschemernjak | 67:d3afd803f40d | 655 | __DSB(); // ensures the completion of memory accesses |
Helmut Tschemernjak | 67:d3afd803f40d | 656 | __WFI(); // wait for interrupt |
Helmut Tschemernjak | 70:1d496aae2819 | 657 | |
Helmut Tschemernjak | 70:1d496aae2819 | 658 | int count = ms_getTicker() - saved_ms; |
Helmut Tschemernjak | 70:1d496aae2819 | 659 | if (count > 0) { // update the Arduino Systicks |
Helmut Tschemernjak | 70:1d496aae2819 | 660 | for (int i = 0; i < count; i++) { |
Helmut Tschemernjak | 70:1d496aae2819 | 661 | SysTick_Handler(); |
Helmut Tschemernjak | 70:1d496aae2819 | 662 | } |
Helmut Tschemernjak | 70:1d496aae2819 | 663 | } |
Helmut Tschemernjak | 70:1d496aae2819 | 664 | SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // enable SysTick |
Helmut Tschemernjak | 67:d3afd803f40d | 665 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 666 | |
Helmut Tschemernjak | 67:d3afd803f40d | 667 | void deepsleep(void) |
Helmut Tschemernjak | 67:d3afd803f40d | 668 | { |
Helmut Tschemernjak | 67:d3afd803f40d | 669 | #if 1 // (SAMD20 || SAMD21) |
Helmut Tschemernjak | 67:d3afd803f40d | 670 | /* Errata: Make sure that the Flash does not power all the way down |
Helmut Tschemernjak | 67:d3afd803f40d | 671 | * when in sleep mode. */ |
Helmut Tschemernjak | 67:d3afd803f40d | 672 | NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val; |
Helmut Tschemernjak | 67:d3afd803f40d | 673 | #endif |
Helmut Tschemernjak | 67:d3afd803f40d | 674 | |
Helmut Tschemernjak | 70:1d496aae2819 | 675 | SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // disbale SysTick |
Helmut Tschemernjak | 70:1d496aae2819 | 676 | |
Helmut Tschemernjak | 67:d3afd803f40d | 677 | SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // standby mode |
Helmut Tschemernjak | 70:1d496aae2819 | 678 | |
Helmut Tschemernjak | 67:d3afd803f40d | 679 | __DSB(); // ensures the completion of memory accesses |
Helmut Tschemernjak | 67:d3afd803f40d | 680 | __WFI(); // wait for interrupt |
Helmut Tschemernjak | 70:1d496aae2819 | 681 | |
Helmut Tschemernjak | 70:1d496aae2819 | 682 | SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // enable SysTick |
Helmut Tschemernjak | 67:d3afd803f40d | 683 | } |
Helmut Tschemernjak | 67:d3afd803f40d | 684 | |
Helmut Tschemernjak | 67:d3afd803f40d | 685 | |
Helmut Tschemernjak | 46:e78a1d0391ac | 686 | #endif // ARDUINO |