I could not resist joining the two modules to obtain a small alarm clock radio:
https://youtu.be/LLS2-pT456g
This is the program:
Code: [Local Link Removed for Guests]
' Clock Radio with 303WIFILC01 and RDA5807
' Files: radioClock.bas / main.css / reloj.png
' replace with the weekday names in your country:
dim weekDay$(6) = "Lunes","Martes","Miercoles","Jueves","Viernes","Sábado","Domingo"
dim alarmDate$(6)
' variables and default values:
' if any file is missing, go create it
' -----------------------------------------------------
volume=0 : brightness=0 : chosen=0 : duration = 0
file$ = "/defaults.dat"
if file.exists(file$) then LOAD_VAR volume, brightness, chosen, duration, file$ else SAVE_VAR volume, brightness, chosen, duration, file$
' -----------------------------------------------------
index = 6
dim isCheck(index) = 1, 1, 1, 1, 1, 0, 0
dim alarmTime$(index) = "08:00","08:00","08:00","08:00","08:00","10:00","10:00"
file$ = "/weekly.dat"
if file.exists(file$) then LOAD_ARRAYS index, isCheck(), alarmTime$(), file$ else SAVE_ARRAYS index, isCheck(), alarmTime$(), file$
' -----------------------------------------------------
index = 3
' replace with the frequency and abbreviation of your favorite stations:
dim freq(index) = 93.0, 96.9, 102.9, 105.0
dim station$(index) = "RNE Clasica","RNE 1","RNE 3","RNE 5"
file$ = "/stations.dat"
if file.exists(file$) then LOAD_ARRAYS index, freq(), station$(), file$ else SAVE_ARRAYS index, freq(), station$(), file$
' -----------------------------------------------------
numDay = 0
nextDateAlarm$ = ""
nextTimeAlarm$ = ""
' =================================
' 303WIFILC01 config and turning on
' Dot display control
noDot=0 : dot1=2 : dot3=8 : colon=4 : led=0
' numbers from zero to nine, blank space and minus sign:
dim font(11) = 252, 132, 186, 174, 198, 110, 126, 164, 254, 238, 0, 2
i2c.setup 13, 12 ' SDA and SCL on the 303WIFILC01
TM_init brightness
radio_On = 0
playing = 0
RDA_Init volume, 0 ' 0 = radio Off
timer0 1000, displayClock
onHtmlReload web
onHtmlChange update
stage = 1 : today = 0 : wakeUp$ = ""
gosub getNext
gosub web
pin.mode 0, input, pullup ' radio on/off button
interrupt 0, radioSwitch
WAIT ' wait for something to happen
END
' -----------
displayClock:
' tomorrow
hour$ = left$(time$,2) + mid$(time$, 4, 2)
if led=0 then led=4 else led=0
TM_show hour$, led
' Check if it is alarm time
second$= right$(time$, 2)
if second$ = "00" then ' new minute
weekDay date$, today ' what weekday is today
if isCheck(today) then ' if it is marked for alarm
wakeUp$ = replace$(alarmTime$(today), ":", "") ' remove colon from alarm time
' wlog wakeUp$, hour$
if wakeUp$ = hour$ then RDA_Init volume, 1
endif
endif
' check if turn off radio
if millis-radio_On >= duration * 60 * 1000 then RDA_Init volume, 0
return
' ----------------
web:
cls
cssexternal "/main.css"
a$ = ""
select case stage
case 1
a$ = a$ + |<div class="main">|
a$ = a$ + |<img src="reloj.png">|
a$ = a$ + |<h1>Current value</h1>|
a$ = a$ + |<table>|
a$ = a$ + |<tr><td><p style="margin-right:25px;">Clock brightnes</p></td><td class="enhanced"><h3>|+str$(brightness)+|</h3></td></tr>|
a$ = a$ + |<tr><td><p>Radio volume</p></td><td class="enhanced"><h3>|+str$(volume)+|</h3></td></tr>|
a$ = a$ + |<tr><td><p>Selected station</p></td><td class="enhanced"><h3>|+station$(chosen)+|</h3></td></tr>|
a$ = a$ + |<tr><td><p>Radio ON time</p></td><td class="enhanced"><h3>|+str$(duration)+|</h3></td></tr>|
a$ = a$ + |<tr><td><p>Next day alarm</p></td><td class="enhanced"><h3>|+nextDateAlarm$+|</h3></td></tr>|
a$ = a$ + |<tr><td><p>Next hour alarm</p></td><td class="enhanced"><h3>|+nextTimeAlarm$+|</h3></td></tr>|
a$ = a$ + |</table>|
a$ = a$ + button$("Radio Setup", radioSetup, "button")
a$ = a$ + button$("Alarm Setup", alarmSetup, "button")
a$ = a$ + |</div>|
case 2
a$ = a$ + |<div class="hora">|
a$ = a$ + |<table>|
a$ = a$ + |<th colspan=2"><h1>Daily Alarm</h1></th>|
for i = 0 to 6
a$ = a$ + |<tr><td><input type="checkbox" data-var="isCheck(| + str$(i) + |)" onchange="cmdChange(event)"></td>|
a$ = a$ + |<td><input type="Time" data-var="alarmTime$(| + str$(i) + |)" onchange="cmdChange(event)" value="| + alarmTime$(i) + |"></td>|
a$ = a$ + |<td><p>| + weekDay$(i) + |</p></td></tr>|
next i
a$ = a$ + |</table>|
a$ = a$ + button$("Radio Setup", radioSetup, "button")
a$ = a$ + button$("Done", done, "button")
a$ = a$ + |</div>|
case 3
a$ = a$ + |<div class="emisora">|
a$ = a$ + |<h1>Waking up with:</h1>|
a$ = a$ + |<table>|
' ====================== TEXTBOX & RADIOBUTTON ============================================
a$ = a$ + |<th><p>MHz</p></th><th><p>Station</p></th><th><p>Sel</p></th>|
for i = 0 to index
a$ = a$ + |<tr>|
a$ = a$ + |<td><input type="textbox" onchange="cmdChange(event)" data-var="freq(| + str$(i) + |)" class="mhz"></td>|
a$ = a$ + |<td><input type="textbox" onchange="cmdChange(event)" data-var="station$(| + str$(i) + |)" class="station"></td>|
a$ = a$ + |<td><input type="radio" onchange="cmdChange(event)" data-var="chosen" name="station" value="| + str$(i) + |"|
if i = chosen then a$ = a$ + |checked|
a$ = a$ + |></td></tr>|
next i
a$ = a$ + |</table><br>|
' ======================================== SLIDERS =======================================
a$ = a$ + |<h2>Volume</h2>|
a$ = a$ + |<div class="slider"><input type="range" onchange="cmdChange(event)" data-var="volume" |
a$ = a$ + |min="0" max="15" oninput="rg1.innerText=this.value"><p id="rg1">|+str$(volume)+|</p></div>|
a$ = a$ + |<h2>Brightness</h2>|
a$ = a$ + |<div class="slider"><input type="range" onchange="cmdChange(event)" data-var="brightness" |
a$ = a$ + |min="1" max="8" oninput="rg2.innerText=this.value"><p id="rg2">|+str$(brightness)+|</p></div>|
a$ = a$ + |<h2>Duration</h2>|
a$ = a$ + |<div class="slider"><input type="range" onchange="cmdChange(event)" data-var="duration" |
a$ = a$ + |min="0" max="60" oninput="rg3.innerText=this.value"><p id="rg3">|+str$(duration)+|</p></div>|
' ======================================== BUTTONS ========================================
a$ = a$ + button$("Alarm Setup", alarmSetup, "button")
a$ = a$ + button$("Done", done, "button")
a$ = a$ + |</div>|
end select
html a$
refresh
a$ = ""
wlog ramfree
return
' ----------------
alarmSetup:
stage = 2
gosub web
return
' ----------------
done:
stage = 1
gosub web
return
' ----------------
radioSetup:
stage = 3
gosub web
return
' ----------------
radioSwitch:
if pin(0) = 0 then return
' Radio On/Off
playing = 1 - playing
if playing = 0 then RDA_Init volume, 0 else RDA_Init volume, 1
return
' ----------------
update:
wlog "update of "; HtmlEventVar$; " since stage "; stage
select case stage
case 2 ' Alarm Setup
gosub getNext
SAVE_ARRAYS 6, isCheck(), alarmTime$(), "/weekly.dat"
case 3 ' Radio Setup
SAVE_VAR volume, brightness, chosen, duration, "/defaults.dat"
SAVE_ARRAYS 3, freq(), station$(), "/stations.dat"
if HtmlEventVar$ = "brightness" then TM_init brightness
if HtmlEventVar$ = "volume" then RDA_Init volume, 1
end select
refresh
return
' ---------------
getNext:
for i = 1 to 7
nextDay$ = unixDate$(dateUnix(date$) + (86400*i))
weekDay nextDay$, numDay
alarmDate$(numDay) = nextDay$
next i
weekDay date$, numDay
if isCheck(numDay) then
if left$(time$, 5) < alarmTime$(numDay) then
nextDateAlarm$ = date$
nextTimeAlarm$ = alarmTime$(numDay)
return
endif
endif
for i = 1 to 6
numDay = numDay + 1
if numDay = 7 then numDay = 0
if isCheck(numDay) then
nextDateAlarm$ = alarmDate$(numDay)
nextTimeAlarm$ = alarmTime$(numDay)
return
endif
next i
nextDateAlarm$ = "NONE"
nextTimeAlarm$ = "NONE"
return
'------------------------
SUB weekDay(day$, numDay)
dim remap(6) = 5, 6, 0, 1, 2, 3, 4
numDay = ((((dateunix(day$)-dateunix("01/01/00")))/(24*3600)) mod 7)
numDay = remap(numDay)
END SUB
' ********** Save/retrieve variables in SPIFFS **********
SUB LOAD_VAR(var1, var2, var3, var4, fileName$)
LOCAL line$
line$ = file.read$(fileName$)
var1 = val(word$(line$, 1, ","))
var2 = val(word$(line$, 2, ","))
var3 = val(word$(line$, 3, ","))
var4 = val(word$(line$, 4, ","))
END SUB
' ---------------------------------------------------
SUB LOAD_ARRAYS(index, arrayN(), arrayC$(), fileName$)
LOCAL i, line$
for i = 0 to index
line$ = file.read$(filename$, i+1)
arrayN(i) = val(word$(line$, 1, ","))
arrayC$(i) = replace$(word$(line$, 2, ","), chr$(13), "") ' remove cr from end of line
next i
END SUB
' -------------------------------------
SUB SAVE_VAR(var1, var2, var3, var4, fileName$)
LOCAL line$
line$ = str$(var1) + "," + str$(var2) + "," + str$(var3) + "," + str$(var4)
file.save fileName$, line$
END SUB
' ---------------------------------------------------
SUB SAVE_ARRAYS(index, arrayN(), arrayC$(), fileName$)
LOCAL r, i, line$
r = file.delete(fileName$)
for i = 0 to index
line$ = str$(arrayN(i)) + "," + arrayC$(i) + chr$(13) + chr$(10) ' append cr+lf to end of line
file.append fileName$, line$
next i
END SUB
' ********** 303WIFILC01 clock board **********
SUB TM_init(brightness)
LOCAL value
value = (16 * brightness) + 1
if brightness = 8 then value = 1 ' brightness 1 (min) to 8 (max)
i2cWrite &H24, value
END SUB
' ----------------------
SUB TM_show(line$, dots)
LOCAL i, value, remap
for i = 1 to 4
value = asc(mid$(line$, i, 1)) - 48 ' 0 = ascii 48
if value = -16 then value = 10 ' blank space
if value = -3 then value = 11 ' minus sign
remap = font(value)
select case dots
case colon : if i = 2 then remap = remap +1
case dot1 : if i = 1 then remap = remap + 1
case dot3 : if i = 3 then remap = remap +1
end select
i2cWrite &H33 + i, remap
next i
END SUB
' --------------------------
SUB i2cWrite(address, value)
i2c.begin address
i2c.write value
i2c.end
END SUB
' ********** RDA5807 FM Radio tuner **********
SUB RDA_Init(volume, enable)
LOCAL level
if enable then radio_On = millis ' init measure time ON
pin.mode 1, output ' set pin TX as output
pin.mode 3, output ' set pin RX as output
i2c.setup 1, 3 ' SDA and SCL on RAD5807
address = &H11 ' I2C device address
level = volume OR &H80
ioBuff.dim(0,4) = &HD0, enable, &H08, level
' init RDA5807
i2c.write_ioBuff(0, 0, 2), address, &H02
i2c.write_ioBuff(0, 2, 2), address, &H05
' tunein sation
tuneIn freq(chosen)
' restore settings
pin.mode 1, SPECIAL
pin.mode 3, SPECIAL
i2c.setup 13, 12 ' SDA and SCL on the 303WIFILC01
END SUB
' --------------------------------------------
SUB tuneIn(frequency)
LOCAL channel, hightByte, lowByte
channel = ((frequency * 100) - 8700) / 10
hightByte = channel >> 2
lowByte = (channel << 6) OR &H10
lowByte = lowByte AND &HFF
ioBuff.dim(1, 2) = hightByte, lowByte
i2c.write_ioBuff(1), address, &H03
END SUB
' *********** FIN *****************
Code: [Local Link Removed for Guests]
body {
margin: 0 auto;
text-align: center;
}
p {
font-family: "trebuchet ms";
font-size: 1.2rem;
margin: 5px 0px 5px 0px;
padding-left: 10px;
text-align: left;
}
h1 {
font-family: "trebuchet ms";
font-size: 2rem;
margin: 10px;
}
h2 {
font-family: "trebuchet ms";
font-size: 1rem;
margin: 0px 0px 30px 0px;
}
h3 {
font-family: "trebuchet ms";
font-size: 1.2rem;
margin: 0;
text-align:center;
}
table {
margin:0 auto;
padding: 0px;
}
th p {
text-align:center;
}
.enhanced {
border:solid 1px blue;
background-color:#F0E68C;
width:150px;
}
#button {
display: inline-block;
margin: 20px 10px 20px 25px;
padding: 10px 20px;
border: none;
border-radius: 16px;
color: black;
background-color: #ddd;
text-align: center;
font-size: 1.2rem;
font-weight: 600;
cursor: pointer;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
}
.hora input {
font-family: verdana;
font-size: 1.5rem;
font-weight: 600;
text-align: center;
margin: 0px;
padding: 0px;
height: 40px;
width: 10rem;
}
.hora input[type="checkbox"] {
width: 40px;
}
.emisora .mhz {
background-color:#FAEBD7;
font-size:15px;
width:80px;
}
.emisora .station {
background-color:#F0FBD7;
font-size:15px;
width:150px;
}
.emisora input {
font-family: verdana;
font-size: 15px;
font-weight: 600;
text-align: center;
margin: 3px;
padding: 8px;
height: 40px;
width: 15rem;
}
.emisora input[type="radio"] {
margin-left: 15px;
width: 30px;
height: 30px;
}
.slider {
position:relative;
top:70%;
left:50%;
transform:translate(-50%,-50%);
width:220px;
height:25px;
padding:10px;
padding-left: 40px;
background:#FFF8DC;
border-radius:20px;
display:flex;
align-items:center;
box-shadow:0px 15px 40px #7E6D5766;
}
.slider p {
font-size:26px;
font-weight:600;
font-family: Open Sans;
margin: 30px 0px;
padding-left:30px;
color:#7E6D57;
}
.slider input[type="range"] {
-webkit-appearance:none !important;
width:420px;
height:2px;
background:#7E6D57;
border:none;
outline:none;
}
.slider input[type="range"]::-webkit-slider-thumb {
-webkit-appearance:none !important;
width:30px;
height:30px;
background:#fcfcfc;
border:2px solid #7E6D57;
border-radius:50%;
cursor:pointer;
}
.slider input[type="range"]::-webkit-slider-thumb:hover {
background:#7E6D57;
}