Share My Creation Cuckoo Clock

DS3231 RTC with TFT display and DF-Player to make the cuckoo sound. Every 15 minutes it sounds once and on the hour it sounds the hour.
The RTC is 2 ppm accuracy so you are going to miss your next birthday by about a minute.
The code in C is for the SPI drive of the TFT. The images are also generated by the code.

B4X:
Sub Process_Globals

    Public Serial1 As Serial
    Private AStream As AsyncStreams
    Private wire As WireMaster
    Dim  adr As Byte= 0x68  
    Private tmr As Timer
    Public CS As Pin
    Public DC As Pin
    Public SDA As Pin
    Public SCK As Pin
    Public RST As Pin
    Public minutePB As Pin
    Public hourPB As Pin
    Public busy As Pin
    Public test As Pin
    Private minL, minH, minS, hourL, hourH, hourS As Byte
    Public yh=4, yc=yh+40 As Int
   
    Public  BLACK  As UInt=0x00
    Public  BLUE  As UInt=0x01F
    Public  RED   As UInt=0xF800
    Public  GREEN   As UInt=0x07E0
    Public  CYAN   As UInt=0x07FF
    Public  MAGENTA   As UInt=0xF81F
    Public  YELLOW   As UInt=0xFFE0
    Public  WHITE   As UInt=0xFFFF
    Public  PINK   As UInt=0xFC58
    Public  ORANGE   As UInt=0xFC00
    Public  BROWN   As UInt=0x8208
     Public  bgr   As UInt=0xFFFF
    Private spires, spidata As Byte


End Sub

Private Sub AppStart
    Serial1.Initialize(9600)
    AStream.Initialize(Serial1.Stream,Null , Null)    '"Astream_NewData"
    wire.Initialize
    tmr.Initialize("tmr_Tick", 500)
    tmr.Enabled = True
    CS.Initialize(10, CS.MODE_OUTPUT)
    DC.Initialize(9, DC.MODE_OUTPUT)
    SCK.Initialize(13, SCK.MODE_OUTPUT)
    RST.Initialize(8, RST.MODE_OUTPUT)
    SDA.Initialize(11, SDA.MODE_OUTPUT)
    minutePB.Initialize(minutePB.A0, minutePB.MODE_INPUT_PULLUP)
    hourPB.Initialize(hourPB.A1, hourPB.MODE_INPUT_PULLUP)
    test.Initialize(test.A2, test.MODE_INPUT_PULLUP)
    'hourPB.AddListener("hourPB_StateChanged")
    RunNative ("set_spi",Null)
    TFTinit
    rectan(0,0,127,159,CYAN)    'clear screen
    house
    door
End Sub

Sub tmr_Tick
    If minutePB.DigitalRead=True And hourPB.DigitalRead=True Then
        get_time
    End If
   
    If minutePB.DigitalRead=False Then
        minL=minL+1
        If minL>9 Then
            minL=0
            minH=minH+1
        End If
        If minH>5 Then minH=0
        drawC(50,yc,minH,BLUE,2)    'minutes
        drawC(63,yc,minL,BLUE,2)
        minS=Bit.ShiftLeft(minH,4) + minL
        setTime(1,minS)
    End If
   
    If hourPB.DigitalRead=False Then
        hourL=hourL+1
        If hourL>9 Then
            hourL=0
            hourH=hourH+1
        End If
        If (hourH*10 + hourL)>23 Then
            hourH=0
            hourL=0
        End If
        drawC(11,yc,hourH,BLUE,2)    'hourS
        drawC(24,yc,hourL,BLUE,2)
        hourS=Bit.ShiftLeft(hourH,4) + hourL
        setTime(2,hourS)
    End If

End Sub

Sub door
  Dim x=51, y=yh+74 As Byte
  rectan(x-20,y-6,x+44,y+46,ORANGE)    'erase
  rectan(x-4,y-6,x+28,y+46,BROWN)    'door
End Sub

Sub bird
  Dim i, x=51, y=yh+74 As Byte
  Dim hue=YELLOW As Int

    rectan(x-20,y-6,x+44,y+46,ORANGE)    'erase
    rectan(x-4,y-4,x+28,y+44,BLACK)    'opening
    rectan(x-20,y-6,x-4,y+46,BROWN)    'door
    rectan(x+28,y-6,x+44,y+46,BROWN)    'door
    'body
    For i=0 To 4
        rectan(x+6-i,y+i+23,x+17+i,y+i+24,ORANGE)
    Next
    rectan(x+2,y+28,x+21,y+32,ORANGE)
    For i=0 To 4
        rectan(x+2+i,y+i+32,x+21-i,y+i+33,ORANGE)
    Next
    rectan(x,y+28,x+2,y+34,YELLOW)    'wing
    rectan(x+21,y+28,x+23,y+34,YELLOW)    'wing
    rectan(x+8,y+38,x+9,y+44,RED)    'leg
    rectan(x+14,y+38,x+15,y+44,RED)    'leg
   
    'head
    rectan(x+9,y,x+14,y+1,hue)    'top
    For i=0 To 4
        rectan(x+6-i,y+i+1,x+i+17,y+i+2,hue)
    Next
    rectan(x+1,y+6,x+22,y+9,hue)
    rectan(x,y+9,x+23,y+15,hue)
    rectan(x+1,y+15,x+22,y+17,hue)
    For i=0 To 4
        rectan(x+i+2,y+i+17,x+21-i,y+i+18,hue)
    Next
    rectan(x+9,y+23,x+14,y+24,hue)
    'eye
    For i=0 To 2
        rectan(x+5-i,y+i+6,x+7+i,y+i+7,WHITE)
    Next
    For i=0 To 2
        rectan(x+5-i,y+i+9,x+7+i,y+i+10,BLACK)
    Next
    For i=0 To 2
        rectan(x+3+i,y+i+13,x+9-i,y+i+14,BLACK)
    Next
   
    For i=0 To 2
        rectan(x+16-i,y+i+6,x+18+i,y+i+7,WHITE)
    Next
    For i=0 To 2
        rectan(x+16-i,y+i+9,x+18+i,y+i+10,BLACK)
    Next
    For i=0 To 2
        rectan(x+14+i,y+i+13,x+20-i,y+i+14,BLACK)
    Next
    'BIC
    rectan(x+10,y+20,x+14,y+21,MAGENTA)
    rectan(x+11,y+21,x+13,y+22,MAGENTA)
    For i=0 To 3
        rectan(x+9,y+i,x+10+i,y+i+1,ORANGE)
    Next
End Sub

Sub bic_closed
  Dim i, x=51, y=yh+74 As Byte
  rectan(x+9,y+16,x+15,y+19,PINK)    'erase
  For i=0 To 2
        rectan(x+11-i,y+i+16,x+13+i,y+i+17,MAGENTA)
    Next
End Sub

Sub bic_open
  Dim x=51, y=yh+74 As Byte
  rectan(x+9,y+16,x+15,y+19,PINK)
  rectan(x+11,y+16,x+13,y+17,MAGENTA)
  rectan(x+9,y+17,x+15,y+18,MAGENTA)
End Sub

Sub house
  Dim i As Byte

    For i=0 To 6    'roof
        rectan(59-i*8,yh+i*4,67+i*8,yh+i*4+4,RED)
    Next
      rectan(0,yh+27,127,yh+31,RED)
      rectan(35,yh,39,yh+12,BLACK)    'chemny
 
    For i=0 To 7    'board
        rectan(15-i*2,yh+120+i*3,111+i*2,yh+i*3+124,GREEN)
    Next

    For i=0 To 5    'house
    rectan(4+i*2,yh+32+i*16,123-i*2,yh+i*16+48,ORANGE)
    Next

    rectan(9,yc-2,118,yc+16,bgr)    '//
    drawC(37,yc,10,MAGENTA,2)    ':
    drawC(76,yc,10,MAGENTA,2)    ':
 
End Sub

Sub setTime (reg As Byte, setting As Byte)
    Dim data(2) As Byte
    data(0)=reg
    data(1)= setting
    wire.WriteTo(adr, data)

End Sub

Sub get_time
  Dim sh, sl, dong, i As Byte    'hh, hl, mh, ml,
  Dim data(1) As Byte
    data(0) = 0
    wire.WriteTo(adr,data)
    Dim res() As Byte = wire.RequestFrom(adr,7)              'request time
    If res.Length>=6 Then
        hourH=Bit.And(Bit.ShiftRight(res(2),4),3)    'res(2)>>4 & 3
          hourL=Bit.And(res(2),15)
        minH=Bit.And(Bit.ShiftRight(res(1),4),7)    'res[1]>>4 & 7
          minL=Bit.And(res(1),15)'res[1] & 15
        sh=Bit.And(Bit.ShiftRight(res(0),4),7)
          sl=Bit.And(res(0),15)
 
    End If

    drawC(11,yc,hourH,BLUE,2)    'hourS
    drawC(24,yc,hourL,BLUE,2)'

    drawC(50,yc,minH,BLUE,2)    'minutes
    drawC(63,yc,minL,BLUE,2)'
 
  drawC(89,yc,sh,BLUE,2)    'seconds
  drawC(102,yc,sl,BLUE,2)

    dong = hourH*10 + hourL    'total hourS
  If res(1)=0 And res(0)=0 Then    'If 00 minutes And 00 seconds
    bird
    Delay(1000)
    For i=1 To dong
        play_df
    Next
    Delay(1000)
    door
  else if    (minH*10+minL) Mod 15=0 And res(0)=0 Then    '((mh*10+ml)%15==0 && res[0]==0)    '15,30,45 minutes
    bird
    Delay(1000)
    play_df
    Delay(1000)
    door
  End If
End Sub

Sub play_df
    Dim ps() As Byte = Array As Byte(0x7E,0xff,0x06,0x03,0x00,0x00,1,0xEF)
   
    Do While busy.DigitalRead=False    'wait For prev track To complete, !busy
        Delay(10)
    Loop
    bic_open
    AStream.Write(ps)
    Delay(1400)
    bic_closed
End Sub

        'draw char
Sub drawC(x As Byte, y As Byte, c As Byte, color As UInt, size As Byte)
    Dim i, j, line As Byte
    Private font() As Byte = Array As Byte( _
    0x3E, 0x41, 0x41, 0x41, 0x3E, _ '0
    0x00, 0x42, 0x7F, 0x40, 0x00, _ '1
    0x72, 0x49, 0x49, 0x49, 0x46, _
    0x21, 0x41, 0x49, 0x4D, 0x33, _
    0x18, 0x14, 0x12, 0x7F, 0x10, _
    0x27, 0x45, 0x45, 0x45, 0x39, _ '5
    0x3C, 0x4A, 0x49, 0x49, 0x31, _
    0x41, 0x21, 0x11, 0x09, 0x07, _
    0x36, 0x49, 0x49, 0x49, 0x36, _
    0x46, 0x49, 0x49, 0x29, 0x1E, _ '9
    0x00, 0x00, 0x14, 0x00, 0x00)    ':
   
        For i=0 To 5
        If i = 5 Then
            line = 0
        Else
            line = font((c*5)+i)
        End If  
            For j = 0 To 7
                If Bit.And(line,0x1)=1 Then  
                    rectan(x+(i*size), y+(j*size), x+(i*size)+size, y+(j*size)+size, color)
                Else
                    rectan(x+(i*size), y+(j*size), x+(i*size)+size, y+(j*size)+size, bgr)
                End If
                line=Bit.ShiftRight(line,1)
            Next
       
    Next
   
End Sub

Sub spi(data As Byte)    'send byte over spi
    spidata=data
    RunNative ("spi",Null)
    Return
End Sub


Sub command(cmd As Byte)
    DC.DigitalWrite(False)    'command Mode
    CS.DigitalWrite(False)    'Select the LCD (active low)
      spi(cmd)'set up data on bus
      CS.DigitalWrite(True)    'Deselect LCD (active low)  
End Sub

Sub send_data(data As Byte)
    DC.DigitalWrite(True)    'data mode
    CS.DigitalWrite(False)    'Select the LCD (active low)
    spi(data)    'set up data on bus
    CS.DigitalWrite(True)    'Deselect LCD (active low)
End Sub

Sub TFTinit
      Dim i As Byte
   
    RST.DigitalWrite(True)    'hardware reset
    Delay(200)
    RST.DigitalWrite(False)
    Delay(10)
    RST.DigitalWrite(True)
    Delay(10)

      command(0x01)    'sw reset
    Delay(200)
     command(0x11)    ' Sleep out
    Delay(200)
   
      command(0x3A)    'color mode
    send_data(0x05)    '16 bits
    'send_data(0x06)    '18 bits

      command(0x36)    'Memory access ctrl (directions)
      send_data(0x10)    '0x10=ver, 0B1100000=0x60=hor
    'send_data(0x08)    '0x48=left to right,BRG,horizontal   0x40=vertical,RGB
      'command(0x21)    'color inversion on

      command(0x2D)    'color look up table
      send_data(0)
    For i = 1 To 31
        send_data(i * 2)
    Next

      For i = 0 To 63
        send_data(i)
      Next
      send_data(0)
    For i = 1 To 31
    send_data(i * 2)
    Next

      command(0x13)    'Normal display on
    command(0x29)    'Main screen turn on
End Sub

Sub area(x0 As Byte, y0 As Byte,  x1 As Byte, y1 As Byte)
  command(0x2A)    'Column addr set
  send_data(0x00)
  send_data(x0)    ' XSTART
  send_data(0x00)
  send_data(x1)    ' XEND

  command(0x2B)    'Row addr set
  send_data(0x00)
  send_data(y0)    ' YSTART
  send_data(0x00)
  send_data(y1)    ' YEND

  command(0x2C)    'write To RAM
End Sub
 
Sub rectan(x0 As Byte, y0 As Byte,  x1 As Byte, y1 As Byte, color As UInt)
  Dim i As Int
  area(x0,y0,x1,y1)
  For i=(y1 - y0 + 1) * (x1 - x0 + 1) To 0 Step -1  

     DC.DigitalWrite(True)    ' data mode
    CS.DigitalWrite(False)
    spi(color / 256)
    spi(color Mod 256)
    CS.DigitalWrite(True)
   Next
End Sub

    #if C
    void spi(B4R::Object* o)
    {  
      SPDR = b4r_main::_spidata;  // Start transmission
      while (!(SPSR & _BV(SPIF)));  // Wait For transmission To complete
      b4r_main::_spires = SPDR;    // received byte
    }

    void set_spi(B4R::Object* o)
    {  
      SPCR = 0B1011100;  // Enable SPI, Master, mode3, set clock rate fck/4 = 4MHz
      //SPSR = 1;    //set clock rate fck/2=8MHz
    }
    #End if
 

Attachments

  • cuckoo405.jpg
    cuckoo405.jpg
    27 KB · Views: 1,314
  • cuckoo.zip
    3.9 KB · Views: 107
  • cuckoo.gif
    cuckoo.gif
    6.5 KB · Views: 110
  • df_player.jpg
    df_player.jpg
    15.3 KB · Views: 109
  • ds3231.jpg
    ds3231.jpg
    23.5 KB · Views: 114
  • cuckoo_sound.zip
    67.8 KB · Views: 103
Top