The personal website of Scott W Harden
Articles typically receive this designation when the technology they describe is no longer relevant, code provided is later deemed to be of poor quality, or the topics discussed are better presented in future articles. Articles like this are retained for the sake of preservation, but their content should be critically assessed.

# pySquelch - Frequency Activity Reports via Python

Update: this project is now on GitHub https://github.com/FredEckert/pySquelch

I've been working on the pySquelch project which is basically a method to graph frequency usage with respect to time. The code I'm sharing below listens to the microphone jack on the sound card (hooked up to a radio) and determines when transmissions begin and end. I ran the code below for 24 hours and this is the result:

This graph represents frequency activity with respect to time. The semi-transparent gray line represents the raw frequency usage in fractional minutes the frequency was tied-up by transmissions. The solid blue line represents the same data but smoothed by 10 minutes (in both directions) by the Gaussian smoothing method modified slightly from my linear data smoothing with Python page.

I used the code below to generate the log, and the code further below to create the graph from the log file. Assuming your microphone is enabled and everything else is working, this software will require you to determine your own threshold for talking vs. no talking. Read the code and you'll figure out how test your sound card settings.

If you want to try this yourself you need a Linux system (a Windows system version could be created simply by replacing getVolEach() with a Windows-based audio level detection system) with Python and the alsaaudio, numpy, and matplotlib libraries. Try running the code on your own, and if it doesn't recognize a library "aptitude search" for it. Everything you need can be installed from packages in the common repository.

``````
# pySquelchLogger.py
import time
import random
import alsaaudio
import audioop
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NONBLOCK)
inp.setchannels(2)
inp.setrate(1000)
inp.setformat(alsaaudio.PCM_FORMAT_S8)
inp.setperiodsize(100)
lastLogTime = 0

testLevel = False  # SET THIS TO 'True' TO TEST YOUR SOUNDCARD

def getVolEach():
# this is a quick way to detect activity.
# modify this function to use alternate methods of detection.
while True:
l, data = inp.read()  # poll the audio device
if l > 0:
break
vol = audioop.max(data, 1)  # get the maximum amplitude
if testLevel:
print vol
if vol > 10:
return True  # SET THIS NUMBER TO SUIT YOUR NEEDS ###
return False

def getVol():
# reliably detect activity by getting 3 consistant readings.
a, b, c = True, False, False
while True:
a = getVolEach()
b = getVolEach()
c = getVolEach()
if a == b == c:
if testLevel:
print "RESULT:", a
break
if a == True:
time.sleep(1)
return a

def updateLog():
# open the log file, append the new data, and save it again.
# print "UPDATING LOG"
f = open('log.txt', 'a')
f.close()
lastLogTime = time.mktime(time.localtime())

def findSquelch():
# this will record a single transmission and store its data.
while True:  # loop until we hear talking
time.sleep(.5)
if getVol() == True:
start = time.mktime(time.localtime())
print start,
break
while True:  # loop until talking stops
time.sleep(.1)
if getVol() == False:
length = time.mktime(time.localtime())-start
print length
break
newLine = "%d,%d " % (start, length)
if start-lastLogTime > 30:
updateLog()  # update the log

while True:
findSquelch()``````

The logging code (above) produces a log file like this (below). The values represent the start time of each transmission (in seconds since epoch) followed by the duration of the transmission.

``````#log.txt
1245300044,5 1245300057,4 1245300063,16 1245300094,13 1245300113,4 1245300120,14 1245300195,4 1245300295,4 1245300348,4 1245300697,7 1245300924,3 1245301157,4 1245301207,12 1245301563,4 1245302104,6 1245302114,6 1245302192,3 1245302349,4 1245302820,4 1245304812,13 1245308364,10 1245308413,14 1245312008,14 1245313953,11 1245314008,6 1245314584,4 1245314641,3 1245315212,5 1245315504,6 1245315604,13 1245315852,3 1245316255,6 1245316480,5 1245316803,3 1245316839,6 1245316848,11 1245316867,5 1245316875,12 1245316893,13 1245316912,59 1245316974,12 1245316988,21 1245317011,17 1245317044,10 1245317060,6 1245317071,7 1245317098,33 1245317140,96 1245317241,15 1245317259,14 1245317277,8 1245317298,18 1245317322,103 1245317435,40 1245317488,18 1245317508,34 1245317560,92 1245317658,29 1245317697,55 1245317755,33 1245317812,5 1245317818,7 1245317841,9 1245317865,25 1245317892,79 1245317972,30 1245318007,8 1245318021,60 1245318083,28 1245318114,23 1245318140,25 1245318167,341 1245318512,154 1245318670,160 1245318834,22 1245318859,9 1245318870,162 1245319042,57 1245319102,19 1245319123,30 1245319154,18 1245319206,5 1245319214,13 1245319229,6 1245319238,6 1245319331,9 1245319341,50 1245319397,71 1245319470,25 1245319497,40 1245319540,8 1245319551,77 1245319629,4 1245319638,36 1245319677,158 1245319837,25 1245319865,40 1245319907,33 1245319948,92 1245320043,26 1245320100,9 1245320111,34 1245320146,8 1245320159,6 1245320167,8 1245320181,12 1245320195,15 1245320212,14 1245320238,18 1245320263,46 1245320310,9 1245320326,22 1245320352,27 1245320381,15 1245320398,24 1245320425,57 1245320483,16 1245320501,40 1245320543,43 1245320589,65 1245320657,63 1245320722,129 1245320853,33 1245320889,50 1245320940,1485 1245322801,7 1245322809,103 1245322923,5 1245322929,66 1245323553,4 1245324203,15 1245324383,5 1245324570,7 1245324835,4 1245325200,8 1245325463,5 1245326414,12 1245327340,12 1245327836,4 1245327973,4 1245330006,12 1245331244,11 1245331938,11 1245332180,5 1245332187,81 1245332573,5 1245333609,12 1245334447,10 1245334924,9 1245334945,4 1245334971,4 1245335031,9 1245335076,11 1245335948,16 1245335965,27 1245335993,113 1245336107,79 1245336187,64 1245336253,37 1245336431,4 1245336588,5 1245336759,7 1245337048,3 1245337206,13 1245337228,4 1245337309,4 1245337486,6 1245337536,8 1245337565,38 1245337608,100 1245337713,25 1245337755,169 1245337930,8 1245337941,20 1245337967,6 1245337978,7 1245337996,20 1245338019,38 1245338060,127 1245338192,30 1245338227,22 1245338250,15 1245338272,15 1245338310,3 1245338508,4 1245338990,5 1245339136,5 1245339489,8 1245339765,4 1245340220,5 1245340233,6 1245340266,10 1245340278,22 1245340307,7 1245340315,28 1245340359,32 1245340395,4 1245340403,41 1245340446,46 1245340494,58 1245340554,17 1245340573,21 1245340599,3 1245340604,5 1245340611,46 1245340661,26 1245340747,4 1245340814,14 1245341043,4 1245341104,4 1245341672,4 1245341896,5 1245341906,3 1245342301,3 1245342649,6 1245342884,5 1245342929,4 1245343314,6 1245343324,10 1245343335,16 1245343353,39 1245343394,43 1245343439,62 1245343561,3 1245343790,4 1245344115,3 1245344189,5 1245344233,4 1245344241,6 1245344408,12 1245344829,3 1245345090,5 1245345457,5 1245345689,4 1245346086,3 1245347112,12 1245348006,14 1245348261,10 1245348873,4 1245348892,3 1245350303,11 1245350355,4 1245350766,5 1245350931,3 1245351605,14 1245351673,55 1245351729,23 1245351754,5 1245352123,37 1245352163,21 1245352186,18 1245352209,40 1245352251,49 1245352305,8 1245352315,5 1245352321,6 1245352329,22 1245352353,48 1245352404,77 1245352483,58 1245352543,17 1245352570,19 1245352635,5 1245352879,3 1245352899,5 1245352954,4 1245352962,6 1245352970,58 1245353031,21 1245353055,14 1245353071,52 1245353131,37 1245353170,201 1245353373,56 1245353431,18 1245353454,47 1245353502,13 1245353519,106 1245353627,10 1245353647,12 1245353660,30 1245353699,42 1245353746,28 1245353776,29 1245353806,9 1245353818,21 1245353841,10 1245353853,6 1245353862,224 1245354226,4 1245354964,63 1245355029,4 1245355036,142 1245355180,148 1245355330,7 1245355338,23 1245355363,9 1245355374,60 1245355437,142 1245355581,27 1245355609,5 1245355615,2 1245355630,64 1245355700,7 1245355709,73 1245355785,45 1245355834,85 1245355925,9 1245356234,5 1245356620,6 1245356629,12 1245356643,29 1245356676,120 1245356798,126 1245356937,62 1245357001,195 1245357210,17 1245357237,15 1245357258,24 1245357284,53 1245357339,2 1245357345,27 1245357374,76 1245357452,28 1245357482,42 1245357529,14 1245357545,35 1245357582,74 1245357661,30 1245357693,19 1245357714,38 1245357758,11 1245357777,37 1245357817,49 1245357868,19 1245357891,31 1245357931,48 1245357990,49 1245358043,24 1245358082,22 1245358108,17 1245358148,18 1245358168,7 1245358179,6 1245358186,19 1245358209,17 1245358229,5 1245358240,9 1245358252,10 1245358263,6 1245358272,9 1245358296,26 1245358328,49 1245358381,6 1245358389,38 1245358453,19 1245358476,24 1245358504,21 1245358533,76 1245358628,24 1245358653,10 1245358669,105 1245358781,20 1245358808,14 1245358836,6 1245358871,61 1245358933,0 1245358936,44 1245358982,11 1245358996,25 1245359023,15 1245359040,32 1245359076,19 1245359099,13 1245359117,16 1245359138,12 1245359161,33 1245359215,32 1245359249,14 1245359272,7 1245359314,10 1245359333,36 1245359371,21 1245359424,10 1245359447,61 1245359514,32 1245359560,42 1245359604,87 1245359700,60 1245359762,23 1245359786,4 1245359791,8 1245359803,6 1245359813,107 1245359922,29 1245359953,22 1245359978,86 1245360069,75 1245360147,22 1245360170,0 1245360184,41 1245360239,15 1245360256,34 1245360301,37 1245360339,1 1245360342,28 1245360372,20 1245360394,32 1245360440,24 1245360526,3 1245360728,3 1245361011,4 1245361026,35 1245361064,137 1245361359,5 1245362172,11 1245362225,21 1245362248,51 1245362302,20 1245362334,42 1245362418,12 1245362468,7 1245362557,9 1245362817,3 1245363175,4 1245363271,4 1245363446,3 1245363539,4 1245363573,4 1245363635,1 1245363637,3 1245363740,5 1245363875,3 1245364075,4 1245364354,14 1245364370,19 1245364391,49 1245364442,34 1245364478,23 1245364502,80 1245364633,15 1245364650,8 1245364673,16 1245364691,47 1245364739,53 1245364795,39 1245364836,25 1245365353,4 1245365640,11 1245365665,5 1245365726,8 1245365778,7 1245365982,4 1245366017,13 1245366042,6 1245366487,4 1245366493,4 1245366500,4 1245366507,3 1245366622,5 1245366690,5 1245366946,4 1245366953,16 1245366975,8 1245366996,7 1245367005,7 1245367031,6 1245367040,9 1245367051,7 1245367059,23 1245367084,76 1245367166,158 1245367740,4 1245367804,3 1245367847,4 1245367887,9 1245369300,10 1245369611,12 1245370038,10 1245370374,8 1245370668,5 1245370883,5 1245370927,7 1245370945,9 1245370961,16 1245370978,414 1245371398,135 1245371535,252 1245371791,238 1245372034,199 1245372621,4 1245372890,5 1245373043,7 1245373060,9 1245373073,6 1245373081,68 1245373151,10 1245373162,49 1245373212,79 1245373300,12 1245373313,38 1245373353,20 1245373374,59 1245373435,28 1245373465,94 1245373560,11 1245373574,53 1245373629,22 1245373654,6 1245373662,334 1245373998,169 1245374176,41 1245374219,26 1245374246,51 1245374299,31 1245374332,57 1245374391,55 1245374535,4 1245374759,7 1245374769,200 1245374971,215 1245375188,181 1245375371,81 1245375455,59 1245375516,33 1245375552,19 1245375572,56 1245375629,220 1245375850,32 1245375884,26 1245375948,7 1245375964,114 1245376473,4 1245376810,13 1245378296,10 1245378950,12 1245379004,3 1245379569,4 1245379582,4 1245379615,6 1245380030,3 1245380211,4 1245380412,14 1245380727,4 1245380850,4``````

This log file is only 7.3 KB. At this rate, a years' worth of log data can be stored in less than 3MB of plain text files. The data presented here can be graphed (producing the image at the top of the page) using the following code:

``````# pySquelchGrapher.py
import numpy
import datetime
import pylab
print "complete"

# load signal/duration from log file
f = open(fname)
f.close()
raw = raw.replace('n', ' ')
raw = raw.split(" ")
signals = []
for line in raw:
if len(line) < 3:
continue
line = line.split(',')
sec = datetime.datetime.fromtimestamp(int(line[0]))
dur = int(line[1])
signals.append([sec, dur])
print "complete"
return signals

def findDays(signals):
# determine which days are in the log file
print "finding days...",
days = []
for signal in signals:
day = signal[0].date()
if not day in days:
days.append(day)
print "complete"
return days

def genMins(day):
# generate an array for every minute in a certain day
print "generating bins...",
mins = []
startTime = datetime.datetime(day.year, day.month, day.day)
minute = datetime.timedelta(minutes=1)
for i in xrange(60*60):
mins.append(startTime+minute*i)
print "complete"
return mins

def fillMins(mins, signals):
print "filling bins...",
vals = [0]*len(mins)
dayToDo = signals[0][0].date()
for signal in signals:
if not signal[0].date() == dayToDo:
continue
sec = signal[0]
dur = signal[1]
prebuf = sec.second
minOfDay = sec.hour*60+sec.minute
if dur+prebuf < 60:  # simple case, no rollover seconds
vals[minOfDay] = dur
else:  # if duration exceeds the minute the signal started in
vals[minOfDay] = 60-prebuf
dur = dur+prebuf
while (dur > 0):  # add rollover seconds to subsequent minutes
minOfDay += 1
dur = dur-60
if dur <= 0:
break
if dur >= 60:
vals[minOfDay] = 60
else:
vals[minOfDay] = dur
print "complete"
return vals

def normalize(vals):
print "normalizing data...",
divBy = float(max(vals))
for i in xrange(len(vals)):
vals[i] = vals[i]/divBy
print "complete"
return vals

def smoothListGaussian(list, degree=10):
print "smoothing...",
window = degree*2-1
weight = numpy.array([1.0]*window)
weightGauss = []
for i in range(window):
i = i-degree+1
frac = i/float(window)
gauss = 1/(numpy.exp((4*(frac))**2))
weightGauss.append(gauss)
weight = numpy.array(weightGauss)*weight
smoothed = [0.0]*(len(list)-window)
for i in range(len(smoothed)):
smoothed[i] = sum(numpy.array(list[i:i+window])*weight)/sum(weight)
while len(list) > len(smoothed)+int(window/2):
smoothed.insert(0, smoothed[0])
while len(list) > len(smoothed):
smoothed.append(smoothed[0])
print "complete"
return smoothed

days = findDays(signals)
for day in days:
mins = genMins(day)
vals = normalize(fillMins(mins, signals))
fig = pylab.figure()
pylab.grid(alpha=.2)
pylab.plot(mins, vals, 'k', alpha=.1)
pylab.plot(mins, smoothListGaussian(vals), 'b', lw=1)
pylab.axis([day, day+datetime.timedelta(days=1), None, None])
fig.autofmt_xdate()
pylab.title("147.120 MHz Usage for "+str(day))
pylab.xlabel("time of day")
pylab.ylabel("fractional usage")
pylab.show()
``````

# UCF Tailgate June 2009

This morning I woke up at 4:45am, hopped out of bed, and raced to the university parking lot for field day. It's pretty much a flea market with an emphasis in ham radio and associated electronics. This is a panorama of the parking lot the tailgate was held in, taken from the roof of a parking garage at about 9am. The UCF ARC (the amateur radio club which sponsored the event) is stationed under the white tent.

My goal was to purchase a [working] oscilloscope, and I lucked-out. I ended-up purchasing two, and I'm glad I did! The 1st one (the one with the green circular screen) crapped-out on me after literally 1 minute. (By crapped-out I mean it started spurring thick gray smoke and made my whole apartment smell like a burned marshmallow). At \$5, I'm not crying over it. The second one is a 1969 Tektronix 561A 10 MHz oscilloscope. Just think, these things just started started being produced the same year Neil Armstrong walked on the moon. I tested it and it seems to be functioning well. At \$10, I'm very happy!

Here you can see it attached to my prime number generator described in agonizingly-boring detail over the last several weeks' posts. It's attached to one of the microcontroller pins responsible for multiplexing the LED display. Finally, a way to assess high speed power output as a function of time. The output of the microcontroller isn't performing like I expected, and since it's a series of pulses I can't use a volt meter to measure its output. Thus, the need [more like desire] for an oscilloscope.

Articles typically receive this designation when the technology they describe is no longer relevant, code provided is later deemed to be of poor quality, or the topics discussed are better presented in future articles. Articles like this are retained for the sake of preservation, but their content should be critically assessed.

# Python-Powered Frequency Activity Logger

I'm often drawn toward projects involving data analysis with Python. When I found out a fellow ham in Orlando was using his computer to stream a popular local repeater frequency over the internet I got excited because of the potential for generating data from the setup. Since this guy already has his radio connected to his PC's microphone jack, I figured I could write a Python app to check the microphone input to determine if anyone is using the frequency. By recording when people start and stop talking, I can create a log of frequency activity. Later I can write software to visualize this data. I'll talk about that in a later post. For now, here's how I used Python and a Linux box (Ubuntu, with the python-alsaaudio package installed) to generate such logs.

We can visualize this data using some more simple Python code. Long term it would be useful to visualize frequency activity similarly to how I graphed computer usage at work over the last year but for now since I don't have any large amount of data to work with. I'll just write cote to visualize a QSO (conversation) with respect to time. It should be self-explanatory. This data came from data points displayed in the video (provided at the end of this post too).

And, of course, the code I used to generate the log files (seen running in video above): Briefly, this program checks the microphone many times every second to determine if its state has changed (talking/no talking) and records this data in a text file (which it updates every 10 seconds). Matplotlib can EASILY be used to graph data from such a text file.

``````import alsaaudio, time, audioop, datetime
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE,alsaaudio.PCM_NONBLOCK)
inp.setchannels(1)
inp.setrate(4000)
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE)
inp.setperiodsize(1)

squelch = False
lastLog = 0
dataToLog = ""

def logIt(nowSquelch):
global dataToLog, lastLog
timeNow = datetime.datetime.now()
epoch = time.mktime(timeNow.timetuple())
if nowSquelch==True: nowSquelch=1
else: nowSquelch=0
logLine="%s %dn"%(timeNow, nowSquelch)
print timeNow, nowSquelch
dataToLog+=logLine
if epoch-lastLog&gt;10:
#print "LOGGING..."
f=open('squelch.txt','a')
f.write(dataToLog)
f.close()
lastLog = epoch
dataToLog=""

while True:
if l:
vol = audioop.max(data,2)
#print vol #USED FOR CALIBRATION
if vol&gt;800: nowSquelch = True
else: nowSquelch = False
if not nowSquelch == squelch:
logIt(nowSquelch)
squelch = nowSquelch
time.sleep(.01)
``````

To use this code make sure that you've properly calibrated it. See the "vol>800" line? That means that if the volume in the microphone is at least 800, it's counted as talking, and less than it's silence. Hopefully you can find a value that counts as silence when the squelch is active, but as talking when the squelch is broken (even if there's silence). This is probably best achieved with the radio outputting at maximum volume. You'll have to run the program live with that line un-commented to view the data values live. Find which values occur for squelch on/off, and pick your threshold accordingly.

After that you can visualize the data with the following code. Note that this is SEVERELY LIMITED and is only useful when graphing a few minutes of data. I don't have hours/days of data to work with right now, so I won't bother writing code to graph it. This code produced the graph seen earlier in this page. Make sure matplotlib is installed on your box.

``````import pylab

#returns Xs
import time, datetime, pylab
f=open('good.txt')
f.close()
onTimes=[]
timeStart=None
lastOn=False
for line in raw:
if len(line)&lt;10: continue
line = line.strip('n').split(" ")
t=line[0]+" "+line[1]
t=t.split('.')
thisDay=time.strptime(t[0], "%Y-%m-%d %H:%M:%S")
e=time.mktime(thisDay)+float("."+t[1])
if timeStart==None: timeStart=e
if line[-1]==1: stat=True
else: stat=False
if not lastOn and line[-1]=="1":
lastOn=e
else:
onTimes.append([(lastOn-timeStart)/60.0,
(e-timeStart)/60.0])
lastOn=False
return onTimes

pylab.figure(figsize=(8,3))
for t in times:
pylab.fill([t[0],t[0],t[1],t[1]],[0,1,1,0],'k',lw=0,alpha=.5)
pylab.axis([None,None,-3,4])
pylab.title("A little QSO")
pylab.xlabel("Time (minutes)")
pylab.show()``````

# Prime Prototype Construction

Now that I've worked-out the software side of the microcontroller-powered prime number generator, it's time to start working on the hardware. I want to make a prototype which is far smaller and simpler than the final version but lets me practice driving lots of LEDs (30). I expect the final version to have around 80. Also, the heart of this project is an ATTiny2313 microcontroller, and for the full version I'd like to use an ATMEega8. I picked up an unfinished wooden box with a magnetic latch from Michaels. It's delicate and tends to chip when you drill it, but moving slowly I'm able to make nice evenly-spaced holes.

This is the circuit concept. The chip is an ATTiny2313, sourced with 5V, where the left pins control the columns (by providing current) and the right pins control the rows (by providing ground). The "holes" at the top of the circuit represent where I hook up my PC and external power for testing purposes.

Thoughts from Future Scott (10 years later, August, 2019)

A+ for enthusiasm and construction but your design is... just no!

Why are you using an external crystal?

The schematic for the crystal is wrong: those capacitors should be to ground not in series!

You made the circuit diagram in InkScape!

You shouldn't drive current directly out of the microcontroller pins.

The majority of the microcontroller CPU cycles will go into managing multiplexing of the display (not calculating primes).

After a little more work I have a functional device and it looks better than I expected. There are a few more features I want to add, and I want to work on the code some more, but I hope to be done tomorrow. The coolest part is that I've included an internal button which drives a pause/resume and speed-controller menu based upon the length of button presses! There's a lot of awesome stuff I want to write, but once again, I'll save it for the completed project page.

I rendered the cover sticker wrong and all the LEDs are mislabled. The first LED should be 2^0 (1), and the second should be 2^1 (2), etc. Also, 2^22 and 2^23 are mislabeled - oops! But the thing really does generate, differentiate, and display [only[ prime numbers. Once again, videos (including demonstration of the menus and the programming options) and source code will be posted soon.

Articles typically receive this designation when the technology they describe is no longer relevant, code provided is later deemed to be of poor quality, or the topics discussed are better presented in future articles. Articles like this are retained for the sake of preservation, but their content should be critically assessed.

# Prime Number Generator Prototype

In my quest to build a hardware-based prime number generator I built a rapid prototype to assess how quickly primes can be found with an 8-bit microcontroller. There is a lot of room for improvement, but the code works. Instead of messing with tons of little LEDs, this design displays numbers on an LCD. Interestingly the library to run the LCD takes up about 90% of the memory of the chip leaving only a handful of bytes to write the prime calculation code in!

``````#define F_CPU 1E6
#include <stdlib.h>
#include <avr/io.h>
#include <math.h>
#include <util/delay.h>
#include "lcd.h"
#include "lcd.c"

const unsigned long int primeMax=pow(2,25);
unsigned long int primeLast=2;
unsigned long int primeTest=0;
unsigned int primeDivy=0;

void wait(void);
void init(void);
void updateDisplay(void);
char *toString(unsigned long int);

int main(void){
init();
short maybePrime;
unsigned int i;
for(primeTest=2;primeTest<sqrt(primeMax);primeTest++){
maybePrime=1;
for (i=2;i<=(sqrt(primeTest)+1);i++){
primeDivy=i;
updateDisplay();
if (primeTest%primeDivy==0){maybePrime=0;break;}
}
if (maybePrime==1){primeLast=primeTest;updateDisplay();}
}
return 0;
}

void updateDisplay(void){
lcd_gotoxy(12,0);lcd_puts(toString(primeLast));
lcd_gotoxy(5,1);lcd_puts(toString(primeTest));
lcd_gotoxy(16,1);lcd_puts(toString(primeDivy));
return;
}

void init(void){
lcd_init(LCD_DISP_ON);
lcd_puts("PRIME IDENTIFICATIONn");
_delay_ms(2000);
lcd_clrscr();
lcd_puts("LAST PRIME:n");
lcd_puts("TRY:");
lcd_gotoxy(14,1);lcd_puts("/");
return;
}

char *toString(unsigned long int x){
char s1[8];
ltoa(x,s1,10);
return s1;
}``````
All Blog Posts