Jun 202020
 

https://jeelabs.org/2012/05/18/generating-a-sine-wave/

 

Generating a sine wave

In Hardware on May 18, 2012 at 00:01

After the recent pretty disappointing results with a transformer-based Component Tester, I’d like to try and generate a ± 10 V sine wave at approximately 50 Hz in some other way. Using as few components as possible.

 Posted by at 7:25 pm
Jun 202020
 

http://www.bristolwatch.com/

 

Arduino based digital clock.

Student-Hobbyist Electronics Projects Tutorials

by Lewis Loflin

 

View all of my You Tube Videos
Also visit and subscribe to My YouTube Channel

 

Introduction – The purpose of these pages is to introduce the student and hobbyist to electronics projects. My hope is generate interest for those thinking about entering a high tech field, or simply to have fun.

I’ve been a part-time adjunct professor at a local community college teaching electricity and electronics. My electronics website reflects what I’ve taught or been asked to look into by visitors. I have 40 years experience in electronics from vacuum tubes to modern solid state and industrial controls. In college I had a year each of physics, chemistry, and biology along with C, C++. Pascal, and assembly.

 Posted by at 6:37 pm
Jun 202020
 

http://www.sillanumsoft.org/prod01.htm

 

Detailed Features about:

  1. Oscilloscope (dual channel, xy, time division, trigger);

  2. Spectrum Analyzer with amplitude and phase display (linear, log, lines, bar, octaves band analysis 1/3, 1/6, 1/9, 1/12, 1/24);

  3. Wave-form generator with “custom functions”, triangular, square, sinus, white noise and pulse generation (NO ALIASING);

  4. Frequency meter (in time and frequency domain) and counter; in time domain by means of a real time zero crossing algorithm;

  5. Volt meter with DC, true RMS, peak to peak and mean display; 

  6. Filtering (low pass, hi pass, band pass, band reject, notch, “diode”, DC removal);

  7. Memo windows (data log) for analysis and storage of time series, spectrum and phase  with “triggering” events; possibility to save in various formats and display them with a viewer;

  8. A TRUE software digital analog conversion (for complete signal reconstruction using Nyquist theorem) ;

  9. Frequency compensation: one can create/edit a custom frequency response and  add it to the spectrum analyzer spectrum ; added standard weighting curves A,B,C in parallel with custom frequency response;

  10. Support for 8/16/24 bit soundcard by means of API calls;

  11. Unlimited frequency sampling (depend from the capabilities of your soundcard);

  12. Cepstrum analysis;

  13. Cross Correlation;

  14. Extended THD measurements, with automatic sweep and compensation.

  15. ZRLC-meter with Vector scope, automatic sweep in time and frequency for automatic measurement.

VA main form (version 8.x.x)

[Product Image]

(1) – Oscilloscope

Click to enlarge in a new window

  1. Dual channel

  2. Bandwith : depends from your soundcard (typical  20 Khz) up to 96 Khz (192 Khz sampling frequency)

  3. Resolution from 8 bit (S/N 46 dB) up to 24 bit (S/N >120 dB)

  4. Time division adjust according the sampling frequency and sample resolution

  5. Trigger (positive/negative slope) independent for both channels

  6. Complete software D/A of digital samples : the Nyquist theorem allows reconstructing exactly the input signal

  7. Utilities for quick frequency determination (hold left mouse button down and move mouse to get frequency/amplitude)

  8. Y-axis in Volt and percent full scale

  9. Auto calibration of scope (and spectrum) in volts (need an input signal of known amplitude)

(2) – Spectrum Analyzer

Click to enlarge in a new window

  1. Dual channel

  2. Bandwidth : same as point (1) (oscilloscope function): is the half of the sampling frequency. Typical for 44100 Hz is 22050 Hz (up to 96 Khz or ore depending of the acquisition board)

  3. Resolution from 8 bit (S/N 46 dB) up to 24 bit (S/N >120 dB)

  4. X-axis in Hz, logarithmic and linear; zoom x1..x16

  5. Y-axis in dB or Volt (calibration needed); linear/logarithmic; zoom

  6. Average on spectrum up to 200 buffer

  7. Direct window for amplitude  with mouse

  8. Auto-scale

  9. Capacity to modify the zero dB level  (manually/automatically)

  10. Octave band analysis (1/1, 1/3, 1/6, 1/9, 1/12, 1/24)

(3) – Wave-form generator

Click to enlarge in a new windowClick to enlarge in a new window

  • Dual channel

  • Independent sampling frequency/resolution from scope/spectrum (up to 192 Khz/24 bit)

  • Phase between channels (degree)

  • Direct real time generation/ loop with predefined buffer

  • Waveform CUSTOM, built with harmonics (with save/load in file “.fun” of defined waveform)

  • Modulation of custom waveform with sinus/square/triangular

  • Predefined waveform : sinus, square, triangular (parametric), white noise, pink noise, pulse, sinusoidal sweep 

  • Local volume levels

  • Real time parameters variation (amplitude, frequency, phase between channels, type of waveform)

(4) – Frequency meter

Click to enlarge in a new window

  • Dual channel

  • Frequency meter in Hz/Time/Counter of the input signal being visualized in spectrum/scope

  • Read the frequency of the harmonic of maximum amplitude

  • Counter with threshold level

(5) – Volt meter (calibration needed)

Click to enlarge in a new window

  • Dual channel

  • Vpp, True Rms

  • Hold function

(6) – Filtering

Click to enlarge in a new window

  • FIR low pass cut-off frequency user defined

  • FIR high pass cut-off frequency user defined

  • FIR band pass cut-off frequencies user defined

  • FIR band reject cut-off frequencies user defined

  • IIR notch cut-off frequency user defined

  • IIR notch-inverted cut-off frequency user defined

  • “Diode” function

  • DC removal

  • Dual filter (one for each channel)

(7) – Memo windows

Click to enlarge in a new windowClick to enlarge in a new window

  • Aquiring of spectrum with average

  • Edit offline (while VA running) of aquired spectrum: zoom, navigate

  • Saving of spectrum in TXT format

  • Clipboard for aquired spectrum

  • Print of aquired spectrum

  • Mark points for each valid point (harmonic) of spectrum

  • Aquiring of scope points (points aquired in time domain)

  • Edit offline (while VA running) of aquired time series: zoom, navigate

  • Saving of samples in TXT format

  • Clipboard for aquired samples

  • Print of aquired samples

  • D/A conversion: the points aquired may be converted using Nyquist theorem for full reconstruction of  signal in time domain (see point 8 for D/A in real time)

(8) – real time DIGITAL/ANALOG conversion

  • D/A in real time

  • Dual channel

  • Allows visualizing each aquired harmonic

Points (8) need a clairification:


VA has the unbeatable feature  to perform a full real time Digital-Analog conversion for the oscilloscope function.

Consider using a frequency sampling of (standard) 44100 Hz, with a 16 bit resolution (resolution is not relevant for the purpose of the discussion below…)

Other programs similar to VA simply plot the raw points on the screen, which means you can’t easily analyze signals with a frequency higher than 3000/5000 Hz (there are limited points to plot). Even worse, think a sinusoidal signal of 20 KHz. You would have only 2 points (more or less) per cycle! … The Nyquist theorem says that it is sufficient to RECONSTRUCT the original  signal…try to see what happens if you draw a sine with only two points …it will appear like a triangular waveform…

Try the power of VA enabling the function “full D/A”, apply a sinusoidal signal of 15-20 KHz (for example using the Waveform generator included in VA) finally use the “Time division” control for the selected channel (mS/d) to display the signal at the desired detail level. You will see a perfect waveform with all the points of the original signal (not only two).

(9) Frequency compensation

Visual Analyser allows you to apply a predefined frequency response to compensate (for instance) the frequency response  of a microphone. You should know the frequency response of your microphone; normally professional microphone should be shipped with the typical frequency response. You can add a limited number of points in VA, and apply. VA will interpolate a continues curve by means of cubic spline interpolation algorithm. You can do it through the windows below.


 Posted by at 1:14 pm
Apr 272020
 

Dr.CH.Ting:

“n FOR-NEXT runs n+1 loops by design”

Why and how to cope with:

https://github.com/TG9541/stm8ef/wiki/eForth-FOR-..-NEXT

eForth FOR .. NEXT

Thomas edited this page on Dec 26, 2018 · 1 revision

Discussion of eForth FOR .. NEXT

While it’s advisable to use the STM8 eForth DO .. LEAVE .. LOOP/+LOOP structure instead of FOR .. NEXT and its variants, the following discussion deals with the most main properties, idioms and limitations of the this “eForth-ism”.

Basic properties of eForth FOR .. NEXT

Among “small Forth implemenations” the eForth FOR .. NEXT construct is idiosyncratic, and some of its properties and idioms are rather difficult to understand.

Here is a the basic FOR .. NEXT loop:

: test-for
   FOR I . NEXT ;

NEXT decrements the loop counter on the return stack (accessible with I or R@) and loops while the counter is positive. 4 test-for prints 4 3 2 1 00 test-for prints 0, and -1 test-for prints -1.

The following FOR .. NEXT properties are noteworthy:

  • at least one iteration, with the loop counter equal to the input to FOR will be performed
  • the nuber of iterations is limited to 32768, and
  • the loop count will be “one-too-many” compared to standard loop structures (e.g. DO .. LOOP)

eForth FOR .. AFT .. THEN .. NEXT

The most unusual feature eForth provides is the word AFT:

: test-aft1 ( n -- )
   FOR
      \ first loop
      ."  for"
      AFT
         \ following iterations
         ."  aft"
      THEN
      \ all iterations
      I .
   NEXT ;

2 test-aft1 prints for 2 aft 1 aft 0. Why one would need such a control structure is all but obvious. The eForth core implementation use of AFT, however, shows that it not only works around the “one-too-many” iterations in FOR .. NEXT, but it also provides loop count testing if the actual “loop clause code” is in the AFT .. THEN block:

: test-aft2 ( n -- )
    FOR AFT
       I .
    THEN NEXT ;

Running 3 test-aft2 prints 2 1 0, and 0 test-aft2 or -1 test-aft2 print nothing at all. This structure is widely used in the eForth core, e.g. in CMOVESAME? and TYPE. The effect is that input testing around FOR .. NEXT, especially for 0 counts, isn’t needed.

eForth FOR .. WHILE .. NEXT .. ELSE .. THEN

A loop structure similar to DO .. LEAVE .. LOOP can be implemented in “pure eForth” with an idiomatic combination of FOR .. NEXTWHILE, and ELSE .. THEN:

: test-for-while ( n1 n2 -- )
   FOR
      DUP I = NOT WHILE
      I . \ limit not reached
   NEXT
      ."  end"
   ELSE
      ."  limit"
      R> DROP \ remove the FOR loop counter
   THEN
   DROP ;   \ drop limit

In this example, 5 10 test-for-while prints 10 9 8 5 6 limit, and 5 4 test-for-while prints 4 3 2 1 0 end.

WHILE puts a the address of its conditional branch target on the stack above the start address of FOR the for loop (which is used when compiling NEXT). During compilation, ELSE then uses this address to make WHILE exit to the code block delimited by THEN. Note that the ELSE clause is responsible of removing the loop counter from the return stack.

Note that the FOR .. WHILE .. NEXT .. ELSE .. THEN idiom can’t be mixed with the FOR .. AFT .. THEN .. NEXT idiom!

 Posted by at 7:22 am
Apr 052020
 

 

https://skilldrick.github.io/easyforth/

 

Easy Forth

by Nick Morgan

View on GitHub

Introduction

This small ebook is here to teach you a programming language called Forth. Forth is a language unlike most others. It’s not functional or object oriented, it doesn’t have type-checking, and it basically has zero syntax. It was written in the 70s, but is still used today for certain applications.

Why would you want to learn such an odd language? Every new programming language you learn helps you think about problems in new ways. Forth is very easy to learn, but it requires you to think in a different way than you’re used to. That makes it a perfect language to broaden your coding horizons.

This book includes a simple implementation of Forth I wrote in JavaScript. It’s by no means perfect, and is missing a lot of the functionality you’d expect in a real Forth system. It’s just here to give you an easy way to try out the examples. (If you’re a Forth expert, please contribute here and make it better!)

I’m going to assume that you know at least one other programming language, and have a basic idea of how stacks work as a data structure.

Adding Some Numbers

The thing that separates Forth from most other languages is its use of the stack. In Forth, everything revolves around the stack. Any time you type a number, it gets pushed onto the stack. If you want to add two numbers together, typing + takes the top two numbers off the stack, adds them, and puts the result back on the stack.

Let’s take a look at an example. Type (don’t copy-paste) the following into the interpreter, typing Enter after each line.

1
2
3
<- Top

Every time you type a line followed by the Enter key, the Forth interpreter executes that line, and appends the string ok to let you know there were no errors. You should also notice that as you execute each line, the area at the top fills up with numbers. That area is our visualization of the stack. It should look like this:

1 2 3 <- Top

Now, into the same interpreter, type a single + followed by the Enter key. The top two elements on the stack, 2 and 3, have been replaced by 5.

1 5 <- Top

At this point, your editor window should look like this:

1 ok 2 ok 3 ok + ok

Type + again and press Enter, and the top two elements will be replaced by 6. If you type + one more time, Forth will try to pop the top two elements off the stack, even though there’s only one element on the stack! This results in a Stack underflow error:

1 ok 2 ok 3 ok + ok + ok + Stack underflow

Forth doesn’t force you to type every token as a separate line. Type the following into the next editor, followed by the Enter key:

123 456 +
<- Top

The stack should now look like this:

579 <- Top

This style, where the operator appears after the operands, is known as Reverse-Polish notation. Let’s try something a bit more complicated, and calculate 10 * (5 + 2). Type the following into the interpreter:

5 2 + 10 *
<- Top

One of the nice things about Forth is that the order of operations is completely based on their order in the program. For example, when executing 5 2 + 10 *, the interpreter pushes 5 to the stack, then 2, then adds them and pushes the resulting 7, then pushes 10 to the stack, then multiplies 7 and 10. Because of this, there’s no need for parentheses to group operators with lower precedence.

Stack Effects

Most Forth words affect the stack in some way. Some take values off the stack, some leave new values on the stack, and some do a mixture of both. These “stack effects” are commonly represented using comments of the form ( before -- after ). For example, + is ( n1 n2 -- sum ) – n1 and n2 are the top two numbers on the stack, and sum is the value left on the stack.

Defining Words

The syntax of Forth is extremely straightforward. Forth code is interpreted as a series of space-delimited words. Almost all non-whitespace characters are valid in words. When the Forth interpreter reads a word, it checks to see if a definition exists in an internal structure known as the Dictionary. If it is found, that definition is executed. Otherwise, the word is assumed to be a number, and it is pushed onto the stack. If the word cannot be converted to a number, an error occurs.

You can try that out yourself below. Type foo (an unrecognized word) and press enter.

<- Top

You should see something like this:

foo foo ?

foo ? means that Forth was unable to find a definition for foo, and it wasn’t a valid number.

We can create our own definition of foo using two special words called : (colon) and ; (semicolon). : is our way of telling Forth we want to create a definition. The first word after the : becomes the definition name, and the rest of the words (until the ;) make up the body of the definition. It’s conventional to include two spaces between the name and the body of the definition. Try entering the following:

: foo  100 + ;
1000 foo
foo foo foo

Warning: A common mistake is to miss out the space before the ; word. Because Forth words are space delimited and can contain most characters, +; is a perfectly valid word and is not parsed as two separate words.

<- Top

As you’ve hopefully figured out, our foo word simply adds 100 to the value on top of the stack. It’s not very interesting, but it should give you an idea of how simple definitions work.

Stack Manipulation

Now we can start taking a look at some of Forth’s predefined words. First, let’s look at some words for manipulating the elements at the top of the stack.

dup ( n -- n n )

dup is short for “duplicate” – it duplicates the top element of the stack. For example, try this out:

1 2 3 dup
<- Top

You should end up with the following stack:

1 2 3 3 <- Top

drop ( n -- )

drop simply drops the top element of the stack. Running:

1 2 3 drop

gives you a stack of:

1 2 <- Top
<- Top

swap ( n1 n2 -- n2 n1 )

swap, as you may have guessed, swaps the top two elements of the stack. For example:

1 2 3 4 swap

will give you:

1 2 4 3 <- Top
<- Top

over ( n1 n2 -- n1 n2 n1 )

over is a bit less obvious: it takes the second element from the top of the stack and duplicates it to the top of the stack. Running this:

1 2 3 over

will result in this:

1 2 3 2 <- Top
<- Top

rot ( n1 n2 n3 -- n2 n3 n1 )

Finally, rot “rotates” the top three elements of the stack. The third element from the top of the stack gets moved to the top of the stack, pushing the other two elements down.

1 2 3 rot

gives you:

2 3 1 <- Top
<- Top

Generating Output

Next, let’s look at some words for outputting text to the console.

. ( n -- ) (period)

The simplest output word in Forth is .. You can use . to output the top of the stack in the output of the current line. For example, try running this (make sure to include all the spaces!):

1 . 2 . 3 . 4 5 6 . . .
<- Top

You should see this:

1 . 2 . 3 . 4 5 6 . . . 1 2 3 6 5 4 ok

Going through this in order, we push 1, then pop it off and output it. Then we do the same with 2 and 3. Next we push 45, and 6 onto the stack. We then pop them off and output them one-by-one. That’s why the last three numbers in the output are reversed: the stack is last in, first out.

emit ( c -- )

emit can be used to output numbers as ascii characters. Just like . outputs the number at the top of the stack, emit outputs that number as an ascii character. For example:

 33 119 111 87 emit emit emit emit
<- Top

I won’t give the output here so as to not ruin the surprise. This could also be written as:

87 emit 111 emit 119 emit 33 emit

Unlike .emit doesn’t output any space after each character, enabling you to build up arbitrary strings of output.

cr ( -- )

cr is short for carriage return – it simply outputs a newline:

cr 100 . cr 200 . cr 300 .
<- Top

This will output:

cr 100 . cr 200 . cr 300 . 100 200 300 ok

." ( -- )

Finally we have ." – a special word for outputting strings. The ." word works differently inside definitions to interactive mode. ." marks the beginning of a string to output, and the end of the string is marked by ". The closing " isn’t a word, and so doesn’t need to be space-delimited. Here’s an example:

: say-hello  ." Hello there!" ;
say-hello
<- Top

You should see the following output

say-hello Hello there! ok

We can combine .".cr, and emit to build up more complex output:

: print-stack-top  cr dup ." The top of the stack is " .
  cr ." which looks like '" dup emit ." ' in ascii  " ;
48 print-stack-top
<- Top

Running this should give you the following output:

48 print-stack-top The top of the stack is 48 which looks like ‘0’ in ascii ok

Conditionals and Loops

Now onto the fun stuff! Forth, like most other languages, has conditionals and loops for controlling the flow of your program. To understand how they work, however, first we need to understand booleans in Forth.

Booleans

There’s actually no boolean type in Forth. The number 0 is treated as false, and any other number is true, although the canonical true value is -1 (all boolean operators return 0 or -1).

To test if two numbers are equal, you can use =:

3 4 = .
5 5 = .

This should output:

3 4 = . 0 ok 5 5 = . -1 ok
<- Top

You can use < and > for less than and greater than. < checks to see if the second item from the top of the stack is less than the top item of the stack, and vice versa for >:

3 4 < .
3 4 > .
3 4 < . -1 ok 3 4 > . 0 ok
<- Top

The boolean operators And, Or, and Not are available as andor, and invert:

3 4 < 20 30 < and .
3 4 < 20 30 > or .
3 4 < invert .

The first line is the equivalent of 3 < 4 & 20 < 30 in a C-based language. The second line is the equivalent of 3 < 4 | 20 > 30. The third line is the equivalent of !(3 < 4).

andor, and invert are all bitwise operations. For well-formed flags (0 and -1) they’ll work as expected, but they’ll give incorrect results for arbitrary numbers.

<- Top

if then

Now we can finally get onto conditionals. Conditionals in Forth can only be used inside definitions. The simplest conditional statement in Forth is if then, which is equivalent to a standard if statement in most languages. Here’s an example of a definition using if then. In this example, we’re also using the mod word, which returns the modulo of the top two numbers on the stack. In this case, the top number is 5, and the other is whatever was placed on the stack before calling buzz?. Therefore, 5 mod 0 = is a boolean expression that checks to see if the top of the stack is divisible by 5.

: buzz?  5 mod 0 = if ." Buzz" then ;
3 buzz?
4 buzz?
5 buzz?
<- Top

This will output:

3 buzz? ok 4 buzz? ok 5 buzz? Buzz ok

It’s important to note that the then word marks the end of the if statement. This makes it equivalent to fi in Bash or end in Ruby, for example.

Another important thing to realize is that if consumes the top value on the stack when it checks to see if it’s true or false.

if else then

if else then is equivalent to an if/else statement in most languages. Here’s an example of its use:

: is-it-zero?  0 = if ." Yes!" else ." No!" then ;
0 is-it-zero?
1 is-it-zero?
2 is-it-zero?
<- Top

This outputs:

0 is-it-zero? Yes! ok 1 is-it-zero? No! ok 2 is-it-zero? No! ok

This time, the if clause (consequent) is everything between if and else, and the else clause (alternative) is everything between else and then.

do loop

do loop in Forth most closely resembles a for loop in most C-based languages. In the body of a do loop, the special word i pushes the current loop index onto the stack.

The top two values on the stack give the starting value (inclusive) and ending value (exclusive) for the i value. The starting value is taken from the top of the stack. Here’s an example:

: loop-test  10 0 do i . loop ;
loop-test
<- Top

This should output:

loop-test 0 1 2 3 4 5 6 7 8 9 ok

The expression 10 0 do i . loop is roughly equivalent to:

for (int i = 0; i < 10; i++) {
  print(i);
}

Fizz Buzz

We can write the classic Fizz Buzz program easily using a do loop:

: fizz?  3 mod 0 = dup if ." Fizz" then ;
: buzz?  5 mod 0 = dup if ." Buzz" then ;
: fizz-buzz?  dup fizz? swap buzz? or invert ;
: do-fizz-buzz  25 1 do cr i fizz-buzz? if i . then loop ;
do-fizz-buzz
<- Top

fizz? checks to see if the top of the stack is divisible by 3 using 3 mod 0 =. It then uses dup to duplicate this result. The top copy of the value is consumed by if. The second copy is left on the stack and acts as the return value of fizz?.

If the number on top of the stack is divisible by 3, the string "Fizz" will be output, otherwise there will be no output.

buzz? does the same thing but with 5, and outputs the string "Buzz".

fizz-buzz? calls dup to duplicate the value on top of the stack, then calls fizz?, converting the top copy into a boolean. After this, the top of the stack consists of the original value, and the boolean returned by fizz?swap swaps these, so the original top-of-stack value is back on top, and the boolean is underneath. Next we call buzz?, which replaces the top-of-stack value with a boolean flag. Now the top two values on the stack are booleans representing whether the number was divisible by 3 or 5. After this, we call or to see if either of these is true, and invert to negate this value. Logically, the body of fizz-buzz? is equivalent to:

!(x % 3 == 0 || x % 5 == 0)

Therefore, fizz-buzz? returns a boolean indicating if the argument is not divisible by 3 or 5, and thus should be printed. Finally, do-fizz-buzz loops from 1 to 25, calling fizz-buzz? on i, and outputting i if fizz-buzz? returns true.

If you’re having trouble figuring out what’s going on inside fizz-buzz?, the example below might help you to understand how it works. All we’re doing here is executing each word of the definition of fizz-buzz? on a separate line. As you execute each line, watch the stack to see how it changes:

: fizz?  3 mod 0 = dup if ." Fizz" then ;
: buzz?  5 mod 0 = dup if ." Buzz" then ;
4
dup
fizz?
swap
buzz?
or
invert
<- Top

Here’s how each line affects the stack:

4         4 <- Top
dup       4 4 <- Top
fizz?     4 0 <- Top
swap      0 4 <- Top
buzz?     0 0 <- Top
or        0 <- Top
invert    -1 <- Top

Remember, the final value on the stack is the return value of the fizz-buzz? word. In this case, it’s true, because the number was not divisible by 3 or 5, and so should be printed.

Here’s the same thing but starting with 5:

5         5 <- Top
dup       5 5 <- Top
fizz?     5 0 <- Top
swap      0 5 <- Top
buzz?     0 -1 <- Top
or        -1 <- Top
invert    0 <- Top

In this case the original top-of-stack value was divisible by 5, so nothing should be printed.

Variables and Constants

Forth also allows you to save values in variables and constants. Variables allow you to keep track of changing values without having to store them on the stack. Constants give you a simple way to refer to a value that won’t change.

Variables

Because the role of local variables is generally played by the stack, variables in Forth are used more to store state that may be needed across multiple words.

Defining variables is simple:

variable balance

This basically associates a particular memory location with the name balancebalance is now a word, and all it does is to push its memory location onto the stack:

variable balance
balance
<- Top

You should see the value 1000 on the stack. This Forth implementation arbitrarily starts storing variables at the memory location 1000.

The word ! stores a value at the memory location referenced by a variable, and the word @ fetches the value from a memory location:

variable balance
123 balance !
balance @
<- Top

This time you should see the value 123 on the stack. 123 balance pushes the value and the memory location onto the stack, and ! stores that value at that memory location. Likewise, @ retrieves the value based on the memory location, and pushes that value onto the stack. If you’ve used C or C++, you can think of balance as a pointer that is dereferenced by @.

The word ? is defined as @ . and it prints the current value of a variable. The word +! is used to increase the value of a variable by a certain amount (like += in C-based languages).

variable balance
123 balance !
balance ?
50 balance +!
balance ?
<- Top

Run this code and you should see:

variable balance ok 123 balance ! ok balance ? 123 ok 50 balance +! ok balance ? 173 ok

Constants

If you have a value that doesn’t change, you can store it as a constant. Constants are defined in one line, like this:

42 constant answer

This creates a new constant called answer with the value 42. Unlike variables, constants just represent values, rather than memory locations, so there’s no need to use @.

42 constant answer
2 answer *
<- Top

Running this will push the value 84 on the stack. answer is treated as if it was the number it represents (just like constants and variables in other languages).

Arrays

Forth doesn’t exactly support arrays, but it does allow you to allocate a zone of contiguous memory, a lot like arrays in C. To allocate this memory, use the allot word.

variable numbers
3 cells allot
10 numbers 0 cells + !
20 numbers 1 cells + !
30 numbers 2 cells + !
40 numbers 3 cells + !
<- Top

This example creates a memory location called numbers, and reserves three extra memory cells after this location, giving a total of four memory cells. (cells just multiplies by the cell-width, which is 1 in this implementation.)

numbers 0 + gives the address of the first cell in the array. 10 numbers 0 + ! stores the value 10 in the first cell of the array.

We can easily write words to simplify array access:

variable numbers
3 cells allot
: number  ( offset -- addr )  cells numbers + ;

10 0 number !
20 1 number !
30 2 number !
40 3 number !

2 number ?
<- Top

number takes an offset into numbers and returns the memory address at that offset. 30 2 number ! stores 30 at offset 2 in numbers, and 2 number ? prints the value at offset 2 in numbers.

Keyboard Input

Forth has a special word called key, which is used for accepting keyboard input. When the key word is executed, execution is paused until a key is pressed. Once a key is pressed, the key code of that key is pushed onto the stack. Try out the following:

key . key . key .
<- Top

When you run this line, you’ll notice that at first nothing happens. This is because the interpreter is waiting for your keyboard input. Try hitting the A key, and you should see the keycode for that key, 65, appear as output on the current line. Now hit B, then C, and you should see the following:

key . key . key . 65 66 67 ok

Printing keys with begin until

Forth has another kind of loop called begin until. This works like a while loop in C-based languages. Every time the word until is hit, the interpreter checks to see if the top of the stack is non-zero (true). If it is, it jumps back to the matching begin. If not, execution continues.

Here’s an example of using begin until to print key codes:

: print-keycode  begin key dup . 32 = until ;
print-keycode
<- Top

This will keep printing key codes until you press space. You should see something like this:

print-keycode 80 82 73 78 84 189 75 69 89 67 79 68 69 32 ok

key waits for key input, then dup duplicates the keycode from key. We then use . to output the top copy of the keycode, and 32 = to check to see if the keycode is equal to 32. If it is, we break out of the loop, otherwise we loop back to begin.

Snake!

Now it’s time to put it all together and make a game! Rather than having you type all the code, I’ve pre-loaded it into the editor.

Before we look at the code, try playing the game. To start the game, execute the word start. Then use the arrow keys to move the snake. If you lose, you can run start again.

<- Top

variable snake-x-head ok

500 cells allot ok

ok

variable snake-y-head ok

500 cells allot ok

ok

variable apple-x ok

variable apple-y ok

ok

0 constant left ok

1 constant up ok

2 constant right ok

3 constant down ok

ok

24 constant width ok

24 constant height ok

ok

variable direction ok

variable length ok

ok

: snake-x ( offset — address )

cells snake-x-head + ; ok

ok

: snake-y ( offset — address )

cells snake-y-head + ; ok

ok

: convert-x-y ( x y — offset ) 24 cells * + ; ok

: draw ( color x y — ) convert-x-y graphics + ! ; ok

: draw-white ( x y — ) 1 rot rot draw ; ok

: draw-black ( x y — ) 0 rot rot draw ; ok

ok

: draw-walls

width 0 do

i 0 draw-black

i height 1 – draw-black

loop

height 0 do

0 i draw-black

width 1 – i draw-black

loop ; ok

ok

: initialize-snake

4 length !

length @ 1 + 0 do

12 i – i snake-x !

12 i snake-y !

loop

right direction ! ; ok

ok

: set-apple-position apple-x ! apple-y ! ; ok

ok

: initialize-apple 4 4 set-apple-position ; ok

ok

: initialize

width 0 do

height 0 do

j i draw-white

loop

loop

draw-walls

initialize-snake

initialize-apple ; ok

ok

: move-up -1 snake-y-head +! ; ok

: move-left -1 snake-x-head +! ; ok

: move-down 1 snake-y-head +! ; ok

: move-right 1 snake-x-head +! ; ok

ok

: move-snake-head direction @

left over = if move-left else

up over = if move-up else

right over = if move-right else

down over = if move-down

then then then then drop ; ok

ok

\ Move each segment of the snake forward by one ok

: move-snake-tail 0 length @ do

i snake-x @ i 1 + snake-x !

i snake-y @ i 1 + snake-y !

-1 +loop ; ok

ok

: is-horizontal direction @ dup

left = swap

right = or ; ok

ok

: is-vertical direction @ dup

up = swap

down = or ; ok

ok

: turn-up is-horizontal if up direction ! then ; ok

: turn-left is-vertical if left direction ! then ; ok

: turn-down is-horizontal if down direction ! then ; ok

: turn-right is-vertical if right direction ! then ; ok

ok

: change-direction ( key — )

37 over = if turn-left else

38 over = if turn-up else

39 over = if turn-right else

40 over = if turn-down

then then then then drop ; ok

ok

: check-input

last-key @ change-direction

0 last-key ! ; ok

ok

\ get random x or y position within playable area ok

: random-position ( — pos )

width 4 – random 2 + ; ok

ok

: move-apple

apple-x @ apple-y @ draw-white

random-position random-position

set-apple-position ; ok

ok

: grow-snake 1 length +! ; ok

ok

: check-apple

snake-x-head @ apple-x @ =

snake-y-head @ apple-y @ =

and if

move-apple

grow-snake

then ; ok

ok

: check-collision ( — flag )

\ get current x/y position

snake-x-head @ snake-y-head @

\ get color at current position

convert-x-y graphics + @

\ leave boolean flag on stack

0 = ; ok

ok

: draw-snake

length @ 0 do

i snake-x @ i snake-y @ draw-black

loop

length @ snake-x @

length @ snake-y @

draw-white ; ok

ok

: draw-apple

apple-x @ apple-y @ draw-black ; ok

ok

ok

: game-loop ( — )

begin

draw-snake

draw-apple

100 sleep

check-input

move-snake-tail

move-snake-head

check-apple

check-collision

until

.” Game Over” ; ok

ok

: start initialize game-loop ; ok

ok

Before we delve too deeply into this code, two disclaimers. First, this is terrible Forth code. I’m by no means a Forth expert, so there’s probably all kinds of things I’m doing in completely the wrong way. Second, this game uses a few non-standard techniques in order to interface with JavaScript. I’ll go through these now.

Non-Standard Additions

The Canvas

You may have noticed that this editor is different from the others: it has an HTML5 Canvas element built in. I’ve created a very simple memory-mapped interface for drawing onto this canvas. The canvas is split up into 24 x 24 “pixels” which can be black or white. The first pixel is found at the memory address given by the variable graphics, and the rest of the pixels are offsets from the variable. So, for example, to draw a white pixel in the top-left corner you could run

1 graphics !
<- Top

The game uses the following words to draw to the canvas:

: convert-x-y ( x y -- offset )  24 cells * + ;
: draw ( color x y -- )  convert-x-y graphics + ! ;
: draw-white ( x y -- )  1 rot rot draw ;
: draw-black ( x y -- )  0 rot rot draw ;

For example, 3 4 draw-white draws a white pixel at the coordinates (3, 4). The y coordinate is multiplied by 24 to get the row, then the x coordinated is added to get the column.

Non-Blocking Keyboard Input

The Forth word key blocks, so is unsuitable for a game like this. I’ve added a variable called last-key which always holds the value of the last key to be pressed. last-key is only updated while the interpreter is running Forth code.

Random Number Generation

The Forth standard doesn’t define a way of generating random numbers, so I’ve added a word called random ( range -- n ) that takes a range and returns a random number from 0 to range – 1. For example, 3 random could return 01, or 2.

sleep ( ms -- )

Finally, I’ve added a blocking sleep word that pauses execution for the number of milliseconds given.

The Game Code

Now we can work through the code from start to finish.

Variables and Constants

The start of the code just sets up some variables and constants:

variable snake-x-head
500 cells allot

variable snake-y-head
500 cells allot

variable apple-x
variable apple-y

0 constant left
1 constant up
2 constant right
3 constant down

24 constant width
24 constant height

variable direction
variable length

snake-x-head and snake-y-head are memory locations used to store the x and y coordinates of the head of the snake. 500 cells of memory are alloted after these two locations to store the coordinates of the tail of the snake.

Next we define two words for accessing memory locations representing the body of the snake.

: snake-x ( offset -- address )
  cells snake-x-head + ;

: snake-y ( offset -- address )
  cells snake-y-head + ;

Just like the number word earlier, these two words are used to access elements in the arrays of snake segments. After this come some words for drawing to the canvas, described above.

We use constants to refer to the four directions (leftupright, and down), and a variable direction to store the current direction.

Initialization

After this we initialize everything:

: draw-walls
  width 0 do
    i 0 draw-black
    i height 1 - draw-black
  loop
  height 0 do
    0 i draw-black
    width 1 - i draw-black
  loop ;

: initialize-snake
  4 length !
  length @ 1 + 0 do
    12 i - i snake-x !
    12 i snake-y !
  loop
  right direction ! ;

: set-apple-position apple-x ! apple-y ! ;

: initialize-apple  4 4 set-apple-position ;

: initialize
  width 0 do
    height 0 do
      j i draw-white
    loop
  loop
  draw-walls
  initialize-snake
  initialize-apple ;

draw-walls uses two do/loops to draw the horizontal and vertical walls, respectively.

initialize-snake sets the length variable to 4, then loops from 0 to length + 1 filling in the starting snake positions. The snake positions are always kept one longer than the length so we can grow the snake easily.

set-apple-position and initialize-apple set the initial position of the apple to (4,4).

Finally, initialize fills everything in white and calls the three initialization words.

Moving the Snake

Here’s the code for moving the snake based on the current value of direction:

: move-up  -1 snake-y-head +! ;
: move-left  -1 snake-x-head +! ;
: move-down  1 snake-y-head +! ;
: move-right  1 snake-x-head +! ;

: move-snake-head  direction @
  left over  = if move-left else
  up over    = if move-up else
  right over = if move-right else
  down over  = if move-down
  then then then then drop ;

\ Move each segment of the snake forward by one
: move-snake-tail  0 length @ do
    i snake-x @ i 1 + snake-x !
    i snake-y @ i 1 + snake-y !
  -1 +loop ;

move-upmove-leftmove-down, and move-right just add or subtract one from the x or y coordinate of the snake head. move-snake-head inspects the value of direction and calls the appropriate move-* word. This over = if pattern is an idiomatic way of doing case statements in Forth.

move-snake-tail goes through the array of snake positions backwards, copying each value forward by 1 cell. This is called before we move the snake head, to move each segment of the snake forward one space. It uses a do/+loop, a variation of a do/loop that pops the stack on every iteration and adds that value to the next index, instead of incrementing by 1 each time. So 0 length @ do -1 +loop loops from length to 0 in increments of -1.

Keyboard Input

The next section of code takes the keyboard input and changes the snake direction if appropriate.

: is-horizontal  direction @ dup
  left = swap
  right = or ;

: is-vertical  direction @ dup
  up = swap
  down = or ;

: turn-up     is-horizontal if up direction ! then ;
: turn-left   is-vertical if left direction ! then ;
: turn-down   is-horizontal if down direction ! then ;
: turn-right  is-vertical if right direction ! then ;

: change-direction ( key -- )
  37 over = if turn-left else
  38 over = if turn-up else
  39 over = if turn-right else
  40 over = if turn-down
  then then then then drop ;

: check-input
  last-key @ change-direction
  0 last-key ! ;

is-horizontal and is-vertical check the current status of the direction variable to see if it’s a horizontal or vertical direction.

The turn-* words are used to set a new direction, but use is-horizontal and is-vertical to check the current direction first to see if the new direction is valid. For example, if the snake is moving horizontally, setting a new direction of left or right doesn’t make sense.

change-direction takes a key and calls the appropriate turn-* word if the key was one of the arrow keys. check-input does the work of getting the last key from the last-key pseudo-variable, calling change-direction, then setting last-key to 0 to indicate that the most recent keypress has been dealt with.

The Apple

The next code is used for checking to see if the apple has been eaten, and if so, moving it to a new (random) location. Also, if the apple has been eaten we grow the snake.

\ get random x or y position within playable area
: random-position ( -- pos )
  width 4 - random 2 + ;

: move-apple
  apple-x @ apple-y @ draw-white
  random-position random-position
  set-apple-position ;

: grow-snake  1 length +! ;

: check-apple ( -- flag )
  snake-x-head @ apple-x @ =
  snake-y-head @ apple-y @ =
  and if
    move-apple
    grow-snake
  then ;

random-position generates a random x or y coordinate in the range of 2 to width - 2. This prevents the apple from ever appearing right next to the wall.

move-apple erases the current apple (using draw-white) then creates a new pair of x/y coordinates for the apple using random-position twice. Finally, it calls set-apple-position to move the apple to the new coordinates.

grow-snake simply adds one to the length variable.

check-apple compares the x/y coordinates of the apple and the snake head to see if they’re the same (using = twice and and to combine the two booleans). If the coordinates are the same, we call move-apple to move the apple to a new position and grow-snake to make the snake 1 segment longer.

Collision Detection

Next we see if the snake has collided with the walls or itself.

: check-collision ( -- flag )
  \ get current x/y position
  snake-x-head @ snake-y-head @

  \ get color at current position
  convert-x-y graphics + @

  \ leave boolean flag on stack
  0 = ;

check-collision checks to see if the new snake head position is already black (this word is called after updating the snake’s position but before drawing it at the new position). We leave a boolean on the stack to say whether a collision has occured or not.

Drawing the Snake and Apple

The next two words are responsible for drawing the snake and apple.

: draw-snake
  length @ 0 do
    i snake-x @ i snake-y @ draw-black
  loop
  length @ snake-x @
  length @ snake-y @
  draw-white ;

: draw-apple
  apple-x @ apple-y @ draw-black ;

draw-snake loops through each cell in the snake arrays, drawing a black pixel for each one. After that it draws a white pixel at an offset of length. The last part of the tail is at length - 1 into the array so length holds the previous last tail segment.

draw-apple simply draws a black pixel at the apple’s current location.

The Game Loop

The game loop constantly loops until a collision occurs, calling each of the words defined above in turn.

: game-loop ( -- )
  begin
    draw-snake
    draw-apple
    100 sleep
    check-input
    move-snake-tail
    move-snake-head
    check-apple
    check-collision
  until
  ." Game Over" ;

: start  initialize game-loop ;

The begin/until loop uses the boolean returned by check-collision to see whether to continue looping or to exit the loop. When the loop is exited the string "Game Over" is printed. We use 100 sleep to pause for 100 ms every iteration, making the game run at rougly 10 fps.

start just calls initialize to reset everything, then kicks off game-loop. Because all the initialization happens in the initialize word, you can call start again after game over.


And that’s it! Hopefully all the code in the game made sense. If not, you can try running individual words to see their effect on the stack and/or on the variables.

The End

Forth is actually much more powerful than what I’ve taught here (and what I implemented in my interpreter). A true Forth system allows you to modify how the compiler works and create new defining words, allowing you to completely customize your environment and create your own languages within Forth.

A great resource for learning the full power of Forth is the short book “Starting Forth” by Leo Brodie. It’s available for free online and teaches you all the fun stuff I left out. It also has a good set of exercises for you to test out your knowledge. You’ll need to download a copy of SwiftForth to run the code though.

 Posted by at 6:11 am
Apr 022020
 

https://udamonic.com/accessing-memory.html

 

 Posted by at 7:37 am
Apr 022020
 

https://sites.google.com/view/forth-books/home/forth-books/dr-tings-collection14

 

FORTH BOOKS 14

DR.TINGS COLLECTION OF OFFETE

original link

http://forth.org/OffeteStore/OffeteStore.html?fbclid=IwAR2qzzV_12rhZL10lnXPa1uqDu5_ygrgWifh2b20Zbqi61AmPXj_BUBEn7Y

Here is a list of pdf document files and zipped software items from Offete Store which are now available for download. Please contact the author, CH Ting, if you have any questions about this material.

Inside Forth – Fourth Edition – 2013 – pdf

Systems Guide to figForth – Third Edition – 2013 – pdf

eForth and Zen – Second Edition – 2013 – pdf

Footsteps in an Empty Valley – NC4000 Single Chip Forth Engine – Third Expanded Edition – 1988 – pdf

Footsteps in an Empty Valley – NC4000 Single Chip Forth Engine – Fourth Edition – 2017 – pdf

F# – 241 – zip

ADUC Compiler – 520 – zip

eForth for SAM7 Chip – 2008 – zip

cEF, eForth in C, Version 1.1 – 2009 – zip

cEF, eForth in C – 2009 – zip

eForth for STM8S – 2010 – zip

eP32 Microcontroller Design in VHDL – 2012 – zip

328eForth for Arduino Uno – 2011– zip

eForth as an Arduino Sketch, Version 2.0 – 2011 – zip

eP16 Microcontroller Design in VHDL – 2012 – zip

430eForth for LaunchPad – 2012 – zip

STM32 eForth – 2014 – zip

Zen of LaunchPad – Version 4.3 – 2015 – zip

86eForth – Version 2.03 – 2016 – zip

ep8080 – 2006 – zip

PDP1 Design Workshop – 2016 – zip

86eForth – Version 5.2 – 2016 – zip

espForth for ESP8266 – zip

ceForth_23 – zip

esp32Forth Serial Monitor – zip

esp32Forth Web Browser – zip

esp32Forth Macro Assembler – zip

ceForth_33 Macro Assembler – zip

Many thanks to Dr. Ting for being one of the best authors and teachers of Forth ! and for his gesture setting all those important documents free available !

 Posted by at 7:28 am
Jan 132020
 

http://vice-emu.sourceforge.net/

What is VICE?

VICE is a program that runs on a Unix, MS-DOS, Win32, OS/2, BeOS, QNX 4.x, QNX 6.x, Amiga, Syllable or Mac OS X machine and executes programs intended for the old 8-bit computers. The current version emulates the C64, the C64DTV, the C128, the VIC20, practically all PET models, the PLUS4 and the CBM-II (aka C610/C510). An extra emulator is provided for C64 expanded with the CMD SuperCPU.

News

[NEW] (24 December 2019) Version 3.4 released

  • What is NEW in the latest release? (This is definitely worth reading 🙂
  • VICE has moved its source repository to public services provided by SourceForge. You can find it at https://sf.net/projects/vice-emu. We like to thank the SourceForge staff for that help.

 

______________________________________________

 

The HP Calculator Emulators for the Atari 800XL and for the Commodore 64

In 1972 the great American company Hewlett-Packard shipped their first pocket calculator. It was called HP-35, and it was the first pocket calculator with transcendental functions and the first with the so-called Reverse Polish Notation (RPN). The HP-35 was a huge success with scientific/engineering users, so HP soon came out with a similar model for business users. It was called HP-80, and could solve problems like present and future values of payment streams, trend line calculations (least squares linear regression), ammortization, date calculation, etc. Hewlett-Packard continued with the HP-45, an improved scientific model (which I happen to own :-), and (after the models 65 and 70) with the HP-55, which was programmable and supported a quartz-controlled stopwatch function. These (so-called “classic”) calculators of HP were based upon a proprietary 4-bit CPU developed just for that purpose.I wrote emulators for these four calculators for the Atari 800XL and for the Commodore 64, which simulate the HP calculator CPU to interpret the original program ROMs of the four models. This enables you to work with your Atari 800 or C64 exactly like with the great classic HP calculators with their sophisticated scientific and business functions.

The emulators for the Atari 800XL can be downloaded here:

The emulators for the Commodore 64 can be downloaded here:

You can use these files with an Atari or Commodore emulator or put it on floppy disks and try it on the real machines.

Much more information on HP’s classic (and more modern) calculators can be found at the Museum of HP Calculators.

In the following you find screenshots of the emulators running on the Atari 800XL and on the C64.

Atari 800XL:
Norbert Kehrer's HP Calculator Emulator for the Atari 800XL Norbert Kehrer's HP Calculator Emulator for the Atari 800XL
Norbert Kehrer's HP Calculator Emulator for the Atari 800XL Norbert Kehrer's HP Calculator Emulator for the Atari 800XL
 Posted by at 5:15 pm
Dec 282019
 

http://insanity4004.blogspot.com/2019/04/simulating-vfd-gridanode-driver.html

 

Simulating the VFD Grid/Anode driver

I was reading through an old posting about the VFD Grid and Anode driver circuit I’m planning to use, when it occurred to me that the resistor between the base of the PNP transistor and the collector of the NPN transistor might not be necessary. This is labeled R1 in the schematic to the right.

To calculate the desired resistance I’d done a bunch of hand calculations in my notebook, trying various combinations of target currents and resistor values. I started to do yet another with R1 set to zero when it occurred to me that this would be easier to do in simulation. At first I entered this circuit into LTspice using 2N3904 and 2N3906 transistors, as these are standard parts in the LTspice library. The simulation results matched my hand-calculated numbers, which gave me confidence that I’d done the calculations properly. I’m driving both transistors into saturation, and my turn-off times are anything but critical, so the choice of transistor isn’t critical.

Then I wondered how closely this approximation matched the real Toshiba RN4604. At first I thought this would be a challenge, as the process for creating a Spice model description for a transistor from its datasheet isn’t that easy. Wouldn’t it be nice if Toshiba provided a Spice model? Well, they do, and it’s available for download from their website. To make it easier to probe the base current of Q1A (Q1 in the Spice schematic) I extracted the transistor models from the subcircuits that add the built-in bias resistors and substituted them into my circuit.

My original plan had been to turn on Q1A by passing about 500 µA through its base. This was based on the spec’d saturation ICE of 5 mA with IBE of 250 µA, giving an hFE of 20. In the actual application I’ve found a grid draws about 6 mA and its 10K pull-down resistor will draw another 3 mA, so I doubled IBE for an ICE of 10 mA. If I eliminate R1 the base current jumps to 606 µA. But this puts almost the full 30 volts across the input (between pins 1 and 2); the datasheet graphs stop with an input voltage of 9 V. Even with the original R1 of 10K the input voltage is almost 25 V. So I’m thinking I should revisit this.

Looking at the hFE graphs I see the worst-case (at -25°C!) current gain at 30 mA is about 100. Of course this is in the transistor’s linear region, but it implies that with a base current of 300 µA and a collector current of only 10 mA the thing will be saturated. So I tweaked my Spice simulation to sweep the value of R1 from 100 ohms to 150 Kohms. I graphed the base and collector currents of the transistor, along with the “input” voltage (the difference between pins 1 and 2 on the package). I also changed the collector load resistor to 1 KΩ to get about 30 mA collector current if the transistor was saturated. This would make it more obvious when decreasing the base drive would start having a significant effect on the collector current.

The trick to interpreting these graphs is to remember that this is a PNP transistor in a common-emitter configuration, so the base and collector currents are negative. Thus a rise in the graph means less current. Also, the horizontal scale represents ohms, even though it’s reported in volts. So the “100KV” tick actually represents 100 KΩ.

It’s pretty obvious I don’t need 500 µA of base current. In fact, it looks like I could make R1 as high as 100 KΩ and still drive this transistor into saturation. Setting R1 to 63 KΩ gives me 250 µA of base current, while 47 KΩ gives me 295 µA. I’ll probably choose 47 KΩ to allow a generous margin for variations in bias resistor values, which can vary

 Posted by at 9:41 am
Dec 282019
 

http://www.intel4004.com/

http://www.4004.com/

http://e4004.szyc.org/

 

capture

Intel 4004 Microprocessor
The emulator, assembler and disassembler is written in JavaScript, so they are easy to execute on whatever platform with the internet browser and implemented JavaScript interpreter. The MCS-4 utilities core and GUI are based on the brilliant virtual 6502 emulator by Norbert Landsteiner, e-tradition.net.

This program is provided for free and AS IS, therefore without any warranty.

 Posted by at 7:23 am
Dec 272019
 

https://wiki.analog.com/university/courses/electronics/electronics-lab-28

 

Wiki

This version (23 Aug 2019 14:04) was approved by amiclaus.The Previously approved version (05 Mar 2019 12:36) is available.Diff

Build CMOS Logic Functions Using CD4007 Array

Objective:

The objective of this lab activity is to build the various CMOS logic functions possible with the CD4007 transistor array. The CD4007 contains 3 complementary pairs of NMOS and PMOS transistors.

Making inverters with the CD4007 transistor array

Below in figure 1 is the schematic and pinout for the CD4007:

Figure 1 CD4007 CMOS transistor array pinout

 Posted by at 2:29 pm
Dec 062019
 

RLC MŮSTEK

Návod k obsluze

Obsah

Popis
Měření
Měření odporů stejnmosměrným napětím
Měření velmi malých odporů
Měření odporů střídavým napětím
Měření kapacit
Měření velmi malých kapacit
Měření indukčností
Technické údaje
Rozpiska el. součástí
Schéma
Záruka a aopravy

 


 

Ovlácací prvky můstku.
RLC můstek TESLA TM 393 je určen k měření odporů, indukčností a kapacit. Je pro provoz ze střídavé sítě a je konstruován jako provozní přístroj, kterého lze použít i pro méně přesná měření laboratorní. Široké měřicí rozsahy umožňují jeho použití v silno- i slaboproudé elektrotechnice k měření jednotlivých částí nízko- i vysokofrekvenčních obvodů.

Konstrukčně náleží do řady provozních přístrojů TESLA, konstruovaných v kovové skřínce s rukojetí.

POPIS

Přístroj sestává z vlastního můstku, ze zesilovače s usměrňovačem, z nízkofrekvenčního oscilátoru, z můstkového napájecího zdroje a galvanometru.

Veškeré tyto části jsou vestavěny do společné skříně.

Můstek

Řada normálních odporů a cejchovaný potenciometr tvoří vlastní můstek, který obsáhne rozsah dvou dekád. Pro měření kapacit přepojuje se do jednoho ramene pevný kapacitní normál 10.000 pF a potenciometr pro vyrovnávání ztrátového úhlu. Při měření indukčností se do tohoto ramene zapojuje kapacitní normál 0,1 uF a event. druhý potenciometr pro vyrovnávání ztrátového úhlu paralelně ke kapacitnímu normálu. Z tohoto důvodu jsou pro měření indukčnosti na přepínači K4 dvě polohy pro měření indukčnosti.

Zesilovač

Vestavěný zesilovač je v provozu vždy při měření kapacit a indukčností a při měření odporů pouze tehdy, měří-li se střídavým napětím. Zesilovač je dvoustupňový a zapojuje se do diagonály mostu přepínačem K 3, je-li tento přepínač v poloze ~. První stupeň zesilovače má elektronku EF 22, v jejímž anodovém okruhu je filtr LC, který slouží k omezení nižších frekvencí, hlavně síťové, kapacitně přenesené na měřený objekt. Za tímto filtrem je potenciometr, kterým se nastavuje citlivost zesilovače. Druhý stupeň je elektronka EBL 21, zapojená jako triodový zesilovač. Diodový systém této elektronky usměrňuje získaný signál pro galvanometr.

Nízkofrekvenční oscilátor

Nízkofrekvenční oscilátor je tvořen obvodem LC v obvyklém zapojení a jako oscilační elektronky je použito EF 22. Oscilátor slouží k napájení můstku při měření střídavým napětím a jeho kmitočet je přibližně 400 c/s.

Napájecí zdroj

Napájecí zdroj je tvořen síťovým trasformátorem a usměrňovací elektronkou AZ l s příslušnými vyhlazovacími kapacitami a odpory. Dodává anodové napětí pro zesilovač, žhavící napětí pro elektronky a střídavé napětí pro suchý usměrňovač, ze kterého se napájí můstek při měření stejnosměrným napětím.

Galvanometr

Galvanometr je normální ručkový přístroj s nulou uprostřed, takže při měření odporů stejnosměrným napětím indikuje i směr rozladění mostu. Při měření střídavým napětím se vychyluje ručka pouze jedním směrem.

Příslušenství

Jako příslušenství je k přístroji dodávána síťová šňůra „Flexo” a sáček s náhradními pojistkami pro síť 220 i 120 V.

Připojeni na síť

Před připojením na síť je nutné přístroj přepnout na jmenovité napětí sítě přepojovačem napětí, umístěným na zadní straně přístroje. Přepnutí provedeme po uvolnění zajišťovacího kovového pásku, vytažením a zasunutím přepínacího kotoučku tak, aby číslo udávající napětí bylo postaveno proti trojúhelníčkové značce (obr. 2). Zajišťovací pásek opět připevníme. Vlevo vedle voliče napětí je síťová pojistka P a dále síťová zástrčka. Vpravo od voliče je anodová pojistka Pa (obr. 3).

Síť zapínáme knoflíkem K2 (povytažením nebo pootočením doprava), přičemž se rozsvítí signální žárovka Z.

Kryt přístroje je zapojen na ochranný vodič.

Umístění voliče napětí a popjistek.
 

MĚŘENÍ

Měření odporů stejnosměrným napětím (obr. 4)

Stejnosměrným napětím lze měřit veškeré ohmické odpory, bez ohledu na jalovou složku. Měřený odpor připojíme na svorky RLC a vytažením

obr. 4 Schéma měření odporu.

(pootočením) knoflíku K2 uvedeme přístroj do provozu. Přepínač K3 přepneme do polohy = a přepínač K4 zapneme do polohy R.

Knoflíkem K2 nastavíme citlivost tak, aby ručka galvanometru nebyla vychýlena až na doraz. Měrný potenciometr postavíme přibližně do střední polohy a přepínačem K 5 přepneme do té polohy, ve které je výchylka galvanornetru nejmenší. Podle potřeby zvýšíme citlivost knoflíkem K2.

Nastavením potenciometru Kl (hrubě velkým knoflíkem a jemně malým knoflíkem) vyvážíme most tak, až ručka galvanornetru ukazuje na nulu. Při takto vyváženém mostě odečteme údaj na síupnici knoflíku K1 a násobíme ho číslem, na které ukazuje šipka přepínače rozsahů K5.

Při měření stejnosměrným napětím jsou funkce knoflíků K6 a K7 vyřazeny a nezáleží na tom, jak jsou knoflíky nastaveny.

Měření velmi malých odporů

Při měření velmi malých odporů je nutné dbát, aby byl vyloučen vliv přechodových odporů. Veškeré tyto odpory měříme tak, že provedeme dvoje měření. Za prvé změříme přechodové odpory tak, že přepínač K5 postavíme do polohy 0,1 Ω a svorky RLC spojíme nakrátko silným drátem. Nyní vyvážíme most a na stupnici Kl odečteme přechodový odpor Rp. Přepínači přístroje dále nemanipulujeme, zkracovací drát odpojíme ze svorek RLC a na jeho místo připojíme malý odpor, který má být změřen. Knoflíkem Kl most znovu vyvážíme a odečteme naměřenou hodnotu Rs. Správná hodnota měřeného odporu je pak rozdíl obou naměřených hodnot, tedy

R = Rs – Rp.

Protože stupnice knoflíku Kl je cejchována přímo v ohmech, je i výsledek měření udán přímo v těchto jednotkách.

Měření odporů střídavým napětím

Střídavým napětím lze měřit pouze odpory čistě ohmické nebo odpory s velmi malou složkou kapacitní nebo induktivní. Měřený odpor připojujeme rovněž na svorky RLC, přepínač K4 zůstane v poloze R, přepínač K3 přepneme do polohy ~. Potenciomelrem K2 nastavíme menší citlivost tak, aby ručka galvanometru nebyla vychýlena až na doraz. Přepínačem K5 najdeme polohu, při které je výchylka ručky nejmenší a knoflíkem K1 vyvážíme pak můstek na nulu. Knoflíkem K 2 zvýšíme citlivost a opětným dostavením potenciometru K1 můstek znovu vyválíme. Jestliže je poteneiometrem K2 nastavena velká citlivost zesilovače, nevrátí se ručka galvanometru na nulu, což je způsobeno vlastním šumem zesilovače, a pak vyvažujeme most na nejmenší výchylku, bez ohledu na to, že ručka neukazuje na nulu. I v tomto případě jsou potenciometry K6 a K7 mimo provoz a nezáleží na jejich postavení. Naměřenou hodnotu odečítáme již známým způsobem.

Měřeni kapacit (obr. 5)

Kapacity se měří pouze střídavým napětím a přepínač K3 musí být proto v poloze ~. Přepínač K4 přepneme do polohy C a měřený kondensátor připojíme na svorky RLC. Potenciometrem K2 nastavíme zprvu malou citlivost, aby ručka galvanometru nebyla vychýlena až na doraz. Přepínačem rozsahů K5 přepneme do polohy nejmenší výchylky indikátoru a most vyvážíme potenciometrem K1. Citlivost zesilovače zvýšíme a opětným dostavením knoflíku Kl vyvážíme most. Protože měřená kapacita způsobí kvalitou svého dielektrika jisté zbytkové napětí, které není s napětím procházejícím čistou kapacitou ve fázi, je ve větvi, ve které je zapojen kapacitní normál, též potenciometr K7, kterým se vliv ztrátového úhlu měřené kapacity kompensuje.

Obr. 5 měření kapacit.
 

Je tedy nutné po vyvážení mostu tímto potenciometrem, označeným na panelu „tg δ”, pootočit tak, aby se výchylka snížila. Opětným dostavením potenciometru K1 vyvážíme most. Naměřenou kapacitu čteme na stupnici knoflíku K1 a násobíme ji číslem, proti kterému je postaven přepínač rozsahů K5.

Údaj knoflíku K7 není cejchován, lze však podle jeho polohy posuzovat jakost dielektrika.

Měření malých kapacit

Při měření malých kapacit je nutné brát v úvahu i vlastní kapacitu svorek přístroje, která je asi 2 pF, a přívodů, není-li kondensátor připojován přímo na svorky přístroje. Měříme-li malou kapacitu s přívodními dráty, musíme předem změřit kapacitu těchto drátů, při čemž má být jejich poloha stejná při připojeném i odpojeném kondensátoru. Druhé měření pak provedeme s připojeným kondensátorem a výsledná kapacita měřeného kondensátoru je dána rozdílem obou naměřených kapacit.

Měření indukčností (viz obr. 6 a 7)

Pro měření indukčnosti jsou na přepínači K4 dvě polohy. Důvodem pro to je, že měřicí rozsah indukčností je velký a tím jsou i velmi rozdílné ztrátové složky měřených indukčností. Těmto polohám odpovídají i oba potenciometry K6 a K7. Je-li funkční přepínač K4 v poloze Ls, vyrovnáváme ztrátovou složku potenciometrem K6, který je v tomto případě zapojen v sérii s vestavěným kapacitním normálem. Přepneme-li funkční přepínač K4 do polohy Lp, vyrovnáváme ztrátovou složku potenciometrem K7, který se v této poloze připojuje ke kapacitnímu normálu paralelně. Všeobecně lze říci, že měření cívek je nutné provádět v té poloze přepínače K4, ve které můžeme příslušným potenciometrem pro vyrovnání ztrátové složky nastavit minimální výchylku indikátoru.

Obr.  6 a 7. Schemata měření indukčnosti.

Při měření indukčností je tedy nutné přepnout přepínač K3 do polohy ~, přepínač K4 do polohy Ls nebo Lp a měřenou indukčnost připojit na svorky RLC. Potenciometrem K 2 nastavíme menší citlivost, aby vyvažování můstku bylo snazší. Přepínačem K5 přepneme do té polohy, ve které je výchylka galvanometru nejmenší, a knoflíkem Kl vyvážíme most.

Potenciometrem pro ztrátovou složku, odpovídajícím poloze přepínače K4, otáčíme tak, aby se výchylka galvanometru dále snížila. Nelze-li otáčením potenciometru dosáhnout minima výchylky, musíme přepínač K4 přepnout do druhé polohy pro měření indukčností a vyrovnat ztrátovou složku potenciometrem příslušným této poloze. Po dosažení nižší výchylky galvanometru musíme můstek knoflíkem K1 znovu vyvážit a po zvýšení citlivosti knoflíkem K2 tento postup opakovat, až dosáhneme nejnižší výchylky obsluhou knoflíku K1 a příslušného potenciometru pro ztrátovou složku. Po takovém vyvážení můstku čteme pak naměřenou indukčnost na stupnici knoflíku K1 a násobíme ji číslem, proti kterému je nastavena šipka přepínače K5. Naměřená indukčnost je pak udána v jednotkách, které označuje šipka přepínače K5, buď v mH nebo v H.

TECHNICKÉ ÚDAJE

Rozsah odporů: 0,01 Ω  — 10 MΩ, rozděleno do osmi rozsahů; možnost měření bud stejnosměrným nebo střídavým napětím.
Rozsah indukčností: 0,01 mH — 1000 H; rozděleno do sedmi rozsahů.
Rozsah kapacit: 1 pF — 100 μF, rozdělený do sedmi rozsahů.
Přesnost měření: pro R a C ± 2%, při měření elektrolytických kondensátorů je přesnost horší; pro L ±3%.
Vlastní kapacita svorek: cca 2 pF.
Měrný kmitočet: cca 400 c/s.
Galvanometr: ±100 μA s mechanickou nulou uprostřed.
Elektronky: EF 22 —  první stupeň zesilovače,
EBL 21 — druhý stupeň zesilovače,
EF 22 — nf. oscilátor
žárovka 6,3 V/0,3 A.
Pojistky (obr. 3): síťová (P) pro 220 V … 0,4 A,
pro 120 V … 1 A,
anodová (Pa) … 0,1 A.
Napájení: střídavé napětí 120 nebo 220 V, 50 c/s.
Spotřeba: 30 W.
Rozměry: šířka 320 mm,
výška 265 mm,
hloubka 225 mm.
Váha: 9,4 kg.

ROZPISKA EL. SOUČÁSTÍ

Odpory
Označení Druh Norma
R1 karta odporová XF 681 00
R2 karta odporová XF 681 00
R3 karta odporová XF 681 03
R4 karta odporová XF 681 02
R5 karta odporová XF 681 01
R6 odpor vrstvový P1A 0024 WK 181 03/M1/D
R7 odpor vrstvový P1A 0024 WK 181 03/M1/D
R8 potenciometr 1AN 690 04
R9 karta odporová 10K XF 681 01
R10 potenciometr 1AN 69003
R11 karta odporová 10K XF 681 02
R12 potenciometr NTN 150 WN 694 02/1k/N
R13+R21 potenciometr 1AN 698 01
R14 odpor vrstvový NTN 050 TR102 2M/A
R15 odpor vrstvový NTN 050 TR102 500/A
R16 odpor vrstvový NTN 050 TR103 M2/A
R17 odpor vrstvový NTN 050 TR103 M4/A
R18 odpor drátový NTN 053 TR601 10/A
R19 odpor vrstvový NTN 050 TR102 20
R20 odpor vrstvový NTN 050 TR103 20k/A
R22 odpor vrstvový NTN 050 TR104 32k/B
R23 odpor vrstvový NTN 050 TR102 10k/A
R24 odpor vrstvový NTN 050 TR102 10k/A
R25 odpor vrstvový NTN 050 TR103 1k/A
R26 odpor vrstvový NTN 050 TR102 10k
R27 odpor vrstvový NTN 050 TR104 32k/B
R28 odpor vrstvový NTN 050 TR102 64k/B
R29 odpor vrstvový NTN 050 TR102 M16/B
R30 odpor vrstvový NTN 050 TR104 10k/A

 

Dostavovací odpory
Označení Norma Dostavovací hodnoty
Rc NTN 050 TR 103 M32 nebo M5, M8, Ml, 1M25/A
Rd PIA 0024 WK 681 03 1M6 nebo 2M5, 4M, 5M, 6M4, 8M, 10 M/C
Re PIA 0024 WK 681 03 1M6 nebo 2M5, 4M, 5M, 6M4, 8M, 10M/C

 

Kondensátory
Označení Druh Norma
C1 slídový WK 714 08/5k/D
C2 styroflexový CK 724 21/M1/D
C3 elektrolytický NTN 092 TC 500 25M
C4 svitkový NTN 060 TC 103 M5/A
C5+C8 elektrolytický NTN 090 TC 521 16/16M
C6 svitkový NTN 060 TC 104 1k/A
C7 svitkový NTN 060 TC 104 1k/A
C9 svitkový NTN 060 TC 103 50k/B
C10 svitkový NTN 060 TC 103 40k/B
C11 elektrolytický NTN 092 TC 500 25M
C12 svitkový NTN 060 TC 103 Ml/A
C13+C14 elektrolytický NTN 090 TC 521 16/16M
C15 slídový NTN 073 TC 212 4k/B
C16 svitkový NTN 060 TC 106 5k
C17 svitkový NTN 060 TC 106 5k
C25 slídový NTN 073 TC 212 4k/B

 

Dostavovací kondensátory
Označení Norma Dostavovací hodnoty
Ca slídový WK 714 08 1k nebo 2k, 5k/B
Cb slídový WK 714 08 1k/B
Cc NTN 060 TC 103 16k nebo 5k, 10k/B

SCHÉMA

Schéma se otevře ve zvláštním okně, protože je příliš velké pro vložení do textu.

ZÁRUKA A OPRAVY

Výrobní závod poskytuje na každý dodaný přístroj 6měsíční záruku podle všeobecných záručních podmínek, platných pro prodej výrobků TESLA.

Vady, které se na výrobku vyskytnou během poskytované záruční doby a budou způsobeny chybami při výrobě nebo vadným materiálem, budou bezplatně opraveny. Záruka zaniká při porušení plomby výrobního závodu nebo při provedení jakýchkoliv vlastních zásahů do elektrické či mechanické funkce přístroje.

Veškeré opravy přístrojů v záruce i mimo záruční dobu provádí výrobní závod vlastní opravnou.

Bude-li někdy třeba zaslat přístroj k opravě nebo k přezkoušení, zašlete jej dobře zabalený s popisem závady na adresu:

TESLA
národní podnik
BRNO, Čechyňská 16. Opravna tel. č. 38753


Nascannoval a do html podoby upravil Ing. Petr Jeníček. Oproti originálu byl na začátek přidán obsah. Poslední změna dne 8.5.2005.

 Posted by at 3:44 pm
Oct 172019
 

https://forum.43oh.com/topic/13361-add-msp432-support-to-arduino/

 

 Sign in to follow this  

mgh

Add MSP432 support to Arduino?

Does anyone know if MSP432 (black) can be added to the standard Arduino setup?

The reason: I’ve got an Adafruit Feather M0+ board working with Arduino, so the ARM Cortex-M compiler is “already there”. I’m hoping maybe I could remove Energia (since I don’t need the ‘430 support). If I add the JSON board file for the black MSP432 launch-pad, will the Arduino IDE get everything it needs to play with the MSP432?     https://energia.nu/packages/package_msp432_black_index.json

Also, is there a JSON file for the Tiva TM4C123 launch-pad?  (same reason, have a Tiva, want to move everything over to one IDE).

Thanks!

 

No, it is not possible as the Energia IDE includes specific features to support the multi-treading of the MSP432.

The black MSP432 is deprecated and no longer supported.

 

But I don’t care about that multitasking – does anyone know if it would work otherwise?

Yes, I know the black MSP432 has been abandoned, but I’m not going to throw away perfectly good hardware.

Thanks for the response!

 

 

  On 1/11/2019 at 2:51 AM, mgh said:

Also, is there a JSON file for the Tiva TM4C123 launch-pad?  (same reason, have a Tiva, want to move everything over to one IDE).

Thanks!

not json but instructions given for linux

https://github.com/RickKimball/tivac-core

Assumes you have openocd and arm-none-eabi-gcc in your path. Probably won’t work for windows. Probably will work for OSX.

 

Although the Arduino IDE should be able to consume the Energia packages, there is a difference between the arduino-builder in Arduino and Energia which makes the msp432 package incompatible with the Arduino IDE. See the pull request here: https://github.com/arduino/arduino-builder/pull/119. I have it on my list to find a different solution and be able to use the stock arduino-builder at which point the Arduino IDE should be able to consume the Energia package.

For TivaC and MSP430, it is possible to use it in the Arduino IDE. Just put this in the preferences: http://energia.nu/packages/package_energia_index.json. Then pull up the board manager and install TivaC support.

 

 

Wow! Thank you Rick, thank you @energia! I’ll try some of these this weekend.

 

If you want to use one single IDE for all the different boards, try

All come as freemium: free for basic features; one-time-fee or subscription for more advanced features.

 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It’s easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

{
  "packages": [
    {
      "name": "energia",
      "maintainer": "Energia",
      "websiteURL": "http://www.energia.nu/",
      "email": "make@energia.nu",
      "help": {
        "online": "http://energia.nu/reference"
      },
      "platforms": [
        {
          "name": "Energia MSP430 boards",
          "architecture": "msp430",
          "version": "1.0.5",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp430-1.0.5.tar.bz2",
          "archiveFileName": "msp430-1.0.5.tar.bz2",
          "checksum": "SHA-256:f40371d7e5140be6ce671aa33ca686b6d0fdfe6fd480dcb5d8dd79a87ce23305",
          "size": "2077472",
          "boards": [
            {"name": "MSP-EXP430F5529"},
            {"name": "MSP-EXP430FR2433"},
            {"name": "MSP-EXP430FR4133"},
            {"name": "MSP-EXP430FR5969"},
            {"name": "MSP-EXP430FR6989"},
            {"name": "MSP-EXP430FR5739"},
            {"name": "MSP-EXP430FR2355"},
            {"name": "MSP-EXP430FR2231"},
            {"name": "MSP-EXP430G2"},
            {"name": "MSP-EXP430G2ET"},
            {"name": "MSP-EXP430FR5994"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"msp430-gcc",
              "version":"4.6.6"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"8.2.0.1400"
            },
            {
              "packager":"energia",
              "name":"mspdebug",
              "version":"0.24"
            }
         ]
        },
        {
          "name": "Energia MSP430 boards",
          "architecture": "msp430",
          "version": "1.0.4",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp430-1.0.4.tar.bz2",
          "archiveFileName": "msp430-1.0.4.tar.bz2",
          "checksum": "SHA-256:84f752999538be0da7305f25a87ccf487008510404182feecbd6e4276642e6f2",
          "size": "2076765",
          "boards": [
            {"name": "MSP-EXP430F5529"},
            {"name": "MSP-EXP430FR2433"},
            {"name": "MSP-EXP430FR4133"},
            {"name": "MSP-EXP430FR5969"},
            {"name": "MSP-EXP430FR6989"},
            {"name": "MSP-EXP430FR5739"},
            {"name": "MSP-EXP430FR2355"},
            {"name": "MSP-EXP430FR2231"},
            {"name": "MSP-EXP430G2"},
            {"name": "MSP-EXP430G2ET"},
            {"name": "MSP-EXP430FR5994"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"msp430-gcc",
              "version":"4.6.6"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"8.2.0.1400"
            },
            {
              "packager":"energia",
              "name":"mspdebug",
              "version":"0.24"
            }
         ]
        },
        {
          "name": "Energia MSP430 boards",
          "architecture": "msp430",
          "version": "1.0.3",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp430-1.0.3.tar.bz2",
          "archiveFileName": "msp430-1.0.3.tar.bz2",
          "checksum": "SHA-256:cc4902a2bcaa43850c0e9a852f10bb5662b3eb4d4388e693d7d71c97bbdcb18a",
          "size": "2072767",
          "boards": [
            {"name": "MSP-EXP430F5529"},
            {"name": "MSP-EXP430FR2433"},
            {"name": "MSP-EXP430FR4133"},
            {"name": "MSP-EXP430FR5969"},
            {"name": "MSP-EXP430FR6989"},
            {"name": "MSP-EXP430FR5739"},
            {"name": "MSP-EXP430G2"},
            {"name": "MSP-EXP430FR5994"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"msp430-gcc",
              "version":"4.6.5"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.4.0.1099"
            },
            {
              "packager":"energia",
              "name":"mspdebug",
              "version":"0.24"
            }
         ]
        },
        {
          "name": "Energia MSP430 boards",
          "architecture": "msp430",
          "version": "1.0.2",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp430-1.0.2.tar.bz2",
          "archiveFileName": "msp430-1.0.2.tar.bz2",
          "checksum": "SHA-256:855ff60aacc129f8633cb4406dc28d1f3102d2edd05da0ba0b3123468bd1d06e",
          "size": "2243478",
          "boards": [
            {"name": "MSP-EXP430F5529LP"},
            {"name": "MSP-EXP430FR4133"},
            {"name": "MSP-EXP430FR5969"},
            {"name": "MSP-EXP430FR6989"},
            {"name": "MSP-EXP430G2"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"msp430-gcc",
              "version":"4.6.4"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.2.0.2096"
            },
            {
              "packager":"energia",
              "name":"mspdebug",
              "version":"0.24"
            }
         ]
        },
        {
          "name": "Energia MSP430 boards",
          "architecture": "msp430",
          "version": "1.0.1",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp430-1.0.1.tar.bz2",
          "archiveFileName": "msp430-1.0.1.tar.bz2",
          "checksum": "SHA-256:3d687d768013a46a580f0b24fb7e7458bc7175e9a60ecb212ea7cb4bfcd80261",
          "size": "2115215",
          "boards": [
            {"name": "MSP-EXP430F5529LP"},
            {"name": "MSP-EXP430FR4133"},
            {"name": "MSP-EXP430FR5969"},
            {"name": "MSP-EXP430FR6989"},
            {"name": "MSP-EXP430G2"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"msp430-gcc",
              "version":"4.6.3"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1594"
            },
            {
              "packager":"energia",
              "name":"mspdebug",
              "version":"0.22"
            }
         ]
        },
        {
          "name": "Energia MSP432E Ethernet RED boards",
          "architecture": "msp432e",
          "version": "5.19.0",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp432e-5.19.0.tar.bz2",
          "archiveFileName": "msp432e-5.19.0.tar.bz2",
          "checksum": "SHA-256:9d4a549ab2a5e810ee9da352dfe12b757d79a6ef2a0b9161a9c43e7fd0d42e33",
          "size": "35290227",
          "boards": [
            {"name": "MSP_EXP432E401Y"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"8.0.0.1202"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.3"
            }
          ]
        },
        {
          "name": "Energia MSP432 EMT RED boards",
          "architecture": "msp432r",
          "version": "5.23.1",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp432r-5.23.1.tar.bz2",
          "archiveFileName": "msp432r-5.23.1.tar.bz2",
          "checksum": "SHA-256:cda2b25b13920933336c95d90f555a30fc49dfbbd5477c0cf8c29523ffbd0ec3",
          "size": "31990061",
          "boards": [
            {"name": "MSP_EXP432P401R"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"8.2.0.1400"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.4"
            }
          ]
        },
        {
          "name": "Energia MSP432 EMT RED boards",
          "architecture": "msp432r",
          "version": "5.6.3",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp432r-5.6.3.tar.bz2",
          "archiveFileName": "msp432r-5.6.3.tar.bz2",
          "checksum": "SHA-256:51e9e24ed69eaef86fb1b7cd05be96269cc12a5358b77d05ad41af323466c5d8",
          "size": "28895842",
          "boards": [
            {"name": "MSP_EXP432P401R"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"8.2.0.1400"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.4"
            }
          ]
        },
        {
          "name": "Energia MSP432 EMT RED boards",
          "architecture": "msp432r",
          "version": "5.6.2",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp432r-5.6.2.tar.bz2",
          "archiveFileName": "msp432r-5.6.2.tar.bz2",
          "checksum": "SHA-256:bcde9150f6a4a703dd74dfc5fde92aa4d3ace45300188bc37f9545723576ec06",
          "size": "28893313",
          "boards": [
            {"name": "MSP_EXP432P401R"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.2.0.2096"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.3"
            }
          ]
        },
        {
          "name": "Energia MSP432 EMT RED boards",
          "architecture": "msp432r",
          "version": "5.6.1",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp432r-5.6.1.tar.bz2",
          "archiveFileName": "msp432r-5.6.1.tar.bz2",
          "checksum": "SHA-256:b2c1d36b95e5f8a5feebca25d4895ce98a46fa7d91604d4439430b62c2c2bcbd",
          "size": "28738809",
          "boards": [
            {"name": "MSP_EXP432P401R"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.2.0.2096"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.3"
            }
          ]
        },
        {
          "name": "Energia MSP432 EMT RED boards",
          "architecture": "msp432r",
          "version": "5.6.0",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp432r-5.6.0.tar.bz2",
          "archiveFileName": "msp432r-5.6.0.tar.bz2",
          "checksum": "SHA-256:fd320297acacdb3787f23e23f790770ff6242dbf86ee96702e1aaf8932aeb02e",
          "size": "28738891",
          "boards": [
            {"name": "MSP_EXP432P401R"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1624"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia MSP432 EMT RED boards",
          "architecture": "msp432r",
          "version": "4.9.1",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp432r-4.9.1.tar.bz2",
          "archiveFileName": "msp432r-4.9.1.tar.bz2",
          "checksum": "SHA-256:617aa2c65addb9e3a0831b015ce2619abafd27d86b74ad75b0449063ca10421e",
          "size": "21093293",
          "boards": [
            {"name": "MSP_EXP432P401R"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1624"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia MSP432 EMT RED boards",
          "architecture": "msp432r",
          "version": "4.9.0",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=msp432r-4.9.0.tar.bz2",
          "archiveFileName": "msp432r-4.9.0.tar.bz2",
          "checksum": "SHA-256:f765300336d56d09af2f48a94445050e5313f4d47a038220d2ad0451d5eb655f",
          "size": "21092774",
          "boards": [
            {"name": "MSP_EXP432P401R"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1624"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia TivaC boards",
          "architecture": "tivac",
          "version": "1.0.3",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=tivac-1.0.3.tar.bz2",
          "archiveFileName": "tivac-1.0.3.tar.bz2",
          "checksum": "SHA-256:d36684ab78ad516c65177d0402919814ab3681fff070d52e8036c3a13a5167ab",
          "size": "2239118",
          "boards": [
            {"name": "EK-TM4C123GXL"},
            {"name": "EK-TM4C1294XL"},
            {"name": "EK-LM4F120XL"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.2.0.2096"
            }
          ]
        },
        {
          "name": "Energia TivaC boards",
          "architecture": "tivac",
          "version": "1.0.2",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=tivac-1.0.2.tar.bz2",
          "archiveFileName": "tivac-1.0.2.tar.bz2",
          "checksum": "SHA-256:932d7d66dddf9ce4e498b737157c671b668cb450536f7223186e03955ae08041",
          "size": "2189817",
          "boards": [
            {"name": "EK-TM4C123GXL"},
            {"name": "EK-TM4C1294XL"},
            {"name": "EK-LM4F120XL"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {

              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1594"
            }
          ]
        },
        {
          "name": "Energia CC13xx boards",
          "architecture": "cc13xx",
          "version": "4.9.1",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc13xx-4.9.1.tar.bz2",
          "archiveFileName": "cc13xx-4.9.1.tar.bz2",
          "checksum": "SHA-256:9e1324c1f42ecb9b5f54b7eb33af40440809cda768e120e2d22a9d87a30d4b37",
          "size": "24263837",
          "boards": [
            {"name": "LAUNCHXL_CC1310"},
            {"name": "LAUNCHXL_CC1350"},
            {"name": "CC1350STK"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.1.0.1917"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC13xx boards",
          "architecture": "cc13xx",
          "version": "4.9.0",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc13xx-4.9.0.tar.bz2",
          "archiveFileName": "cc13xx-4.9.0.tar.bz2",
          "checksum": "SHA-256:4cf43b44a52783bb55994feed5f305b0d26f6a0cee1746cfd14168023ab9c07b",
          "size": "24260076",
          "boards": [
            {"name": "LAUNCHXL_CC1310"},
            {"name": "LAUNCHXL_CC1350"},
            {"name": "CC1350STK"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.1.0.1917"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC13xx boards",
          "architecture": "cc13xx",
          "version": "3.7.4",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc13xx-3.7.4.tar.bz2",
          "archiveFileName": "cc13xx-3.7.4.tar.bz2",
          "checksum": "SHA-256:b1fc52867179ac4b0bb69ef1f877de76ab0a8d2124d16df7bb1ed4585afba884",
          "size": "5008614",
          "boards": [
            {"name": "LAUNCHXL_CC1310"},
            {"name": "LAUNCHXL_CC1350"},
            {"name": "CC1350STK"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.1.0.1917"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC13xx boards",
          "architecture": "cc13xx",
          "version": "3.7.3",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc13xx-3.7.3.tar.bz2",
          "archiveFileName": "cc13xx-3.7.3.tar.bz2",
          "checksum": "SHA-256:55c3cd4265f65119cc6ed60dc1920a5f9762850fa0d8810f6a7735f14453bb5c",
          "size": "5008347",
          "boards": [
            {"name": "LAUNCHXL_CC1310"},
            {"name": "LAUNCHXL_CC1350"},
            {"name": "CC1350STK"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.1.0.1917"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC13xx boards",
          "architecture": "cc13xx",
          "version": "3.7.2",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc13xx-3.7.2.tar.bz2",
          "archiveFileName": "cc13xx-3.7.2.tar.bz2",
          "checksum": "SHA-256:0183e193755d6557e33d5d505c74d63f580dfbc3b424b028723e8242aa851484",
          "size": "5007077",
          "boards": [
            {"name": "LAUNCHXL_CC1310"},
            {"name": "LAUNCHXL_CC1350"},
            {"name": "CC1350STK"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.1.0.1917"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC13xx boards",
          "architecture": "cc13xx",
          "version": "3.7.1",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc13xx-3.7.1.tar.bz2",
          "archiveFileName": "cc13xx-3.7.1.tar.bz2",
          "checksum": "SHA-256:4eebf0ac52fe10be6e88482debeb51727b25a6ab1f7b28ec2417260a9132cdaf",
          "size": "5007403",
          "boards": [
            {"name": "LAUNCHXL_CC1310"},
            {"name": "LAUNCHXL_CC1350"},
            {"name": "CC1350STK"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1624"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC13xx boards",
          "architecture": "cc13xx",
          "version": "3.7.0",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc13xx-3.7.0.tar.bz2",
          "archiveFileName": "cc13xx-3.7.0.tar.bz2",
          "checksum": "SHA-256:9187d55612bf9681b76b1c20fd960021f93f869538e886cf6e109b31b7e5b0dc",
          "size": "5007247",
          "boards": [
            {"name": "LAUNCHXL_CC1310"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1624"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC13xx boards",
          "architecture": "cc13xx",
          "version": "3.6.1",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc13xx-3.6.1.tar.bz2",
          "archiveFileName": "cc13xx-3.6.1.tar.bz2",
          "checksum": "SHA-256:bbdb1404c748a9e8dc3dbad3d267c8de89d04a7aca62249b47866710ce6b6bda",
          "size": "4991866",
          "boards": [
            {"name": "LAUNCHXL_CC1310"}
          ],
          "toolsDependencies": [
            {
              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1624"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC3220 EMT boards",
          "architecture": "cc3220emt",
          "version": "5.6.2",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc3220emt-5.6.2.tar.bz2",
          "archiveFileName": "cc3220emt-5.6.2.tar.bz2",
          "checksum": "SHA-256:be0c700217218db893a504234c5dea5b9618ab7e23dfe9a370db59784de2994e",
          "size": "25967822",
          "boards": [
            {"name": "CC3220S-LAUNCHXL"},
            {"name": "CC3220SF-LAUNCHXL"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.4.0.1099"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.3"
            }
          ]
        },
        {
          "name": "Energia CC3220 EMT boards",
          "architecture": "cc3220emt",
          "version": "5.6.1",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc3220emt-5.6.1.tar.bz2",
          "archiveFileName": "cc3220emt-5.6.1.tar.bz2",
          "checksum": "SHA-256:192561fd563691c6e1559f35d8cfa8b335d77172264d491b55c000d580608110",
          "size": "25969772",
          "boards": [
            {"name": "CC3220S-LAUNCHXL"},
            {"name": "CC3220SF-LAUNCHXL"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.4.0.1099"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC3220 EMT boards",
          "architecture": "cc3220emt",
          "version": "5.6.0",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc3220emt-5.6.0.tar.bz2",
          "archiveFileName": "cc3220emt-5.6.0.tar.bz2",
          "checksum": "SHA-256:9c2d6ca0565e2dc2d0ad82c21193cc0ed0c765534fc07679f20b6f3951b6d623",
          "size": "25970182",
          "boards": [
            {"name": "CC3220S-LAUNCHXL"},
            {"name": "CC3220SF-LAUNCHXL"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"6.3.1-20170620"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.2.0.2096"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC3220 EMT boards",
          "architecture": "cc3220emt",
          "version": "4.9.0",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc3220emt-4.9.0.tar.bz2",
          "archiveFileName": "cc3220emt-4.9.0.tar.bz2",
          "checksum": "SHA-256:e59c6ba609c99c2ec6ee3856e78962c0b3301af2f67a5de42ec50e543c707919",
          "size": "19051776",
          "boards": [
            {"name": "CC3220S-LAUNCHXL"},
            {"name": "CC3220SF-LAUNCHXL"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"7.2.0.1988"
            },
            {
              "packager":"energia",
              "name":"ino2cpp",
              "version":"1.0.2"
            }
          ]
        },
        {
          "name": "Energia CC3200 boards",
          "architecture": "cc3200",
          "version": "1.0.2",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc3200-1.0.2.tar.bz2",
          "archiveFileName": "cc3200-1.0.2.tar.bz2",
          "checksum": "SHA-256:48ad1392d766fd354a368576989e42375da6e072e8337ffa2424463f5c632446",
          "size": "1791123",
          "boards": [
            {"name": "CC3200-LAUNCHXL"},
            {"name": "RedBearLab CC3200"},
            {"name": "RedBearLab WiFi Mini"},
            {"name": "RedBearLab WiFi Micro"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1594"
            },
            {
              "packager":"energia",
              "name":"cc3200prog",
              "version":"1.1.4"
            }
          ]
        },
        {
          "name": "Energia CC3200 boards",
          "architecture": "cc3200",
          "version": "1.0.3",
          "category": "Energia",
          "url": "http://energia.nu/downloads/download_core.php?file=cc3200-1.0.3.tar.bz2",
          "archiveFileName": "cc3200-1.0.3.tar.bz2",
          "checksum": "SHA-256:69f9ac0980bac4ebb8803a161786215228557eba49051af86e980aa8c422cdca",
          "size": "1790853",
          "boards": [
            {"name": "CC3200-LAUNCHXL"},
            {"name": "RedBearLab CC3200"},
            {"name": "RedBearLab WiFi Mini"},
            {"name": "RedBearLab WiFi Micro"}
          ],
          "toolsDependencies": [
            {

              "packager":"energia",
              "name":"arm-none-eabi-gcc",
              "version":"4.8.4-20140725"
            },
            {
              "packager":"energia",
              "name":"dslite",
              "version":"6.2.1.1594"
            },
            {
              "packager":"energia",
              "name":"cc3200prog",
              "version":"1.1.4"
            }
          ]
        }
      ],
      "tools": [
        {
          "name":"msp430-gcc",
          "version":"4.6.6",
          "systems":
          [
            {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/msp430-gcc-4.6.6-i686-mingw32.tar.bz2",
              "archiveFileName":"msp430-gcc-4.6.6-i686-mingw32.tar.bz2",
              "checksum":"SHA-256:3dbfe6453f461ae5d7599c3cf1144dc400852b6d788d298f3dd0004283a9202a",
              "size":"30818330"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/msp430-gcc-4.6.6-i386-apple-darwin11.tar.bz2",
              "archiveFileName":"msp430-gcc-4.6.6-i386-apple-darwin11.tar.bz2",
              "checksum":"SHA-256:82d4df153a9d64a507a48ed3b5db9e21eeb069809976c8b69946801252b622bb",
              "size":"32574759"
            },
            {
              "host": "x86_64-linux-gnu",
              "url": "https://s3.amazonaws.com/energiaUS/tools/linux64/msp430-gcc-4.6.6-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName": "msp430-gcc-4.6.6-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum": "SHA-256:41fbcb3cc73679186989e1fb27cb4578e9164f07d134e650e23089198b87cbfd",
              "size": "98503002"
            }
          ]
        },
        {
          "name":"msp430-gcc",
          "version":"4.6.5",
          "systems":
          [
            {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/msp430-gcc-4.6.5-i686-mingw32.tar.bz2",
              "archiveFileName":"msp430-gcc-4.6.5-i686-mingw32.tar.bz2",
              "checksum":"SHA-256:91496ceffdaf63562d28ca0e27d317f4e22048267efc754450f2b3cf37e69a88",
              "size":"30758086"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/msp430-gcc-4.6.5-i386-apple-darwin11.tar.bz2",
              "archiveFileName":"msp430-gcc-4.6.5-i386-apple-darwin11.tar.bz2",
              "checksum":"SHA-256:9a85b83a0015d1219157e503d0515092171c1a49a9bd695fe14a4ddfbde66ffb",
              "size":"32399439"
            },
            {
              "host": "x86_64-linux-gnu",
              "url": "https://s3.amazonaws.com/energiaUS/tools/linux64/msp430-gcc-4.6.5-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName": "msp430-gcc-4.6.5-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum": "SHA-256:0b5b4ee3e027aa88a8d86b1e5d6bd65f919084f3d3f8678475e4debdbbc930c9",
              "size": "98367482"
            }
          ]
        },
        {
          "name":"msp430-gcc",
          "version":"4.6.4",
          "systems":
          [
            {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/msp430-gcc-4.6.4-i686-mingw32.tar.bz2",
              "archiveFileName":"msp430-gcc-4.6.4-i686-mingw32.tar.bz2",
              "checksum":"SHA-256:21efce29cc6a83ddce3dbce241fcd235437ed1717f8268af169a6429d0c3d20d",
              "size":"30753419"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/msp430-gcc-4.6.4-i386-apple-darwin11.tar.bz2",
              "archiveFileName":"msp430-gcc-4.6.4-i386-apple-darwin11.tar.bz2",
              "checksum":"SHA-256:e1628d6ddce2d0ee6f9134d3d1b20560cf98cda0cb09a9c33028b3a1d210603d",
              "size":"32431529"
            },
            {
              "host": "x86_64-linux-gnu",
              "url": "https://s3.amazonaws.com/energiaUS/tools/linux64/msp430-gcc-4.6.4-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName": "msp430-gcc-4.6.4-i386-x86_64-pc-linux-gnu.tar.bz2",
              "size": "98437003",
              "checksum": "SHA-256:6595fd1dd4ebfd77aec31939e922fb4791e2c74185e908e1a4c27c50cb3b7440"
            }
          ]
        },
        {
          "name":"msp430-gcc",
          "version":"4.6.3",
          "systems":
          [
            {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/msp430-gcc-4.6.3-i686-mingw32.zip",
              "archiveFileName":"msp430-gcc-4.6.3-i686-mingw32.zip",
              "checksum":"SHA-256:5e3722f6651e33991a199f7a7f3182a3ad0d5ddb5eff199e8c27d1fd269132d2",
              "size":"47733038"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/msp430-gcc-4.6.3-i386-apple-darwin11.tar.bz2",
              "archiveFileName":"msp430-gcc-4.6.3-i386-apple-darwin11.tar.bz2",
              "checksum":"SHA-256:b919d80880603b55c64b9095eb80d4005e82d7428b0d7ded3864c200cb4f847c",
              "size":"32357793"
            },
            {
              "host": "x86_64-linux-gnu",
              "url": "https://s3.amazonaws.com/energiaUS/tools/linux64/msp430-gcc-4.6.3-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName": "msp430-gcc-4.6.3-i386-x86_64-pc-linux-gnu.tar.bz2",
              "size": "87607164",
              "checksum": "SHA-256:453832be5150f45a830ea5b0336a911f22fd7553f668a1e93a5c9e58f65f9f7f"
            }
          ]
        },
        {
          "name": "arm-none-eabi-gcc",
          "version": "6.3.1-20170620",
          "systems": [
            {
              "host": "i686-mingw32",
              "url": "https://s3.amazonaws.com/energiaUS/tools/windows/gcc-arm-none-eabi-6.3.1-20170620-windows.tar.bz2",
              "archiveFileName": "gcc-arm-none-eabi-6.3.1-20170620-windows.tar.bz2",
              "checksum": "SHA-256:c28a5c2a5272d09bf396c2dcd4c3188ae0dd8ec04d0ce8f581b1995141fc9044",
              "size": "110277553"
            },
            {
              "host": "x86_64-apple-darwin",
              "url": "https://s3.amazonaws.com/energiaUS/tools/macosx/gcc-arm-none-eabi-6.3.1-20170620-mac.tar.bz2",
              "archiveFileName": "gcc-arm-none-eabi-6.3.1-20170620-mac.tar.bz2",
              "checksum": "SHA-256:70ed9ad76f90f33a14bf47d1c2643ee5374dadef820ab38bf2ad9c3c1981aee1",
              "size": "104268677"
            },
            {
              "host": "x86_64-pc-linux-gnu",
              "url": "https://s3.amazonaws.com/energiaUS/tools/linux64/gcc-arm-none-eabi-6.3.1-20170620-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName": "gcc-arm-none-eabi-6.3.1-20170620-x86_64-pc-linux-gnu.tar.bz2",
              "checksum": "SHA-256:0a98e8cf843c41fdfdfb74cfe5b27e7b0c6054ee92ea1277812513334b6ce02a",
              "size": "100490382"
            }
          ]
        },
        {
          "name": "arm-none-eabi-gcc",
          "version": "4.8.4-20140725",
          "systems": [
            {
              "host": "i686-mingw32",
              "archiveFileName": "gcc-arm-none-eabi-4.8.4-20140725-windows.tar.gz",
              "url": "https://s3.amazonaws.com/energiaUS/tools/windows/gcc-arm-none-eabi-4.8.4-20140725-windows.tar.gz",
              "checksum": "SHA-256:2ab5a6ad2a32f976d17b7ef9222623e6f9881be908047cb05730ccd89eb79a1d",
              "size": "82014307"
            },
            {
              "host": "x86_64-apple-darwin",
              "url": "https://s3.amazonaws.com/energiaUS/tools/macosx/gcc-arm-none-eabi-4.8.4-20140725-mac.tar.bz2",
              "archiveFileName": "gcc-arm-none-eabi-4.8.4-20140725-mac.tar.bz2",
              "checksum": "SHA-256:66c9261fdd6d646931dfe940e8daf38d3b11cfba8a7e714c7a3811146b6dc9c7",
              "size": "52518522"
            },
            {
              "host": "x86_64-pc-linux-gnu",
              "url": "https://s3.amazonaws.com/energiaUS/tools/linux64/gcc-arm-none-eabi-4.8.4-20140725-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName": "gcc-arm-none-eabi-4.8.4-20140725-x86_64-pc-linux-gnu.tar.bz2",
              "checksum": "SHA-256:00636c299e7a420212cdc1643d5c52d3e82eb66c8ce0e4693327cd1e936b52db",
              "size": "68654066"
            }
          ]
        },
        {
          "name":"ino2cpp",
          "version":"1.0.4",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.4.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.4.tar.bz2",
              "checksum":"SHA-256:f1409b404eb650931ab138aea642451d0706deb19210331d3bd62bfe79099f17",
              "size":"537535"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.4.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.4.tar.bz2",
              "checksum":"SHA-256:f1409b404eb650931ab138aea642451d0706deb19210331d3bd62bfe79099f17",
              "size":"537535"
            },
            {
              "host": "x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.4.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.4.tar.bz2",
              "checksum":"SHA-256:f1409b404eb650931ab138aea642451d0706deb19210331d3bd62bfe79099f17",
              "size":"537535"
            }
          ]
        },
        {
          "name":"ino2cpp",
          "version":"1.0.4",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.4.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.4.tar.bz2",
              "checksum":"SHA-256:f1409b404eb650931ab138aea642451d0706deb19210331d3bd62bfe79099f17",
              "size":"537535"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.4.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.4.tar.bz2",
              "checksum":"SHA-256:f1409b404eb650931ab138aea642451d0706deb19210331d3bd62bfe79099f17",
              "size":"537535"
            },
            {
              "host": "x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.4.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.4.tar.bz2",
              "checksum":"SHA-256:f1409b404eb650931ab138aea642451d0706deb19210331d3bd62bfe79099f17",
              "size":"537535"
            }
          ]
        },
        {
          "name":"ino2cpp",
          "version":"1.0.3",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.3.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.3.tar.bz2",
              "checksum":"SHA-256:562c9364db80affc5a5b51a79b70950680c77d7ee62244e18bc8b6f7c114fdeb",
              "size":"485132"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.3.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.3.tar.bz2",
              "checksum":"SHA-256:562c9364db80affc5a5b51a79b70950680c77d7ee62244e18bc8b6f7c114fdeb",
              "size":"485132"
            },
            {
              "host": "x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.3.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.3.tar.bz2",
              "checksum":"SHA-256:562c9364db80affc5a5b51a79b70950680c77d7ee62244e18bc8b6f7c114fdeb",
              "size":"485132"
            }
          ]
        },
        {
          "name":"ino2cpp",
          "version":"1.0.2",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.2.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.2.tar.bz2",
              "checksum":"SHA-256:6f63041767f4f15b1da7b62aa3086e6912f9e05b19bfdf512d573bcc9ac7c9a5",
              "size":"484493"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.2.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.2.tar.bz2",
              "checksum":"SHA-256:6f63041767f4f15b1da7b62aa3086e6912f9e05b19bfdf512d573bcc9ac7c9a5",
              "size":"484493"
            },
            {
              "host": "x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/ino2cpp-1.0.2.tar.bz2",
              "archiveFileName":"ino2cpp-1.0.2.tar.bz2",
              "checksum":"SHA-256:6f63041767f4f15b1da7b62aa3086e6912f9e05b19bfdf512d573bcc9ac7c9a5",
              "size":"484493"
            }
          ]
        },
        {
          "name":"dslite",
          "version":"8.2.0.1400",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/dslite-8.2.0.1400-i686-mingw32.tar.bz2",
              "archiveFileName":"dslite-8.2.0.1400-mingw32.tar.bz2",
              "checksum":"SHA-256:793a4ea6935fd3436cc7f861b23f353609969b951b62812641635bd467814e05",
              "size":"33976575"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/dslite-8.2.0.1400-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"dslite-8.2.0.140-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:366b9139052037e480fcba4b3a4fb5783b6336b93bd5e2f3034f479a8d502784",
              "size":"17527708"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/dslite-8.2.0.1400-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"dslite-8.2.0.1400-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:f95b710f36786ba9d28c9cb96e05c812e7eba875afc69753007c8910c3bce7fd",
              "size":"19182469"
            }
          ]
        },
        {
          "name":"dslite",
          "version":"8.0.0.1202",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/dslite-8.0.0.1202-i686-mingw32.tar.bz2",
              "archiveFileName":"dslite-8.0.0.1202-mingw32.tar.bz2",
              "checksum":"SHA-256:88d45eac72682d35e907cefe101b9b32557d70a5044b872d2ac22594b87ae919",
              "size":"33554889"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/dslite-8.0.0.1202-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"dslite-8.0.0.1202-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:19ccf9a603a528c7b84237fbbcad4fdeb97dff6ff02177086cb3da9eac36041d",
              "size":"16963904"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/dslite-8.0.0.1202-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"dslite-8.0.0.1202-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:8d84a25eab60624fd216d1e8e76948ac6a218ff81cff5118c3942dc67ab78acb",
              "size":"18783730"
            }
          ]
        },
        {
          "name":"dslite",
          "version":"7.4.0.1099",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/dslite-7.4.0.1099-i686-mingw32.tar.bz2",
              "archiveFileName":"dslite-7.4.0.1099-i686-mingw32.tar.bz2",
              "checksum":"SHA-256:298f2d6df8f1122ce8ea437586dfba9c54d394144fdf7853509437a49b642bb8",
              "size":"33486116"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/dslite-7.4.0.1099-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"dslite-7.4.0.1099-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:445bfbf65a709e2e031c2670b7b0300d11b25f6a58953037f27b09c341fd7fc4",
              "size":"17016539"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/dslite-7.4.0.1099-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"dslite-7.4.0.1099-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:187aeafd49f76d841f68d5fa9cac0dcdfce9aa401fd2f2b67bd9da5c14833f67",
              "size":"18597835"
            }
          ]
        },
        {
          "name":"dslite",
          "version":"7.2.0.1988",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/dslite-7.2.0.1988-i686-mingw32.tar.bz2",
              "archiveFileName":"dslite-7.2.0.1988-i686-mingw32.tar.bz2",
              "checksum":"SHA-256:248da7bf2e882587e6e51117b8ab53eb60793aa7362836fdbc0388774367d81c",
              "size":"30119837"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/dslite-7.2.0.1988-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"dslite-7.2.0.1988-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:aa80e246122096f26df9826c8a889c45abeac96f349234c9baff7e2f27f72c36",
              "size":"15546846"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/dslite-7.2.0.1988-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"dslite-7.2.0.1988-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:f43171fac1c09567d22e070e0652dea43eebaf274467e2110cfb826f983054a0",
              "size":"18074747"
            }
          ]
        },
        {
          "name":"dslite",
          "version":"7.1.0.1917",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/dslite-7.1.0.1917-i686-mingw32.zip",
              "archiveFileName":"dslite-7.1.0.1917-mingw32.zip",
              "checksum":"SHA-256:e8ef665bfeaa9264a98771ea89d14f977e8e448116372f6883bb74dc703424a8",
              "size":"36225191"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/dslite-7.1.0.1917-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"dslite-7.1.0.1917-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:629fe0c3c5f066b9dd62e065ac8ba80c5fd260d15d6fe32006e200b9a58343ac",
              "size":"15384479"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/dslite-7.1.0.1917-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"dslite-7.1.0.1917-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:89fa13bec5e5504ccaef25a7d87464cf784c14870e66d7e149b8308839ab83de",
              "size":"17793290"
            }
          ]
        },
       {
          "name":"dslite",
          "version":"7.2.0.2096",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/dslite-7.2.0.2096-i686-mingw32.tar.bz2",
              "archiveFileName":"dslite-7.2.0.2096-mingw32.tar.bz2",
              "checksum":"SHA-256:550922c51ea0c44b1b8f47497d7dadcc81a2695d8aded478307e2d9fcec7d94d",
              "size":"33083804"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/dslite-7.2.0.2096-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"dslite-7.2.0.2096-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:2a0282a4aae506edde5999e7cffd7e8d4daf3f98df4a5ee0dccf1bb71798f471",
              "size":"16666963"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/dslite-7.2.0.2096-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"dslite-7.2.0.2096-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:4c3bff77b27a5ff811fd5b062cbe35b22867b5435e0e29d5b8a380c4ca7ad2b4",
              "size":"19132835"
            }
          ]
        },
        {
          "name":"dslite",
          "version":"6.2.1.1624",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/dslite-6.2.1.1624-i686-mingw32.zip",
              "archiveFileName":"dslite-6.2.1.1624-i686-mingw32.zip",
              "checksum":"SHA-256:fd673ea66fcd8051d91a0138dcddaf0b3104ca1c6b2e0eab0de8b2080ff70094",
              "size":"34948605"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/dslite-6.2.1.1624-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"dslite-6.2.1.1624-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:0a89afb99973ec2b4cf23be277ccc66cb2dc53fdd894924aa871b0e9882011e3",
              "size":"15312608"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/dslite-6.2.1.1624-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"dslite-6.2.1.1624-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:401d9edd1956b87a7b89f162456a8444b2ac73d3d972f8f2231a150a7e384503",
              "size":"17995725"
            }
          ]
        },
        {
          "name":"dslite",
          "version":"6.2.1.1594",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/dslite-6.2.1.1594-i686-mingw32.zip",
              "archiveFileName":"dslite-6.2.1.1594-i686-mingw32.zip",
              "checksum":"SHA-256:aa523ddddbb23fb93fd2705990a10021b3b1ad6553d6149159fc9c0f68b56824",
              "size":"33819921"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/dslite-6.2.1.1594-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"dslite-6.2.1.1594-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:f872f284b090d9c635812ef588645c498eadd1dc8ab8d867b54895d57ddf0127",
              "size":"14735532"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/dslite-6.2.1.1594-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"dslite-6.2.1.1594-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:dfa17d2c26699e1480a13bd7f2941541417c59276ee38d30848e4606e1fba33b",
              "size":"20539172"
            }
          ]
        },
        {
          "name":"mspdebug",
          "version":"0.24",
          "systems":
          [
           {
              "host":"i686-mingw32",
             "url":"https://s3.amazonaws.com/energiaUS/tools/windows/mspdebug-0.24-i686-mingw32.tar.bz2",
              "archiveFileName":"mspdebug-0.24-i686-mingw32.tar.bz2",
              "checksum":"SHA-256:7b3dfb269b58f692d03080a641f543dfe01bcfcef43935c2bb31e2839e284e73",
              "size":"1058435"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/mspdebug-0.24-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"mspdebug-0.24-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:5e0dc170ff259c4fc50a2bd591b1c10c648b9d8ad5770c03ed4228128e206fc0",
              "size":"171307"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/mspdebug-0.24-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"mspdebug-0.24-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:ec6131053a4ddd35b43d44591732313182e3487ffd77181df02ce23f0860a2e5",
              "size":"147947"
            }
          ]
        },
        {
          "name":"mspdebug",
          "version":"0.22",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/mspdebug-0.22.zip",
              "archiveFileName":"mspdebug-0.22.zip",
              "checksum":"SHA-256:e4d061b5cb1de2e17dc7f4fb5c3c6bd8c6f7a3ea013fa16e2332b408440236ec",
              "size":"201798"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"http://www.energia.nu/tools/mspdebug-0.22-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"mspdebug-0.22--x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:efc469b4771367bd5e420eb7d6f36551df8da36dd130d2bbf184131b6876111e",
              "size":"9891660"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"http://www.energia.nu/tools/mspdebug-0.22-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"mspdebug-0.22--x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:efc469b4771367bd5e420eb7d6f36551df8da36dd130d2bbf184131b6876111e",
              "size":"9891660"
            }
          ]
        },
        {
          "name":"cc3200prog",
          "version":"1.1.4",
          "systems":
          [
           {
              "host":"i686-mingw32",
              "url":"https://s3.amazonaws.com/energiaUS/tools/windows/cc3200prog-1.1.4-i686-mingw32.zip",
              "archiveFileName":"cc3200prog-1.1.4-i686-mingw32.zip",
              "checksum":"SHA-256:9701cf08a34c727355261eec502dfa44386b34b2d9cde863eb20c347d7a24f97",
              "size":"400542"
            },
            {
              "host":"x86_64-apple-darwin",
              "url":"https://s3.amazonaws.com/energiaUS/tools/macosx/cc3200prog-1.1.4-x86_64-apple-darwin.tar.bz2",
              "archiveFileName":"cc3200prog-1.1.4-x86_64-apple-darwin.tar.bz2",
              "checksum":"SHA-256:1d499a54ad083869fcc54da60ec4d55f03011fe3bb3d45dd75b5e687694befdd",
              "size":"164785"
            },
            {
              "host":"x86_64-pc-linux-gnu",
              "url":"https://s3.amazonaws.com/energiaUS/tools/linux64/cc3200prog-1.1.4-i386-x86_64-pc-linux-gnu.tar.bz2",
              "archiveFileName":"cc3200prog-1.1.4-i386-x86_64-pc-linux-gnu.tar.bz2",
              "checksum":"SHA-256:892a1ba158ee184451597cd8d1aad32f293dc4279e59deace08e2a67c6b93707",
              "size":"134860"
            }
          ]
        }
      ]
    }
  ]
}
 Posted by at 3:23 pm
Oct 112019
 

Keyboard Matrix Scanning and Debouncing

Keyboard Matrix Scanning and Debouncing

Intro

Without diving into the “why” part, I wanted to make yet another keyboard with Cherry MX keyswitches (just like everyone else these days), and I ended up deciding to make my own keyboard controller (again like everyone else). After all…

customary xkcd/927
(customary https://xkcd.com/927/ )

 Posted by at 4:28 pm
Aug 192019
 

https://medium.com/@ly.lee/build-your-iot-sensor-network-stm32-blue-pill-nrf24l01-esp8266-apache-mynewt-thethings-io-ca7486523f5d

Build Your IoT Sensor Network — STM32 Blue Pill + nRF24L01 + ESP8266 + Apache Mynewt + thethings.io

Lup Yuen Lee 李立源
May 27 · 18 min read

Law of Thermospatiality: Air-conditioning always feels too warm ANDtoo cold by different individuals in a sizeable room

 Posted by at 6:48 am
Jun 072019
 

https://www.computerhistory.org/atchm/who-invented-the-microprocessor/

Who Invented the Microprocessor?

Intel Pentium microprocessor die and wafer

Intel Pentium microprocessor die and wafer

The microprocessor is hailed as one of the most significant engineering milestones of all time. The lack of a generally agreed definition of the term has supported many claims to be the inventor of the microprocessor. The original use of the word “microprocessor” described a computer that employed a microprogrammed architecture—a technique first described by Maurice Wilkes in 1951. Viatron Computer Systems used the term microprocessor to describe its compact System 21 machines for small business use in 1968. Its modern usage is an abbreviation of micro-processing unit (MPU), the silicon device in a computer that performs all the essential logical operations of a computing system. Popular media stories call it a “computer-on-a-chip.” This article describes a chronology of early approaches to integrating the primary building blocks of a computer on to fewer and fewer microelectronic chips, culminating in the concept of the microprocessor.

 Posted by at 6:15 pm
May 032019
 

http://www.pythondiary.com/blog/Oct.15,2014/building-cpu-simulator-python.html

 

Wednesday, October 15th2014

Building a CPU simulator in Python

You can find the entire source listing from this article, plus more interesting code on my Python Experiments BitBucket page. Plus, the source code there will evolve and grow.

Early this morning in my Planet Python feed, I read this really interesting article called Developing Upwards: CARDIAC: The Cardboard Computer, which is about this cardboard computer called the Cardiac. As some of my followers and readers might know, I have another project that I have been working on and evolving for the past months called simple-cpu, which I have released the source code for. I really should give that project a proper license so that others might feel interested in using it in their own projects… Anyways, hopefully I’ll have that done by the time this publishes.

After reading that article and the page it links to, I felt a bit inspired and decided to write my own simulator for it since I already have experience in writing bytecode engines. I plan on following this article up with another on how to write a Assembler for it, then shortly after how to write a compiler. So basically, throughout these articles, you will learn how to create a build toolchain for the Cardiac in Python. The simple-cpu I wrote already has a fully working Assembler, and in the game I am putting it in, already has the first steps of a working compiler. I choose to also use Cardiac as a demonstration machine due to it’s pure simplicity. There are no really complex mnemonics here, each opcode only accepts a single parameter, so it’s perfect as a learning tool. Furthermore, all data parameters are known to be the same, there is no need to detect if the program wants a registera literal, or a memory address. In fact, there is really only one register, the accumulator. So lets get started. We will be making this class-based, so that the scope is contained and so that you can easily sub-class it to say add new opcodes if you want to feel adventurous. First, we will focus on the Initialization routines. This CPU is very simple, so we only need to initialize the following: CPU registersopcodesmemory spacecard reader/input, and the printer/tty/output.

class Cardiac(object):
    """
    This class is the cardiac "CPU".
    """
    def __init__(self):
        self.init_cpu()
        self.reset()
        self.init_mem()
        self.init_reader()
        self.init_output()
    def reset(self):
        """
        This method resets the CPU's registers to their defaults.
        """
        self.pc = 0 #: Program Counter
        self.ir = 0 #: Instruction Register
        self.acc = 0 #: Accumulator
        self.running = False #: Are we running?
    def init_cpu(self):
        """
        This fancy method will automatically build a list of our opcodes into a hash.
        This enables us to build a typical case/select system in Python and also keeps
        things more DRY.  We could have also used the getattr during the process()
        method before, and wrapped it around a try/except block, but that looks
        a bit messy.  This keeps things clean and simple with a nice one-to-one
        call-map. 
        """
        self.__opcodes = {}
        classes = [self.__class__] #: This holds all the classes and base classes.
        while classes:
            cls = classes.pop() # Pop the classes stack and being
            if cls.__bases__: # Does this class have any base classes?
                classes = classes + list(cls.__bases__)
            for name in dir(cls): # Lets iterate through the names.
                if name[:7] == 'opcode_': # We only want opcodes here.
                    try:
                        opcode = int(name[7:])
                    except ValueError:
                        raise NameError('Opcodes must be numeric, invalid opcode: %s' % name[7:])
                    self.__opcodes.update({opcode:getattr(self, 'opcode_%s' % opcode)})
    def init_mem(self):
        """
        This method resets the Cardiac's memory space to all blank strings, as per Cardiac specs.
        """
        self.mem = ['' for i in range(0,100)]
        self.mem[0] = '001' #: The Cardiac bootstrap operation.
    def init_reader(self):
        """
        This method initializes the input reader.
        """
        self.reader = [] #: This variable can be accessed after initializing the class to provide input data.
    def init_output(self):
        """
        This method initializes the output deck/paper/printer/teletype/etc...
        """
        self.output = []

Hopefully I left enough comments in the code above for you to understand exactly what’s going on here. You might notice here a key difference from my simple-cpuproject, is the method which opcodes are handled. I actually plan on incorporating this new way of detecting opcodes into that project in the near future. This method makes it easier for other developers of the library to extend it for their own requirements. As mentioned before, that project has been evolving as I started to understand more about how things should be done. In fact, taking on a CPU simulator project is a really incredible learning experience all on it’s own. If you are truly a computer scientist, you should understand the under workings of a CPU, and how each opcode is processed at it’s lowest level. Plus, developing and seeing a custom built CPU simulator made by your own imagination is a very gratifying experience. It’s almost like giving birth, as this machine was entirely built by your mind alone, and seeing it work, is something magical.

In the next part of this class, we will focus on the utility functions that we may need to call and use multiple times, these methods can also be overridden in subclasses to alter how the CPU actually functions:

    def read_deck(self, fname):
        """
        This method will read a list of instructions into the reader.
        """
        self.reader = [s.rstrip('\n') for s in open(fname, 'r').readlines()]
        self.reader.reverse()
    def fetch(self):
        """
        This method retrieves an instruction from memory address pointed to by the program pointer.
        Then we increment the program pointer.
        """
        self.ir = int(self.mem[self.pc])
        self.pc +=1
    def get_memint(self, data):
        """
        Since our memory storage is *string* based, like the real Cardiac, we need
        a reusable function to grab a integer from memory.  This method could be
        overridden if say a new memory type was implemented, say an mmap one.
        """
        return int(self.mem[data])
    def pad(self, data, length=3):
        """
        This function pads either an integer or a number in string format with
        zeros.  This is needed to replicate the exact behavior of the Cardiac.
        """
        orig = int(data)
        padding = '0'*length
        data = '%s%s' % (padding, abs(data))
        if orig < 0:
            return '-'+data[-length:]
        return data[-length:]

These are the various utility functions, all of which might be overridden in a subclass. Later in this article, I will also provide an alternate source output which displays how this simulator can be built using Python Mixin classes, to make things even more pluggable. Finally, we find ourselves at the final part of code to get this simulator running, the actual processing methods:

    def process(self):
        """
        Process a single opcode from the current program counter.  This is
        normally called from the running loop, but can also be called
        manually to provide a "step-by-step" debugging interface, or
        to slow down execution using time.sleep().  This is the method
        that will also need to used if you build a TK/GTK/Qt/curses frontend
        to control execution in another thread of operation.
        """
        self.fetch()
        opcode, data = int(math.floor(self.ir / 100)), self.ir % 100
        self.__opcodes[opcode](data)
    def opcode_0(self, data):
        """ INPUT Operation """
        self.mem[data] = self.reader.pop()
    def opcode_1(self, data):
        """ Clear and Add Operation """
        self.acc = self.get_memint(data)
    def opcode_2(self, data):
        """ Add Operation """
        self.acc += self.get_memint(data)
    def opcode_3(self, data):
        """ Test Accumulator contents Operation """
        if self.acc < 0:
            self.pc = data
    def opcode_4(self, data):
        """ Shift operation """
        x,y = int(math.floor(data / 10)), int(data % 10)
        for i in range(0,x):
            self.acc = (self.acc * 10) % 10000
        for i in range(0,y):
            self.acc = int(math.floor(self.acc / 10))
    def opcode_5(self, data):
        """ Output operation """
        self.output.append(self.mem[data])
    def opcode_6(self, data):
        """ Store operation """
        self.mem[data] = self.pad(self.acc)
    def opcode_7(self, data):
        """ Subtract Operation """
        self.acc -= self.get_memint(data)
    def opcode_8(self, data):
        """ Unconditional Jump operation """
        self.pc = data
    def opcode_9(self, data):
        """ Halt and Reset operation """
        self.reset()
    def run(self, pc=None):
        """ Runs code in memory until halt/reset opcode. """
        if pc:
            self.pc = pc
        self.running = True
        while self.running:
            self.process()
        print "Output:\n%s" % '\n'.join(self.output)
        self.init_output()

if __name__ == '__main__':
    c = Cardiac()
    c.read_deck('deck1.txt')
    try:
        c.run()
    except:
        print "IR: %s\nPC: %s\nOutput: %s\n" % (c.ir, c.pc, '\n'.join(c.output))
        raise

As mentioned above, I will now refactor the code into Mixin classes and provide a full source output of that:

class Memory(object):
    """
    This class controls the virtual memory space of the simulator.
    """
    def init_mem(self):
        """
        This method resets the Cardiac's memory space to all blank strings, as per Cardiac specs.
        """
        self.mem = ['' for i in range(0,100)]
        self.mem[0] = '001' #: The Cardiac bootstrap operation.
    def get_memint(self, data):
        """
        Since our memory storage is *string* based, like the real Cardiac, we need
        a reusable function to grab a integer from memory.  This method could be
        overridden if say a new memory type was implemented, say an mmap one.
        """
        return int(self.mem[data])
    def pad(self, data, length=3):
        """
        This function pads either an integer or a number in string format with
        zeros.  This is needed to replicate the exact behavior of the Cardiac.
        """
        orig = int(data)
        padding = '0'*length
        data = '%s%s' % (padding, abs(data))
        if orig < 0:
            return '-'+data[-length:]
        return data[-length:]

class IO(object):
    """
    This class controls the virtual I/O of the simulator.
    To enable alternate methods of input and output, swap this.
    """
    def init_reader(self):
        """
        This method initializes the input reader.
        """
        self.reader = [] #: This variable can be accessed after initializing the class to provide input data.
    def init_output(self):
        """
        This method initializes the output deck/paper/printer/teletype/etc...
        """
        self.output = []
    def read_deck(self, fname):
        """
        This method will read a list of instructions into the reader.
        """
        self.reader = [s.rstrip('\n') for s in open(fname, 'r').readlines()]
        self.reader.reverse()
    def format_output(self):
        """
        This method is to format the output of this virtual IO device.
        """
        return '\n'.join(self.output)
    def get_input(self):
        """
        This method is used to get input from this IO device, this could say
        be replaced with raw_input() to manually enter in data.
        """
        try:
            return self.reader.pop()
        except IndexError:
            # Fall back to raw_input() in the case of EOF on the reader.
            return raw_input('INP: ')[:3]
    def stdout(self, data):
        self.output.append(data)

class CPU(object):
    """
    This class is the cardiac "CPU".
    """
    def __init__(self):
        self.init_cpu()
        self.reset()
        try:
            self.init_mem()
        except AttributeError:
            raise NotImplementedError('You need to Mixin a memory-enabled class.')
        try:
            self.init_reader()
            self.init_output()
        except AttributeError:
            raise NotImplementedError('You need to Mixin a IO-enabled class.')
    def reset(self):
        """
        This method resets the CPU's registers to their defaults.
        """
        self.pc = 0 #: Program Counter
        self.ir = 0 #: Instruction Register
        self.acc = 0 #: Accumulator
        self.running = False #: Are we running?
    def init_cpu(self):
        """
        This fancy method will automatically build a list of our opcodes into a hash.
        This enables us to build a typical case/select system in Python and also keeps
        things more DRY.  We could have also used the getattr during the process()
        method before, and wrapped it around a try/except block, but that looks
        a bit messy.  This keeps things clean and simple with a nice one-to-one
        call-map. 
        """
        self.__opcodes = {}
        classes = [self.__class__] #: This holds all the classes and base classes.
        while classes:
            cls = classes.pop() # Pop the classes stack and being
            if cls.__bases__: # Does this class have any base classes?
                classes = classes + list(cls.__bases__)
            for name in dir(cls): # Lets iterate through the names.
                if name[:7] == 'opcode_': # We only want opcodes here.
                    try:
                        opcode = int(name[7:])
                    except ValueError:
                        raise NameError('Opcodes must be numeric, invalid opcode: %s' % name[7:])
                    self.__opcodes.update({opcode:getattr(self, 'opcode_%s' % opcode)})
    def fetch(self):
        """
        This method retrieves an instruction from memory address pointed to by the program pointer.
        Then we increment the program pointer.
        """
        self.ir = self.get_memint(self.pc)
        self.pc +=1
    def process(self):
        """
        Process a single opcode from the current program counter.  This is
        normally called from the running loop, but can also be called
        manually to provide a "step-by-step" debugging interface, or
        to slow down execution using time.sleep().  This is the method
        that will also need to used if you build a TK/GTK/Qt/curses frontend
        to control execution in another thread of operation.
        """
        self.fetch()
        opcode, data = int(math.floor(self.ir / 100)), self.ir % 100
        self.__opcodes[opcode](data)
    def opcode_0(self, data):
        """ INPUT Operation """
        self.mem[data] = self.get_input()
    def opcode_1(self, data):
        """ Clear and Add Operation """
        self.acc = self.get_memint(data)
    def opcode_2(self, data):
        """ Add Operation """
        self.acc += self.get_memint(data)
    def opcode_3(self, data):
        """ Test Accumulator contents Operation """
        if self.acc < 0:
            self.pc = data
    def opcode_4(self, data):
        """ Shift operation """
        x,y = int(math.floor(data / 10)), int(data % 10)
        for i in range(0,x):
            self.acc = (self.acc * 10) % 10000
        for i in range(0,y):
            self.acc = int(math.floor(self.acc / 10))
    def opcode_5(self, data):
        """ Output operation """
        self.stdout(self.mem[data])
    def opcode_6(self, data):
        """ Store operation """
        self.mem[data] = self.pad(self.acc)
    def opcode_7(self, data):
        """ Subtract Operation """
        self.acc -= self.get_memint(data)
    def opcode_8(self, data):
        """ Unconditional Jump operation """
        self.pc = data
    def opcode_9(self, data):
        """ Halt and Reset operation """
        self.reset()
    def run(self, pc=None):
        """ Runs code in memory until halt/reset opcode. """
        if pc:
            self.pc = pc
        self.running = True
        while self.running:
            self.process()
        print "Output:\n%s" % self.format_output()
        self.init_output()

class Cardiac(CPU, Memory, IO):
    pass

if __name__ == '__main__':
    c = Cardiac()
    c.read_deck('deck1.txt')
    try:
        c.run()
    except:
        print "IR: %s\nPC: %s\nOutput: %s\n" % (c.ir, c.pc, c.format_output())
        raise

You can find the code for deck1.txt from the Developing Upwards: CARDIAC: The Cardboard Computer article, I used the counting to 10 example.

Hopefully this article was inspiring to you and gives you a brief understanding on how to built class-bases modular and pluggable code in Python, and also gave you a nice introduction to developing a CPU simulator. In the next article which I hope to publish soon, will guide you through making a basic assembler for this CPU, so that you can easily and effortlessly create decks to play around with in the simulator.

Comment #1: Posted 4 years, 6 months ago by Calvin Spealman

This is such cool work! The simplicity of the CARDIAC is certainly something to admire. If you don’t mind I’ll probably follow up with a nod towards this. Are you planning to put the code up at a proper repo anywhere?

Comment #2: Posted 4 years, 6 months ago by Kevin Veroneau

@Calvin, the code is up in a repo, look inside the information tooltip box at the very top of this article for a click-able link to the BitBucket page.

About Me

My Photo

Names Kevin, hugely into UNIX technologies, not just Linux. I’ve dabbled with the demons, played with the Sun, and now with the Penguins.





Kevin Veroneau Consulting Services
Do you require the services of a Django contractor? Do you need both a website and hosting services? Perhaps I can help.

If you like what you read, please consider donating to help with hosting costs, and to fund future books to review.


Python Powered | © 2012-2019 Kevin Veroneau

 Posted by at 5:44 am
May 032019
 

https://www.cs.drexel.edu/~bls96/museum/cardiac.html

 

CARDIAC

Background

The acronym CARDIAC stands for “CARDboard Illustrative Aid to Computation.” It was developed by David Hagelbarger at Bell Labs as a tool for teaching how computers work in a time when access to real computers was extremely limited. The CARDIAC kit consists of a folded cardboard “computer” and an instruction manual. In July 1969, the Bell Laboratories Record contained an article describing the system and the materials being made available to teachers for working with it.

As illustrated in the following pictures, the CARDIAC computer consisted of a left-hand CPU section and a right-hand memory section. On the CPU side there are five sliders:

  • One slider of input “cards”
  • One slider for the accumulator sign
  • Three sliders for the digits of an instruction

The memory side has a single slider of output “cards.” Portions of the sliders show through cutouts in the card frame. The cutouts for the input and output card sliders each show the current card to be read or written. The combination of the accumulator sign and the three instruction sliders show steps through cutouts that describe the operation of the selected instruction. Effectively, the sliders and cutouts are the instruction decoder of the CPU. Finally, each memory location has a hole in it. A small carboard ladybug serves as the program counter which is moved from location to location in response to the steps described on the CPU side.

The CARDIAC manual is 50+ pages divided into 16 sections describing the basics of computers from a late 1960s perspective. The first six sections cover things like flow charts, instructions, data, addresses, and the stored program concept. Sections 7–12 discuss the CARDIAC and some basic programming techniques including loops and multiplication. Sections 13 and 14 discuss the techniques for bootstrapping and subroutines, both of which we elaborate on below. Section 15 focuses on the development of a program to play NIM. Finally, Section 16 discusses assemblers and compilers. Although there is some duplication of information, the material on this page is not intended to replace the manual. Rather, the material here expands on that in the manual, particularly from the point of view of one who is already familiar with the most basic concepts of computers and programming.

Pictures

Click on these pictures for larger versions.

Book and “Computer”

Open CARDIAC

CARDIAC Architecture

Memory

The CARDIAC has a grand total of 100 memory locations identified by the two-digit decimal numbers 00 through 99. Each memory location holds a signed three-digit decimal numer. (With the exception of a single code example, the CARDIAC book is actually silent on whether memory contains signed or unsigned values.) Locations 00 and 99 are special. Location 00 always contains the value 001, which as we see below is the instruction to read a card into location 01. This special value is used the the bootstrapping process discussed later. Location 99 always contains a value between 800 and 899. The tens and ones digits of the number are the value of the program counter after a jump instruction is executed. This provides the mechanism for a return from subroutine.

CPU

The CARDIAC CPU is a single-accumulator single-address machine. Thus each instruction operates optionally on a single memory location and the accumulator. For example, the ADD instruction reads the data in one memory location, adds it to the current value of the accumulator and stores the result back into the accumulator. The ALU supports addition, subtraction, and decimal shifting. CARDIAC’s CPU architecture is illustrated in the following figure:

The CARDIAC accumulator holds a signed 4-digit number, which seems odd given that everything else is oriented around 3-digit numbers. The manual includes the statement:

Since CARDIAC’s memory can store only 3-digit numbers, you may be puzzled by the inclusion of an extra square in the accumulator. It is there to handle the overflow that will result when two 3-digit numbers whose sum exceeds 999 are added.

What’s not clear is under what conditions that overflow/carry digit is kept or discarded. From the discussion of the SFT instruction in Section 12 of the manual, exactly four digits are kept for the intermediate value between the left and right shift operations. However, the manual doesn’t state whether all four digits are kept between instructions nor what happens when storing the accumulator to memory if the accumulator contains a number whose magnitude is greater than 999. In the case of our simulator, we retain all four digits, effectively implementing a 4-digit ALU. However, when storing the accumulator to memory, we discard the fourth digit. I.e. the number stored in memory is a mod 1000, where a is the contents of the accumulator.

I/O

The CARDIAC has exactly one input device and one output device. These are a card reader and a card punch. Unlike real punch cards, the CARDIAC input and output cards can each hold exactly one signed three-digit number. When a card is read by way of the INP instruction, it is taken into the card reader and removed from the stack of cards to be read. Similarly, on each OUT instruction, a new card is “punched” with the specified value on it, and the card moved to the output card stack.

Instruction Set

The CARDIAC’s instuction set has only 10 instructions, each identified by an operation code (opcode) of 0 through 9. The instructions are as follows:

Opcode Mnemonic Operation
0 INP Read a card into memory
1 CLA Clear accumulator and add from memory (load)
2 ADD Add from memory to accumulator
3 TAC Test accumulator and jump if negative
4 SFT Shift accumulator
5 OUT Write memory location to output card
6 STO Store accumulator to memory
7 SUB Subtract memory from accumulator
8 JMP Jump and save PC
9 HRS Halt and reset

Encoding

All instructions are non-negative numbers expressed as three-digit decimal numerals. The CARDIAC manual doesn’t describe what happens if an attempt is made to execute a negative instruction. In our simulator, we treat negative instructions as no-ops (i.e. they are ignored and the program continues on to the next instruction). The operation code is the most significant of those three digits, i.e., o=⌊i /100⌋, where i is the contents of the instruction register (IR) loaded from the memory location specified by the PC. For most instructions, the lower-order digits are the address of the operand, i.e. a=i mod 100. This arrangement is illustrated in the following figure.

In the cases of the INP and STO instructions, a is the destination address for the data coming from either an input card or the accumulator, respectively. In the cases of the CLA, ADD, OUT, and SUB instructions, a is the source address of the second operand to the ALU or the source address of the operand being written to an output card. For the TAC, JMP, and HRS instructions, a is the address to be loaded into the PC (conditionally, in the case of the TAC instruction). The remaining instruction, SFT, doesn’t treat the lower-order digits as an address. Instead, each of the lower-order digits is a number of digit positions to shift first left, then right. The left shift count is given by l=⌊a /10⌋, and the right shift count is given by r=a mod 10. The instruction format for the SFT instruction is shown in the following figure:

Instruction Execution

The instructions operate as described here. In this discussion, we use the following notation:

Notation Meaning
ACC Contents of the accumulator
PC Contents of the program counter
a Operand address as described in the previous subsection
MEM[x] Contents of memory location x
INPUT Contents of one card read from the input
OUTPUT Contents of one card written to the output
INP
The INP instruction reads a single card from the input and stores the contents of that card into the memory location identified by the operand address. (MEM[a] ← INPUT)
CLA
This instruction causes the contents of the memory location specified by the operand address to be loaded into the accumulator. (ACC ← MEM[a])
ADD
The ADD instruction takes the contents of the accumulator, adds it to the contents of the memory location identified by the operand address and stores the sum into the accumulator. (ACC ← ACC + MEM[a])
TAC
The TAC instruction is the CARDIAC’s only conditional branch instruction. It tests the accumulator, and if the accumulator is negative, then the PC is loaded with the operand address. Otherwise, the PC is not modified and the program continues with the instruction following the TAC. (If ACC < 0, PC ← a)
SFT
This instruction causes the accumulator to be shifted to the left by some number of digits and then back to the right some number of digits. The amounts by which it is shifted are shown above in the encoding for the SFT instruction. (ACC ← (ACC × 10^l) / 10^r)
OUT
The OUT instruction takes the contents of the memory location specified by the operand address and writes them out to an output card. (OUTPUT ← MEM[a])
STO
This is the inverse of the CLA isntruction. The accumulator is copied to the memory location given by the operand address. (MEM[a] ← ACC)
SUB
In the SUB instruction the contents of the memory location identified by the operand address is subtracted from the contents of the accumulator and the difference is stored in the accumulator. (ACC ← ACC − MEM[a])
JMP
The JMP instruction first copies the PC into the operand part of the instruction at address 99. So if the CARDIAC is executing a JMP instruction stored in memory location 42, then the value 843 will be stored in location 99. Then the operand address is copied into the PC, causing the next instruction to be executed to be the one at the operand address. (MEM[99] ← 800 + PC; PC ← a)
HRS
The HRS instruction halts the CARDIAC and puts the operand address into the PC. (PC ← a; HALT)

Assembly Language

All of the code fragments and complete program examples on this page are shown in an assembly language format with each line organized into six columns:

  1. Address: The first column shows the memory address respresented by that line.
  2. Contents: In the second column, we put the number that is stored in that memory location.
  3. In most cases, this is a instruction, but for lines with a DATA pseudo-op, it is a data value.

  4. Label: The third column contains an optional label on the memory location, allowing it to be identified by name, rather than by address.
  5. Opcode: Instruction mnemonics are places in the fourth column. In addition to the ten instructions discussed above, we will use on pseudo-op (or assembler directive), DATA. For memory locations containing a DATA item, the operand is the literal data value stored in the memory location, rather than an operand for an instruction. This pseudo-op is particularly useful when labeled for creating variables.
  6. Operand: The fifth column is the operand part of the instruction or the literal data for a DATA directive. Numerical operands are included directly in the address field of the instruction. When a label name appears as an oeprand, the memory address associated with that label is placed in the address field of the instruction.
  7. Comment: Any desired descriptive text can be placed after the operand.

Indirection, Indexing, and Pointers

Notice that the only way of specifying the address of a memory location we want to use is in the instruction itself. Most comptuer architectures provide a mechanism whereby the address we want to use can be stored in a register or another memory location. Variables which contains memory addresses are usually referred to as pointers.

Indirect Loads

Even though the CARDIAC doesn’t have hardware support for using pointers directly, we can still do simple indirect addressing. Suppose we have a variable stored in a memory location called ptr and it has the value 42 in it. Now if we want to load the accumulator with the contents of memory location 42, we can do something like:

05	100	loader	DATA	100
06	042	ptr	DATA	042

20	105		CLA	loader
21	206		ADD	ptr
22	623		STO	indload
23	100	indload	CLA	00

Notice that even though we have specified that we will load from location 00 in the instruction at location 23, we will have changed it to load from location 42 by the time we run execute that instruction. For that matter, it doesn’t matter if we’ve loaded anything into location 23 before starting this sequence. It will get set before we use it.

Indirect Stores

Storing the accumulator to a memory location identified by a pointer is similar. We just have to be careful not to lose the value we want to store while we’re fiddling about with the store instruction and in the following bit of code:

05	600	storer	DATA	600
06	042	ptr	DATA	042
07	000	acc	DATA	000

20	607		STO	acc
21	105		CLA	storer
22	206		ADD	ptr
23	625		STO	indstor
24	107		CLA	acc
25	600	indstor	STO	00

Array Indexing

Often we aren’t so much interested in a pointer that identifies a single memory location as we are in an array of memory locations we can refer to by index. We will identify our array locations starting at index 0. So the first element of the array is at index 0, the second at index 1, and so on. If we have a variable called base that holds the first address of the array, then we can just add the base and the index together to get the address of a particular element. This is just a slight modification of the indirect accesses above. In particular, to load from an array element:

05	100	loader	DATA	100
06	042	base	DATA	042
07	000	index	DATA	000

20	105		CLA	loader
21	206		ADD	base
22	207		ADD	index
23	624		STO	arrload
24	100	arrload	CLA	00

and for storing to an array element:

05	600	storer	DATA	600
06	042	base	DATA	042
07	000	index	DATA	000
08	000	acc	DATA	000

20	608		STO	acc
21	105		CLA	storer
22	206		ADD	base
23	207		ADD	index
24	626		STO	arrstor
25	108		CLA	acc
26	600	arrstor	STO	00

If we’re dealing with only one array, we could eliminate one add instruction from each sequence by pre-adding the base and loader and pre-adding the base and storer.

Stacks

Another use of indirect address is the stack data structure. If you’re not familiar with a stack, think of it like a stack of plates in a cafateria. A plate is always placed on top of the stack. Likewise, the one removed is always the one on the top of the stack. We refer to the process of putting an element onto a stack as pushing and the process of taking an element off of a stack as popping.Note that we always pop that most recently pushed element. Because of this, the stack is often referred to as a last-in, first-out (LIFO) data structure. Pushing and popping are very similar to storing and loading indirectly, except that we must also adjust the value of the pointer that identifies the top of the stack. In the following code we’ll use a memory location named tos (for top-of-stack) for the pointer. Also, we’ll do as is often done in hardware stacks and let the stack grow downward. That is to say, as we push data onto the stack, the stack pointer moves toward lower memory addresses. With that in mind, here is a fragment of code for pushing the accumulator onto the stack:

05	600	storer	DATA	600
06	100	loader	DATA	100
07	089	tos	DATA	089
08	000	acc	DATA	000

20	608		STO	acc
21	107		CLA	tos
22	205		ADD	storer
23	628		STO	stapsh
24	107		CLA	tos
25	700		SUB	00
26	607		STO	tos
27	108		CLA	acc
28	600	stapsh	STO	00

And similarly to pop from the top of the stack:

20	107		CLA	tos
21	200		ADD	00
22	607		STO	tos
23	206		ADD	loader
24	625		STO	stapop
25	100	stapop	CLA	00

These code fragments (slightly modified) are used in the example below that uses the LIFO properties of the stack to reverse the order of a list of numbers on the input cards.

Subroutines

There are many reasons why we might wish to subdivide a program into a number of smaller parts. In the context of higher level languages and methodologies, these subdivisions are often referred to by names like procedures, functions, and methods. All of these are types of subroutines, the name we usually use when working at the hardware or machine language level. In these sections, we look at the techniques for creating and using subroutines on the CARDIAC. Each subsection progressively builds from the simplest subroutine technique to more complex and advanced techiques. Don’t worry if not all of it makes sense on a first reading. You can get a good sense of the general idea of subroutines without necessarily understanding the details of how recursion is implemented on a machine as limited as the CARDIAC.

Single Simple Subroutines

In the CARDIAC, the JMP instruction is effectively a jump-to-subroutine instruction, storing the return address in location 99. Because the address stored in location 99 is prefixed by the opcode 8, the instruction in that location becomes a return-from-subroutine instruction. Thus any segment of code whose last instruction is at location 99 can be called as a subroutine, simply by jumping to its first instruction. For example, a simple routine to double the value of the accumulator could be coded as:

96	000	accval	DATA	000

97	696	double	STO	accval
98	296		ADD	accval
99	800		JMP	00

and the subroutine can be called with a jump to double:

	897		JMP	double

Multiple Subroutines

Clearly, if our subroutine executes a JMP instruction or if it calls another subroutine, then we will lose our return address, because it will be overwritten by the JMP instruction. Along similar lines, if we have more than one subroutine in our program, only one of them can be at the end of the memory space and flow directly into location 99.

As a result, in many cases, we’ll need a more involved subroutine linkage mechanism. One way to accomplish this is to save the return address somewhere and restore it when needed. If we use this method, we’ll have to devise a mechansism to transfer control to location 99 with the right return address. Although location 99 can itself be used as the return from subroutine instruction, it doesn’t have to be. In many cases, it will be easier to copy it to the end of our actual subroutine. Using this approach, we can write a subroutine that outputs the value of the accumulator as follows:

80	686	aprint	STO	86
81	199		CLA	99
82	685		STO	aexit
83	586		OUT	86
84	186		CLA	86
85	800	aexit	JMP	00

Similarly, our doubling routine would look like:

90	696	double	STO	96
91	199		CLA	99
92	695		STO	dexit
93	196		CLA	96
94	296		ADD	96
95	800	dexit	JMP	00

See below for an example of a program that uses these subroutines to produce a list of powers of two.

Recursion

There’s one more limitation on subroutines still in the techniques we have developed. What happens if a subroutine calls itself? You might reasonably as, is it even useful for a function call itself? The answer is, yes, and it called recursion.

The key to making it possible for a subroutine to call itself is to realize that no matter where we’re called from, we always want to return to the place from which we were most recently called that we haven’t already returned to. That should sound familiar. We should use the return addresses in the same LIFO order that a stack provides. In other words, when we call a recursive subroutine, we want to push the return address onto a stack and then pop it back off when we return from that subroutine. With a little reflection, we can see that this approach applies to all subroutine calls, not just to those that are recursive. This is why pushing return addresses on a stack is the basis for hardware subroutine call support in most architectures since about the 1970s on.

On the CARDIAC, we can implement this technique with a modification of the multiple subroutine technique above. When entering a subroutine, rather than copying location 99 to the return from subroutine instruction, we push the contents of location 99 onto the stack. Then when we’re about to return from the subroutine, we pop the return address off the stack into the return from subroutine instruction. So our code would look something like:

	1xx		CLA	tos
	2yy		ADD	storer
	6zz		STO	stapsh
	1xx		CLA	tos
	700		SUB	00
	6xx		STO	tos
	199		CLA	99
zz	600	stapsh	STO	00
	 .
	 .		body of the subroutine
	 .
	1xx		CLA	tos
	200		ADD	00
	6xx		STO	tos
	2ww		ADD	loader
	6ss		STO	stapop
ss	100	stapop	CLA	00
	6rr		STO	rts
rr	800	rts	JMP	00

There’s one more aspect of recursive subroutines that is also suitable for other subroutines as well. In particular, subroutines often need input data passed to them by whatever code has called them or temporary variables that are needed during the course of their operation. If a subroutine is not recursive, we can get away with just allocating some fixed memory locations for these. However, in the case of recursive subroutines, we need to make sure that we have fresh ones for each time the subroutine is called and not overwrite the ones that might still be needed by other instances we might return back to. The most natural way to handle this is to allocate them on the stack along with the return address.

Putting all these things together, we can summarize the steps for calling a subroutine in the most general cases:

  1. Before calling the subroutine, we push any inputs (also called arguments or parameters) onto the stack.
  2. Transfer control to the first instruction of the subroutine, saving the PC (which holds the return address) in the process.
  3. If the hardware has not already saved the PC onto the stack, the first thing we do in the subroutine is copy it to the stack.
  4. Move the stack pointer to resever space on the stack for any temporary (local) variables the subroutine will need.
  5. Before returning, the subroutine readjusts the stack pointer to remove the temporary variables it allocated.
  6. If the hardware does not already expect the return address to be on the stack, we need to pop it off the stack and copy it back to where it does need to be.
  7. Return control from the subroutine back to the code that called it.
  8. Finally, the calling code adjusts the stack pointer to remove the arguments it pushed onto the stack before calling the subroutine.

Bootstrapping

Like many of the early system designs, the mechanism for loading an initial program into the CARDIAC and getting it running involves a small amount of hardware support and a lot of cleverness. The whole enterprise is often somewhat remenescent of the image of a person attempting to lift themselves off the ground by pulling on their own bootstraps. This is why we usually refrer to the process as bootstrapping or often just booting.

The CARDIAC’s hardware support for bootstrapping is the fixed value of memory location 00. The fixed contents of this memory location are 001 which is the instruction to load a single card into location 01. Naturally, after executing this instruction, the PC moves to location 01 and executes the instruction on the card just read. But what do we put on that card to load? The answer is 002, which is the instruction to load a card into location 02. This causes us to load a second card into location 02 and execut it. At first glance, it would seem we haven’t really improved things any, because we’re right back where we’re still just loading a single card and executing it. But here’s where the first bit of cleverness comes in. The card we load into location 02 has the value 800 on it which causes us to jump back to location 00 which will load another card into location 01. We now have a loop that loads cards into location 01 and executes them. If the instructions we put into location 01 are reads of cards into other memory locations, we now have a little program that reads a whole set of cards into memory. Conveniently, a card containing just a memory address also contains the instruction to read a card into that memory address. So if the next card we read after the 800 is, say, 010, then location 01 will be changed to an instruction to read a card into location 10, after which we’ll execut the 800 instruction to jump back to location 00 and do it all over again. This means that after the 002 and 800 cards, we can have pairs of cards where the first of the pair is the address where we want to put some data, and the second of the pair is the data to put there.

If this is all we did, we’d read all the remaining cards into memory and then the computer would halt when there were no more cards to read. But there’s another trick we can play. If we make the last address-data card pair change location 02 from 800 to a jump to the first instruction of our program, the loader loop will stop and control will transfer to the program we just loaded. So after all of our address-data card pairs, we’ll append the cards 002 and 8xx where xx is the address of the first instruction of our program. The net effect is that we can now load a program and start running it without any manual intervention.

The last piece of this puzzle is how do we include the data we want the program to operate on? It turns out, that’s a simple as just appending the data after the 002 and 8xx cards. When control transfers to the program we loaded, any remaining cards will still be in the reader waiting to be read. When the program executes its first INP instruction, it will happily read the next card, not knowing that there were a bunch of other cards read ahead of it.

So putting all the pieces together, we bootstrap the CARDIAC by putting together a card deck that looks like:

002
800
 .
 .	address-data card pairs
 .
002
8xx	where xx is address of the first instruction
 .
 .	data cards
 .

Then we put that deck into the card reader, and start the computer at address 00. The CARDIAC will first load the two-card bootstrap loader, then load the program into memory, then transfer control to the newly loaded program. If the program itself also includes INP instructions, they read the remaining data cards.

Simulator

We have developed a CARDIAC simulator suitable for running the code discussed on this page. All of the examples in the next section have been tested using this simulator.

To avoid any unnecessary requirements on screen layout, the simulator is laid out a little differently than the physical CARDIAC. At the top of the screen is the CARDIAC logo from a photograph of the actual unit. This picture is also a link back to this page. The next section of the screen is the CARDIAC memory space as appears on the right hand side of the physical device. When the simulator starts up, the value 001 in location 00 and the value 8– in location 99 are preloaded. As a simplification, we don’t use a picture of a ladybug for the program counter, but instead highlight the memory location to which the PC points with a light green background. Each memory location is editable (including the ones that are intended to be fixed), and the tab key moves focus down each column in memory address order.

The bottom section of the simulator is the I/O and CPU. Input is divided into two text areas. The first is the card deck and is editable. The second area is the card reader, and as cards are consumed by the reader they are removed from the listing in the reader. Cards in the deck are loaded into the reader with the Load button. Output cards appear in the Output text area as they are generated with the OUT instruction.

The CPU section of the simulator has four parts showing the status of the CPU and buttons for control. On the top of the CPU section, the Program Counter is shown in an editable text box. Below that is the instruction decoder with non-editable text boxes showing the contents of the Instruction Register and a breakdown of the instruction decoding in the form of an opcode mnemonic and numeric operand. The Accumulator is shown below the instuction decoder. Below the register display are six buttons that control the operation of the simulator:

Reset
The Reset button clears the instruction register, resets the PC and accumulators to 0 and clears the output card deck.
Clear Mem
This button resets all memory locations to blank and re-initializes location 00 to 001 and location 99 to 8–.
Step
Clicking on the Step button causes the simulator to execute the single instruction highlighted in the memory space as pointed to by the program counter. Upon completion of the instruction, the screen is updated to show the state of the computer after the instruction.
Slow
The Slow button causes the simulator to begin executing code starting at the current PC. Instructions are executed at the rate of 10 per second with the screen being updated after each instruction. When the program is run in this way, the movement of the highlighted memory shows the flow of control in the program very clearly.
Run
In the current version of the simulator, the Run button causes the program to be executed beginning from the current PC at the full speed of the JavaScript interpreter. Because of the way JavaScript is typically implemented, the screen contents will not show the effects of code execution until the simulator executes the HRS instruction and the program halts.
Halt
Pressing the Halt button while the program is running in slow mode causes the simulator to stop after the current instruction. The state of the machine remains intact and can be continued with any of the StepSlow, or Run buttons.

Examples

The remainder of this page are a number of examples of programs written for the CARDIAC. They have all been tested using the simulator described above. Because the memory space of the CARDIAC is so limited, none of the programs are particularly complex. You won’t find a compiler, operating system, or web browser here. However, we do have a few of more complexity than you might expect. There’s a pretty simple program for generating a list of the powers of 2. There’s one that recursively solves the Towers of Hanoi problem. For each of them, we include the assembly language source code with assembled machine language code and a card deck suitable for bootstrapping on the CARDIAC.

Note that most of these examples aren’t the most compact way of solving the problem. Rather, they illustrate techniques as described through this page. The primary exception is the Towers of Hanoi solution which requried some effort to squeeze it into the limited memory space of the CARDIAC.

When we take these programs and turn them into decks of cards to be bootstrapped on the CARDIAC, we get the card decks listed below the program listings. If you cut and paste the list into the input deck of the simulator, hit load, and hit slow, you can see the program get loaded into memory and run.

Count from 1 to 10

This is sort of our CARDIAC version of “Hello World.” Our objective is simply to print out a set of output cards with the values 1 to 10. We keep two variables to control the process. One, called n keeps track of how many cards we still have left to print. At any point in time it represents that we need to print n+1 more cards. We also have a variable called cntr wich is the number to print out. Each time through the loop, we check to see if n is negative and if so, we’re done. If not, we decrement it, print cntr and then increment cntr.

Program Listing

04	009	n	DATA	009
05	000	cntr	DATA	000

10	100		CLA	00	Initialize the counter
11	605		STO	cntr	
12	104	loop	CLA	n	If n < 0, exit
13	322		TAC	exit
14	505		OUT	cntr	Output a card
15	105		CLA	cntr	Increment the card
16	200		ADD	00
17	605		STO	cntr
18	104		CLA	n	Decrement n
19	700		SUB	00
20	604		STO	n
21	812		JMP	loop
22	900	exit	HRS	00

Card Deck

002
800
010
100
011
605
012
104
013
322
014
505
015
105
016
200
017
605
018
104
019
700
020
604
021
812
022
900
004
009
002
810

List Reversal

Our next example uses the stack techniques described above to take in a list of cards and output the same list in reverse order. The first card in the input deck (after the bootstrapping and the program code) is the count of how many cards we’re operating on. The remainder of the input deck are the cards to reverse. In the example card deck, we are reversing the first seven Fibonacci numbers.

Program Listing

04	600	storer	DATA	600
05	100	loader	DATA	100
06	089	tos	DATA	089	Stack pointer
07	000	acc	DATA	000	Temp for saving accumulator
08	000	n1	DATA	000	Write counter
09	000	n2	DATA	000	Read counter

10	008		IN	n1	Get the number of cards to reverse
11	108		CLA	n1	Initialize a counter
12	609		STO	n2
13	109	rdlp	CLA	n2	Check to see if there are any more cards to read
14	700		SUB	00
15	327		TAC	wrlp
16	609		STO	n2
17	007		IN	acc	Read a card
18	106		CLA	tos	Push it onto the stack
19	204		ADD	storer
20	625		STO	stapsh
21	106		CLA	tos
22	700		SUB	00
23	606		STO	tos
24	107		CLA	acc
25	600	stapsh	STO	00
26	813		JMP	rdlp
27	108	wrlp	CLA	n1	Check to see if there are any more cards to write
28	700		SUB	00
29	339		TAC	done
30	608		STO	n1	
31	106		CLA	tos	Pop a card off the stack
32	200		ADD	00
33	606		STO	tos
34	205		ADD	loader
35	636		STO	stapop
36	100	stapop	CLA	00
37	890		JMP	aprint	Output a card
38	827		JMP	wrlp
39	900	done	HRS	00

90	696	aprint	STO	96	Write a card containing the contents of the accumulator
91	199		CLA	99
92	695		STO	aexit
93	596		OUT	96
94	196		CLA	96
95	800	aexit	JMP	00

Card Deck

002
800
004
600
005
100
006
089
007
000
008
000
009
000
010
008
011
108
012
609
013
109
014
700
015
327
016
609
017
007
018
106
019
204
020
625
021
106
022
700
023
606
024
107
025
600
026
813
027
108
028
700
029
339
030
608
031
106
032
200
033
606
034
205
035
636
036
100
037
890
038
827
039
900
090
696
091
199
092
695
093
596
094
196
095
800
002
810
007
001
001
002
003
005
008
013

Powers of 2

This is a slightly more interesting version of the list from 1 to 10. In this case, we are printing the powers of 2 from 0 to 9. The main difference is that instead of incrementing the number to output, we call a subroutine that doubles it. The program illustrates the use of multiple subroutines as discussed above.

Program Listing

04	000	n	DATA	000
05	009	cntr	DATA	009

10	100		CLA	00	Initialize the power variable with 2^0
11	880		JMP	aprint
12	604	loop	STO	n
13	105		CLA	cntr	Decrement the counter
14	700		SUB	00
15	321		TAC	exit	Are we done yet?
16	605		STO	cntr
17	104		CLA	n
18	890		JMP	double	Double the power variable
19	880		JMP	aprint	Print it
20	812		JMP	loop
21	900	exit	HRS	00

80	686	aprint	STO	86	Print a card with the contents of the accumulator
81	199		CLA	99
82	685		STO	aexit
83	586		OUT	86
84	186		CLA	86
85	800	aexit	JMP	00

90	696	double	STO	96	Double the contents of the accumulator
91	199		CLA	99
92	695		STO	dexit
93	196		CLA	96
94	296		ADD	96
95	800	dexit	JMP	00

Card Deck

002
800
005
009
010
100
011
880
012
604
013
105
014
700
015
321
016
605
017
104
018
890
019
880
020
812
021
900
080
686
081
199
082
685
083
586
084
186
090
696
091
199
092
695
093
196
094
296
002
810

Towers of Hanoi

By far the most complex example we include is a solution to the Towers of Hanoi problem. The puzzle consists of three posts on which disks can be placed. We begin with a tower of disks on one post with each disk smaller than the one below it. The other two posts are empty. The objective is to move all of the disks from one post to another subject to the following rules:

  1. Only one disk at a time may be moved.
  2. No disk may be placed on top of a smaller disk.

According to legend, there is a set of 64 disks which a group of monks are responsible for moving from one post to another. When the puzzle with 64 disks is finally solved, the world will end.

Although the puzzle sounds like it would be difficult to solve, it’s very easy if we think recursively. Moving n disks from Post a to Post b using Post c as a spare can be done as follows:

  1. Move n−1 disks from Post a to Post c.
  2. Move one disk from Post a to Post b.
  3. Move n−1 disks from Post c to Post b.

The CARDIAC doesn’t have enough memory to solve a 64-disk puzzle, but we can solve smaller instances of the problem. In particular, the program we show here can solve up to six disks. The actual number of disks to solve is given by the first data card, and the initial assignment of source destination and spare posts is given on the second data card. The post assignments as well as the output encoding are shown in the following table.

Output Disk Move
000 1 → 3
001 2 → 3
002 3 → 2
003 3 → 1
004 2 → 1
005 1 → 2

For example, the post assignments indicated by a card with the value 3 are that Post 3 is a, Post 2 is c and Post 1 is b. Similarly, an output card with 3 indicates that we are to move a disk from Post 3 to Post 1.

Before trying to understand the details of this program, note that there are several tricks used to reduce the memory usage. The amount of memory available for the stack allows for a puzzle of up to six disks to be solved with this program. Be aware, however, that slow running this program on six disks takes the better part of a half hour to run.

Program Listing

03	031	tos	DATA	031
04	100	loader	DATA	100
05	600	storer	DATA	600
06	107	r2ld	DATA	r2
07	001	r2	DATA	001
08	000		DATA	000
09	005	five	DATA	005
10	004		DATA	004
11	003	three	DATA	003
12	002		DATA	002

34	033		INP	32	Get the number of disks from the cards
35	032		INP	31	Get the column ordering from the cards
36	838		JMP	tower	Call the tower solver
37	900		HRS

38	199	tower	CLA	99	Push the return address on the stack
39	890		JMP	push
40	111		CLA	three	Fetch n from the stack
41	870		JMP	stkref
42	700		SUB	00	Check for n=0
43	366		TAC	towdone
44	890		JMP	push	Push n-1 for a recursive call
45	111		CLA	three	Get the first recursive order
46	870		JMP	stkref
47	669		STO	t1
48	109		CLA	five
49	769		SUB	t1
50	890		JMP	push
51	838		JMP	tower	Make first recursive call
52	880		JMP	pop
53	111		CLA	three	Get move to output
54	870		JMP	stkref
55	669		STO	t1
56	569		OUT	t1
57	111		CLA	three	Get second recursive order
58	870		JMP	stkref
59	206		ADD	r2ld
60	661		STO	t2
61	100	t2	CLA	00
62	890		JMP	push
63	838		JMP	tower	Make second recursive call
64	880		JMP	pop
65	880		JMP	pop
66	880	towdone	JMP	pop
67	668		STO	towret
68	800	towret	JMP	00

70	679	stkref	STO	refsav	Replace the accumulator with the contents
71	199		CLA	99	of the stack indexed by the accumulator
72	678		STO	refret
73	179		CLA	refsav
74	203		ADD	tos
75	204		ADD	loader
76	677		STO	ref
77	100	ref	CLA	00
78	800	refret	JMP	00

80	199	pop	CLA	99	Pop the stack into the accumulator
81	688		STO	popret
82	103		CLA	tos
83	200		ADD	00
84	603		STO	tos
85	204		ADD	loader
86	687		STO	popa
87	100	popa	CLA	00
88	800	popret	JMP	00

90	689	push	STO	pshsav	Push the accumulator on to the stack
91	103		CLA	tos
92	205		ADD	storer
93	698		STO	psha
94	103		CLA	tos
95	700		SUB	00
96	603		STO	tos
97	189		CLA	pshsav
98	600	psha	STO	00

Card Deck

002
800
003
031
004
100
005
600
006
107
007
001
008
000
009
005
010
004
011
003
012
002
034
033
035
032
036
838
037
900
038
199
039
890
040
111
041
870
042
700
043
366
044
890
045
111
046
870
047
669
048
109
049
769
050
890
051
838
052
880
053
111
054
870
055
669
056
569
057
111
058
870
059
206
060
661
061
100
062
890
063
838
064
880
065
880
066
880
067
668
068
800
070
679
071
199
072
678
073
179
074
203
075
204
076
677
077
100
078
800
080
199
081
688
082
103
083
200
084
603
085
204
086
687
087
100
088
800
090
689
091
103
092
205
093
698
094
103
095
700
096
603
097
189
098
600
002
834
003
000

Pythagorian Triples

The next example comes courtesy of Mark and Will Tapley. It finds sets of three integers which satisfy the Pythagorian property of x2+y2=z2.

Discussion

There is much motivation and explanation for this program at:

https://www.khanacademy.org/math/recreational-math/vi-hart/vi-cool-stuff/v/what-was-up-with-pythagoras

Subroutine to calculate square of a number:

In finding pythagorean triplets, the operation of squaring a number occurs very often, so the program uses a subroutine to perform this function.

  • Addresses 076–099 are loaded with the subroutine to utilize the return function hard-wired at address 099.
  • Addresses 072–075 are used for data storage for the subroutine.
  • Address 072 is loaded with the value 32, one larger than the largest allowable input. The calling program can test an input by subtracting this value from the prospective input and branching if the result is negative. (Negative value means legal input.)
  • Address 073 accepts the input to the subroutine. On return, the absolute value of the input will be in this location.
  • Address 074 is used as a counter during routine execution.
  • Address 075 will contain the calculated square, an integer between 0 and 961 inclusive.
Subroutine INPUT:

Store the number to be squared in address 073
Jump to address 077 (label SQmem in assembly listing)

-OR-

Load the number to be squared into the accumulator
Jump to address 076 (label SQacc in assembly listing)

Subroutine OUTPUT:

On return, the square of the input number is in address 075.

The subroutine has a single loop (addresses 090–098). In each loop, it subtracts one from a counter which is initially set to one greater than the input number N, then adds a copy of N into the output address. When the counter reaches 1, the output address contains the sum of N copies of N=N2 and the loop exits, returning program control to the location from which it was called (per the return capability special function of location 99).

Limitations:

The square of the input number must have 3 or fewer digits to comply with cell storage limitations. Therefore the input number is checked to be 31 or less (since 322=1024). Violating this condition will cause the subroutine to terminate execution (HRS) with the program counter pointing at location 086. The input number is converted from negative to positive if it was negative, so if the calling program needs a copy of the input, it should store it in some location other than Address 073 (SQIN). After the subroutine executes, that location will contain the absolute value of the input.

Main Program:

The main program searches over all allowable lengths of the shortest side S of the right triangles corresponding to pythagorean triplets. For each shortest side, it then searches over all possible lengths of the intermediate side L. For each combination of short and intermediate sides, it checks whether there is a hypotenuse H that satisfies the condition S2+L2=H2. The short side (S) search starts at 0, to avoid missing any triplets with very small values. (This results in identifying the degenerate triplet (0,1,1) which does satisfy 02+12=12 but does not really correspond to a right triangle.) The long side (L) search for each value of S starts at S+1, because L cannot equal S for an integer triplet (see URL above) and if L<S, the corresponding triplet should already have been found with a smaller S. (So, this program will identify (3,4,5) but will not identify (4,3,5).) The hypotenuse (H) search starts at 1.4 times S, since the minimum possible length of the hypotenuse is greater than the square root of 2 (1.404…) times S. (Note: 1.4 times S is calculated by shifting S right and then adding four copies of the result, which is truncated to an integer, to S. For S<10, the result is just S, so the search takes needlessly long until S≥10.)

With the starting values for S, L, and H, the program calculates S2 + L2−H2. If the result is <0, H is too long. In this case, the program increments L and tries again. If the result is =0, a triplet has been found and is printed out. The program then increments L and tries again. If the result is >0, H is too short. In this case, H is incremented and the program tries again. When H is long enough that no more triplets can be found for this value of S, the value of S is incremented, new L and H starting values are calculated, and the loop repeats.

  • Addresses 010–067 are loaded with the main program.
  • Addresses 004–009 are used for data storage.
  • Address 004 contains S, the smallest member of the triplet (length of the short leg of the triangle) and is initially set to 0.
  • Address 005 contains S2, calculated each time S is changed.
  • Address 006 contains L, the intermediate member of the triplet (length of the long “leg” of the triangle) and is re-initialized for each smallest member loop to one greater than the smallest member (which is always the minimum possible value for L; see above)
  • Address 007 contains L2, calculated each time L is changed.
  • Address 008 contains H, the largest member of the triplet (length of the hypotenuse of the triangle) and is initialized for each smallest member to a value <1.4×(the smallest value) (which is always shorter than the minimum possible value for H)
  • Address 009 contains H2, calculated each time H is changed. The same address also contains S/10 (S shifted right by one place), used to initialize H each time S is changed. This value is used to set the initial value of H to 1.4 S, which is just less than √2S.

The “outside” loop of the program (addresses 010–067) tests for all possible sets of triplets with the smallest value S stored in 004. After each loop, it increments the value of S and tries again. This loop will terminate when the value of 1.4×S exceeds 31, since the subroutine will no longer be able to calculate correct squares for any possible hypotenuse value (H). The subroutine will halt execution when this input is sent to it. (The outer loop also contains a check to verify that the value of S itself doesn’t exceed 31, but this check is never reached.)

The next-inner loop (addresses 032–061) starts with a value of L=S+1. Any smaller, and L would take the role of S (and hence, the resulting triplet would have already been found with a smaller S) or would be qual to S (and the length of the corresponding hypotenuse would be irrational). This loop terminates on one of two conditions: first, when the value of H exceeds 31 (in which case the subroutine to calculate squares can no longer work); or second, when 2L>S2. This latter condition applies because once L exceeds S2/2, L2 and H2 cannot differ by as little as S2 even if H=L+1. At that point, H2−L2 = (L+1)2−L2=2L+1>S2.

The innermost section (addresses 032–044) calculates the difference S2+L2−H2. If the difference is positive, H is incremented and the loop repeats. If the difference is zero, a triplet has been found and the values of S, L, and H are printed out. If the difference is negative or zero, L is then incremented and the loop repeats. In any case where H is incremented, its new value is checked against the limit for inputs to the subroutine, and if it exceeds that limit, the inner two loops terminate and the outer loop progresses to the next value of S.

Independent Verification:

The code below is instructions to Mathematica (tested on versions 8 and 3) which should compute the same output as the above program, but using a more general (and slower) algorithm. It will also generate a plot of triplets by (short side) against (intermediate side).

candid = 
Table[
	Table[
		Table[
			{i, j, k}, 
			{k, j, i^2/2 + 2}
		], 
		{j, i+1, i^2/2 + 1}
	], 
    {i, 0, 31}
];

trips = Select[Flatten[candid, 2], #1[[1]]^2 + #1[[2]]^2 == #1[[3]]^2 & ];

smalltrips = Select[trips, #1[[3]] < 32 & ]

ListPlot[(Take[#1, 2] & ) /@ trips]

Program Listing

Symbol map:
Address		Variable
04		S			short side = 0 initially
05		S2			square of short side
06		L			long side
07		L2			square of long side
08		H			hypotenuse
09		H2			square of hypotenuse. (Also used
					to store S/10 in picking initial
					value of H each loop.)
--		----
72		SQLIM			maximum input to Square = 30 initially
73		SQIN			input to square subroutine
74		SQCNT			counter for square subroutine
75		SQOUT			output for square subroutine

Address		Name (as referenced by JMP instruction)
00		BootLp
10		S_Loop
32		L_Loop
45		Next_H
49		PrintTr
52		Inc_L
62		Next_S
--		-----
76		SQacc
77		SQmem
83		SQpos
87		SQgood
90		SQloop

Load	Instr.	
Address	Opcode		Instruction	Comment

		BootLp:
002	800		JMP 	BootLp	Bootstrap loop. Code self-modifies
					to load memory locations.

004	000		(variable)	S Initial value for Short side = 0
072	032		(constant)	SQLIM Limit on input to square = 32

		S_Loop:
010	104		CLA	S		
011	673		STO	SQIN	Input to square subroutine
012	200		ADD	1	(Using ROM value)
013	606		STO	L	Save long side L
014	877		JMP	SQmem	Square subroutine (saved entry)
015	175		CLA	SQOUT	Retrieve result of subroutine
016	605		STO	S2	Store square of S
017	106		CLA	L	Load L
018	876		JMP	SQacc	Square subroutine, entry using ACC
019	175		CLA	SQOUT	Retrieve result of subroutine
020	607		STO	L2	Store square of L
021	104		CLA	S	Load S
022	401		SFT	01	Divide by 10
023	609		STO	H2	Save S/10 temporarily in H2 location
024	209		ADD	H2	Sum into accumulator
025	209		ADD	H2	Sum into accumulator
026	209		ADD	H2	Sum into accumulator
027	204		ADD	S	Sum is now between S and 1.4 S ~ S sqrt(2)
028	608		STO	H	Store initial hypotenuse H
029	876		JMP	SQacc	Square subroutine (accumulator entry)
030	175		CLA	SQOUT
031	609		STO	H2	Store square of H

		L_Loop:
032	105		CLA	S2	Load short side squared
033	207		ADD	L2	Add long side squared
034	709		SUB	H2	Subtract hyp. squared
035	352		TAC	Inc_L	if H2 too big, increment L
036	700		SUB	1	Subtract 1 (ROM)
037	349		TAC	PrintTr	H was just right - print
038	108		CLA	H	H too small, so load H
039	200		ADD	1	Add 1 (ROM)
040	608		STO	H	Store back
041	673		STO	SQIN	Save in input to Square routine
042	772		SUB	SQLIM	Subtract limit for input
043	345		TAC	Next_H	Go on if negative (input < 32)
044	862		JMP	Next_S	Branch to next value of S if not.

		Next_H:
045	877		JMP	SQmem	(saved entry)
046	175		CLA	SQOUT	Get result
047	609		STO	H2
048	832		JMP	L_Loop	Try again

		PrintTr:
049	504		OUT	S	Print S
050	506		OUT	L	Print L
051	508		OUT	H	Print H

		Inc_L:
052	106		CLA	L	Load L
053	200		ADD	1	Increment
054	606		STO	L	Store
055	876		JMP	SQacc	Square subr.
056	175		CLA	SQOUT	get result
057	607		STO	L2	Store new L squared
058	106		CLA	L	Load new L
059	206		ADD	L	Double it
060	705		SUB	S2	Subtract S^2
061	332		TAC	L_Loop	If S^2 still bigger, keep looking

		Next_S:
062	104		CLA	S	Load short side S
063	200		ADD	1	Increment
064	604		STO	S	Store short side S
065	772		SUB	SQLIM	Subtract upper limit for Square
066	310		TAC	S_Loop	If result is negative, new S is low
					enough to loop again
067	900		HRS		Else, S is longer than Square can handle,
					so Done - exit.

---	---		--------
		SQacc:
076	673		STO	SQIN	Jump here if input value is in ACC

		SQmem:
077	173		CLA	SQIN	Jump here if input is already in SQIN
078	773		SUB	SQIN	Input was in both accumulator and SQIN, so this gets 0
079	675		STO	SQOUT	initialize output to 0 for use later
080	773		SUB	SQIN	This gets negative of SQIN
081	383		TAC	SQpos	If the negative is negative, SQIN is positive - good.
082	673		STO	SQIN	If the negative is positive, store that in SQIN.

		SQpos:
083	173		CLA	SQIN	Load Absolute value of input
084	772		SUB	SQLIM	Compare against limit value
085	387		TAC	SQgood	Quit if number to square > limit
086	986		HRS		Halt if error on input.

		SQgood:
087	173		CLA	SQIN	Retrieve number
088	200		ADD	0	Add one
089	674		STO	SQCNT	Count is input + 1

		SQloop:
090	174		CLA	SQCNT	load counter
091	700		SUB	0	subtract 1
092	674		STO	SQCNT	save new counter value
093	175		CLA	SQOUT	load output
094	273		ADD	SQIN	add a copy of input
095	675		STO	SQOUT	store cumulative sum
096	100		CLA	0	load 1 (from ROM)
097	774		SUB	SQCNT	subtract counter
098	390		TAC	SQloop	loop again if counter was > 1

		Jump out of boot loop to 10 (skips initial increment to S)
002	810		JMP	S_Loop

Card Deck

002
800
004
000
072
032
010
104
011
673
012
200
013
606
014
877
015
175
016
605
017
106
018
876
019
175
020
607
021
104
022
401
023
609
024
209
025
209
026
209
027
204
028
608
029
876
030
175
031
609
032
105
033
207
034
709
035
352
036
700
037
349
038
108
039
200
040
608
041
673
042
772
043
345
044
862
045
877
046
175
047
609
048
832
049
504
050
506
051
508
052
106
053
200
054
606
055
876
056
175
057
607
058
106
059
206
060
705
061
332
062
104
063
200
064
604
065
772
066
310
067
900
076
673
077
173
078
773
079
675
080
773
081
383
082
673
083
173
084
772
085
387
086
986
087
173
088
200
089
674
090
174
091
700
092
674
093
175
094
273
095
675
096
100
097
774
098
390
002
810

Other CARDIAC Resources

Related Work


Brian L. StuartDepartment of Computer ScienceDrexel University

 Posted by at 5:43 am
May 032019
 
 Posted by at 5:41 am
Apr 272019
 

 

gatema logo

Výroba
desek
plošných
spojů

Rozšiřujeme povrchové úpravy o Imerzní stříbro
Nová brožura pro vývojáře
Konfigurátor

Nová brožura pro vývojáře

Na 20 stranách formátu A4 najdete celou škálu tabulek, nákresů, fotek nebo popisů důležitých pro kvalitní návrh desek plošných spojů. Přináší důležité informace a odpovědi na vaše dotazy. Navrhnutý stackup, dodržení aspect ratia vrtaného otvoru, výběr správné technologie atp.

OBJEDNAT ZDARMA

Tento web využívá cookies

Tyto stránky používají soubory cookie k poskytování služeb a analýze návštěvnosti. Soubory cookie používáme také k personalizaci reklam, když na tomto webu na něco kliknete nebo přejdete, vyjádříte tím svůj souhlas k našemu používání cookie.Přečtěte si další informace, mimo jiné i to, jaké máte možnosti.

 Posted by at 3:13 pm
Apr 182019
 

https://web.archive.org/web/20180119022941/http://energia.nu/guide/tutorial_energytrace/

https://43oh.com/2015/09/how-to-measure-an-energia-applications-power-usage-with-energytrace

 

https://github.com/carrotIndustries/energytrace-util

How to measure Energy profile in Energia with TI Energy Trace

This tutorial is based on material originally posted at 43oh.com by Frank Milburn: http://43oh.com/2015/09/how-to-measure-an-energia-applications-power-usage-with-energytrace/

While experimenting with an nRF24L01 radio and MSP430G2553 microcontroller powered by a super capacitor and solar panel, the need to better understand the energy usage became increasingly apparent. I was aware of EnergyTrace, but didn’t think it could be used because I was developing with the Energia IDE. After some digging though I found out that it can be used on Energia applications and that it has powerful capabilities.

Figure 1 EnergyTrace sampling an Energia application. (Click for a larger image)

 

This demonstration will show how to measure the energy and power usage of a MSP-EXP430G2LaunchPad running an application developed entirely within the Energia IDE.

In order to use EnergyTrace, it is necessary to have Code Composer Studio version 6.1 or newer and a LaunchPad with supporting hardware such as the MSP-EXP430FR5969 in addition to the target microcontroller. There is a free version of CCS and the MSP-EXP430FR5969 can be obtained for US $15.99. The MSP-EXP430FR5969 powers the MSP-EXP430G2 which allows EnergyTrace to sample the supply voltage and provide energy and power data without using the CCS debugger – so the Energia solution is being measured directly.

Code Composer Studio is a full featured professional IDE and it takes time to learn if you are not familiar with it. Fortunately, a detailed understanding of all the features is not necessary to use EnergyTrace. Code Composer Studio can be downloaded here and the second chapter of this workshop gives an introduction on how to use it. These videos provide an understanding of how to use EnergyTrace – pay particular attention to the one on “Using EnergyTrace Technology without a Debug Session” as that is the basic method used here.

EnergyTrace works by continuously measuring the energy supplied to the target as opposed to discrete measurement of voltage over a shunt resistor. This is done with a software controlled dc-dc converter that generates the power for the target. The pulses from the dc-dc converter are counted and the more pulses per unit time, the higher the current flow. Accordingly, even the most rapid events that contribute to current consumption are captured, although the sampling frequency is only on the order of 1 kHz.

Inefficient Code – Blink Energy 1

As a demonstration, we will use that old standby Blink. The code below gives a pretty standard sketch for Blink although the blink is shortened and the delay time between blinks is lengthened from that which is normally used.

EnergyTrace will be used to estimate how long this will run on two AA batteries.

The sketch was uploaded to a M430G2553 microcontroller on the MSP-EXP430G2 LaunchPad in the normal manner with Energia 16. Then the MSP-EXP430G2 LaunchPad and the MSP-EXP430FR5969 LaunchPad were connected together with female-to-female jumpers as shown in Figure 2.

energia_energyTrace_launchpad

The connections are described in detail starting at the bottom of page 26 of this reference. Pay attention to which side of J3 and J13 the connections are made. Then connect the MSP-EXP430FR5969 via USB to your computer and open up Code Composer Studio. I chose to start a new CCS Project for the MSP430FR5969 with the blink example but this is not important as EnergyTrace will not use the code in the project or the debugger.

Then, follow the directions for Using EnergyTrace Technology without a Debug Session.

AA batteries were chosen in the preferences tab for EnergyTrace. After selecting 30 seconds for the runtime and pressing start, the simulation began and gave the results in Figure 3.

EnergyTrace results from the standard Blink example

The summary table at left in Figure 3 reports an estimated battery life of 77 days.The battery life estimates are just that – battery life depends on chemistry, how the battery was manufactured, its age, the temperature, how it is drained, etc.

The power is graphed in the center chart and reports a rather steady 3 mW base with spikes up to about 15.5 mW every second corresponding to the LED blinking. At right is the energy graph showing a total energy usage of 109 mJ over the 30 second test. It may be hard to see, but there are stair steps every second corresponding to the LED spikes.

More Efficient Code – Blink Energy 2

It looks like the base load is coming from the microcontroller and that it is the primary user of power. Leaving the unused pins floating on the microcontroller can result in incremental power usage. To overcome this, put all pins in OUTPUT mode and then pull them LOW. So, take off the female-to-female jumpers and put the J3 jumpers back in place for the MSP-EXP430G2. The setup() function is then modified as shown in the snippet below.

Upload the revised sketch to the MSP-EXP430G2 and put everything back in place to use Code Composer Studio. Open it up and run EnergyTrace. The results are shown in Figure 4.

Energy Trace results from the Blink example with pins pulled LOW

The energy used has been reduced to 105 mJ and the battery life of the 2xAA batteries is now 80 days. An improvement, but can we do better?

Even More Efficient Code – Blink Energy3

The sleep() function was introduced with Energia version 13. Using it instead of delay() puts the microcontroller into Low Power Mode 3 (LPM3) which should reduce the base load. The code below shows a modified loop() function that uses sleep() instead of delay().

The EnergyTrace results are shown in Figure 5.

EnergyTrace results from the Blink example with pins pulled LOW and using sleep()

Impressive. The base has dropped to where it doesn’t show on the scale while in sleep mode and the total energy is reduced to 19.1 mJ. Battery life is up to 441 days now from 77 days in the first example. The energy chart now clearly shows the stair step that occurs when the LED is turned on.

Two additional observations can be made from Figure 7. The first observation is that the spikes appear to be of uneven width and don’t always drop immediately to the base. The User’s Guide for Code Composer Studio contains the answers in the FAQ section of Chapter 3:

Q: My Power graph seems to include noise. Is my board defective?

A: The power values shown in the Power graph are derived (that is, calculated) from the accumulated energy counted by the measurement system. When the target is consuming little energy, a small number of energy packets over time are supplied to the target, and the software needs to accumulate the dc-dc charge pulses over time before a new current value can be calculated. For currents under 1 µA, this can take up to one second, while for currents in the milliamp range, a current can be calculated every millisecond.

Q: My power mode profile sometimes shows short periods of power modes that I haven’t used anywhere in my code. For example, I’m expecting a transition from active mode to LPM3, but I see a LPM2 during the transition.

A: When capturing in EnergyTrace++ mode, digital information is continuously collected from the target device. One piece of this information is the power mode control signals. Activation of low-power modes requires stepping through a number of intermediate states. Usually this happens too quickly to be captured by the trace function, but sometimes intermediate states can be captured and are displayed for a short period of time as valid low-power modes.

The second observation is that the period is longer between blinks with the sleep() function. This can occur because of the way sleep() is implemented and it may give lower timing resolution than delay().

EnergyTrace can also compare the results between two cases as shown in Figure 6.

Comparison of standard Blink to more efficient example

More on Energy Savings

Energia users interested in improving the energy efficiency of their applications should also be aware of the sleepSeconds(), suspend(), and wakeup() functions.

Briefly, sleepSeconds() should be used whenever the interval is 1 second or greater. The one second intervals of sleepSeconds () are relatively coarse and are subject to some inaccuracy.

The suspend() function puts the microcontroller into Low Power Mode 4 (LPM4) for very low power usage. It can then be woken with an external interrupt by the wakeup() function.

search on 43oh will turn up a number of threads with information on these functions and there is also a post on github here that demonstrates them. To get the full energy reductions and accuracy that are available on MSP430 microcontrollers though it is necessary to use Code Composer Studio with its full access to timers, lower energy states, and peripherals instead of Energia.

Summary

EnergyTrace can provide information on the energy usage of MSP430 processors to Energia users. It is necessary to have Code Composer Studio installed along with a LaunchPad having the necessary supporting hardware such as the MSP-EXP430FR5969. In this demonstration the estimated battery life of a simple example was increased from 77 days to 441 days – an increase of a factor of 5.7. The primary benefit came from using the sleep() function instead of delay(). A reduction in power usage from putting all pins in a known state was also demonstrated.

Other means of improving power usage using the sleepSeconds(), suspend(), and wakeup() functions were briefly introduced. Energia users should be aware that sleep () and sleepSeconds () may result in less accurate sleep intervals.

 Posted by at 6:16 pm
Apr 022019
 

https://jeelabs.net/projects/hardware/wiki/JeeNode

JeeNode v6 – JN

Hardware Reference

The JeeNode is a wireless micro-controller board designed for a variety of Physical Computing tasks. From measuring and reporting temperature, humidity, and other environmental data to tracking and controlling energy consumption around the house. It was inspired by the Arduino Duemilanove and Uno boards, and by the “Real Bare Bones Board” (RBBB) from Modern Device.

At a glance

What’s on a JeeNode v6, from left to right:

  • 6-pin FTDI-compatible serial I/O port, used for power, re-flashing, and communication
  • 3.3V power regulator which accepts 3.5 … 13V as external power source
  • 8-pin combined Power / Serial / I2C / Extended (PSIX) connector
  • ATmega328P microcontroller by Atmel, with 16 MHz ceramic resonator
  • 2×4-pin combined SPI / ISP connector, with 2 general-purpose I/O lines
  • RFM12B wireless RF module for the 433, 868, or 915 MHz ISM band, by Hope RF
  • short wire – acts as radio antenna (78, 82, 165 mm long, for 915, 868, 433 MHz, respectively)

And on the long sides of the board: two I/O “ports” each, with one analog/digital I/O, one digital I/O, +3.3V, ground, PWR, and interrupt (IRQ) line. All ports have an identical pinout for use with “plugs”.

 Posted by at 4:44 am
Mar 242019
 

 

 

How to Install amForth on the Arduino Uno

This is a detailed technical article that describes how to set up an Arduino Uno microcontroller board with a version of the Forth programming language called amForth. My regular readers should ignore this post. Stay tuned though loyal readers, I will be posting more on this topic latter for a general audience.

I recently went through the process of installing amForth on my Arduino Uno. I wasn’t able to find a simple, easy to follow explanation of how to do it. I had to piece together information from a variety of sources and make a number of mistakes before I could make it work. I decided to write this article to make it easier for someone else who wants to avoid the headaches.

The method I am going to describe uses two Arduino Unos: one as the target board that you will install amForth on, and the other as the programmer. There are many other devices that can be used to program the Arduino’s microcontroller, but this is the only one I will describe. Also, the process I will follow uses a Mac. There will obviously be some differences if you are using Windows. I assume you have no knowledge of microcontroller programming, which was the case with me.

Here are the detailed steps:

Install CrossPack on your Mac

CrossPack is a developer environment that works on the Mac for programming Atmel’s AVR line of microcontrollers. The Arduino Uno uses Atmel’s m328p chip. Download CrossPack here. (See Figure 1 below.)

CrossPack

Figure 1: You should see this when you follow the link. Click the Download button.

Download amForth

Next, download the latest version of amForth here. You will see a list of folders with version names on them. (See Figure 2 below.) Above the list of folders are the words “Looking for the latest version?” followed by a highlighted link to a file ending with .tar.gz. Click on that link. The file will download to your Mac and be placed in your Downloads folder. Create a folder on your desktop called Forthduino and drag the .tag.gz file into that folder.

amForth download

Figure 2: Download amForth files.

Open the Forthduino folder you created on your desktop and click on the .tag.gz file to open it. You should see a new folder appear with the name “amforth” followed by the version number. Now you need to look inside the amforth folder to find the files uno.hex and uno.eep.hex. They can be found in amforth/appl/arduino/ (See Figure 3 below.) Copy the two files into the Forthduino folder.

find hex files

Figure 3: Find uno.hex and uno.eep.hex.

Set up the Arduino Programmer

As I said at the start of this article, you are going to program one Arduino Uno with another. Connect the Arduino Uno that will serve as the programmer to your Mac’s USB port now. Then start up the Arduino software on your Mac. Under the File menu look in Examples and find the sketch called ArduinoISP. Click on this sketch and upload it to your Arduino. Make sure that you have selected Arduino Uno as the Board under the Tools menu and you have your USB port selected under the Port heading of the Tools menu. The programmer is now ready. Keep your Arduino software open.

The next task is to connect the target Arduino Uno to the Arduino Uno serving as the programmer. Figure 4 below shows how this should be done. You can power the target Arduino Uno by running two wires from the +5V and Ground pins of the programmer Arduino as shown in Figure 4. Or you can power it separately with a battery pack. Pick one. Don’t do both!

Wire up the two Arduino Uno's as shown in the picture above.

Figure 4: Wire up the two Arduino Unos as shown in the picture above. Source: arduino.cc

Now you are ready to flash amForth to the Arduino…

Flash amForth to the target Arduino Uno

Before you perform the actually flashing process, go back to your Arduino software and look under the Tools menus. The Programmer selected should be Arduino as ISP. If not, change it. Also open up the Arduino Serial Monitor and select a BAUD rate of 19200.

Next, open up the Terminal program on your Mac. First thing you need to do is change Terminal’s directory to the Forthduino folder that has all your amForth files. The easiest way to do this is to type “cd” in the Terminal program follow by a space and then using the mouse pointer drag the Forthduino folder into the Terminal window. You should see the path typed out after the “cd” as in the second line of figure 5 below. If you’ve got that, press the RETURN key now.

Now the fun part. Type the following line in your Terminal window:

avrdude -P /dev/tty.usb* -c avrisp -b 19200 -p m328p -e -U flash:w:uno.hex:i -U eeprom:w:uno.eep.hex:i -U efuse:w:0x05:m -U hfuse:w:0xD9:m -U lfuse:w:0xFF:m

Terminal avrdude

Figure 5: Avrdude command entered into Terminal.

Type the above in one continuous line. Figure 5, above, shows what it should look like. Now press the RETURN key. You should see a readout of the flashing process. If everything worked it will look like the screen pictured below in Figure 6:

Figure 7: This is what you should see if everything has worked correctly.

Figure 6: This is what you should see if the avrdude command has worked correctly.

If you want to understand what this avrdude command with all its obscure add-ons does, I recommend reading this explanation from Limor Fried of Adafruit.

Connect to your Forthduino

Now that amForth is installed on your Arduino Uno, you can disconnect all the jumper wires between the two Arduinos and put the Arduino programmer aside. Plug your new Forthduino directly into your Mac’s USB port. Then, open the Mac’s Terminal program once more. Type this line and hit RETURN:

screen /dev/tty.usb* 38400

You should now see the amForth welcome screen as pictured here:

And that’s all there is to it. If you have any questions or comments add them below this article and I will be sure to respond to you.

 Posted by at 8:41 pm
Mar 192019
 

file:///C:/ti/430eforth-ide/lessons/lesson12.html

( Example 12.      Sines and Cosines )

\ Sines and cosines of angles are among the most often encountered
\ transdential functions, useful in drawing circles and many other
\ different applications.  They are usually computed using floating
\ numbers for accuracy and dynamic range.  However, for graphics
\ applications in digital systems, single integers in the range from
\ -32768 to 32767 are sufficient for most purposes.  We shall
\ study the computation of sines and cosines using the single
\ integers.

\ The value of sine or cosine of an angle lies between -1.0 and +1.0.
\ We choose to use the integer 10000 in decimal to represent 1.0
\ in the computation so that the sines and cosines can be represented
\ with enough precision for most applications.  Pi is therefore
\ 31416, and 90 degree angle is represented by 15708.  Angles
\ are first reduced in to the range from -90 to +90 degrees,
\ and then converted to radians in the ranges from -15708 to
\ +15708.  From the radians we compute the values of sine and
\ cosine.

\ The sines and cosines thus computed are accurate to 1 part in
\ 10000.  This algorithm was first published by John Bumgarner
\ in Forth Dimensions, Volume IV, No. 1, p. 7.

DECIMAL
31415 CONSTANT PI
10000 CONSTANT 10K 

VARIABLE XS                             ( square of scaled angle )

: KN ( n1 n2 -- n3, n3=10000-n1*x*x/n2 where x is the angle )
        XS @ SWAP /                     ( x*x/n2 )
        NEGATE 10K */                   ( -n1*x*x/n2 )
        10K +                           ( 10000-n1*x*x/n2 )
        ;

: (SIN) ( x -- sine*10K, x in radian*10K )
        DUP DUP 10K */                  ( x*x scaled by 10K )
        XS !                            ( save it in XS )
        10K 72 KN                       ( last term )
        42 KN 20 KN 6 KN                ( terms 3, 2, and 1 )
        10K */                          ( times x )
        ;

: (COS) ( x -- cosine*10K, x in radian*10K )
        DUP 10K */ XS !                 ( compute and save x*x )
        10K 56 KN 30 KN 12 KN 2 KN      ( serial expansion )
        ;

: SIN ( degree -- sine*10K )
        PI 180 */                       ( convert to radian )
        (SIN)                           ( compute sine )
        ;

: COS ( degree -- cosine*10K )
        PI 180 */
        (COS)
        ;

\ To test the routines, type:

\        90 SIN .                        10000 
\        45 SIN .                         7070 
\        30 SIN .                         4999 
\         0 SIN .                            0 
\        90 COS .                            0 
\        45 COS .                         7072 
\         0 COS .                         10000 

flush
 Posted by at 6:43 am
Mar 162019
 

https://skilldrick.github.io/easyforth/

Easy Forth

 

by Nick Morgan

View on GitHub

Introduction

This small ebook is here to teach you a programming language called Forth. Forth is a language unlike most others. It’s not functional or object oriented, it doesn’t have type-checking, and it basically has zero syntax. It was written in the 70s, but is still used today for certain applications.

Why would you want to learn such an odd language? Every new programming language you learn helps you think about problems in new ways. Forth is very easy to learn, but it requires you to think in a different way than you’re used to. That makes it a perfect language to broaden your coding horizons.

This book includes a simple implementation of Forth I wrote in JavaScript. It’s by no means perfect, and is missing a lot of the functionality you’d expect in a real Forth system. It’s just here to give you an easy way to try out the examples. (If you’re a Forth expert, please contribute here and make it better!)

I’m going to assume that you know at least one other programming language, and have a basic idea of how stacks work as a data structure.

Adding Some Numbers

 Posted by at 10:07 am
Mar 142019
 
  1. https://www.forth-ev.de/
Forth-Gesellschaft e.V.

Forth-Gesellschaft e.V.

Wir programmieren Forth
Home  :  Mitmachen  :  Erweiterte Suche  :  Statistik  :  Verzeichnis  :  Datenschutzerklärung  :  Forth Büro  :  Impressum  :  Photos  :  Redaktion  :  Download  :  Links  : Umfragen  :  Kalender  :  Wiki
Willkommen bei Forth-Gesellschaft e.V.
Donnerstag, 14. März 2019 @ 08:47 CET

Mitmachen! – Participate please!

Es ist sehr einfach. Der Artikel-Editor hilft dabei. “Plain old text” genügt.
Gib deinem Artikel eine Überschrift, eine *kurze* Einleitung in der du sagst um was es geht, und im Hauptteil folgt dann alles andere. So bleiben die Nachrichtenseiten übersichtlich. Dein Artikel wird dann von einem Admin gelesen, freigegeben, und du erhältst Bescheid per E-Mail. (mehr…)

It is very easy. The Article Editor helps. “Plain old text” is sufficient. Define a heading for your article, a * short please * Introduction about what it is you want to say, and then everything else follows as a text block. Done this way our news site remains easy to read. Your article will be read by an administrator, then released, and you will receive a notification via e-mail. (jp) (more…)

 Posted by at 7:48 am