Commit the AM1805 library
Revision 0:5e0616a05642, committed 2015-12-24
- Comitter:
- marcusC
- Date:
- Thu Dec 24 05:25:32 2015 +0000
- Commit message:
- Commit the AM1805 library
Changed in this revision
AM1805.cpp | Show annotated file Show diff for this revision Revisions of this file |
AM1805.h | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 5e0616a05642 AM1805.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AM1805.cpp Thu Dec 24 05:25:32 2015 +0000 @@ -0,0 +1,607 @@ +/* AM1805 Sample code: external RTC module is used by host MCU */ + +#include "mbed.h" +#include "AM1805.h" + +#define I2C_SDA p28 +#define I2C_SCL p27 +#define AM1805_I2C_ADDRESS 0xD2 +/* Register Map */ +#define AM1805_REG_HUNDREDTHS 0x00 +#define AM1805_REG_ALM_HUN 0x08 +#define AM1805_REG_STATUS 0x0F +#define AM1805_REG_CTRL1 0x10 +#define AM1805_REG_CTRL2 0x11 +#define AM1805_REG_INTMASK 0x12 +#define AM1805_REG_SLEEPCTRL 0x17 +#define AM1805_REG_TIM_CTRL 0x18 +#define AM1805_REG_CDTIM 0x19 +#define AM1805_REG_TIMINIT 0x1A +#define AM1805_REG_WDT 0x1B +#define AM1805_REG_OSCSTATUS 0x1D +#define AM1805_REG_ID0 0x28 +#define AM1805_REG_EXTADDR_REG 0x3F +/* Register Value */ +#define AM1805_VALUE_ID0 0x18 + +#define AM1805_DEBUG 0 + +I2C i2c(I2C_SDA, I2C_SCL); +#if AM1805_DEBUG +Serial pc(p13,p14); +#endif + +static uint8_t get_extension_address(uint8_t address) +{ + uint8_t xadd; + char temp; + + am1805_register_read(AM1805_REG_EXTADDR_REG, &temp, 1); + temp = temp & 0xC0; + + if (address < 64) { xadd = 0x8; } + else if (address < 128) { xadd = 0x9; } + else if (address < 192) { xadd = 0xA; } + else { xadd = 0xB; } + return (xadd | temp); +} + +/* Set one or more bits in the selected register, selected by 1's in the mask */ +static void setreg(char address, uint8_t mask) +{ + char temp; + + am1805_register_read(address, &temp, 1); + temp |= mask; + am1805_register_write(address, temp); +} + +/* Clear one or more bits in the selected register, selected by 1's in the mask */ +static void clrreg(char address, uint8_t mask) +{ + char temp; + + am1805_register_read(address, &temp, 1); + temp &= ~mask; + am1805_register_write(address, temp); +} + +static bool am1805_verify_product_id(void) +{ + char who_am_i[1]; + am1805_register_read(AM1805_REG_ID0, &who_am_i[0], 1); +#if AM1805_DEBUG + pc.printf("ID:%x\r\n",who_am_i[0]); +#endif + if (who_am_i[0] != AM1805_VALUE_ID0) + return false; + else + return true; +} + +bool am1805_init(void) +{ + bool transfer_succeeded = false; + + i2c.frequency(400000); + + /* Read and verify product ID */ + transfer_succeeded = am1805_verify_product_id(); + + return transfer_succeeded; +} + +void am1805_register_read(char register_address, char *destination, uint8_t number_of_bytes) +{ + i2c.write(AM1805_I2C_ADDRESS, ®ister_address, 1, 1); + i2c.read(AM1805_I2C_ADDRESS, destination, number_of_bytes); +} + +void am1805_register_write(char register_address, uint8_t value) +{ + char tx_data[2]; + + tx_data[0] = register_address; + tx_data[1] = value; + i2c.write(AM1805_I2C_ADDRESS, tx_data, 2); + +} + +void am1805_burst_write(uint8_t *tx_data, uint8_t number_of_bytes) +{ + i2c.write(AM1805_I2C_ADDRESS, (char *)tx_data, number_of_bytes); +} + +void am1805_config_input_interrupt(input_interrupt_t index_Interrupt) +{ + switch(index_Interrupt) { + case XT1_INTERRUPT: + /* Set input interrupt pin EX1T */ + clrreg(AM1805_REG_STATUS,0x01); // Clear EX1 + setreg(AM1805_REG_INTMASK,0x01); // Set EX1E + break; + case XT2_INTERRUPT: + /* Set input interrupt pin WDI */ + clrreg(AM1805_REG_STATUS,0x02); // Clear EX2 + setreg(AM1805_REG_INTMASK,0x02); // Set EX2E + break; + default: +#if AM1805_DEBUG + pc.printf("Wrong Input Interrupt Index\r\n"); +#endif + break; + } +} + + +// Read a byte from local RAM +uint8_t am1805_read_ram(uint8_t address) +{ + uint8_t xadd; + char temp; + uint8_t reg_ram = 0; + + xadd = get_extension_address(address); // Calc XADDR value from address + am1805_register_write(AM1805_REG_EXTADDR_REG, xadd); // Load the XADDR register + reg_ram = (address & 0x3F) | 0x40; // Read the data + am1805_register_read(reg_ram, &temp, 1); +#if AM1805_DEBUG + pc.printf("Read from addr:%x Data:%x\r\n",address,temp); +#endif + return (uint8_t)temp; +} + +// Write a byte to local RAM +void am1805_write_ram(uint8_t address, uint8_t data) +{ + uint8_t xadd; + uint8_t reg_ram = 0; + + xadd = get_extension_address(address); // Calc XADDR value from address + am1805_register_write(AM1805_REG_EXTADDR_REG, xadd); // Load the XADDR register + reg_ram = (address & 0x3F) | 0x40; + am1805_register_write(reg_ram, data); // Write the data +} + +/* + * hundredth : 0 ~ 99 + * second : 0 ~ 59 + * minute : 0 ~ 59 + * weekday : 0 ~ 6 + * month : 1 ~ 12 + * year : 0 ~ 99 + * mode : 0 ~ 2 + */ +void am1805_set_time(time_reg_struct_t time_regs) +{ + char temp; + uint8_t temp_buff[9]; + + /* + * Determine whether 12 or 24-hour timekeeping mode is being used + * and set the 1224 bit appropriately + */ + if (time_regs.mode == 2) // 24-hour day + { + clrreg(AM1805_REG_CTRL1, 0x40); + } + else if (time_regs.mode == 1) // 12-hour day PM + { + time_regs.hour |= 0x20; // Set AM/PM + setreg(AM1805_REG_CTRL1, 0x40); + } + else // 12-hour day AM + { + setreg(AM1805_REG_CTRL1, 0x40); + } + + /* Set the WRTC bit to enable counter writes. */ + setreg(AM1805_REG_CTRL1, 0x01); + + /* Set the correct century */ + if (time_regs.century == 0) + { + clrreg(AM1805_REG_STATUS, 0x80); + } + else + { + setreg(AM1805_REG_STATUS, 0x80); + } + + /* Write all of the time counters */ + temp_buff[0] = AM1805_REG_HUNDREDTHS; + temp_buff[1] = time_regs.hundredth; + temp_buff[2] = time_regs.second; + temp_buff[3] = time_regs.minute; + temp_buff[4] = time_regs.hour; + temp_buff[5] = time_regs.date; + temp_buff[6] = time_regs.month; + temp_buff[7] = time_regs.year; + temp_buff[8] = time_regs.weekday; + + /* Write the values to the AM18XX */ + am1805_burst_write(temp_buff, sizeof(temp_buff)); + + /* Load the final value of the WRTC bit based on the value of protect */ + am1805_register_read(AM1805_REG_CTRL1, &temp, 1); + temp &= 0x7E; // Clear the WRTC bit and the STOP bit + //temp_buff[1] |= (0x01 & (~protect)); // Invert the protect bit and update WRTC + am1805_register_write(AM1805_REG_CTRL1, temp); + + return; +} + +void am1805_get_time(time_reg_struct_t *time_regs) +{ + char temp_buff[8]; + char time_mode; + + /* Read the counters. */ + am1805_register_read(AM1805_REG_HUNDREDTHS, temp_buff, 8); + + time_regs->hundredth = temp_buff[0]; + time_regs->second = temp_buff[1]; + time_regs->minute = temp_buff[2]; + time_regs->hour = temp_buff[3]; + time_regs->date = temp_buff[4]; + time_regs->month = temp_buff[5]; + time_regs->year = temp_buff[6]; + time_regs->weekday = temp_buff[7]; + + /* Get the current hours format mode 12:24 */ + am1805_register_read(AM1805_REG_CTRL1, &time_mode, 1); + if ((time_mode & 0x40) == 0) + { + /* 24-hour mode. */ + time_regs->mode = 2; + time_regs->hour = time_regs->hour & 0x3F; // Get tens:ones + } + else + { + /* 12-hour mode. Get PM:AM. */ + time_regs->mode = (time_regs->hour & 0x20) ? 1 : 0; // PM : AM + time_regs->hour &= 0x1F; // Get tens:ones + } + + time_regs->hundredth = temp_buff[0]; + time_regs->second = temp_buff[1]; + time_regs->minute = temp_buff[2]; + time_regs->hour = temp_buff[3]; + time_regs->date = temp_buff[4]; + time_regs->month = temp_buff[5]; + time_regs->year = temp_buff[6]; + time_regs->weekday = temp_buff[7]; + +#if AM1805_DEBUG + pc.printf("hundredth:%x\r\n",time_regs->hundredth); + pc.printf("second:%x\r\n",time_regs->second); + pc.printf("minute:%x\r\n",time_regs->minute); + pc.printf("hour:%x\r\n",time_regs->hour); + pc.printf("date:%x\r\n",time_regs->date); + pc.printf("month:%x\r\n",time_regs->month); + pc.printf("year:%x\r\n",time_regs->year); + pc.printf("weekday:%x\r\n",time_regs->weekday); +#endif +} + +void am1805_config_alarm(time_reg_struct_t time_regs, alarm_repeat_t repeat, interrupt_mode_t intmode, interrupt_pin_t pin) +{ + char temp; + uint8_t temp_buff[9]; + + /* Determine whether a 12-hour or a 24-hour time keeping mode is being used */ + if (time_regs.mode == 1) + { + /* A 12-hour day PM */ + time_regs.hour = time_regs.hour | 0x20; // Set AM/PM + } + + /* Write all of the time counters */ + temp_buff[0] = AM1805_REG_ALM_HUN; + temp_buff[1] = time_regs.hundredth; + temp_buff[2] = time_regs.second; + temp_buff[3] = time_regs.minute; + temp_buff[4] = time_regs.hour; + temp_buff[5] = time_regs.date; + temp_buff[6] = time_regs.month; + temp_buff[7] = time_regs.weekday; + + clrreg(AM1805_REG_TIM_CTRL, 0x1C); // Clear the RPT field + clrreg(AM1805_REG_INTMASK, 0x64); // Clear the AIE bit and IM field + clrreg(AM1805_REG_STATUS, 0x04); // Clear the ALM flag + + if (pin == PIN_FOUT_nIRQ) + { + /* Interrupt on FOUT/nIRQ */ + am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get the Control2 Register + temp = (temp & 0x03); // Extract the OUT1S field + if (temp != 0) // Not already selecting nIRQ + { + setreg(AM1805_REG_CTRL2, 0x03); // Set OUT1S to 3 + } + } + if (pin == PIN_PSW_nIRQ2) + { + /* Interrupt on PSW/nIRQ2 */ + am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get the Control2 Register + temp &= 0x1C; // Extract the OUT2S field + if (temp != 0) // Not already selecting nIRQ + { + clrreg(AM1805_REG_CTRL2, 0x1C); // Clear OUT2S + setreg(AM1805_REG_CTRL2, 0x0C); // Set OUT2S to 3 + } + } + + if (repeat == ONCE_PER_10TH_SEC) + { + /* 10ths interrupt */ + temp_buff[1] |= 0xF0; + repeat = ONCE_PER_SECOND; // Select correct RPT value + } + if (repeat == ONCE_PER_100TH_SEC) + { + /* 100ths interrupt */ + temp_buff[1] = 0xFF; + repeat = ONCE_PER_SECOND; // Select correct RPT value + } + if (repeat != 0) // Don't initiate if repeat = 0 + { + temp = (repeat << 2); // Set the RPT field to the value of repeat + setreg(AM1805_REG_TIM_CTRL, temp); // Was previously cleared + setreg(AM1805_REG_INTMASK, (intmode << 5)); // Set the alarm interrupt mode + setreg(AM1805_REG_INTMASK, 0x60); // Set the alarm interrupt mode + am1805_burst_write(temp_buff, 8); // Execute the burst write + setreg(AM1805_REG_INTMASK, 0x04); // Set the AIE bit + } + else + setreg(AM1805_REG_INTMASK, 0x60); // Set IM field to 0x3 (reset value) to minimize current draw + + return; +} + +void am1805_config_countdown_timer(count_down_range_t range, int32_t period, count_down_repeat_t repeat, interrupt_pin_t pin) +{ + uint8_t tm; + uint8_t trpt; + uint8_t tfs; + uint8_t te; + char temp; + char tctrl; + int32_t timer; + char oscmode; + + /* 0 = XT, 1 = RC */ + am1805_register_read(AM1805_REG_OSCSTATUS, &oscmode, 1); + oscmode = (oscmode & 0x10) ? 1 : 0; + + /* disable count down timer */ + if (pin == INTERNAL_FLAG) + { + te = 0; + } + else + { + te = 1; + if (repeat == SINGLE_LEVEL_INTERRUPT) + { + /* Level interrupt */ + tm = 1; // Level + trpt = 0; // No repeat + if (range == PERIOD_US) + { + /* Microseconds */ + if (oscmode == 0) + { + /* XT Mode */ + if (period <= 62500) // Use 4K Hz + { + tfs = 0; + timer = (period * 4096); + timer = timer / 1000000; + timer = timer - 1; + } + else if (period <= 16384000) // Use 64 Hz + { + tfs = 1; + timer = (period * 64); + timer /= 1000000; + timer = timer - 1; + } + else // Use 1 Hz + { + tfs = 2; + timer = period / 1000000; + timer = timer - 1; + } + } + else + { + /* RC Mode */ + if (period <= 2000000) { // Use 128 Hz + tfs = 0; + timer = (period * 128); + timer /= 1000000; + timer = timer - 1; + } + else if (period <= 4000000) { // Use 64 Hz + tfs = 1; + timer = (period * 64); + timer /= 1000000; + timer = timer - 1; + } + else { // Use 1 Hz + tfs = 2; + timer = period / 1000000; + timer = timer - 1; + } + } + } + else + { + /* Seconds */ + if (period <= 256) + { + /* Use 1 Hz */ + tfs = 2; + timer = period - 1; + } + else + { + /* Use 1/60 Hz */ + tfs = 3; + timer = period / 60; + timer = timer - 1; + } + } + } + else + { + /* Pulse interrupts */ + tm = 0; // Pulse + trpt = repeat & 0x01; // Set up repeat + if (repeat < REPEAT_PLUSE_1_128_SEC) + { + tfs = 0; + if (oscmode == 0) + { + timer = (period * 4096); + timer /= 1000000; + timer = timer - 1; + } + else + { + timer = (period * 128); + timer /= 1000000; + timer = timer - 1; + } + } + else if (repeat < REPEAT_PLUSE_1_64_SEC) + { + tfs = 1; + timer = (period * 128); + timer /= 1000000; + timer = timer - 1; + } + else if (period <= 256) + { + /* Use 1 Hz */ + tfs = 2; + timer = period - 1; + } + else + { + /* Use 1/60 Hz */ + tfs = 3; + timer = period / 60; + timer = timer - 1; + } + } + } + + am1805_register_read(AM1805_REG_TIM_CTRL, &tctrl, 1); // Get TCTRL, keep RPT, clear TE + tctrl = tctrl & 0x1C; + am1805_register_write(AM1805_REG_TIM_CTRL, tctrl); + + tctrl = tctrl | (te * 0x80) | (tm * 0x40) | (trpt * 0x20) | tfs; // Merge the fields + + if (pin == PIN_FOUT_nIRQ) // generate nTIRQ interrupt on FOUT/nIRQ (asserted low) + { + clrreg(AM1805_REG_CTRL2, 0x3); // Clear OUT1S + } + if (pin == PIN_PSW_nIRQ2) // generate nTIRQ interrupt on PSW/nIRQ2 (asserted low) + { + am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get OUT2S + if ((temp & 0x1C) != 0) + { + temp = (temp & 0xE3) | 0x14; // If OUT2S != 0, set OUT2S to 5 + } + am1805_register_write(AM1805_REG_CTRL2, temp); // Write back + } + if (pin != 0) + { + clrreg(AM1805_REG_STATUS,0x08); // Clear TIM + setreg(AM1805_REG_INTMASK,0x08); // Set TIE + am1805_register_write(AM1805_REG_CDTIM, timer); // Initialize the timer + am1805_register_write(AM1805_REG_TIMINIT, timer); // Initialize the timer repeat + am1805_register_write(AM1805_REG_TIM_CTRL, tctrl); // Start the timer + } + + return ; +} + +/** Parameter: + * timeout - minimum timeout period in 7.8 ms periods (0 to 7) + * mode - sleep mode (nRST modes not available in AM08xx) + * 0 => nRST is pulled low in sleep mode + * 1 => PSW/nIRQ2 is pulled high on a sleep + * 2 => nRST pulled low and PSW/nIRQ2 pulled high on sleep + * error ?returned value of the attempted sleep command + * 0 => sleep request accepted, sleep mode will be initiated in timeout seconds + * 1 => illegal input values + * 2 => sleep request declined, interrupt is currently pending + * 3 => sleep request declined, no sleep trigger interrupt enabled +**/ +void am1805_set_sleep(uint8_t timeout, uint8_t mode) +{ + uint8_t slres = 0; + char temp = 0; + +#if AM1805_DEBUG + am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get SLST bit (temp & 0x08) + + if ( ( temp & 0x08 ) == 0) + { + pc.printf("Previous Sleep Failed\r\n"); + } else { + pc.printf("Previous Sleep Successful\r\n"); + } + clrreg(AM1805_REG_CTRL2,0x08); // Clear SLST + + am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get SLST bit (temp & 0x08) + + if ( ( temp & 0x08 ) == 0) + { + pc.printf("Clear Succ\r\n"); + } else { + pc.printf("Clear Fail\r\n"); + } + clrreg(AM1805_REG_CTRL2,0x08); // Clear SLST +#endif + + if (mode > 0) + { + /* Sleep to PSW/nIRQ2 */ + am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Read OUT2S + temp = (temp & 0xE3) | 0x18; // MUST NOT WRITE OUT2S WITH 000 + am1805_register_write(AM1805_REG_CTRL2, temp); // Write value to OUT2S + slres = 0; + } + + temp = timeout | (slres << 6) | 0x80; // Assemble SLEEP register value + am1805_register_write(AM1805_REG_SLEEPCTRL, temp); // Write to the register + +#if AM1805_DEBUG + /* Determine if SLEEP was accepted */ + am1805_register_read(AM1805_REG_CTRL2, &temp, 1); // Get SLP bit (temp & 0x80) + + if ( ( temp & 0x80 ) == 0) + { + char reg_wdi_value = 0; + /* SLEEP did not happen - determine why and return reason. */ + am1805_register_read(AM1805_REG_INTMASK, &temp, 1); // Get status register interrupt enables + am1805_register_read(AM1805_REG_WDT, ®_wdi_value, 1); // Get WDT register + if ((( temp & 0x0F ) == 0) & (((reg_wdi_value & 0x7C) == 0) || ((reg_wdi_value & 0x80) == 0x80))) + { + pc.printf("No trigger interrupts enabled\r\n"); + } + else + { + pc.printf("Interrupt pending\r\n"); + } + } + else + { + pc.printf("SLEEP request successful\r\n"); + } +#endif +}
diff -r 000000000000 -r 5e0616a05642 AM1805.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AM1805.h Thu Dec 24 05:25:32 2015 +0000 @@ -0,0 +1,92 @@ +/* AM1805.h , AM1805 Sample code: external RTC module is used by host MCU */ + +typedef struct +{ + uint8_t hundredth; + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t date; + uint8_t weekday; + uint8_t month; + uint8_t year; + uint8_t century; + uint8_t mode; +} time_reg_struct_t; + +typedef enum +{ + XT1_INTERRUPT = 0x01, /**< WDI input pin will generate XT1 interrupt */ + XT2_INTERRUPT = 0x02 /**< EXTI input pin will generate XT2 interrupt */ +} input_interrupt_t; + +typedef enum +{ + DISABLE_ALARM = 0, /**< disable alarm */ + ONCE_PER_YEAR = 1, /**< once per year */ + ONCE_PER_MONTH = 2, /**< once per month */ + ONCE_PER_WEEK = 3, /**< once per week */ + ONCE_PER_DAY = 4, /**< once per day */ + ONCE_PER_HOUR = 5, /**< once per hour */ + ONCE_PER_MINUTE = 6, /**< once per minute */ + ONCE_PER_SECOND = 7, /**< once per second */ + ONCE_PER_10TH_SEC = 8, /**< once per 10th of a second */ + ONCE_PER_100TH_SEC = 9 /**< once per 100th of a second */ +} alarm_repeat_t; + +typedef enum +{ + PERIOD_US = 0, /**< period in us */ + PERIOD_SEC = 1 /**< period in seconds */ +} count_down_range_t; + +typedef enum +{ + SINGLE_LEVEL_INTERRUPT = 0, /**< single level interrupt */ + REPEAT_PULSE_1_4096_SEC = 1, /**< a repeated pulsed interrupt, 1/4096 s (XT mode), 1/128 s (RC mode) (range must be 0) */ + SINGLE_PULSE_1_4096_SEC = 2, /**< a single pulsed interrupt, 1/4096 s (XT mode), 1/128 s (RC mode) (range must be 0) */ + REPEAT_PLUSE_1_128_SEC = 3, /**< a repeated pulsed interrupt, 1/128 s (range must be 0) */ + SINGLE_PLUSE_1_128_SEC = 4, /**< a single pulsed interrupt, 1/128 s (range must be 0) */ + REPEAT_PLUSE_1_64_SEC = 5, /**< a repeated pulsed interrupt, 1/64 s (range must be 1) */ + SINGLE_PLUSE_1_64_SEC = 6 /**< a single pulsed interrupt, 1/64 s (range must be 1) */ +} count_down_repeat_t; + +typedef enum +{ + LEVEL_INTERRUPT = 0x00, /**< level interrupt */ + PULSE_1_8192_SEC = 0x01, /**< pulse of 1/8192s (XT) or 1/128 s (RC) */ + PULSE_1_64_SEC = 0x10, /**< pulse of 1/64 s */ + PULSE_1_4_SEC = 0x11 /**< pulse of 1/4 s */ +} interrupt_mode_t; + +typedef enum +{ + INTERNAL_FLAG = 0, /**< internal flag only */ + PIN_FOUT_nIRQ = 1, /**< generate the interrupt on FOUT/nIRQ */ + PIN_PSW_nIRQ2 = 2, /**< generate the interrupt on PSW/nIRQ2 */ + PIN_nTIRQ = 3 /**< generate the interrupt on nTIRQ (not apply to ALARM) */ +} interrupt_pin_t; + +bool am1805_init(void); + +void am1805_register_read(char register_address, char *destination, uint8_t number_of_bytes); + +void am1805_register_write(char register_address, uint8_t value); + +void am1805_burst_write(uint8_t *value, uint8_t number_of_bytes); + +uint8_t am1805_read_ram(uint8_t address); + +void am1805_write_ram(uint8_t address, uint8_t data); + +void am1805_config_input_interrupt(input_interrupt_t index_Interrupt); + +void am1805_set_time(time_reg_struct_t time_regs); + +void am1805_get_time(time_reg_struct_t *time_regs); + +void am1805_config_alarm(time_reg_struct_t time_regs, alarm_repeat_t repeat, interrupt_mode_t intmode, interrupt_pin_t pin); + +void am1805_config_countdown_timer(count_down_range_t range, int32_t period, count_down_repeat_t repeat, interrupt_pin_t pin); + +void am1805_set_sleep(uint8_t timeout, uint8_t mode); \ No newline at end of file