Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

using a RTC in SF basic

MrDEB

Well-Known Member
I have a DS-1302 RTC module but how to use it?
I recall Jon Chandler made a vu meter clock but what he used for timing?
Am planning on a clock that has no hands, just LEDs but precision would be nice.
 
Popcorn, I notice that your image above states that the modules are in development. Any later news?

Mike.

The shift module exists – I have used it. As tumbleweed states, sometimes it's hard to find, being hidden away in the LIBRARY folder and all.

FYI, tumbleweed is a true saint, keeping Swordfish Basic up to date to support the latest chips and to deal with the idiosyncrasies Microchip sometimes adds to new chips.
 
Do we really need SHIFT.bas?
All I am doing to sequencely turn ON then OFF sixty blue LEDs one at a time
Then, do the same with 12 green LEDs.
Been looking at different videos and descriptions of similar.
Pouring over some Arduino code examples.
 
Do we really need SHIFT.bas?

When will I ever learn that ANY effort to help MrDEB is absolutely futile and a total waste of some of the few years I have left on the planet???? How can I be so f**king stupid?
 
Last edited:
All I am doing to sequencely turn ON then OFF sixty blue LEDs one at a time
Then, do the same with 12 green LEDs.

I believe this is all you've been trying to do for the eleven pages of this thread and a similar number spread out over several other threads. So far, at least two attempts have failed, largely because you've ignored advice by people who do actually have a clue.

I'm dying to see what [adjective left to the imagination] scheme you're going to concoct next. You said you want to use 74595 shift registers but you don't want to use the Swordfish SHIFT module.

I look forward to the next train wreck, but I won't be commenting.

 
Last edited:
Before I STFU for good, here's a final hint.

Do you know where SetDigitalIO.bas, utils.bas, convert.bas and intosc.bas are? No? How do you include them in your brilliant programs if you don't know?
 
Code:
{
****************************************************************
*  Name    : Shift Module                                      *
*  Author  : David John Barker                                 *
*  Notice  : Copyright (c) 2006 Mecanique                      *
*          : All Rights Reserved                               *
*  Date    : 10 JAN 2023                                       *
*  Version : 1.7 10 JAN 2023                                   *
*          : add default values for pShift param (SHIFT_MAX)   *
*          : allow SHIFT_CLOCK = 0 to 255, add to both hi/low  *
*          : add #option SHIFT_DATA_SETUP                      *
*          : 1.6 19/08/2019                                    *
*          : add PORT/LAT/TRIS offset for devices with         *
*          :   different reg maps (K40, K42, Q10, etc)         *
*  Notes   : 1.5 04/02/2006                                    *
*          :                                                   *
****************************************************************
}
module Shift

// import modules...
include "utils.bas"
include "system.bas"

// shiftin modes...
public const
   MSB_PRE = $00,       // MSB first, sample before clock
   MSB_POST = $02,      // MSB first, sample after clock
   LSB_PRE = $01,       // LSB first, sample before clock
   LSB_POST = $03       // LSB first, sample after clock

// shiftout modes...
public const
   LSB_FIRST = $00,     // LSB first
   MSB_FIRST = $01      // MSB first

// a pin structure...
structure TPin
   PortAddr as word         // PORT addr (input), LAT addr (output)
   TrisAddr as word         // TRIS addr
   Pin      as byte
   PinMask  as byte
end structure

// local working variables...
dim
   FDataIn as TPin,
   FDataOut as TPin,
   FClock as TPin

// maximum shift size can be 8, 16 or 32 bits
// using a smaller maximum shift size will reduce code overhead
// the default is 16 bits
#if IsOption(SHIFT_MAX) and not (SHIFT_MAX in (8, 16, 32))
   #error SHIFT_MAX, "Invalid option. MAX must be 8, 16 or 32 bits."
#endif
#option SHIFT_MAX = 16
const DEFAULT_SHIFT as byte = SHIFT_MAX

#if (SHIFT_MAX = 8)
  type TType = byte
#elseif (SHIFT_MAX = 16)
  type TType = word
#else  // SHIFT_MAX = 32
  type TType = longword
#endif

// speed of shift clock, in usecs
#if IsOption(SHIFT_CLOCK) and (SHIFT_CLOCK > 255)
   #error SHIFT_CLOCK, "Invalid option. SHIFT_CLOCK must be < 256"
#endif
#option SHIFT_CLOCK = 1
const SHIFT_CLOCK_US = SHIFT_CLOCK

// shift clock delay usage
//   0 = only call delay after first transition (previous versions)
//   1 = delay after both transitions (v1.7)
#option SHIFT_CLOCK_DELAY = 0

// optional data setup time (output data to clk, in usecs)
#option SHIFT_DATA_SETUP = 0
const SHIFT_DATA_SETUP_US = SHIFT_DATA_SETUP

{
****************************************************************************
* Name    : ToggleClock (PRIVATE)                                          *
* Purpose : Toggle the shift clock.                                        *
*         : The default minimum clock width will be 1us for frequencies    *
*         : above 4MHz. For 4Mhz and below, the minimum clock width will   *
*         : be 2us. Using #option SHIFT_CLOCK = 2 will force a minimum     *
*         : clock width of 2us for all frequencies.                         *
*         : NOTE - These figures assume a perfect clock. A plus or minus   *
*         : variation of the clock width will be observed for all real     *
*         : world clock frequencies that deviate from the ideal            *
****************************************************************************
}
inline sub ClockDelay()
   #if (SHIFT_CLOCK = 0)
       asm-          // at least one nop between clock transitions
       nop
       end asm
   #elseif (SHIFT_CLOCK > 2)
       delayus(SHIFT_CLOCK_US)
   #else    // SHIFT_CLOCK = 1 or 2 (previous versions)
      // force minimum 2us... 
      #if SHIFT_CLOCK = 2
       #if _clock >= 8
       delayus(1)
       #endif
      #endif

       // burn 8...
       #if _clock > 36
       asm-
       bra $ + 2
       bra $ + 2
       bra $ + 2
       bra $ + 2   
       end asm

       // burn 7...
       #elseif _clock > 32
       asm-
       bra $ + 2
       bra $ + 2
       bra $ + 2
       nop
       end asm

       // burn 6...
       #elseif _clock > 28
       asm-
       bra $ + 2
       bra $ + 2
       bra $ + 2
       end asm

       // burn 5...
       #elseif _clock > 24
       asm-
       bra $ + 2
       bra $ + 2
       nop
       end asm

       // burn 4...
       #elseif _clock > 20
       asm-
       bra $ + 2
       bra $ + 2
       end asm

       // burn 3...
       #elseif _clock > 16
       asm-
       bra $ + 2
       nop
       end asm

       // burn 2...
       #elseif _clock > 12
       asm-
       bra $ + 2
       end asm

       // burn 1...
       #elseif _clock > 8
       asm-
       nop
       end asm
       #endif
   #endif
end sub

inline sub DataSetup()
  #if (SHIFT_DATA_SETUP > 0)
  delayus(SHIFT_DATA_SETUP_US)
  #endif
end sub

inline sub ToggleClock()
   // toggle clock...
   INDF1 = INDF1 xor FClock.Pin
   ClockDelay()

   // toggle clock...
   INDF1 = INDF1 xor FClock.Pin
  #if (SHIFT_CLOCK_DELAY > 0)   // added v1.7
   ClockDelay()
  #endif
end sub   
{
****************************************************************************
* Name    : MakeOutput(PRIVATE)                                            *
* Purpose : Make the data pin an output                                    *
****************************************************************************
}
inline sub MakeOutput()
   FSR1 = FDataOut.TrisAddr
   INDF1 = INDF1 and FDataOut.PinMask
end sub   
{
****************************************************************************
* Name    : MakeInput (PRIVATE)                                            *
* Purpose : Make the data pin an input                                     *
****************************************************************************
}
inline sub MakeInput()
   FSR1 = FDataIn.TrisAddr       
   INDF1 = INDF1 or FDataIn.Pin
end sub
{
****************************************************************************
* Name    : LoadDataInAndClockAddr (PRIVATE)                               *
* Purpose : Load the data and clock pin address into FSR(x)                *
****************************************************************************
}
inline sub LoadDataInAndClockAddr()
   FSR0 = FDataIn.PortAddr
   FSR1 = FClock.PortAddr
end sub   
{
****************************************************************************
* Name    : LoadDataOutAndClockAddr (PRIVATE)                              *
* Purpose : Load the data and clock pin address into FSR(x)                *
****************************************************************************
}
inline sub LoadDataOutAndClockAddr()
   FSR0 = FDataOut.PortAddr
   FSR1 = FClock.PortAddr
end sub   

{
****************************************************************************
* Name    : LAT_OFFSET/TRIS_OFFSET                                         *
* Purpose : these macros load 'wresult' with the LAT and TRIS register     *
*         : offsets from PORT. they assume wresult is a 16-bit word        *
*         : located in the access bank (PROD is a good choice)             *
****************************************************************************
}
macro LAT_OFFSET(wresult)
    asm-
        movlw low(LATA-PORTA)
        movwf wresult
        movlw high(LATA-PORTA)
        movwf wresult+1
    end asm
end macro

macro TRIS_OFFSET(wresult)
    asm-
        movlw low(TRISA-PORTA)
        movwf wresult
        movlw high(TRISA-PORTA)
        movwf wresult+1
    end asm
end macro
{
****************************************************************************
* Name    : SetInput                                                       *
* Purpose : Sets the shift data in pin                                     *
****************************************************************************
}
public sub SetInput(byref pDataPin as bit)
   dim reg_offset as PROD      // 16-bit reg (must be in access bank)
  
   FDataIn.PortAddr = addressof(pDataPin)               // point address to port
   TRIS_OFFSET(reg_offset)                              // get TRIS offset
   FDataIn.TrisAddr = FDataIn.PortAddr + reg_offset     // TRIS addr
  
   FDataIn.Pin = bitof(pDataPin)
   FDataIn.PinMask = not FDataIn.Pin
end sub
{
****************************************************************************
* Name    : SetOutput                                                      *
* Purpose : Sets the shift data out clock pin                              *
****************************************************************************
}
public sub SetOutput(byref pDataPin as bit)
   dim reg_offset as PROD      // 16-bit reg (must be in access bank)

   FDataOut.PortAddr = addressof(pDataPin)              // PORT addr
   TRIS_OFFSET(reg_offset)                              // get TRIS offset
   FDataOut.TrisAddr = FDataOut.PortAddr + reg_offset   // TRIS addr
   LAT_OFFSET(reg_offset)                               // get LAT offset
   FDataOut.PortAddr = FDataOut.PortAddr + reg_offset   // change PortAddr to LAT addr

   FDataOut.Pin = bitof(pDataPin)
   FDataOut.PinMask = not FDataOut.Pin
end sub
{
****************************************************************************
* Name    : Set                                                            *
* Purpose : Sets the clock pins. An optional idle high determines if the   *
*         : clock pin idles high or low. The default is to idle low        *
*         : The clock address points to a port latch                       *
****************************************************************************
}
public sub SetClock(byref pClockPin as bit, pIdleHigh as boolean = false)
   dim reg_offset as PROD      // 16-bit reg (must be in access bank)

   FClock.PortAddr = addressof(pClockPin)               // PORT addr
   TRIS_OFFSET(reg_offset)                              // get TRIS offset
   FClock.TrisAddr = FClock.PortAddr + reg_offset       // TRIS addr
   LAT_OFFSET(reg_offset)                               // get LAT offset
   FClock.PortAddr = FClock.PortAddr + reg_offset       // change PortAddr to LAT addr

   FClock.Pin = bitof(pClockPin)
   FClock.PinMask = not FClock.Pin 
  
   // set clock idle state...
   FSR1 = FClock.PortAddr
   if pIdleHigh then
      INDF1 = INDF1 or FClock.Pin
   else
      INDF1 = INDF1 and FClock.PinMask   
   endif
  
   // make clock pin an output...
   FSR1 = FClock.TrisAddr
   INDF1 = INDF1 and FClock.PinMask
end sub
{
****************************************************************************
* Name    : Out                                                            *
* Purpose : Shift out a value by pShift bits. Date values can be up to 32  *
*         : bits in size. Mode can be either LSB_FIRST or MSB_FIRST        *
****************************************************************************
}
public sub Out(pMode as byte, pData as TType, pShift as byte=DEFAULT_SHIFT)
  
   // set data pin to output and load
   // data and clock address...
   MakeOutput()
   LoadDataOutAndClockAddr()
  
   // MSB first...
   if pMode.0 = 1 then
      pData = Reverse(pData, pShift)
   endif
    
   // shift out... 
   while (pShift > 0)
      if pData.0 = 0 then
         INDF0 = INDF0 and FDataOut.PinMask
      else
         INDF0 = INDF0 or FDataOut.Pin
      endif
      DataSetup()     
      ToggleClock()
      pData = pData >> 1
      dec(pShift)
   wend
   ClrWDT
end sub
{
****************************************************************************
* Name    : In                                                             *
* Purpose : Shift in a value by pShift bits. Date values can be up to 32   *
*         : bits in size. Mode can be MSB_PRE, MSB_POST, LSB_PRE or        *
*         : LSB_POST                                                       *
****************************************************************************
}
public function In(pMode as byte, pShift as byte=DEFAULT_SHIFT) as TType
   dim Index as byte

   // set data pin to input and load
   // data and clock address...
   MakeInput()
   LoadDataInAndClockAddr()
  
   // shift in...
   Result = 0
   Index = pShift
   while (Index > 0)
      Result = Result << 1
      
      // sample before clock...
      if pMode.1 = 0 then
         if (INDF0 and FDataIn.Pin) = 0 then
            Result.0 = 0
         else
            Result.0 = 1
         endif     
         ToggleClock()
      
      // sample after clock...
      else
         ToggleClock()
         if (INDF0 and FDataIn.Pin) = 0 then
            Result.0 = 0
         else
            Result.0 = 1
         endif     
      endif   
      dec(Index)
   wend
  
   // LSB first...
   if pMode.0 = 1 then
      Result = Reverse(Result,pShift)
   endif
   ClrWDT 
end function

end module

There you go
 
Well, I redid the schematic using the 74hc595 chips and am now going with SMD LEDs instead of through the hole.
Working on chopping the PCB into 6 pieces per clock. (not sure if I need more?)
I looked over the SF bas shift file and was thinking about how to implement it.
Jon suggested 9 pieces but I want a ring like post#122

Beau Schwabe

 
MrDEB - My suggestion not just for this project, but for ANY project you do is to bread board everything until you get the code and everything the way you want it. It is reckless to do otherwise. Get into the habit of building a schematic from your bread board design, and then replicate the design, on another breadboard, from the schematic. You will thank me later. It is not busy work, it reinforces accuracy. Also, I am a bit old school when it comes to programming, I taught myself assembly language when I was 12, the internet would not even be available for another 10+ years. Many things like shifting data into or outof a shift register become very bloated when you just throw a library at it and hope for the best when it is actually a very trivial requirement. I would simply suggest focus on your behalf and take time to understand some fundamentals. That means read and understand the datasheets, make with absolute certainty you are using the correct footprint for the part, and simply think things through carefully in your design.
 
Beau's design in post #105 uses 10 identical pcbs with 2 concentric rings of 60 LEDs each, to display hours and minutes, minutes and seconds or any desired quantity. That puts 6 LEDs per ring in each segment.

Since a clock face is mod 12 (i.e., 12 hours with 5 minutes between each hour), this doesn't work very well with MrDEB'S concept of a ring of 60 LEDs for minutes and a ring of 12 LEDs for hours – the hour position isn't consistent for each segment. Two rings of 60 LEDs works; a ring of 60 and a ring of 12 does not.

In posts #117 – #120, I looked at using six 60° slices. This provides for identical locations for two hour LEDs per board. If I was designing this for a 60 LED ring and a 12 LED ring (10 minute LEDs and 2 hour LEDs), I would use two 74595 shift registers on each segment, with 4 blank outputs.

The problem with this idea is that the chord becomes the controlling factor to board size rather than truncated radius (see the diagrams in posts #117 and # 118. The overall radius of the clock must be reduced to fit these boards in a 100mm × 100mm cheap board.

An alternative is to make the clock using twelve 30° segments. This puts 7 LEDs on each board with one shift register. The limitation of this approach is having enough room for the microcontroller.

The 2 × 60 LED rings is brilliant with 10 segments. The 60 LED + 12 LED rings are suboptimal for this approach.

I know this will be beyond Greek to the target audience, but it may benefit others.
 
I have discarded the mosfets and going with the 74hc595's
Looking over post3 119, a question comes to mind.
2- 60 led rings? =(120 leds)
Looking at post# 118 I see where your referring to the correct position of the minute leds
 
Looking over post3 119, a question comes to mind.
2- 60 led rings? =(120 leds)

There is no question in this statement.

That which can be explained has been explained. The rest, as they say, is left as an exercise for the reader.

As per Beau Schwabe 's suggestion, stop drawing schematics and laying out circuit boards until you understand what you're trying to do.
 
Big question?
post#105 has a schematic showing 2 transistors connected to outputs G & H
WHY?

Answered in post #119, along with the reason *I* would opt NOT to do that.

There are many fine points to understand in this. If you don't take time to understand them, and think everything through this will be another project for the scrap pile.
 
I am waiting for the shipment of 74hc595 chips. I have 20 smd and 20 the devices ordered.
In the meantime, I found a 74hc595 in the Arduino experimenters kit I have and breadboarded it but I don't have something right? Pressing the switches connected to the three inputs does nothing.
Need to recheck my circuit board. Note I have the switched wired so the inputs (CLOCK, DATA, & LATCH) are all grounded through a 10k resistor. Pressing a switch causes that input to go high.
 

Latest threads

New Articles From Microcontroller Tips

Back
Top