diff --git a/lua_modules/ds3231/ds3231.EN.md b/lua_modules/ds3231/ds3231.EN.md
index 32b62527..a69e207a 100644
--- a/lua_modules/ds3231/ds3231.EN.md
+++ b/lua_modules/ds3231/ds3231.EN.md
@@ -39,10 +39,11 @@ package.loaded["ds3231"]=nil
## setTime()
####Description
-Sets the current date and time.
+Sets the current date and time.
+if _disableOscillator_ is set to 1 the oscillator will **stops** on battery.
####Syntax
-setTime(second, minute, hour, day, date, month, year)
+setTime(second, minute, hour, day, date, month, year, disableOscillator)
####Parameters
second: 00-59
@@ -52,6 +53,7 @@ day: 1-7 (Sunday = 1, Saturday = 7)
date: 01-31
month: 01-12
year: 00-99
+disableOscillator: (optional) 0-1
####Returns
nil
@@ -110,5 +112,243 @@ ds3231 = nil
package.loaded["ds3231"]=nil
```
+####See also
+**-** []()
+
+
+## setAlarm()
+####Description
+Set an alarm to be triggered on SQW pin:
+_alarm1_ has a precision of **seconds**; _alarm2_ has a precision of **minutes** (`second` parameter will be ignored).
+
+Alarms sets gpio.LOW over the SQW pin and let it unchanged until reloaded. When reloaded sets gpio.HIGH.
+Alarms trigger **only once**, after that, if you want them to trigger again, you need to call `reloadAlarms()` or `setAlarm(...)` again.
+
+Alarm type set the alarm match conditions:
+- `ds3231.EVERYSECOND` works only with _alarm1_ and triggers every second;
+- `ds3231.EVERYMINUTE` works only with _alarm2_ and triggers every minute (at 00 seconds);
+- `ds3231.SECOND` triggers when time match given `seconds` parameter;
+- `ds3231.MINUTE` triggers when time match given `seconds` and `minutes` parameters;
+- `ds3231.HOUR` triggers when time match given `seconds`, `minutes`, and `hours` parameters;
+- `ds3231.DAY` triggers when time match given `seconds`, `minutes`, and `hours` on week day `date/day` parameters;
+- `ds3231.DATE` triggers when time match given `seconds`, `minutes`, and `hours` on date (day of the month) `date/day` parameters;
+
+####Syntax
+setAlarm(alarmId, alarmType, seconds, minutes, hours, date/day)
+
+####Parameters
+alarmId: 1-2
+alarmType: 1-7
+seconds: 00-59
+minutes: 00-59
+hours: 00-23
+date/day: 01-31 or 1-7 (Sunday = 1, Saturday = 7)
+
+####Returns
+nil
+
+####Example
+```lua
+ds3231=require("ds3231")
+ds3231.init(3, 4)
+
+-- Setting PIN1 to triggers on interrupt when alarm triggers
+gpio.mode(1,gpio.INT)
+gpio.trig(1,'down',function(level)
+ print('Time is passing')
+ -- If not reloaded it will be triggered only once
+ ds3231.reloadAlarms()
+end)
+
+ds3231.setAlarm(2,ds3231.EVERYMINUTE)
+
+-- Don't forget to release it after use
+ds3231 = nil
+package.loaded["ds3231"]=nil
+```
+
+####See also
+**-** []()
+
+
+## reloadAlarms()
+####Description
+Reload an already triggered alarm. Otherwise it will never be triggered again.
+Alarms have to be reloaded both to let them triggers.
+
+####Syntax
+reloadAlarms()
+
+####Parameters
+nil
+
+####Returns
+nil
+
+####Example
+```lua
+ds3231=require("ds3231")
+ds3231.init(3, 4)
+
+-- Setting PIN1 to triggers on interrupt when alarm triggers
+gpio.mode(1,gpio.INT)
+gpio.trig(1,'down',function(level)
+ print('Time is passing')
+ -- If not reloaded it will be triggered only once
+ ds3231.reloadAlarms()
+end)
+
+ds3231.setAlarm(2,ds3231.EVERYMINUTE)
+
+-- Don't forget to release it after use
+ds3231 = nil
+package.loaded["ds3231"]=nil
+```
+
+####See also
+**-** []()
+
+
+## enableAlarm()
+####Description
+Enable an already setted alarm with the previous matching conditions. It reload alarms internally.
+
+####Syntax
+enableAlarm(alarmId)
+
+####Parameters
+alarmId: 1-2
+
+####Returns
+nil
+
+####Example
+```lua
+ds3231=require("ds3231")
+ds3231.init(3, 4)
+
+-- Trigger on x:20:15
+ds3231.setAlarm(1,ds3231.MINUTE,15,20)
+
+if badThing == 1 then
+ ds3231.disableAlarm(1)
+end
+
+if goodThing == 1 then
+ ds3231.enableAlarm(1)
+end
+
+-- Don't forget to release it after use
+ds3231 = nil
+package.loaded["ds3231"]=nil
+```
+
+####See also
+**-** []()
+
+
+## disableAlarm()
+####Description
+Disable an already setted alarm with the previous matching conditions.
+if _alarmId_ is not 1 or 2 it disables both alarms.
+**Warning**: `disableAlarm()` prevent alarms to trigger interrupt over SQW pin but alarm itself will triggers at the matching conditions as it could be seen on _status byte_.
+
+####Syntax
+disableAlarm(alarmId)
+
+####Parameters
+alarmId: 0-2
+
+####Returns
+nil
+
+####Example
+```lua
+ds3231=require("ds3231")
+ds3231.init(3, 4)
+
+-- Trigger on x:20:15
+ds3231.setAlarm(1,ds3231.MINUTE,15,20)
+
+if badThing == 1 then
+ ds3231.disableAlarm(1)
+end
+
+if goodThing == 1 then
+ ds3231.enableAlarm(1)
+end
+
+-- Don't forget to release it after use
+ds3231 = nil
+package.loaded["ds3231"]=nil
+```
+
+####See also
+**-** []()
+
+
+## getBytes()
+####Description
+Get bytes of control, for debug purpose, and status of DS3231. To see what they means check the [Datasheet](http://datasheets.maximintegrated.com/en/ds/DS3231.pdf)
+
+####Syntax
+getBytes()
+
+####Parameters
+nil
+
+####Returns
+control: integer. Control 0-255
+status: integer. Status 0-143 (bit 6-5-4 unused)
+
+####Example
+```lua
+ds3231=require("ds3231")
+ds3231.init(3, 4)
+
+control,status = ds3231.getBytes()
+print('Control byte: '..control)
+print('Status byte: '..status)
+
+-- Don't forget to release it after use
+ds3231 = nil
+package.loaded["ds3231"]=nil
+```
+
+####See also
+**-** []()
+
+
+## resetStopFlag()
+####Description
+Stop flag on status byte means that the oscillator either is stopped or was stopped for some period and may be used to judge the validity of the timekeeping data.
+When setted to 1 this flag keeps that values until changed to 0.
+Call `resetStopFlag()` if you need to check validity of time data after that.
+
+####Syntax
+resetStopFlag()
+
+####Parameters
+nil
+
+####Returns
+nil
+
+####Example
+```lua
+ds3231=require("ds3231")
+ds3231.init(3, 4)
+
+control,status = ds3231.getBytes()
+if bit.band(bit.rshift(status, 7),1) == 1 then
+ print('[WARNING] RTC has stopped')
+ ds3231.resetStopFlag()
+end
+
+-- Don't forget to release it after use
+ds3231 = nil
+package.loaded["ds3231"]=nil
+```
+
####See also
**-** []()
\ No newline at end of file
diff --git a/lua_modules/ds3231/ds3231.lua b/lua_modules/ds3231/ds3231.lua
index d13b89e8..a93064ca 100644
--- a/lua_modules/ds3231/ds3231.lua
+++ b/lua_modules/ds3231/ds3231.lua
@@ -9,6 +9,16 @@ local moduleName = ...
local M = {}
_G[moduleName] = M
+-- Constants:
+M.EVERYSECOND = 6
+M.EVERYMINUTE = 7
+M.SECOND = 1
+M.MINUTE = 2
+M.HOUR = 3
+M.DAY = 4
+M.DATE = 5
+M.DISABLE = 0
+
-- Default value for i2c communication
local id = 0
@@ -16,6 +26,7 @@ local id = 0
local dev_addr = 0x68
local function decToBcd(val)
+ if val == nil then return 0 end
return((((val/10) - ((val/10)%1)) *16) + (val%10))
end
@@ -23,6 +34,11 @@ local function bcdToDec(val)
return((((val/16) - ((val/16)%1)) *10) + (val%16))
end
+local function addAlarmBit(val,day)
+ if day == 1 then return bit.bor(val,64) end
+ return bit.bor(val,128)
+end
+
-- initialize i2c
--parameters:
--d: sda
@@ -32,10 +48,10 @@ function M.init(d, l)
sda = d
scl = l
else
- print("iic config failed!") return nil
+ print("[ERROR] i2c config failed!") return nil
end
- print("init done")
- i2c.setup(id, sda, scl, i2c.SLOW)
+ print("[LOG] DS3231 init done")
+ i2c.setup(id, sda, scl, i2c.SLOW)
end
--get time from DS3231
@@ -58,7 +74,8 @@ function M.getTime()
end
--set time for DS3231
-function M.setTime(second, minute, hour, day, date, month, year)
+-- enosc setted to 1 disables oscilation on battery, stopping time
+function M.setTime(second, minute, hour, day, date, month, year, disOsc)
i2c.start(id)
i2c.address(id, dev_addr, i2c.TRANSMITTER)
i2c.write(id, 0x00)
@@ -70,6 +87,179 @@ function M.setTime(second, minute, hour, day, date, month, year)
i2c.write(id, decToBcd(month))
i2c.write(id, decToBcd(year))
i2c.stop(id)
+
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0E)
+ i2c.stop(id)
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.RECEIVER)
+ local c = string.byte(i2c.read(id, 1), 1)
+ i2c.stop(id)
+ if disOsc == 1 then c = bit.bor(c,128)
+ else c = bit.band(c,127) end
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0E)
+ i2c.write(id, c)
+ i2c.stop(id)
+end
+
+-- Reset alarmId flag to let alarm to be triggered again
+function M.reloadAlarms ()
+ if bit == nil or bit.band == nil or bit.bor == nil then
+ print("[ERROR] Module bit is required to use alarm function")
+ return nil
+ end
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0F)
+ i2c.stop(id)
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.RECEIVER)
+ local d = string.byte(i2c.read(id, 1), 1)
+ i2c.stop(id)
+ -- Both flag needs to be 0 to let alarms trigger
+ d = bit.band(d,252)
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0F)
+ i2c.write(id, d)
+ i2c.stop(id)
+ print('[LOG] Alarm '..almId..' reloaded')
+end
+
+-- Enable alarmId bit. Let it to be triggered
+function M.enableAlarm (almId)
+ if bit == nil or bit.band == nil or bit.bor == nil then
+ print("[ERROR] Module bit is required to use alarm function")
+ return nil
+ end
+ if almId ~= 1 and almId ~= 2 then print('[ERROR] Wrong alarm id (1 or 2): '..almId) return end
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0E)
+ i2c.stop(id)
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.RECEIVER)
+ local c = string.byte(i2c.read(id, 1), 1)
+ i2c.stop(id)
+ c = bit.bor(c,4)
+ if almId == 1 then c = bit.bor(c,1)
+ else c = bit.bor(c,2) end
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0E)
+ i2c.write(id, c)
+ i2c.stop(id)
+ M.reloadAlarms()
+ print('[LOG] Alarm '..almId..' enabled')
+end
+-- If almID equals 1 or 2 disable that alarm, otherwise disables both.
+function M.disableAlarm (almId)
+ if bit == nil or bit.band == nil or bit.bor == nil then
+ print("[ERROR] Module bit is required to use alarm function")
+ return nil
+ end
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0E)
+ i2c.stop(id)
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.RECEIVER)
+ local c = string.byte(i2c.read(id, 1), 1)
+ i2c.stop(id)
+ if almId == 1 then c = bit.band(c, 254)
+ elseif almId == 2 then c = bit.band(c, 253)
+ else
+ almId = '1 and 2'
+ c = bit.band(c, 252)
+ end
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0E)
+ i2c.write(id, c)
+ i2c.stop(id)
+ print('[LOG] Alarm '..almId..' disabled')
+end
+
+-- almId can be 1 or 2;
+-- almType should be taken from constants
+function M.setAlarm (almId, almType, second, minute, hour, date)
+ if bit == nil or bit.band == nil or bit.bor == nil then
+ print("[ERROR] Module bit is required to use alarm function")
+ return nil
+ end
+ if almId ~= 1 and almId ~= 2 then print('[ERROR] Wrong alarm id (1 or 2): '..almId) return end
+ M.enableAlarm(almId)
+ second = decToBcd(second)
+ minute = decToBcd(minute)
+ hour = decToBcd(hour)
+ date = decToBcd(date)
+ if almType == M.EVERYSECOND or almType == M.EVERYMINUTE then
+ second = addAlarmBit(second)
+ minute = addAlarmBit(minute)
+ hour = addAlarmBit(hour)
+ date = addAlarmBit(date)
+ elseif almType == M.SECOND then
+ minute = addAlarmBit(minute)
+ hour = addAlarmBit(hour)
+ date = addAlarmBit(date)
+ elseif almType == M.MINUTE then
+ hour = addAlarmBit(hour)
+ date = addAlarmBit(date)
+ elseif almType == M.HOUR then
+ date = addAlarmBit(date)
+ elseif almType == M.DAY then
+ date = addAlarmBit(date,1)
+ end
+ local almStart = 0x07
+ if almId == 2 then almStart = 0x0B end
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, almStart)
+ if almId == 1 then i2c.write(id, second) end
+ i2c.write(id, minute)
+ i2c.write(id, hour)
+ i2c.write(id, date)
+ i2c.stop(id)
+ print('[LOG] Alarm '..almId..' setted')
+end
+
+-- Get Control and Status bytes
+function M.getBytes ()
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0E)
+ i2c.stop(id)
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.RECEIVER)
+ local c = i2c.read(id, 2)
+ i2c.stop(id)
+ return tonumber(string.byte(c, 1)), tonumber(string.byte(c, 2))
+end
+
+-- Resetting RTC Stop Flag
+function M.resetStopFlag ()
+ if bit == nil or bit.band == nil or bit.bor == nil then
+ print("[ERROR] Module bit is required to reset stop flag")
+ return nil
+ end
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0F)
+ i2c.stop(id)
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.RECEIVER)
+ local s = string.byte(i2c.read(id, 1))
+ i2c.stop(id)
+ s = bit.band(s,127)
+ i2c.start(id)
+ i2c.address(id, dev_addr, i2c.TRANSMITTER)
+ i2c.write(id, 0x0F)
+ i2c.write(id, s)
+ i2c.stop(id)
+ print('[LOG] RTC stop flag resetted')
end
return M