Commit the AM1805 library

Committer:
marcusC
Date:
Thu Dec 24 05:25:32 2015 +0000
Revision:
0:5e0616a05642
Commit the AM1805 library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcusC 0:5e0616a05642 1 /* AM1805 Sample code: external RTC module is used by host MCU */
marcusC 0:5e0616a05642 2
marcusC 0:5e0616a05642 3 #include "mbed.h"
marcusC 0:5e0616a05642 4 #include "AM1805.h"
marcusC 0:5e0616a05642 5
marcusC 0:5e0616a05642 6 #define I2C_SDA p28
marcusC 0:5e0616a05642 7 #define I2C_SCL p27
marcusC 0:5e0616a05642 8 #define AM1805_I2C_ADDRESS 0xD2
marcusC 0:5e0616a05642 9 /* Register Map */
marcusC 0:5e0616a05642 10 #define AM1805_REG_HUNDREDTHS 0x00
marcusC 0:5e0616a05642 11 #define AM1805_REG_ALM_HUN 0x08
marcusC 0:5e0616a05642 12 #define AM1805_REG_STATUS 0x0F
marcusC 0:5e0616a05642 13 #define AM1805_REG_CTRL1 0x10
marcusC 0:5e0616a05642 14 #define AM1805_REG_CTRL2 0x11
marcusC 0:5e0616a05642 15 #define AM1805_REG_INTMASK 0x12
marcusC 0:5e0616a05642 16 #define AM1805_REG_SLEEPCTRL 0x17
marcusC 0:5e0616a05642 17 #define AM1805_REG_TIM_CTRL 0x18
marcusC 0:5e0616a05642 18 #define AM1805_REG_CDTIM 0x19
marcusC 0:5e0616a05642 19 #define AM1805_REG_TIMINIT 0x1A
marcusC 0:5e0616a05642 20 #define AM1805_REG_WDT 0x1B
marcusC 0:5e0616a05642 21 #define AM1805_REG_OSCSTATUS 0x1D
marcusC 0:5e0616a05642 22 #define AM1805_REG_ID0 0x28
marcusC 0:5e0616a05642 23 #define AM1805_REG_EXTADDR_REG 0x3F
marcusC 0:5e0616a05642 24 /* Register Value */
marcusC 0:5e0616a05642 25 #define AM1805_VALUE_ID0 0x18
marcusC 0:5e0616a05642 26
marcusC 0:5e0616a05642 27 #define AM1805_DEBUG 0
marcusC 0:5e0616a05642 28
marcusC 0:5e0616a05642 29 I2C i2c(I2C_SDA, I2C_SCL);
marcusC 0:5e0616a05642 30 #if AM1805_DEBUG
marcusC 0:5e0616a05642 31 Serial pc(p13,p14);
marcusC 0:5e0616a05642 32 #endif
marcusC 0:5e0616a05642 33
marcusC 0:5e0616a05642 34 static uint8_t get_extension_address(uint8_t address)
marcusC 0:5e0616a05642 35 {
marcusC 0:5e0616a05642 36 uint8_t xadd;
marcusC 0:5e0616a05642 37 char temp;
marcusC 0:5e0616a05642 38
marcusC 0:5e0616a05642 39 am1805_register_read(AM1805_REG_EXTADDR_REG, &temp, 1);
marcusC 0:5e0616a05642 40 temp = temp & 0xC0;
marcusC 0:5e0616a05642 41
marcusC 0:5e0616a05642 42 if (address < 64) { xadd = 0x8; }
marcusC 0:5e0616a05642 43 else if (address < 128) { xadd = 0x9; }
marcusC 0:5e0616a05642 44 else if (address < 192) { xadd = 0xA; }
marcusC 0:5e0616a05642 45 else { xadd = 0xB; }
marcusC 0:5e0616a05642 46 return (xadd | temp);
marcusC 0:5e0616a05642 47 }
marcusC 0:5e0616a05642 48
marcusC 0:5e0616a05642 49 /* Set one or more bits in the selected register, selected by 1's in the mask */
marcusC 0:5e0616a05642 50 static void setreg(char address, uint8_t mask)
marcusC 0:5e0616a05642 51 {
marcusC 0:5e0616a05642 52 char temp;
marcusC 0:5e0616a05642 53
marcusC 0:5e0616a05642 54 am1805_register_read(address, &temp, 1);
marcusC 0:5e0616a05642 55 temp |= mask;
marcusC 0:5e0616a05642 56 am1805_register_write(address, temp);
marcusC 0:5e0616a05642 57 }
marcusC 0:5e0616a05642 58
marcusC 0:5e0616a05642 59 /* Clear one or more bits in the selected register, selected by 1's in the mask */
marcusC 0:5e0616a05642 60 static void clrreg(char address, uint8_t mask)
marcusC 0:5e0616a05642 61 {
marcusC 0:5e0616a05642 62 char temp;
marcusC 0:5e0616a05642 63
marcusC 0:5e0616a05642 64 am1805_register_read(address, &temp, 1);
marcusC 0:5e0616a05642 65 temp &= ~mask;
marcusC 0:5e0616a05642 66 am1805_register_write(address, temp);
marcusC 0:5e0616a05642 67 }
marcusC 0:5e0616a05642 68
marcusC 0:5e0616a05642 69 static bool am1805_verify_product_id(void)
marcusC 0:5e0616a05642 70 {
marcusC 0:5e0616a05642 71 char who_am_i[1];
marcusC 0:5e0616a05642 72 am1805_register_read(AM1805_REG_ID0, &who_am_i[0], 1);
marcusC 0:5e0616a05642 73 #if AM1805_DEBUG
marcusC 0:5e0616a05642 74 pc.printf("ID:%x\r\n",who_am_i[0]);
marcusC 0:5e0616a05642 75 #endif
marcusC 0:5e0616a05642 76 if (who_am_i[0] != AM1805_VALUE_ID0)
marcusC 0:5e0616a05642 77 return false;
marcusC 0:5e0616a05642 78 else
marcusC 0:5e0616a05642 79 return true;
marcusC 0:5e0616a05642 80 }
marcusC 0:5e0616a05642 81
marcusC 0:5e0616a05642 82 bool am1805_init(void)
marcusC 0:5e0616a05642 83 {
marcusC 0:5e0616a05642 84 bool transfer_succeeded = false;
marcusC 0:5e0616a05642 85
marcusC 0:5e0616a05642 86 i2c.frequency(400000);
marcusC 0:5e0616a05642 87
marcusC 0:5e0616a05642 88 /* Read and verify product ID */
marcusC 0:5e0616a05642 89 transfer_succeeded = am1805_verify_product_id();
marcusC 0:5e0616a05642 90
marcusC 0:5e0616a05642 91 return transfer_succeeded;
marcusC 0:5e0616a05642 92 }
marcusC 0:5e0616a05642 93
marcusC 0:5e0616a05642 94 void am1805_register_read(char register_address, char *destination, uint8_t number_of_bytes)
marcusC 0:5e0616a05642 95 {
marcusC 0:5e0616a05642 96 i2c.write(AM1805_I2C_ADDRESS, &register_address, 1, 1);
marcusC 0:5e0616a05642 97 i2c.read(AM1805_I2C_ADDRESS, destination, number_of_bytes);
marcusC 0:5e0616a05642 98 }
marcusC 0:5e0616a05642 99
marcusC 0:5e0616a05642 100 void am1805_register_write(char register_address, uint8_t value)
marcusC 0:5e0616a05642 101 {
marcusC 0:5e0616a05642 102 char tx_data[2];
marcusC 0:5e0616a05642 103
marcusC 0:5e0616a05642 104 tx_data[0] = register_address;
marcusC 0:5e0616a05642 105 tx_data[1] = value;
marcusC 0:5e0616a05642 106 i2c.write(AM1805_I2C_ADDRESS, tx_data, 2);
marcusC 0:5e0616a05642 107
marcusC 0:5e0616a05642 108 }
marcusC 0:5e0616a05642 109
marcusC 0:5e0616a05642 110 void am1805_burst_write(uint8_t *tx_data, uint8_t number_of_bytes)
marcusC 0:5e0616a05642 111 {
marcusC 0:5e0616a05642 112 i2c.write(AM1805_I2C_ADDRESS, (char *)tx_data, number_of_bytes);
marcusC 0:5e0616a05642 113 }
marcusC 0:5e0616a05642 114
marcusC 0:5e0616a05642 115 void am1805_config_input_interrupt(input_interrupt_t index_Interrupt)
marcusC 0:5e0616a05642 116 {
marcusC 0:5e0616a05642 117 switch(index_Interrupt) {
marcusC 0:5e0616a05642 118 case XT1_INTERRUPT:
marcusC 0:5e0616a05642 119 /* Set input interrupt pin EX1T */
marcusC 0:5e0616a05642 120 clrreg(AM1805_REG_STATUS,0x01); // Clear EX1
marcusC 0:5e0616a05642 121 setreg(AM1805_REG_INTMASK,0x01); // Set EX1E
marcusC 0:5e0616a05642 122 break;
marcusC 0:5e0616a05642 123 case XT2_INTERRUPT:
marcusC 0:5e0616a05642 124 /* Set input interrupt pin WDI */
marcusC 0:5e0616a05642 125 clrreg(AM1805_REG_STATUS,0x02); // Clear EX2
marcusC 0:5e0616a05642 126 setreg(AM1805_REG_INTMASK,0x02); // Set EX2E
marcusC 0:5e0616a05642 127 break;
marcusC 0:5e0616a05642 128 default:
marcusC 0:5e0616a05642 129 #if AM1805_DEBUG
marcusC 0:5e0616a05642 130 pc.printf("Wrong Input Interrupt Index\r\n");
marcusC 0:5e0616a05642 131 #endif
marcusC 0:5e0616a05642 132 break;
marcusC 0:5e0616a05642 133 }
marcusC 0:5e0616a05642 134 }
marcusC 0:5e0616a05642 135
marcusC 0:5e0616a05642 136
marcusC 0:5e0616a05642 137 // Read a byte from local RAM
marcusC 0:5e0616a05642 138 uint8_t am1805_read_ram(uint8_t address)
marcusC 0:5e0616a05642 139 {
marcusC 0:5e0616a05642 140 uint8_t xadd;
marcusC 0:5e0616a05642 141 char temp;
marcusC 0:5e0616a05642 142 uint8_t reg_ram = 0;
marcusC 0:5e0616a05642 143
marcusC 0:5e0616a05642 144 xadd = get_extension_address(address); // Calc XADDR value from address
marcusC 0:5e0616a05642 145 am1805_register_write(AM1805_REG_EXTADDR_REG, xadd); // Load the XADDR register
marcusC 0:5e0616a05642 146 reg_ram = (address & 0x3F) | 0x40; // Read the data
marcusC 0:5e0616a05642 147 am1805_register_read(reg_ram, &temp, 1);
marcusC 0:5e0616a05642 148 #if AM1805_DEBUG
marcusC 0:5e0616a05642 149 pc.printf("Read from addr:%x Data:%x\r\n",address,temp);
marcusC 0:5e0616a05642 150 #endif
marcusC 0:5e0616a05642 151 return (uint8_t)temp;
marcusC 0:5e0616a05642 152 }
marcusC 0:5e0616a05642 153
marcusC 0:5e0616a05642 154 // Write a byte to local RAM
marcusC 0:5e0616a05642 155 void am1805_write_ram(uint8_t address, uint8_t data)
marcusC 0:5e0616a05642 156 {
marcusC 0:5e0616a05642 157 uint8_t xadd;
marcusC 0:5e0616a05642 158 uint8_t reg_ram = 0;
marcusC 0:5e0616a05642 159
marcusC 0:5e0616a05642 160 xadd = get_extension_address(address); // Calc XADDR value from address
marcusC 0:5e0616a05642 161 am1805_register_write(AM1805_REG_EXTADDR_REG, xadd); // Load the XADDR register
marcusC 0:5e0616a05642 162 reg_ram = (address & 0x3F) | 0x40;
marcusC 0:5e0616a05642 163 am1805_register_write(reg_ram, data); // Write the data
marcusC 0:5e0616a05642 164 }
marcusC 0:5e0616a05642 165
marcusC 0:5e0616a05642 166 /*
marcusC 0:5e0616a05642 167 * hundredth : 0 ~ 99
marcusC 0:5e0616a05642 168 * second : 0 ~ 59
marcusC 0:5e0616a05642 169 * minute : 0 ~ 59
marcusC 0:5e0616a05642 170 * weekday : 0 ~ 6
marcusC 0:5e0616a05642 171 * month : 1 ~ 12
marcusC 0:5e0616a05642 172 * year : 0 ~ 99
marcusC 0:5e0616a05642 173 * mode : 0 ~ 2
marcusC 0:5e0616a05642 174 */
marcusC 0:5e0616a05642 175 void am1805_set_time(time_reg_struct_t time_regs)
marcusC 0:5e0616a05642 176 {
marcusC 0:5e0616a05642 177 char temp;
marcusC 0:5e0616a05642 178 uint8_t temp_buff[9];
marcusC 0:5e0616a05642 179
marcusC 0:5e0616a05642 180 /*
marcusC 0:5e0616a05642 181 * Determine whether 12 or 24-hour timekeeping mode is being used
marcusC 0:5e0616a05642 182 * and set the 1224 bit appropriately
marcusC 0:5e0616a05642 183 */
marcusC 0:5e0616a05642 184 if (time_regs.mode == 2) // 24-hour day
marcusC 0:5e0616a05642 185 {
marcusC 0:5e0616a05642 186 clrreg(AM1805_REG_CTRL1, 0x40);
marcusC 0:5e0616a05642 187 }
marcusC 0:5e0616a05642 188 else if (time_regs.mode == 1) // 12-hour day PM
marcusC 0:5e0616a05642 189 {
marcusC 0:5e0616a05642 190 time_regs.hour |= 0x20; // Set AM/PM
marcusC 0:5e0616a05642 191 setreg(AM1805_REG_CTRL1, 0x40);
marcusC 0:5e0616a05642 192 }
marcusC 0:5e0616a05642 193 else // 12-hour day AM
marcusC 0:5e0616a05642 194 {
marcusC 0:5e0616a05642 195 setreg(AM1805_REG_CTRL1, 0x40);
marcusC 0:5e0616a05642 196 }
marcusC 0:5e0616a05642 197
marcusC 0:5e0616a05642 198 /* Set the WRTC bit to enable counter writes. */
marcusC 0:5e0616a05642 199 setreg(AM1805_REG_CTRL1, 0x01);
marcusC 0:5e0616a05642 200
marcusC 0:5e0616a05642 201 /* Set the correct century */
marcusC 0:5e0616a05642 202 if (time_regs.century == 0)
marcusC 0:5e0616a05642 203 {
marcusC 0:5e0616a05642 204 clrreg(AM1805_REG_STATUS, 0x80);
marcusC 0:5e0616a05642 205 }
marcusC 0:5e0616a05642 206 else
marcusC 0:5e0616a05642 207 {
marcusC 0:5e0616a05642 208 setreg(AM1805_REG_STATUS, 0x80);
marcusC 0:5e0616a05642 209 }
marcusC 0:5e0616a05642 210
marcusC 0:5e0616a05642 211 /* Write all of the time counters */
marcusC 0:5e0616a05642 212 temp_buff[0] = AM1805_REG_HUNDREDTHS;
marcusC 0:5e0616a05642 213 temp_buff[1] = time_regs.hundredth;
marcusC 0:5e0616a05642 214 temp_buff[2] = time_regs.second;
marcusC 0:5e0616a05642 215 temp_buff[3] = time_regs.minute;
marcusC 0:5e0616a05642 216 temp_buff[4] = time_regs.hour;
marcusC 0:5e0616a05642 217 temp_buff[5] = time_regs.date;
marcusC 0:5e0616a05642 218 temp_buff[6] = time_regs.month;
marcusC 0:5e0616a05642 219 temp_buff[7] = time_regs.year;
marcusC 0:5e0616a05642 220 temp_buff[8] = time_regs.weekday;
marcusC 0:5e0616a05642 221
marcusC 0:5e0616a05642 222 /* Write the values to the AM18XX */
marcusC 0:5e0616a05642 223 am1805_burst_write(temp_buff, sizeof(temp_buff));
marcusC 0:5e0616a05642 224
marcusC 0:5e0616a05642 225 /* Load the final value of the WRTC bit based on the value of protect */
marcusC 0:5e0616a05642 226 am1805_register_read(AM1805_REG_CTRL1, &temp, 1);
marcusC 0:5e0616a05642 227 temp &= 0x7E; // Clear the WRTC bit and the STOP bit
marcusC 0:5e0616a05642 228 //temp_buff[1] |= (0x01 & (~protect)); // Invert the protect bit and update WRTC
marcusC 0:5e0616a05642 229 am1805_register_write(AM1805_REG_CTRL1, temp);
marcusC 0:5e0616a05642 230
marcusC 0:5e0616a05642 231 return;
marcusC 0:5e0616a05642 232 }
marcusC 0:5e0616a05642 233
marcusC 0:5e0616a05642 234 void am1805_get_time(time_reg_struct_t *time_regs)
marcusC 0:5e0616a05642 235 {
marcusC 0:5e0616a05642 236 char temp_buff[8];
marcusC 0:5e0616a05642 237 char time_mode;
marcusC 0:5e0616a05642 238
marcusC 0:5e0616a05642 239 /* Read the counters. */
marcusC 0:5e0616a05642 240 am1805_register_read(AM1805_REG_HUNDREDTHS, temp_buff, 8);
marcusC 0:5e0616a05642 241
marcusC 0:5e0616a05642 242 time_regs->hundredth = temp_buff[0];
marcusC 0:5e0616a05642 243 time_regs->second = temp_buff[1];
marcusC 0:5e0616a05642 244 time_regs->minute = temp_buff[2];
marcusC 0:5e0616a05642 245 time_regs->hour = temp_buff[3];
marcusC 0:5e0616a05642 246 time_regs->date = temp_buff[4];
marcusC 0:5e0616a05642 247 time_regs->month = temp_buff[5];
marcusC 0:5e0616a05642 248 time_regs->year = temp_buff[6];
marcusC 0:5e0616a05642 249 time_regs->weekday = temp_buff[7];
marcusC 0:5e0616a05642 250
marcusC 0:5e0616a05642 251 /* Get the current hours format mode 12:24 */
marcusC 0:5e0616a05642 252 am1805_register_read(AM1805_REG_CTRL1, &time_mode, 1);
marcusC 0:5e0616a05642 253 if ((time_mode & 0x40) == 0)
marcusC 0:5e0616a05642 254 {
marcusC 0:5e0616a05642 255 /* 24-hour mode. */
marcusC 0:5e0616a05642 256 time_regs->mode = 2;
marcusC 0:5e0616a05642 257 time_regs->hour = time_regs->hour & 0x3F; // Get tens:ones
marcusC 0:5e0616a05642 258 }
marcusC 0:5e0616a05642 259 else
marcusC 0:5e0616a05642 260 {
marcusC 0:5e0616a05642 261 /* 12-hour mode. Get PM:AM. */
marcusC 0:5e0616a05642 262 time_regs->mode = (time_regs->hour & 0x20) ? 1 : 0; // PM : AM
marcusC 0:5e0616a05642 263 time_regs->hour &= 0x1F; // Get tens:ones
marcusC 0:5e0616a05642 264 }
marcusC 0:5e0616a05642 265
marcusC 0:5e0616a05642 266 time_regs->hundredth = temp_buff[0];
marcusC 0:5e0616a05642 267 time_regs->second = temp_buff[1];
marcusC 0:5e0616a05642 268 time_regs->minute = temp_buff[2];
marcusC 0:5e0616a05642 269 time_regs->hour = temp_buff[3];
marcusC 0:5e0616a05642 270 time_regs->date = temp_buff[4];
marcusC 0:5e0616a05642 271 time_regs->month = temp_buff[5];
marcusC 0:5e0616a05642 272 time_regs->year = temp_buff[6];
marcusC 0:5e0616a05642 273 time_regs->weekday = temp_buff[7];
marcusC 0:5e0616a05642 274
marcusC 0:5e0616a05642 275 #if AM1805_DEBUG
marcusC 0:5e0616a05642 276 pc.printf("hundredth:%x\r\n",time_regs->hundredth);
marcusC 0:5e0616a05642 277 pc.printf("second:%x\r\n",time_regs->second);
marcusC 0:5e0616a05642 278 pc.printf("minute:%x\r\n",time_regs->minute);
marcusC 0:5e0616a05642 279 pc.printf("hour:%x\r\n",time_regs->hour);
marcusC 0:5e0616a05642 280 pc.printf("date:%x\r\n",time_regs->date);
marcusC 0:5e0616a05642 281 pc.printf("month:%x\r\n",time_regs->month);
marcusC 0:5e0616a05642 282 pc.printf("year:%x\r\n",time_regs->year);
marcusC 0:5e0616a05642 283 pc.printf("weekday:%x\r\n",time_regs->weekday);
marcusC 0:5e0616a05642 284 #endif
marcusC 0:5e0616a05642 285 }
marcusC 0:5e0616a05642 286
marcusC 0:5e0616a05642 287 void am1805_config_alarm(time_reg_struct_t time_regs, alarm_repeat_t repeat, interrupt_mode_t intmode, interrupt_pin_t pin)
marcusC 0:5e0616a05642 288 {
marcusC 0:5e0616a05642 289 char temp;
marcusC 0:5e0616a05642 290 uint8_t temp_buff[9];
marcusC 0:5e0616a05642 291
marcusC 0:5e0616a05642 292 /* Determine whether a 12-hour or a 24-hour time keeping mode is being used */
marcusC 0:5e0616a05642 293 if (time_regs.mode == 1)
marcusC 0:5e0616a05642 294 {
marcusC 0:5e0616a05642 295 /* A 12-hour day PM */
marcusC 0:5e0616a05642 296 time_regs.hour = time_regs.hour | 0x20; // Set AM/PM
marcusC 0:5e0616a05642 297 }
marcusC 0:5e0616a05642 298
marcusC 0:5e0616a05642 299 /* Write all of the time counters */
marcusC 0:5e0616a05642 300 temp_buff[0] = AM1805_REG_ALM_HUN;
marcusC 0:5e0616a05642 301 temp_buff[1] = time_regs.hundredth;
marcusC 0:5e0616a05642 302 temp_buff[2] = time_regs.second;
marcusC 0:5e0616a05642 303 temp_buff[3] = time_regs.minute;
marcusC 0:5e0616a05642 304 temp_buff[4] = time_regs.hour;
marcusC 0:5e0616a05642 305 temp_buff[5] = time_regs.date;
marcusC 0:5e0616a05642 306 temp_buff[6] = time_regs.month;
marcusC 0:5e0616a05642 307 temp_buff[7] = time_regs.weekday;
marcusC 0:5e0616a05642 308
marcusC 0:5e0616a05642 309 clrreg(AM1805_REG_TIM_CTRL, 0x1C); // Clear the RPT field
marcusC 0:5e0616a05642 310 clrreg(AM1805_REG_INTMASK, 0x64); // Clear the AIE bit and IM field
marcusC 0:5e0616a05642 311 clrreg(AM1805_REG_STATUS, 0x04); // Clear the ALM flag
marcusC 0:5e0616a05642 312
marcusC 0:5e0616a05642 313 if (pin == PIN_FOUT_nIRQ)
marcusC 0:5e0616a05642 314 {
marcusC 0:5e0616a05642 315 /* Interrupt on FOUT/nIRQ */
marcusC 0:5e0616a05642 316 am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get the Control2 Register
marcusC 0:5e0616a05642 317 temp = (temp & 0x03); // Extract the OUT1S field
marcusC 0:5e0616a05642 318 if (temp != 0) // Not already selecting nIRQ
marcusC 0:5e0616a05642 319 {
marcusC 0:5e0616a05642 320 setreg(AM1805_REG_CTRL2, 0x03); // Set OUT1S to 3
marcusC 0:5e0616a05642 321 }
marcusC 0:5e0616a05642 322 }
marcusC 0:5e0616a05642 323 if (pin == PIN_PSW_nIRQ2)
marcusC 0:5e0616a05642 324 {
marcusC 0:5e0616a05642 325 /* Interrupt on PSW/nIRQ2 */
marcusC 0:5e0616a05642 326 am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get the Control2 Register
marcusC 0:5e0616a05642 327 temp &= 0x1C; // Extract the OUT2S field
marcusC 0:5e0616a05642 328 if (temp != 0) // Not already selecting nIRQ
marcusC 0:5e0616a05642 329 {
marcusC 0:5e0616a05642 330 clrreg(AM1805_REG_CTRL2, 0x1C); // Clear OUT2S
marcusC 0:5e0616a05642 331 setreg(AM1805_REG_CTRL2, 0x0C); // Set OUT2S to 3
marcusC 0:5e0616a05642 332 }
marcusC 0:5e0616a05642 333 }
marcusC 0:5e0616a05642 334
marcusC 0:5e0616a05642 335 if (repeat == ONCE_PER_10TH_SEC)
marcusC 0:5e0616a05642 336 {
marcusC 0:5e0616a05642 337 /* 10ths interrupt */
marcusC 0:5e0616a05642 338 temp_buff[1] |= 0xF0;
marcusC 0:5e0616a05642 339 repeat = ONCE_PER_SECOND; // Select correct RPT value
marcusC 0:5e0616a05642 340 }
marcusC 0:5e0616a05642 341 if (repeat == ONCE_PER_100TH_SEC)
marcusC 0:5e0616a05642 342 {
marcusC 0:5e0616a05642 343 /* 100ths interrupt */
marcusC 0:5e0616a05642 344 temp_buff[1] = 0xFF;
marcusC 0:5e0616a05642 345 repeat = ONCE_PER_SECOND; // Select correct RPT value
marcusC 0:5e0616a05642 346 }
marcusC 0:5e0616a05642 347 if (repeat != 0) // Don't initiate if repeat = 0
marcusC 0:5e0616a05642 348 {
marcusC 0:5e0616a05642 349 temp = (repeat << 2); // Set the RPT field to the value of repeat
marcusC 0:5e0616a05642 350 setreg(AM1805_REG_TIM_CTRL, temp); // Was previously cleared
marcusC 0:5e0616a05642 351 setreg(AM1805_REG_INTMASK, (intmode << 5)); // Set the alarm interrupt mode
marcusC 0:5e0616a05642 352 setreg(AM1805_REG_INTMASK, 0x60); // Set the alarm interrupt mode
marcusC 0:5e0616a05642 353 am1805_burst_write(temp_buff, 8); // Execute the burst write
marcusC 0:5e0616a05642 354 setreg(AM1805_REG_INTMASK, 0x04); // Set the AIE bit
marcusC 0:5e0616a05642 355 }
marcusC 0:5e0616a05642 356 else
marcusC 0:5e0616a05642 357 setreg(AM1805_REG_INTMASK, 0x60); // Set IM field to 0x3 (reset value) to minimize current draw
marcusC 0:5e0616a05642 358
marcusC 0:5e0616a05642 359 return;
marcusC 0:5e0616a05642 360 }
marcusC 0:5e0616a05642 361
marcusC 0:5e0616a05642 362 void am1805_config_countdown_timer(count_down_range_t range, int32_t period, count_down_repeat_t repeat, interrupt_pin_t pin)
marcusC 0:5e0616a05642 363 {
marcusC 0:5e0616a05642 364 uint8_t tm;
marcusC 0:5e0616a05642 365 uint8_t trpt;
marcusC 0:5e0616a05642 366 uint8_t tfs;
marcusC 0:5e0616a05642 367 uint8_t te;
marcusC 0:5e0616a05642 368 char temp;
marcusC 0:5e0616a05642 369 char tctrl;
marcusC 0:5e0616a05642 370 int32_t timer;
marcusC 0:5e0616a05642 371 char oscmode;
marcusC 0:5e0616a05642 372
marcusC 0:5e0616a05642 373 /* 0 = XT, 1 = RC */
marcusC 0:5e0616a05642 374 am1805_register_read(AM1805_REG_OSCSTATUS, &oscmode, 1);
marcusC 0:5e0616a05642 375 oscmode = (oscmode & 0x10) ? 1 : 0;
marcusC 0:5e0616a05642 376
marcusC 0:5e0616a05642 377 /* disable count down timer */
marcusC 0:5e0616a05642 378 if (pin == INTERNAL_FLAG)
marcusC 0:5e0616a05642 379 {
marcusC 0:5e0616a05642 380 te = 0;
marcusC 0:5e0616a05642 381 }
marcusC 0:5e0616a05642 382 else
marcusC 0:5e0616a05642 383 {
marcusC 0:5e0616a05642 384 te = 1;
marcusC 0:5e0616a05642 385 if (repeat == SINGLE_LEVEL_INTERRUPT)
marcusC 0:5e0616a05642 386 {
marcusC 0:5e0616a05642 387 /* Level interrupt */
marcusC 0:5e0616a05642 388 tm = 1; // Level
marcusC 0:5e0616a05642 389 trpt = 0; // No repeat
marcusC 0:5e0616a05642 390 if (range == PERIOD_US)
marcusC 0:5e0616a05642 391 {
marcusC 0:5e0616a05642 392 /* Microseconds */
marcusC 0:5e0616a05642 393 if (oscmode == 0)
marcusC 0:5e0616a05642 394 {
marcusC 0:5e0616a05642 395 /* XT Mode */
marcusC 0:5e0616a05642 396 if (period <= 62500) // Use 4K Hz
marcusC 0:5e0616a05642 397 {
marcusC 0:5e0616a05642 398 tfs = 0;
marcusC 0:5e0616a05642 399 timer = (period * 4096);
marcusC 0:5e0616a05642 400 timer = timer / 1000000;
marcusC 0:5e0616a05642 401 timer = timer - 1;
marcusC 0:5e0616a05642 402 }
marcusC 0:5e0616a05642 403 else if (period <= 16384000) // Use 64 Hz
marcusC 0:5e0616a05642 404 {
marcusC 0:5e0616a05642 405 tfs = 1;
marcusC 0:5e0616a05642 406 timer = (period * 64);
marcusC 0:5e0616a05642 407 timer /= 1000000;
marcusC 0:5e0616a05642 408 timer = timer - 1;
marcusC 0:5e0616a05642 409 }
marcusC 0:5e0616a05642 410 else // Use 1 Hz
marcusC 0:5e0616a05642 411 {
marcusC 0:5e0616a05642 412 tfs = 2;
marcusC 0:5e0616a05642 413 timer = period / 1000000;
marcusC 0:5e0616a05642 414 timer = timer - 1;
marcusC 0:5e0616a05642 415 }
marcusC 0:5e0616a05642 416 }
marcusC 0:5e0616a05642 417 else
marcusC 0:5e0616a05642 418 {
marcusC 0:5e0616a05642 419 /* RC Mode */
marcusC 0:5e0616a05642 420 if (period <= 2000000) { // Use 128 Hz
marcusC 0:5e0616a05642 421 tfs = 0;
marcusC 0:5e0616a05642 422 timer = (period * 128);
marcusC 0:5e0616a05642 423 timer /= 1000000;
marcusC 0:5e0616a05642 424 timer = timer - 1;
marcusC 0:5e0616a05642 425 }
marcusC 0:5e0616a05642 426 else if (period <= 4000000) { // Use 64 Hz
marcusC 0:5e0616a05642 427 tfs = 1;
marcusC 0:5e0616a05642 428 timer = (period * 64);
marcusC 0:5e0616a05642 429 timer /= 1000000;
marcusC 0:5e0616a05642 430 timer = timer - 1;
marcusC 0:5e0616a05642 431 }
marcusC 0:5e0616a05642 432 else { // Use 1 Hz
marcusC 0:5e0616a05642 433 tfs = 2;
marcusC 0:5e0616a05642 434 timer = period / 1000000;
marcusC 0:5e0616a05642 435 timer = timer - 1;
marcusC 0:5e0616a05642 436 }
marcusC 0:5e0616a05642 437 }
marcusC 0:5e0616a05642 438 }
marcusC 0:5e0616a05642 439 else
marcusC 0:5e0616a05642 440 {
marcusC 0:5e0616a05642 441 /* Seconds */
marcusC 0:5e0616a05642 442 if (period <= 256)
marcusC 0:5e0616a05642 443 {
marcusC 0:5e0616a05642 444 /* Use 1 Hz */
marcusC 0:5e0616a05642 445 tfs = 2;
marcusC 0:5e0616a05642 446 timer = period - 1;
marcusC 0:5e0616a05642 447 }
marcusC 0:5e0616a05642 448 else
marcusC 0:5e0616a05642 449 {
marcusC 0:5e0616a05642 450 /* Use 1/60 Hz */
marcusC 0:5e0616a05642 451 tfs = 3;
marcusC 0:5e0616a05642 452 timer = period / 60;
marcusC 0:5e0616a05642 453 timer = timer - 1;
marcusC 0:5e0616a05642 454 }
marcusC 0:5e0616a05642 455 }
marcusC 0:5e0616a05642 456 }
marcusC 0:5e0616a05642 457 else
marcusC 0:5e0616a05642 458 {
marcusC 0:5e0616a05642 459 /* Pulse interrupts */
marcusC 0:5e0616a05642 460 tm = 0; // Pulse
marcusC 0:5e0616a05642 461 trpt = repeat & 0x01; // Set up repeat
marcusC 0:5e0616a05642 462 if (repeat < REPEAT_PLUSE_1_128_SEC)
marcusC 0:5e0616a05642 463 {
marcusC 0:5e0616a05642 464 tfs = 0;
marcusC 0:5e0616a05642 465 if (oscmode == 0)
marcusC 0:5e0616a05642 466 {
marcusC 0:5e0616a05642 467 timer = (period * 4096);
marcusC 0:5e0616a05642 468 timer /= 1000000;
marcusC 0:5e0616a05642 469 timer = timer - 1;
marcusC 0:5e0616a05642 470 }
marcusC 0:5e0616a05642 471 else
marcusC 0:5e0616a05642 472 {
marcusC 0:5e0616a05642 473 timer = (period * 128);
marcusC 0:5e0616a05642 474 timer /= 1000000;
marcusC 0:5e0616a05642 475 timer = timer - 1;
marcusC 0:5e0616a05642 476 }
marcusC 0:5e0616a05642 477 }
marcusC 0:5e0616a05642 478 else if (repeat < REPEAT_PLUSE_1_64_SEC)
marcusC 0:5e0616a05642 479 {
marcusC 0:5e0616a05642 480 tfs = 1;
marcusC 0:5e0616a05642 481 timer = (period * 128);
marcusC 0:5e0616a05642 482 timer /= 1000000;
marcusC 0:5e0616a05642 483 timer = timer - 1;
marcusC 0:5e0616a05642 484 }
marcusC 0:5e0616a05642 485 else if (period <= 256)
marcusC 0:5e0616a05642 486 {
marcusC 0:5e0616a05642 487 /* Use 1 Hz */
marcusC 0:5e0616a05642 488 tfs = 2;
marcusC 0:5e0616a05642 489 timer = period - 1;
marcusC 0:5e0616a05642 490 }
marcusC 0:5e0616a05642 491 else
marcusC 0:5e0616a05642 492 {
marcusC 0:5e0616a05642 493 /* Use 1/60 Hz */
marcusC 0:5e0616a05642 494 tfs = 3;
marcusC 0:5e0616a05642 495 timer = period / 60;
marcusC 0:5e0616a05642 496 timer = timer - 1;
marcusC 0:5e0616a05642 497 }
marcusC 0:5e0616a05642 498 }
marcusC 0:5e0616a05642 499 }
marcusC 0:5e0616a05642 500
marcusC 0:5e0616a05642 501 am1805_register_read(AM1805_REG_TIM_CTRL, &tctrl, 1); // Get TCTRL, keep RPT, clear TE
marcusC 0:5e0616a05642 502 tctrl = tctrl & 0x1C;
marcusC 0:5e0616a05642 503 am1805_register_write(AM1805_REG_TIM_CTRL, tctrl);
marcusC 0:5e0616a05642 504
marcusC 0:5e0616a05642 505 tctrl = tctrl | (te * 0x80) | (tm * 0x40) | (trpt * 0x20) | tfs; // Merge the fields
marcusC 0:5e0616a05642 506
marcusC 0:5e0616a05642 507 if (pin == PIN_FOUT_nIRQ) // generate nTIRQ interrupt on FOUT/nIRQ (asserted low)
marcusC 0:5e0616a05642 508 {
marcusC 0:5e0616a05642 509 clrreg(AM1805_REG_CTRL2, 0x3); // Clear OUT1S
marcusC 0:5e0616a05642 510 }
marcusC 0:5e0616a05642 511 if (pin == PIN_PSW_nIRQ2) // generate nTIRQ interrupt on PSW/nIRQ2 (asserted low)
marcusC 0:5e0616a05642 512 {
marcusC 0:5e0616a05642 513 am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get OUT2S
marcusC 0:5e0616a05642 514 if ((temp & 0x1C) != 0)
marcusC 0:5e0616a05642 515 {
marcusC 0:5e0616a05642 516 temp = (temp & 0xE3) | 0x14; // If OUT2S != 0, set OUT2S to 5
marcusC 0:5e0616a05642 517 }
marcusC 0:5e0616a05642 518 am1805_register_write(AM1805_REG_CTRL2, temp); // Write back
marcusC 0:5e0616a05642 519 }
marcusC 0:5e0616a05642 520 if (pin != 0)
marcusC 0:5e0616a05642 521 {
marcusC 0:5e0616a05642 522 clrreg(AM1805_REG_STATUS,0x08); // Clear TIM
marcusC 0:5e0616a05642 523 setreg(AM1805_REG_INTMASK,0x08); // Set TIE
marcusC 0:5e0616a05642 524 am1805_register_write(AM1805_REG_CDTIM, timer); // Initialize the timer
marcusC 0:5e0616a05642 525 am1805_register_write(AM1805_REG_TIMINIT, timer); // Initialize the timer repeat
marcusC 0:5e0616a05642 526 am1805_register_write(AM1805_REG_TIM_CTRL, tctrl); // Start the timer
marcusC 0:5e0616a05642 527 }
marcusC 0:5e0616a05642 528
marcusC 0:5e0616a05642 529 return ;
marcusC 0:5e0616a05642 530 }
marcusC 0:5e0616a05642 531
marcusC 0:5e0616a05642 532 /** Parameter:
marcusC 0:5e0616a05642 533 * timeout - minimum timeout period in 7.8 ms periods (0 to 7)
marcusC 0:5e0616a05642 534 * mode - sleep mode (nRST modes not available in AM08xx)
marcusC 0:5e0616a05642 535 * 0 => nRST is pulled low in sleep mode
marcusC 0:5e0616a05642 536 * 1 => PSW/nIRQ2 is pulled high on a sleep
marcusC 0:5e0616a05642 537 * 2 => nRST pulled low and PSW/nIRQ2 pulled high on sleep
marcusC 0:5e0616a05642 538 * error ?returned value of the attempted sleep command
marcusC 0:5e0616a05642 539 * 0 => sleep request accepted, sleep mode will be initiated in timeout seconds
marcusC 0:5e0616a05642 540 * 1 => illegal input values
marcusC 0:5e0616a05642 541 * 2 => sleep request declined, interrupt is currently pending
marcusC 0:5e0616a05642 542 * 3 => sleep request declined, no sleep trigger interrupt enabled
marcusC 0:5e0616a05642 543 **/
marcusC 0:5e0616a05642 544 void am1805_set_sleep(uint8_t timeout, uint8_t mode)
marcusC 0:5e0616a05642 545 {
marcusC 0:5e0616a05642 546 uint8_t slres = 0;
marcusC 0:5e0616a05642 547 char temp = 0;
marcusC 0:5e0616a05642 548
marcusC 0:5e0616a05642 549 #if AM1805_DEBUG
marcusC 0:5e0616a05642 550 am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get SLST bit (temp & 0x08)
marcusC 0:5e0616a05642 551
marcusC 0:5e0616a05642 552 if ( ( temp & 0x08 ) == 0)
marcusC 0:5e0616a05642 553 {
marcusC 0:5e0616a05642 554 pc.printf("Previous Sleep Failed\r\n");
marcusC 0:5e0616a05642 555 } else {
marcusC 0:5e0616a05642 556 pc.printf("Previous Sleep Successful\r\n");
marcusC 0:5e0616a05642 557 }
marcusC 0:5e0616a05642 558 clrreg(AM1805_REG_CTRL2,0x08); // Clear SLST
marcusC 0:5e0616a05642 559
marcusC 0:5e0616a05642 560 am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get SLST bit (temp & 0x08)
marcusC 0:5e0616a05642 561
marcusC 0:5e0616a05642 562 if ( ( temp & 0x08 ) == 0)
marcusC 0:5e0616a05642 563 {
marcusC 0:5e0616a05642 564 pc.printf("Clear Succ\r\n");
marcusC 0:5e0616a05642 565 } else {
marcusC 0:5e0616a05642 566 pc.printf("Clear Fail\r\n");
marcusC 0:5e0616a05642 567 }
marcusC 0:5e0616a05642 568 clrreg(AM1805_REG_CTRL2,0x08); // Clear SLST
marcusC 0:5e0616a05642 569 #endif
marcusC 0:5e0616a05642 570
marcusC 0:5e0616a05642 571 if (mode > 0)
marcusC 0:5e0616a05642 572 {
marcusC 0:5e0616a05642 573 /* Sleep to PSW/nIRQ2 */
marcusC 0:5e0616a05642 574 am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Read OUT2S
marcusC 0:5e0616a05642 575 temp = (temp & 0xE3) | 0x18; // MUST NOT WRITE OUT2S WITH 000
marcusC 0:5e0616a05642 576 am1805_register_write(AM1805_REG_CTRL2, temp); // Write value to OUT2S
marcusC 0:5e0616a05642 577 slres = 0;
marcusC 0:5e0616a05642 578 }
marcusC 0:5e0616a05642 579
marcusC 0:5e0616a05642 580 temp = timeout | (slres << 6) | 0x80; // Assemble SLEEP register value
marcusC 0:5e0616a05642 581 am1805_register_write(AM1805_REG_SLEEPCTRL, temp); // Write to the register
marcusC 0:5e0616a05642 582
marcusC 0:5e0616a05642 583 #if AM1805_DEBUG
marcusC 0:5e0616a05642 584 /* Determine if SLEEP was accepted */
marcusC 0:5e0616a05642 585 am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get SLP bit (temp & 0x80)
marcusC 0:5e0616a05642 586
marcusC 0:5e0616a05642 587 if ( ( temp & 0x80 ) == 0)
marcusC 0:5e0616a05642 588 {
marcusC 0:5e0616a05642 589 char reg_wdi_value = 0;
marcusC 0:5e0616a05642 590 /* SLEEP did not happen - determine why and return reason. */
marcusC 0:5e0616a05642 591 am1805_register_read(AM1805_REG_INTMASK, &temp, 1); // Get status register interrupt enables
marcusC 0:5e0616a05642 592 am1805_register_read(AM1805_REG_WDT, &reg_wdi_value, 1); // Get WDT register
marcusC 0:5e0616a05642 593 if ((( temp & 0x0F ) == 0) & (((reg_wdi_value & 0x7C) == 0) || ((reg_wdi_value & 0x80) == 0x80)))
marcusC 0:5e0616a05642 594 {
marcusC 0:5e0616a05642 595 pc.printf("No trigger interrupts enabled\r\n");
marcusC 0:5e0616a05642 596 }
marcusC 0:5e0616a05642 597 else
marcusC 0:5e0616a05642 598 {
marcusC 0:5e0616a05642 599 pc.printf("Interrupt pending\r\n");
marcusC 0:5e0616a05642 600 }
marcusC 0:5e0616a05642 601 }
marcusC 0:5e0616a05642 602 else
marcusC 0:5e0616a05642 603 {
marcusC 0:5e0616a05642 604 pc.printf("SLEEP request successful\r\n");
marcusC 0:5e0616a05642 605 }
marcusC 0:5e0616a05642 606 #endif
marcusC 0:5e0616a05642 607 }