PDA

View Full Version : How to shoehorn MORE text into 2k or how to squeeze in the most bytes.



ofuzzy1
- 18th October 2011, 07:04
Sample code for:
Working with Strings via EEPROM, can be used for LCD output as well.
Doing Serial I/O using the DEBUG / DEBUGIN commands.
Moving strings from the internal EEPROM using the READ command
Storing on the internal EEPROM using the DATA command.
Fun with DCD command [see the A2D - ANSELA]

For the temperature sensor used:
MICROCHIP - MCP9701A-E/TO - IC, TEMP SNSR, ±1°C, 3-TO-92
@ $0.31 each from newark.com Nice easy and get ~.1C resolution using directly connected ANx input & used a .1uf cap for filtering.

.1C -- more than I needed. And don't believe it either :)

Sample output

Alarm_Min= 2 < NormalOn= 4 <? TempIn= 27.8 <? TempOut= 27.2 <? NormalOff= 29 < Alarm_Max= 32

Working on the the 12f1822, [think of a 12f683 with more vrooom and cheaper] -

12f1822= 8pin with 12f1822 2K ram 128 eeprom 256 io= 6 a2d= 4 timers= 2/1


Doing Serial I/O using the DEBUG / DEBUGIN commands.
Some other details of using Debug for outputs.
DEBUG stores the string as TWO BYTES each
So use it wisely.

Needed more space and the eeprom was not being used after $10.

So here are two version of using the eeprom space. [256 bytes -- use a byte for indexing]

6070

Used in both examples:


' ---- The temps they do all the grunt work with little or no pay :)
AB VAR BYTE ' TEMP Used in Text output
BB VAR BYTE ' TEMP Used in Text output
zb var byte ' temp Used in Text output
....

#1 is easy to see what the text is, but wastes a byte for the end of text marker.




' EEPROM Storage done at compilation time
'========== ends with a ZERO ====== Wastes a byte ==========
W_Enter Data "Enter",0
W_YNRQ Data "Y=Yes R=Redo N=No Q=Quit ?",0
W_Want_to Data "Want to",0

....
Main


' Call the print progam that uses zero as the end of text marker.
zb= W_YNRQ : GOSUB Print_ROM_0

End



'== SUBROUTINE ================================================== ===========

Print_ROM_0: ' Call with zb = ROM_Memory_Location
ab = 0
[B]debug "ROM Memory= ", #zb , CR,LF ' normal debug output command
Do
read zb, ab
if !ab then debug ab
zb= zb + 1
loop until !ab ' SAME AS AB = 0
Return



#2 is mostly easy to see what the text until the last char. The last char has $80 [128] added to it.
This does not waste a byte for the end of text marker.



' EEPROM Storage done at compilation time
CharBump con $80
' @$10 ==> starts the data at eeprom location $10

'========== ends with the last character >128 - Does not Waste a byte ========
Ofuzzy1 data @$10, "(C)2011 Ofuzzy1 - Not for Life Critical Use", "!" + CharBump
W_Alarm Data "Alarm", "_" + CharBump
W_Min Data "Mi", "n" + CharBump

....

Main

' Call the print progam that uses last byte over 128 as the end of text marker.
zb= W_Alarm : gosub Print_ROM_127

End

'== SUBROUTINE ================================================== ===========

Print_ROM_127: ' Call with zb = ROM_Memory_Location [byte]
bb = 1
Do until !BB ' SAME AS "Do until BB = 0" but uses one less byte
read zb, ab
if ab > CharBump-1 then ' > 127
ab = ab - CharBump
bb = 0
endif
debug ab ' Debug like all the other printing commands does not allow any math operations
zb= zb + 1
loop
return
'================================================= =====================================




Also included is the 'pre-amble' for setting up the 12f1822 or 16f1925 or 16f1829

To compile for the 12f683...
This is close, don't ask me about this, if not complete, on this thread I will post my 12f683 preamble later. Did it from memory. :}


comment out: OSCCON, fvcon, ADCON1
Change: ANASELA TO ANASEL,
TRISA TO TRIS

CHANGE THE TWO CONFIG LINES TO:
@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF



OTHER 12F683 CLUES: FROM SOME MY EARLY CODE
' CMCON = $07 '12F675 CMCON — COMPARATOR CONTROL REGISTER ALL DIGITAL
CMCON0 = $07 '12F683 CMCON0 — COMPARATOR CONTROL REGISTER ALL DIGITAL
' TRISIO = 111011 'SET TO ALL OUTPUTS 1=INPUT
' ADCON1 = 100000 ' Set a2d convert at clk/6 [slowest]
' ADCON1 = 000000 ' Set a2d convert at clk/2 [fastest]
ANSEL = 000000 ' AN0/RA0 as analog input 1=ANALOG
' ADCON0 = 000001 ' .7=10bits left justify result!! / .0 1=a2d ON
ADCON0 = 000000 ' .7=10bits left justify result!! / .0 1=a2d ON
' WPUA = 000000 ' TURN ON WEAK PULLUP 1=ON VALID=.5.4.2.1.0








' Compiles for the 12f1822 or 16f1825 or 16f1829
' 16f1825 & 16f1829 are the 'same' just different # of pins
'
' chip Prog Ram Eeprom IO A2D Timers .....see sheets for more info
' 8/16 bit
' 12f1822 2K 128 256 6 4 2/1
' 16f1825 8k 1k 256 12 8 4/1
' 16f1829 8k 1k 256 18 12 4/1
'
' This is a demo to show how to use the EEPROM for text storage
' The text can be summoned for use via the LCD or a serial output
' -- this example is how to use the SERIAL command "DEBUG" & "DEBUGIN"
' for serial output on any pin of our choosing.
' Debug like all the other printing commands does not allow any math operations
' Debug like all the other printing commands does not allow any math operations
' Debug like all the other printing commands does not allow any math operations
' Debug like all the other printing commands does not allow any math operations
' Debug like all the other printing commands does not allow any math operations
' Yes, that was repeated on purpose!
'
' Some other details of using Debug for outputs
' DEBUG stores the text byte in the string using as TWO BYTES each
' So use it wisely.
' Stuff you need to repeat often should be stored as subroutines which takes 2 bytes to access gosub =1
'
' Also, this example demonstrates the CONFIG command for using Master Clear Pin #4
' ra3 as an IO
' be sure the mclr is set to I/o fiddle with the compiler config lines
' or block them out and move the config lines to the program.
' c:\pbp\xxFxxxx.INC
' _MCLRE_OFF & _CLKOUTEN_OFF INC
' As always RTFM a few dozen times, just to repeat "RTFM"
'
' Also See the UNSUED a2d code section.
' Features the joys of:
' Setting up the FVRCON
' --- comment it out for use on the older mid-range chips 12f683 ...
' Using DCD command to make easier assigning of the Analog ports
'
' Yes, entire pages from the Manual is included, part of that dreaded RTFM!
'



'
' 12f1822
' ---v---
' +5v 1 8 gnd
' rA5 2 7 rA0/AN0
' rA4/AN3 3 6 rA1/AN1
' rA3/_MC 4 5 rA2/AN2
'
' rA3 is digital input only
'
' rAx = output, alarm
' rAx = output, fan
' rA2 = Analog in, Temp inside
' rA3 = Rx Serial in
' rA4 = Analog in, Temp outside
' rAx = Tx Serial out
'
'

'===================== The Joys of Config ====================
'========== Config can only be changed during compile
'========== or just before programming, do it here & Choose wisely
'================================================= ====================

'CONFIG 1 & 2
'bit 2-0 FOSC<2:0>: Oscillator Selection bits
'100 =INTOSC oscillator: I/O function on CLKIN pin
' ignore @ __config _CONFIG1, _MCLRE_OFF & _FOSC_INTOSC
' ignore @ __config _CONFIG2, _PLLEN_OFF & _LVP_OFF
'set Master Clear Off - PORTA.3 is an Input
'@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _CP_OFF
'
' WHEN PROGRAMMING PROGRAM $2007.5 TO LOW THIS WILL ENABLE PORTA.3 AS AN INPUT
' option_reg.5 = 0 'set _mreset pin to a input PORTA.3
' define _MCLR_OFF ----> sadly this dose not work in the compiler
' ** you must use do it in the programmer
' * or modify c:\pbp\xxLxxx.inc
'
@ __config _CONFIG1, _FOSC_INTOSC & _MCLRE_OFF & _CLKOUTEN_OFF
@ __config _CONFIG2, _PLLEN_OFF & _LVP_OFF


'================================================= ====================
'=========== Setting up the speed on the new chips ===================
'=========== 12f182x or 16f182x and many others =====================
'================================================= ====================

DEFINE OSC 4

' 76543210
OSCCON = 101111

'PIC16F182X OSSCON SEE PAGE 71
'bit 7 SPLLEN: Software PLL Enable
' If PLLEN in Configuration Word 1 = 1:
'SPLLEN bit is ignored. 4x PLL is always enabled (subject to oscillator requirements)
' If PLLEN in Configuration Word 1 = 0:
' 1 =4x PLL Is enabled
' 0 =4x PLL is disabled
'bit 6-3 IRCF<3:0>: Internal Oscillator Frequency Select bits
' 6543 (bits count) >>> for slower clock timing considerations
' 000x =31kHz LF 7 128
' 0010 =31.25kHz MF 7 128
' 0011 =31.25kHz HF(1) 7 128
' 0100 =62.5kHz MF 6 64
' 0101 =125kHz MF 5 32
' 0110 =250kHz MF 4 16
' 0111 =500kHz MF (default upon Reset) 3 8
' 1000 =125kHz HF(1) 5 32
' 1001 =250kHz HF(1) 4 16
' 1010 =500kHz HF(1) 3 8
' 1011 =1MHz HF 2 4
' 1100 =2MHz HF 1 2
' 1101 =4MHz HF 0
' 1110 =8MHz or 32 MHz HF(see Section5.2.2.1 “HFINTOSC”)
' 1111 =16MHz HF
'bit 2 Unimplemented: Read as ‘0’
'bit 1-0 SCS<1:0>: System Clock Select bits
'1x = Internal oscillator block
'01 = Timer1 oscillator
'00 = Clock determined by FOSC<2:0> in Configuration Word 1.

' rA0 = output, alarm
' rA1 = output, fan
' rA2 = Analog in, Temp inside
' rA3 = Rx Serial in
' rA4 = Analog in, Temp outside
' rA5 = Tx Serial out

' ****** I/O PIN defines ***********************************************
' rA.?
' 76543210
Alarm_PIN con 000001 'PORTA.0
T_In_PIN CON 000100 ' T INside pin rA.2
T_Out_PIN CON 010000 ' T OUTside pin rA.4
Fan_PIN con 100000 'PORTA.5

PIN_Alarm var PORTA.0
PIN_Fan var PORTA.5


'SER_PIN_OUT con 1 ' var PORTA.? 'GPIO.? ' digital only
'SER_PIN_IN con 3' var PORTA.3 'GPIO.3 ' input only

' ========================================
' SERIAL OUT METHOD
DEFINE DEBUG_PACING 100
DEFINE DEBUG_REG PORTA
DEFINE DEBUG_BIT 1
DEFINE DEBUG_BAUD 1200
DEFINE DEBUG_MODE 0
DEFINE DEBUGIN_REG PORTA
DEFINE DEBUGIN_BIT 3

' ========================================


' ================ We live in an analog world .... =========
' ============ FVRCON Is not valid on the "older chips" ===========
' Just comment it out and the A2d section code should
' compile for the older 'midrange chips' ie 12f683 ....
' ====== Considering the newer chips are actually cheaper ===
' ====== I wonder why you'd want to use them. ================
'========= other than it's what I got on the shelf. :o) ===========
'********************* a2D setup *********************************
' 76543210
FVRCON = 000010 'set for 2.048V
'FVRCON: FIXED VOLTAGE REFERENCE CONTROL REGISTER
'1 bit 7 FVREN: Fixed Voltage Reference Enable: 1= on, 0 =off
'0 bit 6 FVRRDY: Fixed Voltage Reference Ready Flag 0 = Not Ready or NOT ENABLED, 1= Ready
'0 bit 5 0=12f1822 TSEN: Temperature Indicator Enable: 0 = disabled, 1 =enabled
'0 bit 4 0=12f1822 TSRNG: Temperature Indicator Range Selection: 0 =VOUT = VDD - 4VT (High) , 1 =VOUT = VDD - 2VT (Low )
' bit 3-2 CDAFVR<1:0>: Comparator and DAC Fixed Voltage Reference Selection bit
'00 00 =Comparator and DAC Fixed Voltage Reference Peripheral output is off
' 01 =Comparator and DAC Fixed Voltage Reference Peripheral output is 1x (1.024V)
' 10 =Comparator and DAC Fixed Voltage Reference Peripheral output is 2x (2.048V)
' 11 =Comparator and DAC Fixed Voltage Reference Peripheral output is 4x (4.096V)
' bit 1-0 ADFVR<1:0>: ADC Fixed Voltage Reference Selection bit
' 00 =ADC Fixed Voltage Reference Peripheral output is off
' 01 =ADC Fixed Voltage Reference Peripheral output is 1x (1.024V)
'10 10 =ADC Fixed Voltage Reference Peripheral output is 2x (2.048V)
' 11 =ADC Fixed Voltage Reference Peripheral output is 4x (4.096V)

ADCON0 = 000001 ' .1= GO, .0 1=a2d ON
' ADCON0 *** Selects the channel ***
' bit7 = unused
' bits6-2 = channel
' bit6 = 0 + bits5-2: [0-B] = select channel
' 11101 =Temperature Indicator
' 11110 =DAC output
' 11111 =FVR (Fixed Voltage Reference) Buffer 1 Output
'bit 1 GO/DONE: A/D Conversion Status bit
' 1 = A/D conversion cycle in progress. Setting this bit starts an A/D conversion cycle.
' This bit is automatically cleared by hardware when the A/D conversion has completed.
' 0 = A/D conversion completed/not in progress
' bit 0 ADON: ADC Enable bit, 1 = ADC enabled, 0= ADC disabled & consumes NO operating current

ADCON1 = 110011 ' Right Justify, FRC, Vref- =GND, Vref+ = FRV, Set to 4.096V [so each bit = 4mV ... easier Math]
'ADCON1
' bit 7 ADFM: A/D Result Format Select bit Justified 1= *Right* or 0 = Left
' bit 6-4 ADCS<2:0>: A/D Conversion Clock Select bits
'000 =FOSC/2
'001 =FOSC/8
'010 =FOSC/32
'011 =FRC (clock supplied from a dedicated RC oscillator)
'100 =FOSC/4
'101 =FOSC/16
'110 =FOSC/64
'111 =FRC (clock supplied from a dedicated RC oscillator)
' bit 3 Unimplemented: Read as ‘0’
' bit 2 ADNREF: A/D Negative Voltage Reference Configuration bit
'0 =VREF- is connected to VSS
'1 =VREF- is connected to external VREF- pin(1)
'bit 1-0 ADPREF<1:0>: A/D Positive Voltage Reference Configuration bits
'00 =VREF+ is connected to VDD
'01 =Reserved
'10 =VREF+ is connected to external VREF+ pin(1)
'11 =VREF+ is connected to internal Fixed Voltage Reference (FVR) module(1)

'Turn off Comparators
'CM1CON0 = $0
'CM1CON1 = $0
'CM2CON0 = $0
'CM2CON1 = $0
'
'AN 0 1 2 3
'REG A0 A1 A2 A3
'PIN 7 6 5 3
' 76543210
'DEFINE THE ANALOG LOCATIONS

' ************************************
' **** THIS does not work properly!!!! ****
' **** Use the other code below. ******
'TRIA = T_In_PIN + T_out_PIN '010100
' ************************************


' ==============
' ####### May NOT be the same as the port #######
'AN 0 1 2 3
'REG A0 A1 A2 A3
'PIN 7 6 5 3
' 76543210
'DEFINE THE ANALOG LOCATIONS'
' ####### May NOT be the same as the port #######
T_In_AN con 2 ' T INside Analog port # May NOT be the same as the port#
T_Out_AN con 3 ' T OUTside Analog port # May NOT be the same as the port#

' ENABLE THE ANALOG LOCATIONS
' An 3210
ANSELA = (dcd T_Out_AN) + (dcd T_in_AN) ' 01100 DCD = 2<<n

' DISABLE DIGITAL I/O on the Analog locations [1]high = input
TRISA = T_In_PIN + T_out_PIN '010100
'TRISA = $14
wpua = $ff - $14
ADCON0 = 000001 ' bit.1 1= GO : bit.0 1=a2d ON
PAUSE 100 ' WAIT FOR STUFF TO WAKE UP: A2D & LCD

' PB Basic A2D config info
define ADC_BITS 10
DEFINE ADC_CLOCK 3 ' SOURCE = RC3
DEFINE ADC_SAMPLESUS 500 ' Sampling time in microseconds

'********************* end a2D setup *********************************


'--------EEPROM LOCATIONS
' LOCATION 00-01 IS RESERVED FOR THE TEST OF VALID INFO
T_Min_Default_LOC con $02
' ========================================

' ---- The temps they do all the grunt work with little or no pay :)
AB VAR BYTE ' TEMP Used in Text output
BB VAR BYTE ' TEMP Used in Text output
zb var byte ' temp Used in Text output


' print character defines
CR con 13
LF con 10
VTAB CON 11 ' VERTICAL TAB = Clear Screen
DEGREE CON $DF
Dash con 45
Space con $20





data @00, word 0 ' clear the burner's blanking
data @T_Min_Default_LOC, word 20

' 012345678901234567890123456789
' 01234567890ABCDEF0123456789
' *** Mark the end of the words with Char + 128
CharBump con $80
' @$10 starts the data at eeprom location $10

'========== ends with the last character >128 - Does not Waste a byte ========
Ofuzzy1 data @$10, "(C)2011 Ofuzzy1 - Not for Life Critical Use", "!" + CharBump
W_Alarm Data "Alarm", "_" + CharBump
W_Min Data "Mi", "n" + CharBump

'========== ends with a ZERO ====== Wastes a byte ==========
W_Enter Data "Enter",0
W_YNRQ Data "Y=Yes R=Redo N=No Q=Quit ?",0
W_Want_to Data "Want to",0




Main:

gosub CR_LF ' call the print a linefeed and a carriage return
DEBUG CR, LF, Vtab ' directly output via serial:
' CR LF & VTAB [clear screen - works on some terminal programs]

' Call the print progam that uses last byte over 128 as the end of text marker.
zb= W_Alarm : gosub Print_ROM_127
gosub CR_LF : gosub CR_LF

' Call the print progam that uses zero as the end of text marker.
zb= W_YNRQ : GOSUB Print_ROM_0
gosub CR_LF : gosub CR_LF


gosub Print_Copyright ' example as call for multiple use printing


End ' All good things need to come to an end.


'================================================= =====================================
'======= The subroutines ================================================== ============
'================================================= =====================================

CR_LF:
debug CR,LF
return
'================================================= =====================================

Print_SP:
debug " "
return
'================================================= =====================================

' uses last byte over 128 as the end of text marker.
Print_Copyright:
gosub Print_SP : gosub Print_SP : gosub CR_LF ': gosub CR_LF
zb= Ofuzzy1 : gosub Print_ROM_127
gosub CR_LF : gosub CR_LF
return
'================================================= =====================================

Print_ROM_127: ' Call with zb = ROM_Memory_Location [byte]
bb = 1
Do until !BB ' SAME AS "Do until BB = 0" but uses one less byte
read zb, ab
if ab > CharBump-1 then ' > 127
ab = ab - CharBump
bb = 0
endif
debug ab ' Debug like all the other printing commands does not allow any math operations
zb= zb + 1
loop
return
'================================================= =====================================

Print_ROM_0: ' Call with zb = ROM_Memory_Location [byte]
ab = 0
debug "ROM Memory= ", #zb , CR,LF
Do
read zb, ab
if !ab then debug ab ' same as ab <> 0 then ...
zb= zb + 1
loop until !ab ' SAME AS AB = 0
Return

'================================================= =====================================

ofuzzy1
- 28th October 2011, 05:47
Here's a slightly better version for #2




Print_ROM_127: ' Call with zb = INTERNAL ROM_Memory_Location
[B]Do until AB > 128
READ ZB, AB BB = AB & $7F ' drop the upper bit, DEBUG does not allow any math functions during output.
DEBUG BB ' Debug like all the other printing commands does not allow any math operations
ZB= ZB + 1 ' Increment through the string
Loop
return




==============================

I've noticed that Debug and the other "Print" commands use 2 bytes per Char.

Is there a way to do the above string "Peeking" in the program memory?
Does Grasshopper need to explore
PEEKCODE
AND
@ STRING_LOC DT "Text here"

Stay tuned on this bat channel.