+ Reply to Thread
Results 1 to 40 of 69
-
- 14th January 2019, 20:30 #1
Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Hello.
I'm building a nixie clock, which does not uses any specific decoder ICs or multiplexer. Instead, all nixie digits are connected to individual MCU pins via transistors. It uses DS1302 as clock source. Time received from DS1302 is converted into single number in 24 hour format, for example, it time is 15:53, this number will read as 1553. Using DIG statement I'm extracting individual digits from it, so I have 4 variables, called T1-T4, which have data for individual number to be displayed on specific digit. The pin numbers to which nixies are connected are aliases in the following way - A0-A9 for numbers in 1st digit, B0-B9 for numbers in 2nd digit, C0-C9 and D0-D9 for 3rd and 4th digits correspondingly. So now, to display time, I need to run the following code:
IF T1=0 THEN A0=1
IF T1=1 THEN A1=1
IF T1=2 THEN A2=1
IF T1=3 THEN A3=1
IF T1=4 THEN A4=1
and so on, total, 40 lines (not shown is code for extinguishing all non-used numbers, but I'm doing it at same time for all digits)
So question is, is there a way to avoid all these if-then lines and do it somehow in more elegant way?
Thanks in advance!
-
- 14th January 2019, 23:00 #2
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Arrays?
Code:A_Vals var word(4) 'A0-A9, B0-B9, C0-C9, D0-D9 in each element; T_Vals var byte(4) 'T1-T4 i var byte Tx var byte Xx var word Begin: for i = 0 to 3 ' Clear array. A_Vals(i) = 0 T_Vals(i) = 0 next i Start: for i = 0 to 3 ' Scan 0-3 => T1-T4 Tx = T_Vals(i) ' Get the value of Tx variable. Xx = A_Vals(i) ' Get the value of Ax value. Xx[Tx]= 1 ' Change Ax value based on Tx value. A_Vals(i)=Xx ' Get the value back. next i goto start END
' Now you have all your pins masked in array A_Vals;
' A0 => A_Vals(0) bit.0-bit.9
' A4 => A_Vals(3) bit.0-bit.9
'.....
' you have to read them back from A_Vals, and assign your corresponding pins on its bits 0-9.
' For example,
' xx = A_Vals(0)
' A0 = ax.0(0)
' A9 = ax.0(8)
'...
' xx = A_Vals(3)
' B0 = ax.0(0)
' B9 = ax.0(8)"If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte
-
- 15th January 2019, 12:47 #3
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
How about a lookup table, 5 bytes (40 bits) wide and 10 deep (0-9).
George
-
- 15th January 2019, 17:53 #4
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Yes, table would be nice, but how to do with less iF-THEN ?
-
- 15th January 2019, 18:08 #5
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Here is a routine I wrote for my 6 digit nixie clock using 2 each HV5530P high voltage shift registers. That's 64 bits.
I use a 16F1825 14 pin processor running @ 10 Mhz. I don't like to use all of that hardware....
HVCLK VAR LATC.0 '0-SHIFT REGISTER CLOCK
HVSTB VAR LATC.1 '0-SHIFT REGISTER STROBE
HVDAT VAR LATC.2 '0-SHIFT REGISTER DATA
' ************************************************** ******************
CLOCKIT: 'ENCODE OUTPUT SEQUENCE AND SEND TO SHIFT REGISTER W/COLLONS
' ************************************************** ******************
'------------------------ 64 BIT ENCODE SEQUENCE ------------------------
'9876543210,9876543210,cc,9876543210,9876543210,cc ,9876543210,9876543210
'10's HOURs,1's HOURs ,::,10's MIN's,1's MIN's ,::,10'S SEC's,1'S SEC's
'------------------------------------------------------------------------
JUNK = 7 'FIRST CLEAR THE OUTPUT ARRAY
WHILE JUNK < 255
OUTPUTS(JUNK) = 0
JUNK = JUNK - 1
WEND
JUNK = 0 'NEXT SET THE OUTPUT ARRAY
WHILE JUNK < 6 'CYCLE THRU ALL 6 DIGITS TO DISPLAY
PATDOG = 1 'FEED THE DOG
SELECT CASE JUNK
CASE 0 'UNIT SECONDS 'BIT POSITION
OUTPUTS.0((JUNK * 10) + (SECONDS DIG 0)) = 1 '0-9
CASE 1 'TEN'S OF SECONDS
OUTPUTS.0((JUNK * 10) + (SECONDS DIG 1)) = 1 '10-19
OUTPUTS.0((JUNK * 10) + 10) = MINSECCOL '20
OUTPUTS.0((JUNK * 10) + 11) = MINSECCOL '21
CASE 2 'UNIT MINUTES
OUTPUTS.0((JUNK * 10) + 2 + (MINUTES DIG 0)) = 1 '22-31
CASE 3 'TEN'S OF MINUTES
OUTPUTS.0((JUNK * 10) + 2 + (MINUTES DIG 1)) = 1 '32-41
OUTPUTS.0((JUNK * 10) + 12) = HOURMINCOL '42
OUTPUTS.0((JUNK * 10) + 13) = HOURMINCOL '43
CASE 4 'UNIT HOURS
OUTPUTS.0((JUNK * 10) + 4 + (HOURS DIG 0)) = 1 '44-53
CASE 5 'TEN'S OF HOURS
'DISPLAY 10'S OF HOURS IF THERE IS SOMETHING TO DISPLAY
IF HOURS DIG 1 <> 0 THEN 'IF THERE IS A DIGIT TO DISPLAY
OUTPUTS.0((JUNK * 10) + 4 + (HOURS DIG 1)) = 1 '54-63
ENDIF
END SELECT
JUNK = JUNK + 1
WEND
SHIFTOUT HVDAT,HVCLK,MSBFIRST,[OUTPUTS(7)\8,OUTPUTS(6)\8,OUTPUTS(5)\8,OUTPUTS(4)\ 8,OUTPUTS(3)\8,OUTPUTS(2)\8,OUTPUTS(1)\8,OUTPUTS(0 )\8]
PULSOUT HVSTB,PULSE
RETURNDave Purola,
N8NTA
EN82fn
-
- 15th January 2019, 19:28 #6
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
I typically use DATA statements (simple with internal EEPROM) to map each 7 segment character in a byte value. 'A' segment is least significant digit, 'G' segment is bit 6. Bit 7 is unused. For example, the number 8 is %01111111 (all segments on), 1 is %00000011, etc. I then read the bit value and write it to a port or series of pins. If you store the digits in the corresponding memory location, you may simply READ [DIGIT VALUE + 1] to retrieve the segment code.
-
- 15th January 2019, 23:53 #7
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Single Nixie tube need 10 pin from micro. It's not 7 segment display. And only 1 pin need to te activated at time.
So most of suggestion wont work.
Unfortunately you need 40 statements to set pins. eg
IF T1=0 THEN
A0=1
ELSE
A0=0
ENDIF
By time you write first post you could write 40 IF statements without any problem.
That way you probably get smallest program size.
-
- 16th January 2019, 00:48 #8
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
If your ports and pins are consecutively mapped ie
Code:MAP PORTC PORTD PORTE PORTF PORTG 0127456701234567012345670123456701234567 DIG0 DIG1 DIG0 DIG3
;DIGO
PORTC.0[BIN VALUE OF DIGO]=1
;DIG1
PORTC.0[BIN VALUE OF DIG1+10]=1
;DIG2
PORTC.0[BIN VALUE OF DIG2+20]=1
;DIG3
PORTC.0[BIN VALUE OF DIG3+30]=1Last edited by richard; - 16th January 2019 at 00:53. Reason: white space
This is more entertaining than Free to Air TV
-
- 16th January 2019, 06:39 #9
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
I already wrote code with if-then-else, and it works fine, just wanted to make it more nice and tidy.
regarding port mapping, ports are 8 bit wide, but nixies are 10 bit, so that way won't work also....
-
- 16th January 2019, 06:41 #10
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
regarding port mapping, ports are 8 bit wide, but nixies are 10 bit, so that way won't work also....This is more entertaining than Free to Air TV
-
- 16th January 2019, 16:10 #11
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
If you are building a clock, the minutes digits never exceed 60 - you require 10 digits for the "ones" (0 - 9), but only 6 for the "tens" (0 - 5). So, it will be possible to map every possible minute on two ports or, in one word value. By writing in DATA statements the "ON" pattern for each possible minute, the DATA statements become a lookup table. For example at XX:34, the 70th DATA position (2 positions for each WORD value and allowing for "Zero" and 1 base offset ) contains the bit code (across two bytes) to turn on the 3 and the 4 on the relevant PORTs. Write the high byte to PORTB, the low to PORTA (or whatever). Of course some minutes - say 59 will be fully contained in the upper byte: 10000010_00000000 -because the two low order bits of the high byte are conscripted for the 9 and 0.
The Hours portion may be handled similarly. As before, you will use ten pins for the "ones" in the hours, but only - at most - three in the "tens" digit (0 - 1 - 2) . Place these values subsequent to the previous.
To retrieve the "minutes" value READ CURRENTMINUTE * 2 + 2, MIN_VAR. For hours, READ 122 + (CURRENTHOUR * 2), HOUR_VAR. The offset values are figures in my head and may require adjustment.
This method requires only two word variables - one for the minute value, one for the hour value and 144 - 168 EEPROM bytes. In truth, the values are easily calculated and it may be you determine only to calculate the bit value rather than store it.
-
- 16th January 2019, 21:57 #12
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
amoque's suggestion makes good sense
my map would become [note can be any 4 consecutive ports][can start at any bit too]
;DIGO
PORTC.0[BIN VALUE OF DIGO]=1
;DIG1
PORTC.0[BIN VALUE OF DIG1+10]=1
;DIG2
PORTC.0[BIN VALUE OF DIG2+17]=1
;DIG3
PORTC.0[BIN VALUE OF DIG3+27]=1Last edited by richard; - 16th January 2019 at 22:00.
This is more entertaining than Free to Air TV
-
- 16th January 2019, 23:09 #13
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
If DIG0 is "ones" digit of minutes, and DIG1 is "tens" digit, then:
READ [MINUTEVALUE + 1], WORD WordVar
PORTC = WordVar.lowbyte
PORTD = WordVar.HighByte
In fact, you could then:
READ [HOURVALUE + 1], WORD Wordvar
PORTE = WordVar.lowbyte
PORTF = WordVar.HighByte
This would overwrite F.6..7, but if you aren't using them...
.
.
.
' BIT CODE OF "00", BIT CODE OF "01", BIT CODE OF "02"...
DATA %00000100_00000001, %00000100_00000010, %00000100_00000100,
Will set PORTC.0 and PORTD.2 HIGH (presumably turning on the "0" digit in both positions. It may be your transistors are active low and would therefore require the inverse bit values (%11111011_11111110). WARNING: I did NOT look up the specific syntax of the READ and DATA statements, you should verify these.Last edited by Amoque; - 16th January 2019 at 23:34.
-
- 17th January 2019, 02:22 #14
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
IF you do it my way, assuming HOUR,MINUTE are bcd byte values read from a rtc
Code:GOSUB SETDISPLAY LATC=0 LATD=0 LATE=0 LATF=0 LATC.0[MINUTE&$0F]=1 LATC.0[(MINUTE>>4)+10]=1 LATC.0[HOUR&$0F)+17]=1 LATC.0[(HOUR>>4)+27]=1 RETURN
This is more entertaining than Free to Air TV
-
- 17th January 2019, 06:36 #15
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
It seems that nobody paid attention to my routine.
"If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte
-
- 17th January 2019, 06:57 #16
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
It seems that nobody paid attention to my routine.
1 understand how to feed the time from say two bcd encoded bytes into it
2 how it maps the resultant data onto the pins
perhaps you could explain more fully and develop the process a bit further
naming the var more meaningfully helps , i know when i'm deep in a pgm at the time its easy to see the big picture and keep track
but when i come back at a later time i wonder what was i doing here and why, i often wish i named things better with more commentsThis is more entertaining than Free to Air TV
-
- 17th January 2019, 10:31 #17
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Actually, for the number of digits:
Tens of hours n: 0 1 2 - 3 pins
Ones of hours: 0 1 2 3 4 5 6 7 8 9 - 10 pins
Tens of minutes: 0 1 2 3 4 5 - 6 pins
Ones of minutes: 0 1 2 3 4 5 6 7 8 9 - 10 pins
Single pin is needed for blinking middle dot.
So we have 3+10+6+10+1=30 pins. But I can't map them sequentially, due to pcb and other assembly restrictions. Currently say "4" in tens of minutes is PORTB.2, but "5" is PORTC.4 and so on
-
- 17th January 2019, 14:47 #18
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Code:' These epins are just example pins. ' Pin number can be in any order; does not have to be in a sequence. A0 var PORTA.0 A1 var PORTB.0 A2 var PORTC.0 A3 var PORTD.0 A4 var PORTE.0 A5 var PORTF.0 A6 var PORTA.0 A7 var PORTA.0 A8 var PORTA.0 A9 var PORTA.0 B0 var PORTA.0 B1 var PORTD.0 B2 var PORTC.0 B3 var PORTE.0 B4 var PORTG.0 B5 var PORTB.0 B6 var PORTB.0 B7 var PORTB.0 B8 var PORTB.0 B9 var PORTB.0 C0 var PORTB.0 C1 var PORTF.0 C2 var PORTD.0 C3 var PORTE.0 C4 var PORTC.0 C5 var PORTC.0 C6 var PORTC.0 C7 var PORTC.0 C8 var PORTC.0 C9 var PORTC.0 D0 var PORTE.0 D1 var PORTF.0 D2 var PORTH.0 D3 var PORTA.0 D4 var PORTB.0 D5 var PORTC.0 D6 var PORTD.0 D7 var PORTD.0 D8 var PORTD.0 D9 var PORTD.0 A_Vals var word(4) 'A0-A9, B0-B9, C0-C9, D0-D9 in each element; T_Vals var byte(4) 'T1-T4 i var byte Tx var byte Xx var word '===== These are your T Vals ======== '=== Use them in your code, and assign the values to them. T1 var T_Vals(0) T2 var T_Vals(1) T3 var T_Vals(2) T4 var T_Vals(3) AVal var A_Vals(0) BVal var A_Vals(1) CVal var A_Vals(2) DVal var A_Vals(3) Begin: for i = 0 to 3 ' Clear array. A_Vals(i) = 0 T_Vals(i) = 0 next i Start: 'Here, your T1-T4 variables get their values from your routine somewhere in your code. gosub GetPinValues for i = 0 to 3 ' Scan 0-3 => T1-T4 Tx = T_Vals(i) ' Get the value of Tx variable which can be 0...9 Xx = A_Vals(i) ' Get the value of Ax value. We use bits from 0 to 9 inside Xx word. Xx.0[Tx]= 1 ' Change Ax value based on Tx value. If TX = 0 then Xx.0[0] = 1, if Tx=9 then Xx.0[9] = 1 ... etc. ' Now here, something may be missing?!! Where do you make the pin = 0 after it gets to be = 1 ?? A_Vals(i)=Xx ' Get the assigned bits to be masked on A_vals. Now your bit arrangement is in A_Vals(i). next i 'Here, you now have all your corresponding bit values assigned into A_Vals(0-3). gosub AssignPins goto start GetPinValues: ' Assign your Tx values. T1 = 1 T2 = 2 T3 = 3 T4 = 4 ' or use T_Vals() array.... Return AssignPins: A0 = AVal.0 A1 = AVal.1 A2 = AVal.2 A3 = AVal.3 A4 = AVal.4 A5 = AVal.5 A6 = AVal.6 A7 = AVal.7 A8 = AVal.8 A9 = AVal.9 B0 = bVal.0 B1 = bVal.1 B2 = bVal.2 B3 = bVal.3 B4 = bVal.4 B5 = bVal.5 B6 = bVal.6 B7 = bVal.7 B8 = bVal.8 B9 = bVal.9 C0 = cVal.0 C1 = cVal.1 C2 = cVal.2 C3 = cVal.3 C4 = cVal.4 C5 = cVal.5 C6 = cVal.6 C7 = cVal.7 C8 = cVal.8 C9 = cVal.9 D0 = DVal.0 D1 = DVal.1 D2 = DVal.2 D3 = DVal.3 D4 = DVal.4 D5 = DVal.5 D6 = DVal.6 D7 = DVal.7 D8 = DVal.8 D9 = DVal.9 return END
Use pins in any order;
Assign your T values before getting into scan routine.
After scan, assign your pins to scanned & masked variables AVal...DVal.
Much cleaner, shorter, smaller and easier."If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte
-
- 17th January 2019, 20:29 #19
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Thanks, looks really promising, will give it try this weekend....
-
- 22nd January 2019, 12:19 #20
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
-
- 22nd January 2019, 17:46 #21
-
- 22nd January 2019, 17:58 #22
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
I looked at it and, frankly, suggest that:
Code you write (and understand) is far more maintainable, and therefore "better" than code someone else writes that cannot be modified later. The difficulty in this specific case is that there are few options to IF THEN. You may look at SELECT CASE, but it will be only marginally different. Initially, I dismissed the topic because - it worked! It was only when I read Richard's comment "Look again" that I did so - and realized the inefficiency of reading, calculating, and setting each bit and digit individually that I thought about what I saw.
I maintain that code you understand is paramount. I made a suggestion for change because you can save a significant number of pins by dealing with HOURS and MINUTES as individual units (as I described) and, so long as you have EEPROM, you are perhaps able to save significant resources. It is also a possibility that the EEPROM map can be modified to enhance certain features. For example - you may, perhaps, define two sets of hour maps - on with the decimal lit and one without, then load alternates based on odd/ even seconds - thus, a "flashing" second indicator. When using matrix LEDs I find it handy to be able to redesign characters (via the map) without changing the code.
It will depend on your aim in this project. If you want only a Nixie Clock and have no intention of evolving your ability (in regard) and learning from it in the future, then any solution that "works" is good enough. You need not understand it or be comfortable modifying it. However, depending on future goals, starting with code you understand, having a flexible design, and continuing to revisit with a growing understanding become greater priorities.
As always, DIY is about solving your own priorities - and enjoying the satisfaction of doing it.
Amoque
-
- 27th January 2019, 20:25 #23
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
The reason why I'm using separate pins for each digit can be seen in this short video:
And as you can guess, there are no PIC16 chips with 40 available IO ports at all
I've finished first revision of PCB, and DS1302 now is mapped on PORTA.5-7 ports now. And it does not works. While segments can be turn on/off without issues on PORTA, clock chip gives no response. The MCU used is PIC16F1519 and config looks like this:
Code:OSCCON = %01111010 'SET INTOSC TO 16MHZ ANSELC=%00000000 ANSELD=%00000000 'disable ADC ANSELB=%00000000 ANSELA=%00000000 ANSELE=%00000000 TRISC=%00000000 'set PORTS as output all TRISD=%00000000 TRISB=%00000000 TRISA=%00111000 '3 ports are inputs, but changing them to outputs also does nothing TRISE=%00000000 DEFINE OSC 16 'OSC SPEED
-
- 27th January 2019, 20:36 #24
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
"If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte
-
- 27th January 2019, 20:50 #25
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Well chip works fine, and I can light up any digits via any pins in software.
here is config used in above code
Code:;----[16F1519 Hardware Configuration]------------------------------------------- #IF __PROCESSOR__ = "16F1519" #DEFINE MCU_FOUND 1 #CONFIG cfg1 = _FOSC_INTOSC ; INTOSC oscillator: I/O function on CLKIN pin cfg1&= _WDTE_OFF ; WDT disabled cfg1&= _PWRTE_OFF ; PWRT disabled cfg1&= _MCLRE_ON ; MCLR/VPP pin function is MCLR cfg1&= _CP_OFF ; Program memory code protection is disabled cfg1&= _BOREN_OFF ; Brown-out Reset disabled cfg1&= _CLKOUTEN_OFF ; CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin cfg1&= _IESO_OFF ; Internal/External Switchover mode is disabled cfg1&= _FCMEN_OFF ; Fail-Safe Clock Monitor is disabled __CONFIG _CONFIG1, cfg1 cfg2 = _WRT_OFF ; Write protection off cfg2&= _VCAPEN_OFF ; VCAP pin function disabled cfg2&= _STVREN_ON ; Stack Overflow or Underflow will cause a Reset cfg2&= _BORV_LO ; Brown-out Reset Voltage (Vbor), low trip point selected. cfg2&= _LPBOR_OFF ; Low-Power BOR is disabled cfg2&= _LVP_OFF ; High-voltage on MCLR/VPP must be used for programming __CONFIG _CONFIG2, cfg2 #ENDCONFIG #ENDIF ;----[Verify Configs have been specified for Selected Processor]---------------- ; Note: Only include this routine once, after all #CONFIG blocks #IFNDEF MCU_FOUND #ERROR "No CONFIGs found for [" + __PROCESSOR__ +"]" #ENDIF
-
- 28th January 2019, 00:25 #26
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
CuriousOne
Sorry to go off topic, but how did you menage to create that turn on?
It look amazing...
-
- 28th January 2019, 00:30 #27
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
If you can " light up any digits via any pins in software", it is unlikely to be the configuration. More likely in my mind the I2C routines to retrieve clock data. Can you get Hour and Minute values to display on LCD or via the serial comms provided in PB? If you don't have any of the cheap TTL to Serial modules available on Ebay or Amazon for a few bucks, they are (with a serial cable) a worthwhile investment. A 4x20 LCD can also be very helpful in providing some troubleshooting output, if you haven't anything else.
Presuming you have serial, this should (configure the serial com screen (in PB) to match):
'-----DEBUG (SERIAL) SETUP----------------------------------------
DEFINE DEBUG_REG PORTB
DEFINE DEBUG_BIT 5
DEFINE DEBUG_BAUD 2400
DEFINE DEBUG_MODE 0
Should get you some output and a way to demonstrate you are getting output from the clock. You can read up on all the formatting codes, but start with "TEST", 13, then start adding variables when you're sure you've got it going.
Once you know you can output to serial... Here are some routines I use with the DS series clocks. I use the DS1337 - its supposed to be high accuracy, but I just found them in battery backed-up modules for cheap and... no fiddling with crystals, or wires.
Code:'-----I2C SET-UP------------------------------------------------- SDA VAR PORTB.1 SCL VAR PORTB.4 '-----CLOCK SET-UP------------------------------------------------ RTC_ADD CON %11010000 REG_TIM CON $00 REG_AL1 CON $07 ' Not implemented REG_AL2 CON $0B ' Not implemented REG_SPC CON$0E REG_STS CON $0F '-----TIME/ CLOCK VARIABLES---------------------------------------- REG_VAL VAR Byte[7] ' Seconds, minutes, hours, day of week, date, month, year '-----SET INITIAL TIME----------------------------------------------- 'FOR FUNCTION TEST, JUST SET EACH REGISTER TO ITS POSITION - LP[0] = 0 SECONDS, LP[1] = 1 MINUTE, LP[2] = 2 HOUR... FOR LP = 0 TO 6 ' For each register REG_VAL[LP] = LP ' Set value to address NEXT LP ' Loop GOSUB CLK_WRITE '+++++MAIN LOOP+++++++++++++++++++++++++++++++++++++++++++++++++++ MAIN: GOSUB CLK_READ: ' Read clock PAUSE 500 ' Pause GOTO MAIN END CLK_READ: '-----READ TIME, CONVERT FROM BCD TO DECIMAL, DISPLAY-------------------------------------------------------------------- I2CRead SDA, SCL, RTC_ADD, REG_TIM, [REG_VAL[0], REG_VAL[1], REG_VAL[2], REG_VAL[3], REG_VAL[4], REG_VAL[5], REG_VAL[6]] FOR LP = 0 TO 6 ' For each register D0 = (REG_VAL[LP] >> 4) * 10 ' Decode 10's digit D1 = REG_VAL[LP] & %0001111 ' Blank 10's, get 1's REG_VAL[LP] = D0 + D1 ' Write Decimal value to register NEXT LP ' Next register DEBUG "TIME:[", dec1 REG_VAL[3], "] ", dec2 REG_VAL[5], "/", dec2 REG_VAL[4], "/", dec2 REG_VAL[6], " ", dec2 REG_VAL[2], ":", dec2 REG_VAL[1], ":", DEC2 REG_VAL[0], 13 RETURN CLK_WRITE: '-----CONVERT TO BCD VALUES, WRITE TO CLOCK REGISTERS ---------------------------------------------------------------------- FOR LP = 0 TO 6 ' For each register D0 = REG_VAL[LP] / 10 ' Get decimal 10's digit D1 = REG_VAL[LP] // 10 ' Get decimal 1's REG_VAL[LP] = (D0 << 4) + D1 ' Shift BCD 10's in, add 1's NEXT LP ' Next register I2CWrite SDA, SCL, RTC_ADD, REG_TIM, [REG_VAL[0], REG_VAL[1], REG_VAL[2], REG_VAL[3], REG_VAL[4], REG_VAL[5], REG_VAL[6]] GOSUB CLK_READ ' Update display RETURN
Last edited by Amoque; - 28th January 2019 at 00:49.
-
- 28th January 2019, 05:55 #28
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
The animated turn on/off is created via a hardware trick, which we were using in times, when SN74141 was not widely available (~30 years ago). It requires 2 transistors per each digit, so this clock uses 60 pcs of MPSA42 transistors just to do this
I'm planning to put this clock on instructables, so all details, including schematics and PCB will be available there.
For the code (I'm using one from PBP examples). Initially, I had test setup assembled on breadboard. DS1302 module was connected to PORTC.1-2-3 and worked fine. I had MAX7219 connected and code worked as it should. However, when moving to PCB, to ease process of PCB design, I had to move DS1302 to PORTA. So now it does not works. The reason might be that I've messed up with wiring, but I wanted to be sure to ask, whenever there might be some specific additional configs needed for PORTA.
-
- 28th January 2019, 07:28 #29
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Thanks, please post link to instructables.
Do you have pull up resistors on I2C lines?
Also post code for reading RTC, so we can help. This way is hard to guess what is wrong.
All address for used for I2C should be byte or word, for proper function off i2CREAD/WRITE.
I2C command uses variables size to send proper no of bits for addresses(8 or 16 bits).Last edited by pedja089; - 28th January 2019 at 07:33.
-
- 28th January 2019, 08:09 #30
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Here is complete code, but a lot of "water" in it
Code:;----[16F1519 Hardware Configuration]------------------------------------------- #IF __PROCESSOR__ = "16F1519" #DEFINE MCU_FOUND 1 #CONFIG cfg1 = _FOSC_INTOSC ; INTOSC oscillator: I/O function on CLKIN pin cfg1&= _WDTE_OFF ; WDT disabled cfg1&= _PWRTE_OFF ; PWRT disabled cfg1&= _MCLRE_ON ; MCLR/VPP pin function is MCLR cfg1&= _CP_OFF ; Program memory code protection is disabled cfg1&= _BOREN_OFF ; Brown-out Reset disabled cfg1&= _CLKOUTEN_OFF ; CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin cfg1&= _IESO_OFF ; Internal/External Switchover mode is disabled cfg1&= _FCMEN_OFF ; Fail-Safe Clock Monitor is disabled __CONFIG _CONFIG1, cfg1 cfg2 = _WRT_OFF ; Write protection off cfg2&= _VCAPEN_OFF ; VCAP pin function disabled cfg2&= _STVREN_ON ; Stack Overflow or Underflow will cause a Reset cfg2&= _BORV_LO ; Brown-out Reset Voltage (Vbor), low trip point selected. cfg2&= _LPBOR_OFF ; Low-Power BOR is disabled cfg2&= _LVP_OFF ; High-voltage on MCLR/VPP must be used for programming __CONFIG _CONFIG2, cfg2 #ENDCONFIG #ENDIF ;----[Verify Configs have been specified for Selected Processor]---------------- ; Note: Only include this routine once, after all #CONFIG blocks #IFNDEF MCU_FOUND #ERROR "No CONFIGs found for [" + __PROCESSOR__ +"]" #ENDIF 'nixie led clock electronics direct drive include "modedefs.bas" OSCCON = %01111010 'SET INTOSC TO 16MHZ ANSELC=%00000000 ANSELD=%00000000 'disable ADC ANSELB=%00000000 ANSELA=%00000000 ANSELE=%00000000 TRISC=%00000000 'set PORTC as output all TRISD=%00000000 'set PORTD as output all TRISB=%00000000 'set PORTD as output all TRISA=%00111000 TRISE=%00000000 DEFINE OSC 16 'OSC SPEED X VAR WORD ' TEMP VARIABLE X=200 'TENS HOURS PINS A0 VAR PORTD.7 A1 VAR PORTD.6 A2 VAR PORTD.5 'ONES HOURS PINS B0 VAR PORTB.2 B1 VAR PORTB.3 B2 VAR PORTB.5 B3 VAR PORTB.4 B4 VAR PORTD.4 B5 VAR PORTA.0 B6 VAR PORTA.1 B7 VAR PORTA.2 B8 VAR PORTE.0 B9 VAR PORTB.1 'BLINKING DOT DOT VAR PORTE.1 'TENS OF MINUTES C0 VAR PORTC.7 C1 VAR PORTB.0 C2 VAR PORTE.2 C3 VAR PORTA.7 C4 VAR PORTC.0 C5 VAR PORTC.1 'ONES OF MINUTES D0 var PORTD.3 D1 VAR PORTC.4 D2 VAR PORTC.5 D3 VAR PORTC.6 D4 VAR PORTC.2 D5 VAR PORTC.3 D6 VAR PORTD.0 D7 var PORTD.1 D8 VAR PORTA.6 D9 var PORTD.2 'DS 1302 pins RST Var PORTA.5 IO Var PORTA.4 SCLK Var PORTA.3 ' DS1302 Allocate variables rtcyear Var byte rtcday Var byte rtcmonth Var byte rtcdate Var byte rtchr Var byte rtcmin Var byte rtcsec Var byte rtccontrol Var byte 'my time variables saatebi var word cutebi var word DRO var word T1 VAR WORD 'VARIABLES FOR TIME DIGITS T2 VAR WORD T3 VAR WORD T4 VAR WORD ' MTAVARI KODI AQ ' Set initial time to 8:00:00AM 07/16/99 rtcyear = $99 rtcday = $06 rtcmonth = $07 rtcdate = $16 rtchr = $23 rtcmin = $48 rtcsec = 0 Gosub settime ' Set the time mtavari: 'high dot gosub gettime 't1=2 't2=3 't3=4 't4=5 gosub display 'pause 100 'low dot 'pause 100 goto mtavari DISPLAY: 'DECODE VALUES AND DISPLAY THEM 'tens hours IF T1=0 THEN HIGH A0 ELSE LOW A0 ENDIF IF T1=1 THEN HIGH A1 ELSE LOW A1 ENDIF IF T1=2 THEN HIGH A2 ELSE LOW A2 ENDIF 'ONES HOURS IF T2=0 THEN HIGH B0 ELSE LOW B0 ENDIF IF T2=1 THEN HIGH B1 ELSE LOW B1 ENDIF IF T2=2 THEN HIGH B2 ELSE LOW B2 ENDIF IF T2=3 THEN HIGH B3 ELSE LOW B3 ENDIF IF T2=4 THEN HIGH B4 ELSE LOW B4 ENDIF IF T2=5 THEN HIGH B5 ELSE LOW B5 ENDIF IF T2=6 THEN HIGH B6 ELSE LOW B6 ENDIF IF T2=7 THEN HIGH B7 ELSE LOW B7 ENDIF IF T2=8 THEN HIGH B8 ELSE LOW B8 ENDIF IF T2=9 THEN HIGH B9 ELSE LOW B9 ENDIF 'tens of minutes IF T3=0 THEN HIGH C0 ELSE LOW C0 ENDIF IF T3=1 THEN HIGH C1 ELSE LOW C1 ENDIF IF T3=2 THEN HIGH C2 ELSE LOW C2 ENDIF IF T3=3 THEN HIGH C3 ELSE LOW C3 ENDIF IF T3=4 THEN HIGH C4 ELSE LOW C4 ENDIF IF T3=5 THEN HIGH C5 ELSE LOW C5 ENDIF 'ONES OF MINUTES IF T4=0 THEN HIGH D0 ELSE LOW D0 ENDIF IF T4=1 THEN HIGH D1 ELSE LOW D1 ENDIF IF T4=2 THEN HIGH D2 ELSE LOW D2 ENDIF IF T4=3 THEN HIGH D3 ELSE LOW D3 ENDIF IF T4=4 THEN HIGH D4 ELSE LOW D4 ENDIF IF T4=5 THEN HIGH D5 ELSE LOW D5 ENDIF IF T4=6 THEN HIGH D6 ELSE LOW D6 ENDIF IF T4=7 THEN HIGH D7 ELSE LOW D7 ENDIF IF T4=8 THEN HIGH D8 ELSE LOW D8 ENDIF IF T4=9 THEN HIGH D9 ELSE LOW D9 ENDIF 'ended return ' Subroutine to write time to RTC settime: RST = 1 ' Ready for transfer ' Enable write Shiftout IO, SCLK, LSBFIRST, [$8e, 0] RST = 0 ' Reset RTC RST = 1 ' Ready for transfer ' Write all 8 RTC registers in burst mode Shiftout IO, SCLK, LSBFIRST, [$be, rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, 0] RST = 0 ' Reset RTC Return ' Subroutine to read time from RTC gettime: RST = 1 ' Ready for transfer Shiftout IO, SCLK, LSBFIRST, [$bf] ' Read all 8 RTC registers in burst mode Shiftin IO, SCLK, LSBPRE, [rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, rtccontrol] RST = 0 ' Reset RTC saatebi =( rtchr >> 4 * 10 ) + ( rtchr // 16 ) 'GET TIME VALUES INTO 4 DIGIT VARIABLE cutebi =( rtcmin >> 4 * 10 ) + ( rtcmin // 16 ) DRO=SAATEBI*100+CUTEBI 'DECODE TIME INTO SEGMENT VARIABLES T1=DRO DIG 1 T2=DRO DIG 2 T3=DRO DIG 3 T4=DRO DIG 4 'T4=rtcsec //16 'test Return :SEGTEST 'test all segments HIGH A0 PAUSE X LOW A0 HIGH A1 PAUSE X LOW A1 HIGH A2 PAUSE X LOW A2 HIGH B0 PAUSE X LOW B0 HIGH B1 PAUSE X LOW B1 HIGH B2 PAUSE X LOW B2 HIGH B3 PAUSE X LOW B3 HIGH B4 PAUSE X LOW B4 HIGH B5 PAUSE X LOW B5 HIGH B6 PAUSE X LOW B6 HIGH B7 PAUSE X LOW B7 HIGH B8 PAUSE X LOW B8 HIGH B9 PAUSE X LOW B9 HIGH C0 PAUSE X LOW C0 HIGH C1 PAUSE X LOW C1 HIGH C2 PAUSE X LOW C2 HIGH C3 PAUSE X LOW C3 high c4 pause x low c4 high c5 pause x low c5 high d0 pause x low d0 high d1 pause x low d1 high d2 pause x low d2 high d3 pause x low d3 high d4 pause x low d4 high d5 pause x low d5 high d6 pause x low d6 high d7 pause x low d7 high d8 pause x low d8 high d9 pause x low d9 high dot pause x low dot RETURN
-
- 28th January 2019, 09:01 #31
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
I din't look at datasheet, so I assume that RTC is I2C.
RST is input, so it wont never go high. And your clock isn't selected.
Things like this:
RST = 0 ' Reset RTC
RST = 1 ' Ready for transfer
Can make a lot of problem. Depending on how long are your traces, etc it can fail. Look up about RMW issue on PIC.
You can try to add pauses, or slow down PIC clock. and try to use HIGH and LOW, this is little slower and it will set pin to output.
Also try to put LED on 3 pin used by RTC, and drive them with HIGH LOW, to see if they work.
-
- 28th January 2019, 11:45 #32
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
It appears to be config issue. When using PORTC for DS1302, all works correctly. When try to use PORTA, even on breadboard it does not works.
-
- 28th January 2019, 13:32 #33
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
fixed configs, it now works on breadboard. later will try with nixies.
-
- 28th January 2019, 14:07 #34
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Can you tell what was issue. Because I still don't see it...
-
- 28th January 2019, 19:14 #35
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
When copying code, I was missing this during initialisation:
Low RST ' Reset RTC
Low SCLK
after I added it, it now works, but now I have another issue - DIG does not converts time properly. The code for that I'm using is as follows:
Code:gettime: RST = 1 ' Ready for transfer Shiftout IO, SCLK, LSBFIRST, [$bf] ' Read all 8 RTC registers in burst mode Shiftin IO, SCLK, LSBPRE, [rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, rtccontrol] RST = 0 ' Reset RTC saatebi =( rtchr >> 4 * 10 ) + ( rtchr // 16 ) 'GET TIME VALUES INTO 4 DIGIT VARIABLE cutebi =( rtcmin >> 4 * 10 ) + ( rtcmin // 16 ) DRO=SAATEBI*100+CUTEBI 'DECODE TIME INTO SEGMENT VARIABLES T1=DRO dig 1 T2=DRO DIG 2 T3=DRO DIG 3 T4=DRO DIG 4 Return
-
- 28th January 2019, 19:23 #36
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
This works, but only for ones of hours and ones for minutes. Does not works for tens of hours and tens for minutes. But the problem is, that I've copied this code from somewhere, and have no clue how it works...
t1=rtchr >> 4 * 10
t2=rtchr // 16
T3=rtcmin >> 4 * 10
T4=rtcmin // 16
-
- 28th January 2019, 19:27 #37
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
Oh, need to read manual
removed * 10 and all works fine.
-
- 29th January 2019, 02:09 #38
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
I use similar code, but it's faster, and take less space.
t1=rtchr >> 4
t2=rtchr & %00001111
T3=rtcmin >> 4
T4=rtcmin & %00001111
It is always faster to do logic, than math.
-
- 29th January 2019, 09:10 #39
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
I'm facing another problem
statement like WRITE 1, variable or READ 1, variable give "symbol not previously defined" error, but I have variable defined and it can be used with other statements without an issues.
-
- 29th January 2019, 09:29 #40
Re: Need to drive 40 pins on variable change, is there a way to do it in elegant way?
you need a chip that has some eeprom to use read/write
This is more entertaining than Free to Air TV
Similar Threads
-
Can not change variable while using DT_INT?
By hvguy0 in forum mel PIC BASIC ProReplies: 6Last Post: - 30th March 2013, 00:05 -
Change a variable to the opposite?
By Hylan in forum mel PIC BASIC ProReplies: 10Last Post: - 21st June 2012, 07:00 -
LCD DB4-DB7 4bit mode change pins?
By erice1984 in forum mel PIC BASIC ProReplies: 2Last Post: - 6th March 2009, 02:36 -
Accessing pins with a variable
By Desterline in forum mel PIC BASIC ProReplies: 9Last Post: - 20th August 2004, 16:03 -
Let a variable change from bin to dec.
By Roy in forum mel PIC BASIC ProReplies: 2Last Post: - 25th May 2004, 19:57
Bookmarks