Demo the function of RTC module AM1805

Dependencies:   mbed-dev

Fork of I2C_HelloWorld_Mbed by mbed official

Committer:
marcusC
Date:
Thu Dec 24 05:15:42 2015 +0000
Revision:
2:16b8f527b5c7
Parent:
1:c45df8c46fa8
Remove the redundant log

Who changed what in which revision?

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